Good day and Roll Tide. Alabama managed to get to the SEC Championship Game in Kalen DeBoer’s second year; that has to have some value, but they did very little with it, putting on an embarrassing display in a 28-7 loss to the Georgia Bulldogs.
You’ll have to excuse my being relatively terse today: It was an extremely unpleasant game, but also a pretty simple loss that I don’t think has very much analytical intrigue.
We also now have the context that Alabama did not drop at all in the CFP Rankings and will be going to the Playoffs. So apparently this game did not matter, hence, “whatever.”
.cfb-chart-embed-cfb-chart-1765138185644-mzkgiv5qf {
font-family: -apple-system, BlinkMacSystemFont, ‘Segoe UI’, ‘Roboto’, sans-serif;
margin: 0;
padding: 0;
}
.cfb-chart-embed-cfb-chart-1765138185644-mzkgiv5qf .chart-container {
background: white;
border-radius: 12px;
border: 1px solid #e5e5e5;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
overflow: hidden;
}
.cfb-chart-embed-cfb-chart-1765138185644-mzkgiv5qf .chart-header {
padding: 18px 24px 14px;
border-bottom: 1px solid #e5e5e5;
background: white;
}
.cfb-chart-embed-cfb-chart-1765138185644-mzkgiv5qf .chart-title {
font-size: 18px;
font-weight: 600;
color: #171717;
margin: 0;
}
.cfb-chart-embed-cfb-chart-1765138185644-mzkgiv5qf .chart-subtitle {
font-size: 11px;
font-weight: 400;
color: #737373;
margin: 4px 0 0 0;
}
.cfb-chart-embed-cfb-chart-1765138185644-mzkgiv5qf .chart-content {
padding: 20px 24px 24px !important;
}
.cfb-chart-embed-cfb-chart-1765138185644-mzkgiv5qf .chart-content { height: 325px; }
@media (max-width: 640px) {
.cfb-chart-embed-cfb-chart-1765138185644-mzkgiv5qf .chart-content {
padding: 12px 16px 20px !important;
height: 280px !important;
}
.cfb-chart-embed-cfb-chart-1765138185644-mzkgiv5qf .chart-header {
padding: 12px 16px 12px !important;
}
.cfb-chart-embed-cfb-chart-1765138185644-mzkgiv5qf .embed-footer-top {
padding: 8px 12px !important;
}
.cfb-chart-embed-cfb-chart-1765138185644-mzkgiv5qf .data-definitions {
padding: 12px !important;
}
}
.cfb-chart-embed-cfb-chart-1765138185644-mzkgiv5qf .embed-footer {
border-top: 1px solid #e5e5e5;
font-size: 12px;
color: #737373;
}
.cfb-chart-embed-cfb-chart-1765138185644-mzkgiv5qf .embed-footer-top {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 16px;
}
.cfb-chart-embed-cfb-chart-1765138185644-mzkgiv5qf .embed-footer-link {
color: #737373;
text-decoration: none;
font-weight: 500;
}
.cfb-chart-embed-cfb-chart-1765138185644-mzkgiv5qf .embed-footer-link:hover {
color: #525252;
text-decoration: underline;
}
.cfb-chart-embed-cfb-chart-1765138185644-mzkgiv5qf .data-definitions-toggle {
background: none;
border: none;
color: #737373;
font-size: 12px;
font-weight: 500;
cursor: pointer;
display: flex;
align-items: center;
gap: 4px;
padding: 0;
}
.cfb-chart-embed-cfb-chart-1765138185644-mzkgiv5qf .data-definitions-toggle:hover {
color: #525252;
}
.cfb-chart-embed-cfb-chart-1765138185644-mzkgiv5qf .caret {
transition: transform 0.2s ease;
font-size: 10px;
}
.cfb-chart-embed-cfb-chart-1765138185644-mzkgiv5qf .caret.expanded {
transform: rotate(180deg);
}
.cfb-chart-embed-cfb-chart-1765138185644-mzkgiv5qf .data-definitions {
display: none;
padding: 16px;
background: #fafafa;
border-top: 1px solid #e5e5e5;
font-size: 12px;
line-height: 1.4;
}
.cfb-chart-embed-cfb-chart-1765138185644-mzkgiv5qf .data-definitions.expanded {
display: block;
}
.cfb-chart-embed-cfb-chart-1765138185644-mzkgiv5qf .data-definitions ul {
margin: 0;
padding-left: 0;
list-style: none;
}
.cfb-chart-embed-cfb-chart-1765138185644-mzkgiv5qf .data-definitions li {
margin-bottom: 4px;
}
Win Probability
Alabama vs. Georgia • Dec 6, 2025
- Win Probability: Likelihood of winning based on game situation
- Line Color: Gradient reflects which team is favored
- 50% Line: Dashed line indicates even odds
- Data Source: CollegeFootballData.com win probability models
// Toggle data definitions accordion – unique function per embed
function toggleDefinitions_cfb_chart_1765138185644_mzkgiv5qf() {
const definitions = document.getElementById(‘dataDefinitions_cfb-chart-1765138185644-mzkgiv5qf’);
const caret = document.getElementById(‘caret_cfb-chart-1765138185644-mzkgiv5qf’);
if (definitions.classList.contains(‘expanded’)) {
definitions.classList.remove(‘expanded’);
caret.classList.remove(‘expanded’);
} else {
definitions.classList.add(‘expanded’);
caret.classList.add(‘expanded’);
}
}
// Sequential script loading for better reliability
(function() {
‘use strict’;
let retryCount = 0;
const maxRetries = 50; // 5 seconds total
// Load scripts sequentially
function loadScript(url, callback) {
const script = document.createElement(‘script’);
script.src = url;
script.onload = callback;
script.onerror = function() {
console.error(‘Failed to load script:’, url);
showError(‘Failed to load required chart library’);
};
document.head.appendChild(script);
}
function showError(message) {
const canvas = document.getElementById(‘cfb-chart-1765138185644-mzkgiv5qf’);
if (canvas && canvas.parentNode) {
canvas.parentNode.innerHTML = ‘
‘;
}
}
function initChart() {
retryCount++;
// Check if Chart.js is available
if (typeof Chart === ‘undefined’) {
if (retryCount >= maxRetries) {
showError(‘Chart library failed to load. Please refresh the page.’);
return;
}
setTimeout(initChart, 100);
return;
}
// Check if datalabels plugin is available
if (typeof ChartDataLabels === ‘undefined’) {
if (retryCount >= maxRetries) {
showError(‘Chart plugin failed to load. Please refresh the page.’);
return;
}
setTimeout(initChart, 100);
return;
}
// Check if canvas element exists
const canvas = document.getElementById(‘cfb-chart-1765138185644-mzkgiv5qf’);
if (!canvas) {
console.warn(‘Canvas element not found yet, retrying…’);
setTimeout(initChart, 100);
return;
}
// Prevent multiple chart instances
if (canvas.chartInstance) {
console.log(‘Chart already initialized’);
return;
}
try {
// Register the datalabels plugin
Chart.register(ChartDataLabels);
// Embed actual chart data directly
const chartData = {
“labels”: [
0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45,
46,
47,
48,
49,
50,
51,
52,
53,
54,
55,
56,
57,
58,
59,
60,
61,
62,
63,
64,
65,
66,
67,
68,
69,
70,
71,
72,
73,
74,
75,
76,
77,
78,
79,
80,
81,
82,
83,
84,
85,
86,
87,
88,
89,
90,
91,
92,
93,
94,
95,
96,
97,
98,
99,
100,
101,
102,
103,
104,
105,
106,
107,
108,
109,
110,
111,
112,
113,
114,
115,
116,
117,
118,
119,
120,
121,
122,
123,
124,
125,
126,
127,
128,
129,
130,
131,
132,
133,
134,
135,
136,
137,
138,
139,
140,
141,
142,
143,
144,
145,
146
],
“datasets”: [
{
“label”: “Win Probability”,
“data”: [
{
“x”: 0,
“y”: 58.449697494506836
},
{
“x”: 1,
“y”: 56.44407868385315
},
{
“x”: 2,
“y”: 52.025169134140015
},
{
“x”: 3,
“y”: 56.91106915473938
},
{
“x”: 4,
“y”: 61.33887767791748
},
{
“x”: 5,
“y”: 61.371028423309326
},
{
“x”: 6,
“y”: 58.371829986572266
},
{
“x”: 7,
“y”: 58.207422494888306
},
{
“x”: 8,
“y”: 58.251798152923584
},
{
“x”: 9,
“y”: 57.673537731170654
},
{
“x”: 10,
“y”: 53.48825454711914
},
{
“x”: 11,
“y”: 58.9715838432312
},
{
“x”: 12,
“y”: 60.443949699401855
},
{
“x”: 13,
“y”: 55.06293773651123
},
{
“x”: 14,
“y”: 56.92055821418762
},
{
“x”: 15,
“y”: 56.92055821418762
},
{
“x”: 16,
“y”: 56.341809034347534
},
{
“x”: 17,
“y”: 54.06621694564819
},
{
“x”: 18,
“y”: 50.14472007751465
},
{
“x”: 19,
“y”: 45.173391699790955
},
{
“x”: 20,
“y”: 45.138657093048096
},
{
“x”: 21,
“y”: 45.717018842697144
},
{
“x”: 22,
“y”: 31.602370738983154
},
{
“x”: 23,
“y”: 34.01043713092804
},
{
“x”: 24,
“y”: 32.83179998397827
},
{
“x”: 25,
“y”: 32.70324170589447
},
{
“x”: 26,
“y”: 37.4027281999588
},
{
“x”: 27,
“y”: 37.210360169410706
},
{
“x”: 28,
“y”: 35.65240204334259
},
{
“x”: 29,
“y”: 23.086069524288177
},
{
“x”: 30,
“y”: 24.164967238903046
},
{
“x”: 31,
“y”: 24.737191200256348
},
{
“x”: 32,
“y”: 24.737191200256348
},
{
“x”: 33,
“y”: 22.727076709270477
},
{
“x”: 34,
“y”: 24.008584022521973
},
{
“x”: 35,
“y”: 22.367990016937256
},
{
“x”: 36,
“y”: 23.305945098400116
},
{
“x”: 37,
“y”: 25.08980631828308
},
{
“x”: 38,
“y”: 25.733143091201782
},
{
“x”: 39,
“y”: 22.014760971069336
},
{
“x”: 40,
“y”: 23.543167114257812
},
{
“x”: 41,
“y”: 22.509098052978516
},
{
“x”: 42,
“y”: 23.766525089740753
},
{
“x”: 43,
“y”: 23.347453773021698
},
{
“x”: 44,
“y”: 12.210091948509216
},
{
“x”: 45,
“y”: 13.56402188539505
},
{
“x”: 46,
“y”: 13.088841736316681
},
{
“x”: 47,
“y”: 12.455590069293976
},
{
“x”: 48,
“y”: 10.944878309965134
},
{
“x”: 49,
“y”: 8.347881585359573
},
{
“x”: 50,
“y”: 10.645715147256851
},
{
“x”: 51,
“y”: 11.132529377937317
},
{
“x”: 52,
“y”: 10.706605017185211
},
{
“x”: 53,
“y”: 11.469555646181107
},
{
“x”: 54,
“y”: 14.091236889362335
},
{
“x”: 55,
“y”: 11.570368707180023
},
{
“x”: 56,
“y”: 11.492323875427246
},
{
“x”: 57,
“y”: 11.864566057920456
},
{
“x”: 58,
“y”: 11.362392455339432
},
{
“x”: 59,
“y”: 10.768584907054901
},
{
“x”: 60,
“y”: 10.220003128051758
},
{
“x”: 61,
“y”: 9.380307048559189
},
{
“x”: 62,
“y”: 8.835984021425247
},
{
“x”: 63,
“y”: 8.895999193191528
},
{
“x”: 64,
“y”: 10.151544958353043
},
{
“x”: 65,
“y”: 10.313834249973297
},
{
“x”: 66,
“y”: 8.071663975715637
},
{
“x”: 67,
“y”: 7.501506060361862
},
{
“x”: 68,
“y”: 8.382219821214676
},
{
“x”: 69,
“y”: 9.326758980751038
},
{
“x”: 70,
“y”: 11.165531724691391
},
{
“x”: 71,
“y”: 11.165531724691391
},
{
“x”: 72,
“y”: 11.38678714632988
},
{
“x”: 73,
“y”: 9.944332391023636
},
{
“x”: 74,
“y”: 10.145866870880127
},
{
“x”: 75,
“y”: 8.94583985209465
},
{
“x”: 76,
“y”: 6.011980399489403
},
{
“x”: 77,
“y”: 6.995503604412079
},
{
“x”: 78,
“y”: 7.125180214643478
},
{
“x”: 79,
“y”: 7.703311741352081
},
{
“x”: 80,
“y”: 5.651657283306122
},
{
“x”: 81,
“y”: 4.854795336723328
},
{
“x”: 82,
“y”: 0.12882710434496403
},
{
“x”: 83,
“y”: 1.8923712894320488
},
{
“x”: 84,
“y”: 2.0229337736964226
},
{
“x”: 85,
“y”: 0.7550650276243687
},
{
“x”: 86,
“y”: 0
},
{
“x”: 87,
“y”: 2.457525208592415
},
{
“x”: 88,
“y”: 2.272985689342022
},
{
“x”: 89,
“y”: 3.032182529568672
},
{
“x”: 90,
“y”: 2.828531712293625
},
{
“x”: 91,
“y”: 5.110610648989677
},
{
“x”: 92,
“y”: 5.9646375477313995
},
{
“x”: 93,
“y”: 2.54383645951748
},
{
“x”: 94,
“y”: 2.228699624538424
},
{
“x”: 95,
“y”: 1.9181927666068121
},
{
“x”: 96,
“y”: 0.6453395821154739
},
{
“x”: 97,
“y”: 2.1498586982488734
},
{
“x”: 98,
“y”: 1.7247494310143008
},
{
“x”: 99,
“y”: 1.577329076826707
},
{
“x”: 100,
“y”: 2.048958279192704
},
{
“x”: 101,
“y”: 2.0130114629878584
},
{
“x”: 102,
“y”: 4.04618494212888
},
{
“x”: 103,
“y”: 4.325368627952822
},
{
“x”: 104,
“y”: 2.4694800377599404
},
{
“x”: 105,
“y”: 2.234785072595993
},
{
“x”: 106,
“y”: 2.641590684745561
},
{
“x”: 107,
“y”: 3.1338676811460053
},
{
“x”: 108,
“y”: 3.6715801812011137
},
{
“x”: 109,
“y”: 4.066292197709259
},
{
“x”: 110,
“y”: 4.28727790884581
},
{
“x”: 111,
“y”: 3.543825820903405
},
{
“x”: 112,
“y”: 5.140087382237428
},
{
“x”: 113,
“y”: 4.566977547207043
},
{
“x”: 114,
“y”: 8.77204909508657
},
{
“x”: 115,
“y”: 6.392665205554558
},
{
“x”: 116,
“y”: 5.331951753216578
},
{
“x”: 117,
“y”: 4.704622936967005
},
{
“x”: 118,
“y”: 4.766420638559165
},
{
“x”: 119,
“y”: 4.696270926472545
},
{
“x”: 120,
“y”: 7.786239973299998
},
{
“x”: 121,
“y”: 5.470012414326568
},
{
“x”: 122,
“y”: 4.5566783950473155
},
{
“x”: 123,
“y”: 5.406438760609812
},
{
“x”: 124,
“y”: 3.7351591293619695
},
{
“x”: 125,
“y”: 1.8347449543490244
},
{
“x”: 126,
“y”: 2.2508865570988275
},
{
“x”: 127,
“y”: 1.4674778428110629
},
{
“x”: 128,
“y”: 1.0164439067423203
},
{
“x”: 129,
“y”: 2.839817159312326
},
{
“x”: 130,
“y”: 3.2389373451229173
},
{
“x”: 131,
“y”: 2.5598725934059576
},
{
“x”: 132,
“y”: 0.54864650404408
},
{
“x”: 133,
“y”: 3.356958103389654
},
{
“x”: 134,
“y”: 2.9854142428838286
},
{
“x”: 135,
“y”: 1.5666810610823436
},
{
“x”: 136,
“y”: 4.902863179378947
},
{
“x”: 137,
“y”: 3.5315753955096154
},
{
“x”: 138,
“y”: 1.774600937820865
},
{
“x”: 139,
“y”: 0.7979213239149877
},
{
“x”: 140,
“y”: 2.59028737005211
},
{
“x”: 141,
“y”: 3.5994748377520245
},
{
“x”: 142,
“y”: 9.829430299569218
},
{
“x”: 143,
“y”: 5.793493219969284
},
{
“x”: 144,
“y”: 6.4229076995006835
},
{
“x”: 145,
“y”: 7.633775511876771
},
{
“x”: 146,
“y”: 0
}
],
“borderColor”: “#af283c”,
“backgroundColor”: “transparent”,
“pointBackgroundColor”: [
“rgb(175, 40, 60)”,
“rgb(177, 38, 59)”,
“rgb(184, 31, 55)”,
“rgb(176, 39, 59)”,
“rgb(175, 40, 60)”,
“rgb(175, 40, 60)”,
“rgb(175, 40, 60)”,
“rgb(175, 40, 60)”,
“rgb(175, 40, 60)”,
“rgb(175, 40, 60)”,
“rgb(182, 34, 56)”,
“rgb(175, 40, 60)”,
“rgb(175, 40, 60)”,
“rgb(179, 36, 58)”,
“rgb(176, 39, 59)”,
“rgb(176, 39, 59)”,
“rgb(177, 38, 59)”,
“rgb(181, 35, 57)”,
“rgb(187, 28, 53)”,
“rgb(196, 20, 48)”,
“rgb(196, 20, 48)”,
“rgb(195, 21, 49)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”
],
“pointBorderColor”: [
“rgb(175, 40, 60)”,
“rgb(177, 38, 59)”,
“rgb(184, 31, 55)”,
“rgb(176, 39, 59)”,
“rgb(175, 40, 60)”,
“rgb(175, 40, 60)”,
“rgb(175, 40, 60)”,
“rgb(175, 40, 60)”,
“rgb(175, 40, 60)”,
“rgb(175, 40, 60)”,
“rgb(182, 34, 56)”,
“rgb(175, 40, 60)”,
“rgb(175, 40, 60)”,
“rgb(179, 36, 58)”,
“rgb(176, 39, 59)”,
“rgb(176, 39, 59)”,
“rgb(177, 38, 59)”,
“rgb(181, 35, 57)”,
“rgb(187, 28, 53)”,
“rgb(196, 20, 48)”,
“rgb(196, 20, 48)”,
“rgb(195, 21, 49)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”
],
“pointRadius”: 0,
“pointHoverRadius”: 4,
“tension”: 0.15,
“borderWidth”: 2.2,
“fill”: false,
“selectedTeam”: “Alabama”,
“opponentTeam”: “Georgia”,
“isSelectedTeamHome”: true,
“playTexts”: [
“(14:57) Shotgun #14 G.Stockton pass complete short left to #1 Z.Branch caught at UGA22, for 17 yards to the UGA42 (#3 K.Sabb; #10 J.Jefferson), out of bounds, 1ST DOWN”,
“(14:22) No Huddle-Shotgun #14 G.Stockton rush middle for 3 yards gain to the UGA45 (#42 Y.Pierre)”,
“(13:43) No Huddle-Shotgun #14 G.Stockton pass complete short right to #1 Z.Branch caught at UGA40, for 0 yards to the UGA45 (#2 Z.Brown; #3 K.Sabb) PENALTY UGA Holding (#86 D.Bell) 10 yards from UGA45 to UGA35. NO PLAY”,
“(13:23) No Huddle-Shotgun #3 N.Frazier rush right for 3 yards loss to the UGA32 (#11 J.Renaud)”,
“(12:41) No Huddle-Shotgun #14 G.Stockton rush middle for 6 yards gain to the UGA38 (#42 Y.Pierre)”,
“(12:04) #92 B.Thorson punt 43 yards to the ALA19 fair catch by #7 C.Adams at ALA19”,
“(11:56) Shotgun #4 D.Hill rush middle for 5 yards gain to the ALA24 (#94 X.McLeod)”,
“(11:12) Shotgun #4 D.Hill rush middle for 2 yards gain to the ALA26 (#6 D.Everette)”,
“(10:31) Shotgun #17 L.Brooks rush right for 0 yards to the ALA26 (#1 E.Robinson IV)”,
“(09:56) #38 B.Doud punt 44 yards to the UGA30 fair catch by #1 Z.Branch at UGA30”,
“(09:51) Shotgun #14 G.Stockton pass complete short right to #2 J.McCray caught at UGA26, for 4 yards loss to the UGA26, End Of Play”,
“(09:16) No Huddle-Shotgun #14 G.Stockton pass incomplete short right to #3 N.Frazier thrown to UGA26 broken up by #1 D.Jackson”,
“(09:11) Shotgun #14 G.Stockton pass complete short middle to #32 C.Jones caught at UGA30, for 13 yards to the UGA39 (#41 N.Hill-Green)”,
“(08:33) #92 B.Thorson punt 53 yards to the ALA08, out of bounds at ALA08”,
“(08:25) Shotgun #15 T.Simpson pass complete short middle to #1 I.Horton caught at ALA15, for 12 yards to the ALA20 (#20 J.Thomas), 1ST DOWN”,
“(08:00) #4 D.Hill rush middle for 2 yards gain to the ALA22 (#94 X.McLeod)”,
“(07:24) Shotgun #15 T.Simpson rush middle for 1 yard loss to the ALA21 (#0 G.Harris Jr.)”,
“(06:41) Shotgun #15 T.Simpson pass incomplete short middle to #5 G.Bernard thrown to ALA30”,
“(06:37) #38 B.Doud punt 0 yards to the ALA21 blocked by #83 C.Speer recovered by UGA #19 J.Williams at ALA25 #19 J.Williams return 4 yards to the ALA21 (#14 M.Pritchett)”,
“(06:23) #3 N.Frazier rush middle for 14 yards gain to the ALA07 (#18 B.Hubbard), 1ST DOWN”,
“(05:49) #3 N.Frazier rush middle for 1 yard loss to the ALA08 (#2 Z.Brown)”,
“(05:14) No Huddle-Shotgun #86 D.Bell rush middle for 7 yards gain to the ALA01 (#94 E.Hill; #3 K.Sabb)”,
“(04:37) #14 G.Stockton pass complete short right to #0 R.Robinson II caught at ALA00, for 1 yard to the ALA00 TOUCHDOWN, clock 04:36 #91 P.Woodring kick attempt good (H: #14 G.Stockton, LS: #60 B.Gardner)”,
“(04:33) Shotgun #0 A.Dear rush middle for 2 yards gain to the ALA27 (#5 R.Wilson)”,
“(03:55) Shotgun #15 T.Simpson pass complete short right to #4 D.Hill caught at ALA30, for 4 yards to the ALA31 (#9 C.Cole)”,
“(03:09) Shotgun #15 T.Simpson pass complete short left to #2 R.Williams caught at ALA36, for 20 yards to the UGA49, out of bounds at UGA49, 1ST DOWN”,
“(02:24) Shotgun #15 T.Simpson pass incomplete short right to #1 I.Horton thrown to UGA32 broken up by #1 E.Robinson IV”,
“(02:19) No Huddle-Shotgun #15 T.Simpson pass complete short middle to #5 G.Bernard caught at UGA47, for 4 yards to the UGA45 (#20 J.Thomas)”,
“(01:33) Shotgun #15 T.Simpson pass intercepted by #6 D.Everette at UGA28 #6 D.Everette return 34 yards to the ALA38 (#5 G.Bernard), out of bounds PENALTY UGA Face Mask (#6 D.Everette) 15 yards from ALA42 to UGA43”,
“(01:21) #2 J.McCray rush middle for 2 yards gain to the UGA45 (#90 L.Simmons)”,
“(00:49) #14 G.Stockton pass complete short right to #4 O.Delp caught at UGA44, for 5 yards to the UGA50 (#10 J.Jefferson; #8 J.Hill)”,
“(00:20) #14 G.Stockton rush middle for 3 yards gain to the ALA47 (#31 K.Keeley), 1ST DOWN”,
“End of 1st quarter.”,
“(14:56) Shotgun #3 N.Frazier rush middle for 1 yard gain to the ALA46 (#0 D.Lawson)”,
“(14:24) Shotgun #3 N.Frazier rush middle for 11 yards gain to the ALA35 (#0 D.Lawson), 1ST DOWN”,
“(13:42) No Huddle-Shotgun #33 C.Bowens rush left for 2 yards gain to the ALA33 (#1 D.Jackson)”,
“(13:05) No Huddle-Shotgun #33 C.Bowens rush middle for 0 yards to the ALA33 (#96 T.Keenan III)”,
“(12:27) No Huddle-Shotgun #14 G.Stockton rush middle for 7 yards gain to the ALA26 (#18 B.Hubbard; #10 J.Jefferson)”,
“(11:47) #14 G.Stockton rush middle for 3 yards gain to the ALA23 (#42 Y.Pierre), 1ST DOWN”,
“(11:09) No Huddle #14 G.Stockton pass incomplete short right to #3 N.Frazier thrown to ALA23 broken up by #42 Y.Pierre QB hurried by #23 J.Smith”,
“(11:04) No Huddle-Shotgun #14 G.Stockton pass complete short right to #86 D.Bell caught at ALA13, for 19 yards to the ALA04 (#3 K.Sabb; #18 B.Hubbard), 1ST DOWN”,
“(10:22) Shotgun #3 N.Frazier rush middle for 1 yard loss to the ALA05 (#88 I.Faga; #41 N.Hill-Green)”,
“(09:45) PENALTY UGA False Start (#71 E.Greene III) 5 yards from ALA05 to ALA10. NO PLAY”,
“(09:25) Shotgun #14 G.Stockton rush middle for 5 yards gain to the ALA05 (#41 N.Hill-Green)”,
“(08:44) No Huddle-Shotgun #14 G.Stockton pass complete short middle to #86 D.Bell caught at ALA00, for 5 yards to the ALA00 TOUCHDOWN, clock 08:43 #91 P.Woodring kick attempt good (H: #14 G.Stockton, LS: #60 B.Gardner)”,
“(08:39) Shotgun #15 T.Simpson pass complete short right to #2 R.Williams caught at ALA21, for 13 yards to the ALA38, out of bounds at ALA38, 1ST DOWN. UGA is challenging the ruling on the field – “Runner was out of bounds”. CALL OVERTURNED. (Original Play: (08:39) Shotgun #15 T.Simpson pass complete short right to #2 R.Williams caught at ALA21, for 21 yards to the ALA46 (#20 J.Thomas), out of bounds, 1ST DOWN)”,
“(07:47) Shotgun #15 T.Simpson pass incomplete short right thrown to ALA40 QB hurried by #3 C.Allen”,
“(07:41) Shotgun #15 T.Simpson pass incomplete short right to #4 D.Hill thrown to ALA40 broken up by #33 Q.Johnson”,
“(07:37) No Huddle-Shotgun #15 T.Simpson pass incomplete short left to #17 L.Brooks thrown to ALA45”,
“(07:33) #38 B.Doud punt 42 yards to the UGA20 fair catch by #1 Z.Branch at UGA20”,
“(07:24) Shotgun #86 D.Bell rush left for 12 yards gain to the UGA32 (#3 K.Sabb; #0 D.Lawson), 1ST DOWN”,
“(06:50) Shotgun #14 G.Stockton pass complete short left to #3 N.Frazier caught at UGA30, for 2 yards to the UGA34 (#1 D.Jackson)”,
“(06:18) No Huddle-Shotgun #14 G.Stockton pass complete short right to #18 S.White-Helton caught at UGA31, for 2 yards to the UGA36 (#10 J.Jefferson)”,
“(05:33) No Huddle-Shotgun #14 G.Stockton pass incomplete short left to #1 Z.Branch thrown to ALA45”,
“(05:28) #92 B.Thorson punt 39 yards to the ALA25 fair catch by #7 C.Adams at ALA25”,
“(05:21) #0 A.Dear rush middle for 3 yards gain to the ALA28 (#3 C.Allen)”,
“(04:40) #2 R.Williams rush right for 5 yards gain to the ALA33 (#5 R.Wilson), out of bounds”,
“(04:07) Shotgun #15 T.Simpson pass incomplete short left to #4 D.Hill thrown to ALA30”,
“(04:02) #38 B.Doud punt 49 yards to the UGA18 fair catch by #1 Z.Branch at UGA18”,
“(03:55) Shotgun #14 G.Stockton pass complete short right to #1 Z.Branch caught at UGA15, for 10 yards to the UGA28 (#4 Q.Russaw; #18 B.Hubbard), 1ST DOWN”,
“(03:17) No Huddle-Shotgun #14 G.Stockton pass complete short right to #86 D.Bell caught at UGA25, for 8 yards to the UGA36 (#1 D.Jackson), out of bounds”,
“(02:52) No Huddle-Shotgun #3 N.Frazier rush middle for 4 yards gain to the UGA40 (#8 J.Hill), 1ST DOWN”,
“(02:17) #33 C.Bowens rush middle for 2 yards gain to the UGA42 (#90 L.Simmons)”,
“(01:56) #14 G.Stockton rush right for 5 yards gain to the UGA47 (#94 E.Hill)”,
“(01:15) #14 G.Stockton pass complete short left to #33 C.Bowens caught at UGA45, for 2 yards to the UGA49 (#8 J.Hill)”,
“(01:06) #2 J.McCray rush left for 4 yards gain to the ALA47 (#0 D.Lawson), 1ST DOWN”,
“(00:45) No Huddle-Shotgun #14 G.Stockton pass incomplete short left to #86 D.Bell thrown to ALA30 broken up by #41 N.Hill-Green”,
“(00:43) Shotgun #32 C.Jones rush left for 2 yards gain to the ALA45 (#11 J.Renaud)”,
“(00:20) Shotgun #14 G.Stockton pass incomplete short right thrown to ALA45 QB hurried by #11 J.Renaud”,
“(00:17) #92 B.Thorson punt 36 yards to the ALA09 fair catch by #7 C.Adams at ALA09”,
“(00:11) Shotgun #15 T.Simpson pass complete short middle to #14 M.Pritchett caught at ALA12, for 7 yards to the ALA16 (#5 R.Wilson) PENALTY ALA Personal Foul offsetting UGA Roughing The Passer offsetting. NO PLAY”,
“(00:00) Kneel down by #15 T.Simpson at ALA08 for loss of 1 yard”,
“End of 2nd quarter.”,
“(14:57) #15 T.Simpson pass complete short right to #17 L.Brooks caught at ALA24, for 1 yard to the ALA26 (#27 R.Dinkins), out of bounds”,
“(14:17) Shotgun #15 T.Simpson pass incomplete short left to #17 L.Brooks thrown to ALA40 QB hurried by #94 X.McLeod”,
“(14:09) Shotgun #15 T.Simpson sacked for loss of 9 yards to the ALA17 (#20 J.Thomas)”,
“(13:26) #38 B.Doud punt 47 yards to the UGA36 #1 Z.Branch return 24 yards to the ALA40 (#18 B.Hubbard)”,
“(13:14) Shotgun #3 N.Frazier rush middle for 1 yard gain to the ALA39 (#41 N.Hill-Green)”,
“(12:42) Shotgun #14 G.Stockton pass complete short right to #3 N.Frazier caught at ALA37, for 6 yards to the ALA33 (#2 Z.Brown)”,
“(12:07) Shotgun #14 G.Stockton pass complete short left to #1 Z.Branch caught at ALA29, for 6 yards to the ALA27 (#16 R.Morgan; #1 D.Jackson), 1ST DOWN”,
“(11:33) Shotgun #14 G.Stockton pass complete short right to #7 L.Luckie caught at ALA15, for 18 yards to the ALA09 (#3 K.Sabb), out of bounds, 1ST DOWN”,
“(10:53) Shotgun #14 G.Stockton pass incomplete short middle to #11 T.Taylor thrown to ALA04 broken up by #41 N.Hill-Green”,
“(10:49) #3 N.Frazier rush left for 9 yards gain to the ALA00 TOUCHDOWN, clock 10:47 #91 P.Woodring kick attempt good (H: #14 G.Stockton, LS: #60 B.Gardner)”,
“(10:38) Shotgun #0 A.Dear rush left for 5 yards gain to the ALA18 (#5 R.Wilson; #20 J.Thomas)”,
“(09:56) No Huddle-Shotgun #15 T.Simpson rush left for 5 yards loss to the ALA13, End Of Play”,
“PENALTY ALA False Start (#75 W.Formby) 5 yards from ALA13 to ALA08. NO PLAY”,
“(08:52) Shotgun #15 T.Simpson pass complete short right to #14 M.Pritchett caught at ALA09, for 12 yards to the ALA20 (#9 C.Cole; #3 C.Allen), out of bounds”,
“(08:15) #38 B.Doud punt 45 yards to the UGA35 fair catch by #1 Z.Branch at UGA35”,
“(08:07) #86 D.Bell rush left for 0 yards to the UGA35 (#0 D.Lawson; #41 N.Hill-Green)”,
“(07:35) No Huddle-Shotgun #14 G.Stockton rush middle for 8 yards gain to the UGA43 (#96 T.Keenan III)”,
“(06:52) #14 G.Stockton pass complete short left to #16 L.Humphreys caught at ALA45, for 11 yards to the ALA46 (#18 B.Hubbard), out of bounds PENALTY UGA Personal Foul (#63 D.Glover) 15 yards from UGA43 to UGA28. NO PLAY”,
“(06:25) Shotgun #14 G.Stockton pass complete short middle to #86 D.Bell caught at UGA41, for 13 yards to the UGA41, End Of Play”,
“(05:46) #92 B.Thorson punt 59 yards to the ALA00, Touchback”,
“(05:36) Shotgun #15 T.Simpson pass complete short left to #4 D.Hill caught at ALA24, for 4 yards to the ALA24, End Of Play”,
“(05:08) No Huddle-Shotgun #4 D.Hill rush middle for 2 yards gain to the ALA26 (#5 R.Wilson; #90 E.Griffin)”,
“(04:29) No Huddle-Shotgun #15 T.Simpson pass complete short left to #4 D.Hill caught at ALA26, for 2 yards to the ALA28 (#20 J.Thomas), out of bounds”,
“(03:49) #38 B.Doud punt 37 yards to the UGA35, out of bounds at UGA35”,
“(03:45) #3 N.Frazier rush middle for 9 yards gain to the UGA44 (#18 B.Hubbard)”,
“(03:08) #3 N.Frazier rush middle for 4 yards gain to the UGA48 (#42 Y.Pierre), 1ST DOWN”,
“(02:33) PENALTY UGA False Start (#7 L.Luckie) 5 yards from UGA48 to UGA43. NO PLAY”,
“(02:12) #86 D.Bell rush left for 5 yards gain to the UGA48 (#16 R.Morgan; #41 N.Hill-Green)”,
“(01:33) #2 J.McCray rush middle for 3 yards loss to the UGA45 (#8 J.Hill)”,
“(00:57) Shotgun #14 G.Stockton pass complete short left to #32 C.Jones caught at UGA47, for 8 yards to the ALA47 (#9 C.Calhoun), out of bounds”,
“(00:12) #92 B.Thorson punt 38 yards to the ALA09 fair catch by #7 C.Adams at ALA09”,
“(00:07) Shotgun #15 T.Simpson pass complete short middle to #81 K.Edwards caught at ALA18, for 21 yards to the ALA30 (#9 C.Cole), 1ST DOWN”,
“End of 3rd quarter.”,
“(14:56) Shotgun #15 T.Simpson pass complete short middle to #4 D.Hill caught at ALA35, for 9 yards to the ALA39 (#9 C.Cole)”,
“(14:31) No Huddle-Shotgun #15 T.Simpson sacked for loss of 9 yards to the ALA30 (#33 Q.Johnson, #9 C.Cole) PENALTY UGA Personal Foul (#15 D.Jones) 15 yards from ALA30 to ALA45, 1ST DOWN”,
“(13:59) Shotgun #15 T.Simpson pass complete short middle to #81 K.Edwards caught at ALA48, for 13 yards to the UGA42 (#4 K.Bolden; #20 J.Thomas), 1ST DOWN”,
“(13:29) No Huddle-Shotgun #15 T.Simpson pass complete short middle to #4 D.Hill caught at UGA38, for 4 yards to the UGA38 (#3 C.Allen)”,
“(12:59) No Huddle-Shotgun #15 T.Simpson pass incomplete short right to #4 D.Hill thrown to UGA40”,
“(12:56) Shotgun #15 T.Simpson pass incomplete deep left to #2 R.Williams thrown to UGA10 PENALTY UGA Pass Interference (#15 D.Jones) 15 yards from UGA38 to UGA23, 1ST DOWN. NO PLAY”,
“(12:50) Shotgun #15 T.Simpson pass incomplete deep middle to #17 L.Brooks thrown to UGA00”,
“(12:44) Shotgun #15 T.Simpson pass incomplete deep left to #2 R.Williams thrown to UGA00 broken up by #1 E.Robinson IV”,
“(12:40) Shotgun #15 T.Simpson pass complete short middle to #5 G.Bernard caught at UGA25, for 23 yards to the UGA00 TOUCHDOWN, clock 12:33, 1ST DOWN #31 C.Talty kick attempt good (H: #38 B.Doud, LS: #44 A.Rozier)”,
“(12:30) Shotgun #14 G.Stockton pass complete short right to #1 Z.Branch caught at UGA29, for 7 yards to the UGA32 (#31 K.Keeley)”,
“(11:47) #14 G.Stockton pass complete short right to #4 O.Delp caught at UGA35, for 5 yards to the UGA37 (#5 D.Lee Jr.), out of bounds, 1ST DOWN”,
“(11:13) Shotgun #14 G.Stockton rush middle for 1 yard loss to the UGA36 (#96 T.Keenan III)”,
“(10:34) Shotgun #14 G.Stockton rush middle for 7 yards gain to the UGA43 (#41 N.Hill-Green)”,
“(09:58) No Huddle-Shotgun #14 G.Stockton rush middle for 0 yards to the UGA43 (#4 Q.Russaw)”,
“(09:13) #92 B.Thorson punt 49 yards to the ALA08 muffed by #7 C.Adams at ALA08 recovered by ALA #7 C.Adams at ALA04, End Of Play”,
“(09:04) Shotgun #15 T.Simpson pass incomplete short middle to #81 K.Edwards thrown to ALA06 QB hurried by #94 X.McLeod”,
“(09:00) No Huddle-Shotgun #15 T.Simpson pass complete short left to #5 G.Bernard caught at ALA09, for 8 yards to the ALA12 (#4 K.Bolden)”,
“(08:17) Shotgun #15 T.Simpson pass incomplete short middle to #81 K.Edwards thrown to ALA15 broken up by #3 C.Allen”,
“(08:14) No Huddle-Shotgun #15 T.Simpson pass incomplete short right to #5 G.Bernard thrown to ALA17, TURNOVER ON DOWNS”,
“(08:09) Shotgun #14 G.Stockton rush middle for 1 yard loss to the ALA13 (#42 Y.Pierre)”,
“(07:31) #3 N.Frazier rush middle for 0 yards to the ALA13 (#0 D.Lawson)”,
“(06:55) Shotgun #14 G.Stockton pass complete short left to #1 Z.Branch caught at ALA16, for 13 yards to the ALA00 TOUCHDOWN, clock 06:51, 1ST DOWN #91 P.Woodring kick attempt good (H: #14 G.Stockton, LS: #60 B.Gardner)”,
“(06:48) Shotgun #15 T.Simpson pass complete short left to #5 G.Bernard caught at ALA35, for 16 yards to the ALA41 (#5 R.Wilson; #4 K.Bolden), 1ST DOWN”,
“(06:22) No Huddle-Shotgun #15 T.Simpson pass complete short left to #5 G.Bernard caught at ALA49, for 8 yards to the ALA49 (#15 D.Jones)”,
“(05:57) No Huddle-Shotgun #15 T.Simpson pass incomplete short left to #5 G.Bernard thrown to UGA40 broken up by #6 D.Everette”,
“(05:53) Shotgun #15 T.Simpson rush middle for 1 yard gain to the ALA50 (#3 C.Allen)”,
“(05:20) Shotgun #15 T.Simpson pass complete short middle to #81 K.Edwards caught at ALA48, for 8 yards to the UGA42 (#1 E.Robinson IV; #3 C.Allen), 1ST DOWN”,
“(04:58) Shotgun #15 T.Simpson pass incomplete short left to #2 R.Williams thrown to UGA32 broken up by #4 K.Bolden”,
“(04:53) Shotgun #15 T.Simpson sacked for loss of 5 yards to the UGA47 (#10 Z.Walker)”,
“(04:09) Shotgun #15 T.Simpson pass complete short middle to #5 G.Bernard caught at UGA44, for 30 yards to the UGA17 lateral to #4 D.Hill for 27 yards gain to the UGA17 (#6 D.Everette), out of bounds, 1ST DOWN”,
“(03:41) No Huddle-Shotgun #15 T.Simpson pass incomplete short right to #5 G.Bernard thrown to UGA00”,
“(03:39) Shotgun #15 T.Simpson pass incomplete short left to #0 A.Dear thrown to UGA22”,
“(03:34) Shotgun #15 T.Simpson pass incomplete short right to #2 R.Williams thrown to UGA08”,
“(03:30) Shotgun #15 T.Simpson pass incomplete short right to #5 G.Bernard thrown to UGA00 QB hurried by #19 J.Williams and #91 J.Greene, TURNOVER ON DOWNS”,
“(03:18) #3 N.Frazier rush middle for 4 yards gain to the UGA21 (#96 T.Keenan III)”,
“(02:34) #14 G.Stockton sacked for loss of 6 yards to the UGA15 (#31 K.Keeley, #23 J.Smith)”,
“(02:28) #33 C.Bowens rush middle for 19 yards gain to the UGA34 (#16 R.Morgan), 1ST DOWN”,
“(01:55) Kneel down by #14 G.Stockton at UGA33 for loss of 1 yard”,
“(01:14) Kneel down by #14 G.Stockton at UGA33 for loss of 0 yards”,
“(00:33) Kneel down by #14 G.Stockton at UGA32 for loss of 1 yard”,
“Game ended”
],
“segmentColors”: [
“rgb(175, 40, 60)”,
“rgb(177, 38, 59)”,
“rgb(184, 31, 55)”,
“rgb(176, 39, 59)”,
“rgb(175, 40, 60)”,
“rgb(175, 40, 60)”,
“rgb(175, 40, 60)”,
“rgb(175, 40, 60)”,
“rgb(175, 40, 60)”,
“rgb(175, 40, 60)”,
“rgb(182, 34, 56)”,
“rgb(175, 40, 60)”,
“rgb(175, 40, 60)”,
“rgb(179, 36, 58)”,
“rgb(176, 39, 59)”,
“rgb(176, 39, 59)”,
“rgb(177, 38, 59)”,
“rgb(181, 35, 57)”,
“rgb(187, 28, 53)”,
“rgb(196, 20, 48)”,
“rgb(196, 20, 48)”,
“rgb(195, 21, 49)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”,
“rgb(200, 16, 46)”
]
},
{
“label”: “50% Line”,
“data”: [
{
“x”: 0,
“y”: 50
},
{
“x”: 146,
“y”: 50
}
],
“borderColor”: “rgba(0,0,0,0.3)”,
“borderWidth”: 1.5,
“borderDash”: [
5,
5
],
“backgroundColor”: “transparent”,
“pointRadius”: 0,
“showLine”: true,
“fill”: false,
“tension”: 0,
“order”: 90,
“datalabels”: {
“display”: false
}
},
{
“label”: “Quarters”,
“data”: [
{
“x”: 33,
“y”: 0
},
{
“x”: 33,
“y”: 100
},
{
“x”: 146,
“y”: 100
},
{
“x”: 146,
“y”: 0
},
{
“x”: 73,
“y”: 0
},
{
“x”: 73,
“y”: 100
},
{
“x”: 146,
“y”: 100
},
{
“x”: 146,
“y”: 0
},
{
“x”: 106,
“y”: 0
},
{
“x”: 106,
“y”: 100
},
{
“x”: 146,
“y”: 100
},
{
“x”: 146,
“y”: 0
}
],
“borderColor”: “rgba(0,0,0,0.1)”,
“borderWidth”: 1,
“pointRadius”: 0,
“showLine”: true,
“fill”: false,
“tension”: 0,
“order”: 100,
“datalabels”: {
“display”: false
}
}
],
“currentParams”: {
“year”: 2025,
“week”: 15,
“seasonType”: “regular”,
“team”: “Alabama”,
“gameId”: “401777351”
}
};
// Chart options (WordPress-safe)
const chartOptions = {
responsive: true,
maintainAspectRatio: false,
animation: {
duration: 1 // Minimal animation to trigger layout calculation (fixes label positioning)
},
elements: ‘line’ === ‘line’ ? ‘win-probability’.includes(‘play-map’) ? {
line: {
tension: 0,
borderWidth: 0
}
} : ‘win-probability’ === ‘win-probability’ ? {
line: {
tension: 0.15,
borderWidth: 2.2,
fill: false
},
point: {
pointRadius: 0,
pointHoverRadius: 4
}
} : {
line: {
tension: 0.25,
borderWidth: 2.2
},
point: {
pointRadius: ‘win-probability’.includes(‘team-lines’) ? 0 : undefined
}
} : {},
plugins: {
datalabels: {
display: function(context) {
// Suppress data labels on line charts
if (‘line’ === ‘line’) {
return false;
}
return context.dataset.datalabels && context.dataset.datalabels.display === true;
},
formatter: function(value, context) {
// Special handling for Overall Team Performance chart
if (‘win-probability’ === ‘overall-team-performance’ && context.dataset.label === ‘Success Rate (SR)’) {
// Use the stored play count data
if (context.dataset.playCountData && context.dataset.playCountData[context.dataIndex]) {
return context.dataset.playCountData[context.dataIndex];
}
// Fallback to percentage if play count data not available
return Math.round(value * 100) + ‘%’;
}
// Handle bar charts with count data (play-type, quarter, down, etc.)
if (context.dataset.label && context.dataset.label.includes(‘ SR’) &&
(chartData.teamCounts || chartData.oppCounts)) {
// Find the first team SR dataset in the chart to determine team order
const allDatasets = context.chart.data.datasets;
const teamSRDataset = allDatasets.find(d => d.label && d.label.includes(‘ SR’) && !d.label.includes(‘NCAA’));
// If this is the first team’s SR dataset, use teamCounts
if (teamSRDataset && context.dataset.label === teamSRDataset.label && chartData.teamCounts) {
return chartData.teamCounts[context.dataIndex] || 0;
}
// Otherwise, use oppCounts for the second team
else if (chartData.oppCounts) {
return chartData.oppCounts[context.dataIndex] || 0;
}
}
// For player charts, show value only if > 0 (matches non-embedded behavior)
if (‘win-probability’.includes(‘top-rushers’) || ‘win-probability’.includes(‘top-passers’) || ‘win-probability’.includes(‘top-receivers’)) {
// Hide data labels for zero or negative values, show actual value for positive values
return value > 0 ? value : null;
}
// For other charts, show values based on type
if (typeof value === ‘number’) {
// If value is between 0 and 1, treat as percentage
if (value >= 0 && value 0 ? ‘#26262660’ : ‘transparent’;
},
borderColor: function(context) {
const value = context.dataset.data[context.dataIndex];
return value > 0 ? ‘rgba(255, 255, 255, 0.2)’ : ‘transparent’;
},
borderRadius: 4,
align: ‘center’,
anchor: ‘center’
},
legend: ‘win-probability’ === ‘win-probability’ ? {
display: false
} : ‘line’ === ‘line’ ? {
position: ‘top’,
align: ‘start’,
labels: ‘win-probability’.includes(‘play-map’) ? {
usePointStyle: true,
generateLabels: function(chart) {
// Call the original generateLabels to get default styling
const original = Chart.defaults.plugins.legend.labels.generateLabels;
const labels = original.call(this, chart);
// Filter and customize each label
const filteredLabels = labels.filter(label => {
return !label.text.includes(‘ {
const dataset = chart.data.datasets[label.datasetIndex];
if (dataset && dataset.label) {
if (dataset.label.includes(‘Rush’)) {
label.pointStyle = ‘circle’;
label.pointStyleWidth = 4;
label.fillStyle = ‘white’;
} else if (dataset.label.includes(‘Pass’)) {
label.pointStyle = ‘triangle’;
label.pointStyleWidth = 4;
label.fillStyle = ‘white’;
} else {
label.pointStyle = ‘rect’;
label.pointStyleWidth = 4;
label.fillStyle = ‘white’;
}
}
});
return filteredLabels;
},
boxWidth: 20,
padding: 12
} : {
usePointStyle: false,
boxWidth: 12,
boxHeight: 12,
padding: 12,
generateLabels: function(chart) {
const original = Chart.defaults.plugins.legend.labels.generateLabels;
const labels = original.call(this, chart);
// Filter out reference areas and ensure white fill
const filteredLabels = labels.filter(label => {
return !label.text.includes(‘NCAA Avg SR’) &&
!label.text.includes(’50/50′) &&
!label.text.includes(‘Quarters’);
});
// Ensure white fill for all line chart legend boxes
filteredLabels.forEach((label) => {
label.fillStyle = ‘white’;
});
return filteredLabels;
}
}
} : {
position: ‘top’,
align: ‘start’,
labels: {
usePointStyle: false,
boxWidth: 12,
boxHeight: 12,
padding: 12,
filter: function(legendItem, chartData) {
return !legendItem.text.includes(‘NCAA Avg SR’) &&
!legendItem.text.includes(‘Quarters’) &&
!legendItem.text.includes(’50/50′);
},
generateLabels: function(chart) {
const data = chart.data;
if (data.datasets.length) {
return data.datasets.map((dataset, i) => {
// Handle backgroundColor arrays (like in Overall Team Performance chart)
let fillColor = dataset.backgroundColor;
if (dataset.label === ‘# Plays’) {
fillColor = ‘white’;
} else if (Array.isArray(dataset.backgroundColor)) {
// For datasets with backgroundColor arrays, use the first color for legend
fillColor = dataset.backgroundColor[0];
}
return {
text: dataset.label,
fillStyle: fillColor,
strokeStyle: dataset.label === ‘# Plays’ ? ‘#666’ : dataset.borderColor,
lineWidth: dataset.label === ‘# Plays’ ? 1 : dataset.borderWidth,
hidden: !chart.isDatasetVisible(i),
datasetIndex: i
};
}).filter((item, index) => {
// Apply the same filter logic as above
const dataset = chart.data.datasets[index];
if (!dataset || !dataset.data) return false;
if (dataset.label === ‘# Plays’) return true; // Always show # Plays
if (dataset.label && (dataset.label.includes(‘NCAA Avg SR’) ||
dataset.label.includes(‘Quarters’) ||
dataset.label.includes(’50/50′))) return false;
return dataset.data.some((value) => value > 0);
});
}
return [];
}
}
},
tooltip: ‘win-probability’ === ‘win-probability’ ? {
mode: ‘index’,
intersect: false,
callbacks: {
title: function(tooltipItems) {
if (tooltipItems && tooltipItems[0]) {
return ‘Play ‘ + (tooltipItems[0].dataIndex + 1);
}
return ”;
},
label: function(context) {
const selectedTeamWinProb = context.parsed.y;
const opponentWinProb = 100 – selectedTeamWinProb;
const selectedTeam = context.dataset.selectedTeam || ‘Team’;
const opponentTeam = context.dataset.opponentTeam || ‘Opponent’;
return [
selectedTeam + ‘: ‘ + selectedTeamWinProb.toFixed(1) + ‘%’,
opponentTeam + ‘: ‘ + opponentWinProb.toFixed(1) + ‘%’
];
},
afterLabel: function(context) {
if (context.dataset.playTexts && context.dataset.playTexts[context.dataIndex]) {
return ‘n’ + context.dataset.playTexts[context.dataIndex];
}
return ”;
}
}
} : {
filter: function(tooltipItem) {
if (‘win-probability’.includes(‘play-map’)) {
return !tooltipItem.dataset.label.includes(‘< 0’) &&
!tooltipItem.dataset.label.includes(‘Quarters’) &&
!tooltipItem.dataset.label.includes(‘Drive’);
}
return !tooltipItem.dataset.label.includes(‘NCAA Avg SR’) &&
!tooltipItem.dataset.label.includes(’50/50′) &&
!tooltipItem.dataset.label.includes(‘ ds.label === ‘Win Probability’);
if (wpDataset && wpDataset.segmentColors) {
wpDataset.segment = {
borderColor: function(ctx) {
// Use p1DataIndex (ending point) so the line inherits the destination color
// This makes momentum shifts more visually intuitive
const index = ctx.p1DataIndex;
if (index !== undefined && wpDataset.segmentColors[index]) {
return wpDataset.segmentColors[index];
}
return wpDataset.borderColor || ‘#8B0000’;
}
};
}
}
// Initialize the chart
const ctx = canvas.getContext(‘2d’);
const chart = new Chart(ctx, {
type: ‘line’,
data: chartData,
options: chartOptions
});
// Store reference to prevent re-initialization
canvas.chartInstance = chart;
console.log(‘CFB Chart initialized successfully’);
} catch (error) {
console.error(‘Error initializing CFB chart:’, error);
// Fallback: show error message in canvas container
const container = document.getElementById(‘cfb-chart-1765138185644-mzkgiv5qf’).parentNode;
if (container) {
container.innerHTML = ‘
‘;
}
}
}
// Start loading scripts sequentially
function startLoading() {
// First, check if scripts are already loaded (multiple embeds on same page)
if (typeof Chart !== ‘undefined’ && typeof ChartDataLabels !== ‘undefined’) {
initChart();
return;
}
// Load Chart.js first
if (typeof Chart === ‘undefined’) {
loadScript(‘https://cdn.jsdelivr.net/npm/chart.js@3.9.1/dist/chart.min.js’, function() {
// Then load ChartDataLabels
if (typeof ChartDataLabels === ‘undefined’) {
loadScript(‘https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2.2.0’, function() {
initChart();
});
} else {
initChart();
}
});
} else if (typeof ChartDataLabels === ‘undefined’) {
// Chart.js loaded but not ChartDataLabels
loadScript(‘https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2.2.0’, function() {
initChart();
});
} else {
initChart();
}
}
// Initialize when DOM is ready
if (document.readyState === ‘loading’) {
document.addEventListener(‘DOMContentLoaded’, startLoading);
} else {
startLoading();
}
})();
Win probability actually did like the Tide in the first part of the first quarter. Alabama’s defense was holding up well, even though its offense couldn’t really do all that much.
Things swung quickly though after Georgia’s first score and then fell even further in the beginning of the second quarter after their next. By midway through the second quarter, it was pretty clear what was going on here: a rout. Georgia just needed to bide their time and close it out.
.cfb-chart-embed-cfb-chart-1765138194324-qynkvbh4j {
font-family: -apple-system, BlinkMacSystemFont, ‘Segoe UI’, ‘Roboto’, sans-serif;
margin: 0;
padding: 0;
}
.cfb-chart-embed-cfb-chart-1765138194324-qynkvbh4j .chart-container {
background: white;
border-radius: 12px;
border: 1px solid #e5e5e5;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
overflow: hidden;
}
.cfb-chart-embed-cfb-chart-1765138194324-qynkvbh4j .chart-header {
padding: 18px 24px 14px;
border-bottom: 1px solid #e5e5e5;
background: white;
}
.cfb-chart-embed-cfb-chart-1765138194324-qynkvbh4j .chart-title {
font-size: 18px;
font-weight: 600;
color: #171717;
margin: 0;
}
.cfb-chart-embed-cfb-chart-1765138194324-qynkvbh4j .chart-subtitle {
font-size: 11px;
font-weight: 400;
color: #737373;
margin: 4px 0 0 0;
}
.cfb-chart-embed-cfb-chart-1765138194324-qynkvbh4j .chart-content {
padding: 20px 24px 24px !important;
}
.cfb-chart-embed-cfb-chart-1765138194324-qynkvbh4j .chart-content { height: 325px; }
@media (max-width: 640px) {
.cfb-chart-embed-cfb-chart-1765138194324-qynkvbh4j .chart-content {
padding: 12px 16px 20px !important;
height: 280px !important;
}
.cfb-chart-embed-cfb-chart-1765138194324-qynkvbh4j .chart-header {
padding: 12px 16px 12px !important;
}
.cfb-chart-embed-cfb-chart-1765138194324-qynkvbh4j .embed-footer-top {
padding: 8px 12px !important;
}
.cfb-chart-embed-cfb-chart-1765138194324-qynkvbh4j .data-definitions {
padding: 12px !important;
}
}
.cfb-chart-embed-cfb-chart-1765138194324-qynkvbh4j .embed-footer {
border-top: 1px solid #e5e5e5;
font-size: 12px;
color: #737373;
}
.cfb-chart-embed-cfb-chart-1765138194324-qynkvbh4j .embed-footer-top {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 16px;
}
.cfb-chart-embed-cfb-chart-1765138194324-qynkvbh4j .embed-footer-link {
color: #737373;
text-decoration: none;
font-weight: 500;
}
.cfb-chart-embed-cfb-chart-1765138194324-qynkvbh4j .embed-footer-link:hover {
color: #525252;
text-decoration: underline;
}
.cfb-chart-embed-cfb-chart-1765138194324-qynkvbh4j .data-definitions-toggle {
background: none;
border: none;
color: #737373;
font-size: 12px;
font-weight: 500;
cursor: pointer;
display: flex;
align-items: center;
gap: 4px;
padding: 0;
}
.cfb-chart-embed-cfb-chart-1765138194324-qynkvbh4j .data-definitions-toggle:hover {
color: #525252;
}
.cfb-chart-embed-cfb-chart-1765138194324-qynkvbh4j .caret {
transition: transform 0.2s ease;
font-size: 10px;
}
.cfb-chart-embed-cfb-chart-1765138194324-qynkvbh4j .caret.expanded {
transform: rotate(180deg);
}
.cfb-chart-embed-cfb-chart-1765138194324-qynkvbh4j .data-definitions {
display: none;
padding: 16px;
background: #fafafa;
border-top: 1px solid #e5e5e5;
font-size: 12px;
line-height: 1.4;
}
.cfb-chart-embed-cfb-chart-1765138194324-qynkvbh4j .data-definitions.expanded {
display: block;
}
.cfb-chart-embed-cfb-chart-1765138194324-qynkvbh4j .data-definitions ul {
margin: 0;
padding-left: 0;
list-style: none;
}
.cfb-chart-embed-cfb-chart-1765138194324-qynkvbh4j .data-definitions li {
margin-bottom: 4px;
}
Overall Team Performance
Alabama vs. Georgia • Dec 6, 2025
- Based roughly on the SP+ analytic system
- Successful play: Gains enough needed yards (50% 1st down, 70% on 2nd, 100% on 3rd/4th)
- Success Rate (SR): Percentage of plays that were successful
- Explosiveness Rate (XR): Percentage of plays gaining 15+ yards
- # Plays: Numbers shown in bars represent total play counts
- NCAA Avg: Dashed line shows 42% (roughly NCAA average) success rate
// Toggle data definitions accordion – unique function per embed
function toggleDefinitions_cfb_chart_1765138194324_qynkvbh4j() {
const definitions = document.getElementById(‘dataDefinitions_cfb-chart-1765138194324-qynkvbh4j’);
const caret = document.getElementById(‘caret_cfb-chart-1765138194324-qynkvbh4j’);
if (definitions.classList.contains(‘expanded’)) {
definitions.classList.remove(‘expanded’);
caret.classList.remove(‘expanded’);
} else {
definitions.classList.add(‘expanded’);
caret.classList.add(‘expanded’);
}
}
// Sequential script loading for better reliability
(function() {
‘use strict’;
let retryCount = 0;
const maxRetries = 50; // 5 seconds total
// Load scripts sequentially
function loadScript(url, callback) {
const script = document.createElement(‘script’);
script.src = url;
script.onload = callback;
script.onerror = function() {
console.error(‘Failed to load script:’, url);
showError(‘Failed to load required chart library’);
};
document.head.appendChild(script);
}
function showError(message) {
const canvas = document.getElementById(‘cfb-chart-1765138194324-qynkvbh4j’);
if (canvas && canvas.parentNode) {
canvas.parentNode.innerHTML = ‘
‘;
}
}
function initChart() {
retryCount++;
// Check if Chart.js is available
if (typeof Chart === ‘undefined’) {
if (retryCount >= maxRetries) {
showError(‘Chart library failed to load. Please refresh the page.’);
return;
}
setTimeout(initChart, 100);
return;
}
// Check if datalabels plugin is available
if (typeof ChartDataLabels === ‘undefined’) {
if (retryCount >= maxRetries) {
showError(‘Chart plugin failed to load. Please refresh the page.’);
return;
}
setTimeout(initChart, 100);
return;
}
// Check if canvas element exists
const canvas = document.getElementById(‘cfb-chart-1765138194324-qynkvbh4j’);
if (!canvas) {
console.warn(‘Canvas element not found yet, retrying…’);
setTimeout(initChart, 100);
return;
}
// Prevent multiple chart instances
if (canvas.chartInstance) {
console.log(‘Chart already initialized’);
return;
}
try {
// Register the datalabels plugin
Chart.register(ChartDataLabels);
// Embed actual chart data directly
const chartData = {
“labels”: [
“Alabama”,
“Georgia”
],
“datasets”: [
{
“label”: “Explosiveness Rate (XR)”,
“data”: [
0.08928571428571429,
0.05970149253731343
],
“backgroundColor”: [
“rgba(101, 0, 20, 0.8)”,
“rgba(130, 0, 25, 0.8)”
],
“stack”: “SRXR”,
“datalabels”: {
“display”: false
}
},
{
“label”: “Success Rate (SR)”,
“data”: [
0.2857142857142857,
0.3582089552238806
],
“backgroundColor”: [
“rgba(175, 40, 60, 0.8)”,
“rgba(200, 16, 46, 0.8)”
],
“stack”: “SRXR”,
“datalabels”: {
“display”: true
},
“playCountData”: [
56,
67
]
},
{
“type”: “line”,
“data”: [
0.42,
0.42
],
“label”: “NCAA Avg SR”,
“borderColor”: “#757575”,
“borderWidth”: 2,
“borderDash”: [
3,
3
],
“pointRadius”: 0,
“datalabels”: {
“display”: false
}
},
{
“type”: “line”,
“data”: [
null,
null
],
“label”: “# Plays”,
“backgroundColor”: “rgba(0, 0, 0, 0)”,
“borderColor”: “rgba(0, 0, 0, 0)”,
“borderWidth”: 0,
“pointRadius”: 0,
“showLine”: false,
“fill”: false,
“datalabels”: {
“display”: false
}
}
],
“teamColors”: {
“success”: “rgba(175, 40, 60, 0.8)”,
“explosive”: “rgba(101, 0, 20, 0.8)”,
“light”: “rgba(245, 229, 233, 0.8)”
},
“opponentColors”: {
“success”: “rgba(200, 16, 46, 0.8)”,
“explosive”: “rgba(130, 0, 25, 0.8)”,
“light”: “rgba(248, 228, 233, 0.8)”
},
“teamPlayCount”: 56,
“opponentPlayCount”: 67,
“currentParams”: {
“year”: 2025,
“week”: 15,
“seasonType”: “regular”,
“team”: “Alabama”,
“gameId”: “401777351”
}
};
// Chart options (WordPress-safe)
const chartOptions = {
responsive: true,
maintainAspectRatio: false,
animation: {
duration: 1 // Minimal animation to trigger layout calculation (fixes label positioning)
},
elements: ‘bar’ === ‘line’ ? ‘overall-team-performance’.includes(‘play-map’) ? {
line: {
tension: 0,
borderWidth: 0
}
} : ‘overall-team-performance’ === ‘win-probability’ ? {
line: {
tension: 0.15,
borderWidth: 2.2,
fill: false
},
point: {
pointRadius: 0,
pointHoverRadius: 4
}
} : {
line: {
tension: 0.25,
borderWidth: 2.2
},
point: {
pointRadius: ‘overall-team-performance’.includes(‘team-lines’) ? 0 : undefined
}
} : {},
plugins: {
datalabels: {
display: function(context) {
// Suppress data labels on line charts
if (‘bar’ === ‘line’) {
return false;
}
return context.dataset.datalabels && context.dataset.datalabels.display === true;
},
formatter: function(value, context) {
// Special handling for Overall Team Performance chart
if (‘overall-team-performance’ === ‘overall-team-performance’ && context.dataset.label === ‘Success Rate (SR)’) {
// Use the stored play count data
if (context.dataset.playCountData && context.dataset.playCountData[context.dataIndex]) {
return context.dataset.playCountData[context.dataIndex];
}
// Fallback to percentage if play count data not available
return Math.round(value * 100) + ‘%’;
}
// Handle bar charts with count data (play-type, quarter, down, etc.)
if (context.dataset.label && context.dataset.label.includes(‘ SR’) &&
(chartData.teamCounts || chartData.oppCounts)) {
// Find the first team SR dataset in the chart to determine team order
const allDatasets = context.chart.data.datasets;
const teamSRDataset = allDatasets.find(d => d.label && d.label.includes(‘ SR’) && !d.label.includes(‘NCAA’));
// If this is the first team’s SR dataset, use teamCounts
if (teamSRDataset && context.dataset.label === teamSRDataset.label && chartData.teamCounts) {
return chartData.teamCounts[context.dataIndex] || 0;
}
// Otherwise, use oppCounts for the second team
else if (chartData.oppCounts) {
return chartData.oppCounts[context.dataIndex] || 0;
}
}
// For player charts, show value only if > 0 (matches non-embedded behavior)
if (‘overall-team-performance’.includes(‘top-rushers’) || ‘overall-team-performance’.includes(‘top-passers’) || ‘overall-team-performance’.includes(‘top-receivers’)) {
// Hide data labels for zero or negative values, show actual value for positive values
return value > 0 ? value : null;
}
// For other charts, show values based on type
if (typeof value === ‘number’) {
// If value is between 0 and 1, treat as percentage
if (value >= 0 && value 0 ? ‘#26262660’ : ‘transparent’;
},
borderColor: function(context) {
const value = context.dataset.data[context.dataIndex];
return value > 0 ? ‘rgba(255, 255, 255, 0.2)’ : ‘transparent’;
},
borderRadius: 4,
align: ‘center’,
anchor: ‘center’
},
legend: ‘overall-team-performance’ === ‘win-probability’ ? {
display: false
} : ‘bar’ === ‘line’ ? {
position: ‘top’,
align: ‘start’,
labels: ‘overall-team-performance’.includes(‘play-map’) ? {
usePointStyle: true,
generateLabels: function(chart) {
// Call the original generateLabels to get default styling
const original = Chart.defaults.plugins.legend.labels.generateLabels;
const labels = original.call(this, chart);
// Filter and customize each label
const filteredLabels = labels.filter(label => {
return !label.text.includes(‘ {
const dataset = chart.data.datasets[label.datasetIndex];
if (dataset && dataset.label) {
if (dataset.label.includes(‘Rush’)) {
label.pointStyle = ‘circle’;
label.pointStyleWidth = 4;
label.fillStyle = ‘white’;
} else if (dataset.label.includes(‘Pass’)) {
label.pointStyle = ‘triangle’;
label.pointStyleWidth = 4;
label.fillStyle = ‘white’;
} else {
label.pointStyle = ‘rect’;
label.pointStyleWidth = 4;
label.fillStyle = ‘white’;
}
}
});
return filteredLabels;
},
boxWidth: 20,
padding: 12
} : {
usePointStyle: false,
boxWidth: 12,
boxHeight: 12,
padding: 12,
generateLabels: function(chart) {
const original = Chart.defaults.plugins.legend.labels.generateLabels;
const labels = original.call(this, chart);
// Filter out reference areas and ensure white fill
const filteredLabels = labels.filter(label => {
return !label.text.includes(‘NCAA Avg SR’) &&
!label.text.includes(’50/50′) &&
!label.text.includes(‘Quarters’);
});
// Ensure white fill for all line chart legend boxes
filteredLabels.forEach((label) => {
label.fillStyle = ‘white’;
});
return filteredLabels;
}
}
} : {
position: ‘top’,
align: ‘start’,
labels: {
usePointStyle: false,
boxWidth: 12,
boxHeight: 12,
padding: 12,
filter: function(legendItem, chartData) {
return !legendItem.text.includes(‘NCAA Avg SR’) &&
!legendItem.text.includes(‘Quarters’) &&
!legendItem.text.includes(’50/50′);
},
generateLabels: function(chart) {
const data = chart.data;
if (data.datasets.length) {
return data.datasets.map((dataset, i) => {
// Handle backgroundColor arrays (like in Overall Team Performance chart)
let fillColor = dataset.backgroundColor;
if (dataset.label === ‘# Plays’) {
fillColor = ‘white’;
} else if (Array.isArray(dataset.backgroundColor)) {
// For datasets with backgroundColor arrays, use the first color for legend
fillColor = dataset.backgroundColor[0];
}
return {
text: dataset.label,
fillStyle: fillColor,
strokeStyle: dataset.label === ‘# Plays’ ? ‘#666’ : dataset.borderColor,
lineWidth: dataset.label === ‘# Plays’ ? 1 : dataset.borderWidth,
hidden: !chart.isDatasetVisible(i),
datasetIndex: i
};
}).filter((item, index) => {
// Apply the same filter logic as above
const dataset = chart.data.datasets[index];
if (!dataset || !dataset.data) return false;
if (dataset.label === ‘# Plays’) return true; // Always show # Plays
if (dataset.label && (dataset.label.includes(‘NCAA Avg SR’) ||
dataset.label.includes(‘Quarters’) ||
dataset.label.includes(’50/50′))) return false;
return dataset.data.some((value) => value > 0);
});
}
return [];
}
}
},
tooltip: ‘overall-team-performance’ === ‘win-probability’ ? {
mode: ‘index’,
intersect: false,
callbacks: {
title: function(tooltipItems) {
if (tooltipItems && tooltipItems[0]) {
return ‘Play ‘ + (tooltipItems[0].dataIndex + 1);
}
return ”;
},
label: function(context) {
const selectedTeamWinProb = context.parsed.y;
const opponentWinProb = 100 – selectedTeamWinProb;
const selectedTeam = context.dataset.selectedTeam || ‘Team’;
const opponentTeam = context.dataset.opponentTeam || ‘Opponent’;
return [
selectedTeam + ‘: ‘ + selectedTeamWinProb.toFixed(1) + ‘%’,
opponentTeam + ‘: ‘ + opponentWinProb.toFixed(1) + ‘%’
];
},
afterLabel: function(context) {
if (context.dataset.playTexts && context.dataset.playTexts[context.dataIndex]) {
return ‘n’ + context.dataset.playTexts[context.dataIndex];
}
return ”;
}
}
} : {
filter: function(tooltipItem) {
if (‘overall-team-performance’.includes(‘play-map’)) {
return !tooltipItem.dataset.label.includes(‘< 0’) &&
!tooltipItem.dataset.label.includes(‘Quarters’) &&
!tooltipItem.dataset.label.includes(‘Drive’);
}
return !tooltipItem.dataset.label.includes(‘NCAA Avg SR’) &&
!tooltipItem.dataset.label.includes(’50/50′) &&
!tooltipItem.dataset.label.includes(‘ ds.label === ‘Win Probability’);
if (wpDataset && wpDataset.segmentColors) {
wpDataset.segment = {
borderColor: function(ctx) {
// Use p1DataIndex (ending point) so the line inherits the destination color
// This makes momentum shifts more visually intuitive
const index = ctx.p1DataIndex;
if (index !== undefined && wpDataset.segmentColors[index]) {
return wpDataset.segmentColors[index];
}
return wpDataset.borderColor || ‘#8B0000’;
}
};
}
}
// Initialize the chart
const ctx = canvas.getContext(‘2d’);
const chart = new Chart(ctx, {
type: ‘bar’,
data: chartData,
options: chartOptions
});
// Store reference to prevent re-initialization
canvas.chartInstance = chart;
console.log(‘CFB Chart initialized successfully’);
} catch (error) {
console.error(‘Error initializing CFB chart:’, error);
// Fallback: show error message in canvas container
const container = document.getElementById(‘cfb-chart-1765138194324-qynkvbh4j’).parentNode;
if (container) {
container.innerHTML = ‘
‘;
}
}
}
// Start loading scripts sequentially
function startLoading() {
// First, check if scripts are already loaded (multiple embeds on same page)
if (typeof Chart !== ‘undefined’ && typeof ChartDataLabels !== ‘undefined’) {
initChart();
return;
}
// Load Chart.js first
if (typeof Chart === ‘undefined’) {
loadScript(‘https://cdn.jsdelivr.net/npm/chart.js@3.9.1/dist/chart.min.js’, function() {
// Then load ChartDataLabels
if (typeof ChartDataLabels === ‘undefined’) {
loadScript(‘https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2.2.0’, function() {
initChart();
});
} else {
initChart();
}
});
} else if (typeof ChartDataLabels === ‘undefined’) {
// Chart.js loaded but not ChartDataLabels
loadScript(‘https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2.2.0’, function() {
initChart();
});
} else {
initChart();
}
}
// Initialize when DOM is ready
if (document.readyState === ‘loading’) {
document.addEventListener(‘DOMContentLoaded’, startLoading);
} else {
startLoading();
}
})();
And no, this wasn’t really a mirage of statistics, like some scoreboard results are. The Georgia Bulldogs benefited from some short fields, a few good early breaks, and some charmed 3rd-and-long conversions; but they were solidly more efficient than Alabama (if slightly less explosive).
In fact, Alabama’s efficiency here, at 29% SR, is terrible. In fact, it’s similar to the Oklahoma efficiencies (28% SR vs. Bama, 29% vs. Mizzou) that I’ve been complaining about in my posts. In those, I call out Oklahoma for skating by with a terrible offense and some lucky bounces. Which, after the last two Alabama games (and in some ways, after the last month of games) is apparently a label I need to start applying to Alabama.
Maybe it’s destiny that these two offense-optional teams are meeting again in the Playoff.
body {
font-family: -apple-system, BlinkMacSystemFont, ‘Segoe UI’, ‘Roboto’, sans-serif;
margin: 0;
padding: 0;
background: #f8fafc;
}
.embed-container {
background: white;
border-radius: 12px;
border: 1px solid #e5e5e5;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
overflow: hidden;
max-width: 800px;
margin: 0 auto;
padding: 0;
}
.header {
padding: 18px 24px 14px;
border-bottom: 1px solid #e5e5e5;
background: white;
}
.title {
font-size: 18px;
font-weight: 600;
color: #171717;
margin: 0;
}
.subtitle {
font-size: 11px;
font-weight: 400;
color: #737373;
margin: 4px 0 0 0;
}
.table-wrapper {
padding: 0;
}
table {
min-width: 100%;
table-layout: fixed;
border-collapse: collapse;
}
.col-stat { width: auto; }
.col-team { width: 140px; }
thead tr {
background-color: #525252;
color: white;
}
th {
padding: 12px 16px;
text-align: left;
font-size: 14px;
font-weight: 600;
border-bottom: 4px solid #475569;
text-align: center;
}
th.stat-header {
text-align: left;
}
tbody tr {
border-bottom: 1px solid #e5e5e5;
}
.bg-white {
background-color: #ffffff;
}
.bg-neutral-50 {
background-color: #fafafa;
}
.px-4 { padding-left: 1rem; padding-right: 1rem; }
.py-3 { padding-top: 0.75rem; padding-bottom: 0.75rem; }
.text-sm { font-size: 0.875rem; }
.font-medium { font-weight: 500; }
.font-semibold { font-weight: 600; }
.text-neutral-900 { color: #171717; }
.text-center { text-align: center; }
.embed-footer {
border-top: 1px solid #e5e5e5;
font-size: 12px;
color: #737373;
}
.embed-footer-top {
display: flex;
justify-content: center;
align-items: center;
padding: 12px 16px;
}
.embed-footer-link {
color: #737373;
text-decoration: none;
font-weight: 500;
}
.embed-footer-link:hover {
color: #525252;
text-decoration: underline;
}
@media (max-width: 640px) {
.header { padding: 12px 16px; }
th, td { padding: 8px 12px; }
.title { font-size: 16px; }
.embed-footer-top { padding: 8px 12px; }
.col-team { width: 80px; }
th, td { font-size: 13px; }
}
Box Score
Alabama vs. Georgia • Dec 6, 2025
| Stats | Alabama | Georgia |
|---|---|---|
| Points | 7 | 28 |
| Game Excitement | 2.5 | 2.5 |
| Total yards | 209 | 297 |
| Rush yards | -3 | 141 |
| Rush attempts | 16 | 41 |
| Yards per rush | -0.2 | 3.4 |
| Pass yards | 212 | 156 |
| Pass attempts | 19-39 | 20-26 |
| Yards per pass | 5.4 | 6.0 |
| 1st downs | 11 | 16 |
| 3rd down eff | 3-14 | 6-16 |
| 4th down eff | 1-3 | 2-2 |
| Explosiveness | 1.30 | 1.25 |
| Turnovers | 1 | 0 |
| Tackles | 42 | 22 |
| Sacks | 1 | 3 |
| Penalties-Yds | 1-5 | 7-80 |
| Possession | 23:08 | 36:52 |
Most of the box score is horrible, as you’d expect, but there are some odd silver linings in there:
- Bama only lagged the Dawgs by 88 total yards. (Short fields and all that, an echo of the Oklahoma loss).
- Ty and his Cursed Crew actually did have more passing yards (212 to 156) than UGA (who decided they didn’t need to pass the ball downfield to do just fine and dandy in this game).
- Bama actually did get 11 first downs to Georgia’s 16. Those are very different numbers in a relatively low-scoring game like this, but it doesn’t look like a “one team got quadruple the points of the other” kind of gap.
- Alabama was slightly more explosive (in part, in my view, due to some shenanigans on that lone scoring drive)
- Alabama was excellent on Penalties. What a weird stat to take from a blowout loss, but Georgia racked up the penalties while Alabama just had a single snap infraction on the day. Zero penalties on defense (again, Stockton didn’t try to throw the ball downfield much).
- Bama held UGA to 6-for-16 on 3rd down (a 37.5% SR). That’s below average, but unfortunately UGA was 2-for-2 on 4th downs, so some of that is wiped away. (The Dawgs always seem to be good on 4th down, with a notable exception being Alabama’s stop in the game earlier this season).
But obviously the other numbers are bad. And in the end, Alabama was only able to muster a game that delivered a 2.5 Game Excitement score, which might be the lowest I’ve seen. (The first game in Athens was a 6.3).
Choo choo, here comes the pain train
Let’s do a lightning round through the bad stuff. (Yes, I’m finding myself doing this two games in a row; um, Roll Tide?)
.cfb-chart-embed-cfb-chart-1765138217684-tg2mwe4yg {
font-family: -apple-system, BlinkMacSystemFont, ‘Segoe UI’, ‘Roboto’, sans-serif;
margin: 0;
padding: 0;
}
.cfb-chart-embed-cfb-chart-1765138217684-tg2mwe4yg .chart-container {
background: white;
border-radius: 12px;
border: 1px solid #e5e5e5;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
overflow: hidden;
}
.cfb-chart-embed-cfb-chart-1765138217684-tg2mwe4yg .chart-header {
padding: 18px 24px 14px;
border-bottom: 1px solid #e5e5e5;
background: white;
}
.cfb-chart-embed-cfb-chart-1765138217684-tg2mwe4yg .chart-title {
font-size: 18px;
font-weight: 600;
color: #171717;
margin: 0;
}
.cfb-chart-embed-cfb-chart-1765138217684-tg2mwe4yg .chart-subtitle {
font-size: 11px;
font-weight: 400;
color: #737373;
margin: 4px 0 0 0;
}
.cfb-chart-embed-cfb-chart-1765138217684-tg2mwe4yg .chart-content {
padding: 20px 24px 24px !important;
}
.cfb-chart-embed-cfb-chart-1765138217684-tg2mwe4yg .chart-content { height: 325px; }
@media (max-width: 640px) {
.cfb-chart-embed-cfb-chart-1765138217684-tg2mwe4yg .chart-content {
padding: 12px 16px 20px !important;
height: 280px !important;
}
.cfb-chart-embed-cfb-chart-1765138217684-tg2mwe4yg .chart-header {
padding: 12px 16px 12px !important;
}
.cfb-chart-embed-cfb-chart-1765138217684-tg2mwe4yg .embed-footer-top {
padding: 8px 12px !important;
}
.cfb-chart-embed-cfb-chart-1765138217684-tg2mwe4yg .data-definitions {
padding: 12px !important;
}
}
.cfb-chart-embed-cfb-chart-1765138217684-tg2mwe4yg .embed-footer {
border-top: 1px solid #e5e5e5;
font-size: 12px;
color: #737373;
}
.cfb-chart-embed-cfb-chart-1765138217684-tg2mwe4yg .embed-footer-top {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 16px;
}
.cfb-chart-embed-cfb-chart-1765138217684-tg2mwe4yg .embed-footer-link {
color: #737373;
text-decoration: none;
font-weight: 500;
}
.cfb-chart-embed-cfb-chart-1765138217684-tg2mwe4yg .embed-footer-link:hover {
color: #525252;
text-decoration: underline;
}
.cfb-chart-embed-cfb-chart-1765138217684-tg2mwe4yg .data-definitions-toggle {
background: none;
border: none;
color: #737373;
font-size: 12px;
font-weight: 500;
cursor: pointer;
display: flex;
align-items: center;
gap: 4px;
padding: 0;
}
.cfb-chart-embed-cfb-chart-1765138217684-tg2mwe4yg .data-definitions-toggle:hover {
color: #525252;
}
.cfb-chart-embed-cfb-chart-1765138217684-tg2mwe4yg .caret {
transition: transform 0.2s ease;
font-size: 10px;
}
.cfb-chart-embed-cfb-chart-1765138217684-tg2mwe4yg .caret.expanded {
transform: rotate(180deg);
}
.cfb-chart-embed-cfb-chart-1765138217684-tg2mwe4yg .data-definitions {
display: none;
padding: 16px;
background: #fafafa;
border-top: 1px solid #e5e5e5;
font-size: 12px;
line-height: 1.4;
}
.cfb-chart-embed-cfb-chart-1765138217684-tg2mwe4yg .data-definitions.expanded {
display: block;
}
.cfb-chart-embed-cfb-chart-1765138217684-tg2mwe4yg .data-definitions ul {
margin: 0;
padding-left: 0;
list-style: none;
}
.cfb-chart-embed-cfb-chart-1765138217684-tg2mwe4yg .data-definitions li {
margin-bottom: 4px;
}
SR and XR by Down
Alabama vs. Georgia • Dec 6, 2025
- Based roughly on the SP+ analytic system
- Successful play: Gains enough needed yards (50% 1st down, 70% on 2nd, 100% on 3rd/4th)
- Success Rate (SR): Percentage of plays that were successful
- Explosiveness Rate (XR): Percentage of plays gaining 15+ yards
- # Plays: Numbers shown in bars represent total play counts
- NCAA Avg: Dashed line shows 42% (roughly NCAA average) success rate
// Toggle data definitions accordion – unique function per embed
function toggleDefinitions_cfb_chart_1765138217684_tg2mwe4yg() {
const definitions = document.getElementById(‘dataDefinitions_cfb-chart-1765138217684-tg2mwe4yg’);
const caret = document.getElementById(‘caret_cfb-chart-1765138217684-tg2mwe4yg’);
if (definitions.classList.contains(‘expanded’)) {
definitions.classList.remove(‘expanded’);
caret.classList.remove(‘expanded’);
} else {
definitions.classList.add(‘expanded’);
caret.classList.add(‘expanded’);
}
}
// Sequential script loading for better reliability
(function() {
‘use strict’;
let retryCount = 0;
const maxRetries = 50; // 5 seconds total
// Load scripts sequentially
function loadScript(url, callback) {
const script = document.createElement(‘script’);
script.src = url;
script.onload = callback;
script.onerror = function() {
console.error(‘Failed to load script:’, url);
showError(‘Failed to load required chart library’);
};
document.head.appendChild(script);
}
function showError(message) {
const canvas = document.getElementById(‘cfb-chart-1765138217684-tg2mwe4yg’);
if (canvas && canvas.parentNode) {
canvas.parentNode.innerHTML = ‘
‘;
}
}
function initChart() {
retryCount++;
// Check if Chart.js is available
if (typeof Chart === ‘undefined’) {
if (retryCount >= maxRetries) {
showError(‘Chart library failed to load. Please refresh the page.’);
return;
}
setTimeout(initChart, 100);
return;
}
// Check if datalabels plugin is available
if (typeof ChartDataLabels === ‘undefined’) {
if (retryCount >= maxRetries) {
showError(‘Chart plugin failed to load. Please refresh the page.’);
return;
}
setTimeout(initChart, 100);
return;
}
// Check if canvas element exists
const canvas = document.getElementById(‘cfb-chart-1765138217684-tg2mwe4yg’);
if (!canvas) {
console.warn(‘Canvas element not found yet, retrying…’);
setTimeout(initChart, 100);
return;
}
// Prevent multiple chart instances
if (canvas.chartInstance) {
console.log(‘Chart already initialized’);
return;
}
try {
// Register the datalabels plugin
Chart.register(ChartDataLabels);
// Embed actual chart data directly
const chartData = {
“labels”: [
“1st Down”,
“2nd Down”,
“3rd Down”,
“4th Down”
],
“datasets”: [
{
“data”: [
0.08695652173913043,
0,
0.21428571428571427,
0
],
“stack”: “Team”,
“label”: “Alabama XR”,
“backgroundColor”: “rgba(101, 0, 20, 0.8)”,
“datalabels”: {
“display”: false
}
},
{
“data”: [
0.43478260869565216,
0.125,
0.21428571428571427,
0.3333333333333333
],
“stack”: “Team”,
“label”: “Alabama SR”,
“backgroundColor”: “rgba(175, 40, 60, 0.8)”,
“datalabels”: {
“display”: true
}
},
{
“data”: [
0.07142857142857142,
0.047619047619047616,
0.0625,
0
],
“stack”: “Opponent”,
“label”: “Georgia XR”,
“backgroundColor”: “rgba(130, 0, 25, 0.8)”,
“datalabels”: {
“display”: false
}
},
{
“data”: [
0.2857142857142857,
0.38095238095238093,
0.375,
1
],
“stack”: “Opponent”,
“label”: “Georgia SR”,
“backgroundColor”: “rgba(200, 16, 46, 0.8)”,
“datalabels”: {
“display”: true
}
},
{
“type”: “line”,
“data”: [
0.42,
0.42,
0.42,
0.42
],
“label”: “NCAA Avg SR”,
“borderColor”: “#757575”,
“borderWidth”: 2,
“borderDash”: [
3,
3
],
“pointRadius”: 0,
“datalabels”: {
“display”: false
}
},
{
“type”: “line”,
“data”: [
null,
null,
null,
null
],
“label”: “# Plays”,
“backgroundColor”: “rgba(0, 0, 0, 0)”,
“borderColor”: “rgba(0, 0, 0, 0)”,
“borderWidth”: 0,
“pointRadius”: 0,
“showLine”: false,
“fill”: false,
“datalabels”: {
“display”: false
}
}
],
“teamCounts”: [
23,
16,
14,
3
],
“oppCounts”: [
28,
21,
16,
2
],
“currentParams”: {
“year”: 2025,
“week”: 15,
“seasonType”: “regular”,
“team”: “Alabama”,
“gameId”: “401777351”
}
};
// Chart options (WordPress-safe)
const chartOptions = {
responsive: true,
maintainAspectRatio: false,
animation: {
duration: 1 // Minimal animation to trigger layout calculation (fixes label positioning)
},
elements: ‘bar’ === ‘line’ ? ‘down-bars’.includes(‘play-map’) ? {
line: {
tension: 0,
borderWidth: 0
}
} : ‘down-bars’ === ‘win-probability’ ? {
line: {
tension: 0.15,
borderWidth: 2.2,
fill: false
},
point: {
pointRadius: 0,
pointHoverRadius: 4
}
} : {
line: {
tension: 0.25,
borderWidth: 2.2
},
point: {
pointRadius: ‘down-bars’.includes(‘team-lines’) ? 0 : undefined
}
} : {},
plugins: {
datalabels: {
display: function(context) {
// Suppress data labels on line charts
if (‘bar’ === ‘line’) {
return false;
}
return context.dataset.datalabels && context.dataset.datalabels.display === true;
},
formatter: function(value, context) {
// Special handling for Overall Team Performance chart
if (‘down-bars’ === ‘overall-team-performance’ && context.dataset.label === ‘Success Rate (SR)’) {
// Use the stored play count data
if (context.dataset.playCountData && context.dataset.playCountData[context.dataIndex]) {
return context.dataset.playCountData[context.dataIndex];
}
// Fallback to percentage if play count data not available
return Math.round(value * 100) + ‘%’;
}
// Handle bar charts with count data (play-type, quarter, down, etc.)
if (context.dataset.label && context.dataset.label.includes(‘ SR’) &&
(chartData.teamCounts || chartData.oppCounts)) {
// Find the first team SR dataset in the chart to determine team order
const allDatasets = context.chart.data.datasets;
const teamSRDataset = allDatasets.find(d => d.label && d.label.includes(‘ SR’) && !d.label.includes(‘NCAA’));
// If this is the first team’s SR dataset, use teamCounts
if (teamSRDataset && context.dataset.label === teamSRDataset.label && chartData.teamCounts) {
return chartData.teamCounts[context.dataIndex] || 0;
}
// Otherwise, use oppCounts for the second team
else if (chartData.oppCounts) {
return chartData.oppCounts[context.dataIndex] || 0;
}
}
// For player charts, show value only if > 0 (matches non-embedded behavior)
if (‘down-bars’.includes(‘top-rushers’) || ‘down-bars’.includes(‘top-passers’) || ‘down-bars’.includes(‘top-receivers’)) {
// Hide data labels for zero or negative values, show actual value for positive values
return value > 0 ? value : null;
}
// For other charts, show values based on type
if (typeof value === ‘number’) {
// If value is between 0 and 1, treat as percentage
if (value >= 0 && value 0 ? ‘#26262660’ : ‘transparent’;
},
borderColor: function(context) {
const value = context.dataset.data[context.dataIndex];
return value > 0 ? ‘rgba(255, 255, 255, 0.2)’ : ‘transparent’;
},
borderRadius: 4,
align: ‘center’,
anchor: ‘center’
},
legend: ‘down-bars’ === ‘win-probability’ ? {
display: false
} : ‘bar’ === ‘line’ ? {
position: ‘top’,
align: ‘start’,
labels: ‘down-bars’.includes(‘play-map’) ? {
usePointStyle: true,
generateLabels: function(chart) {
// Call the original generateLabels to get default styling
const original = Chart.defaults.plugins.legend.labels.generateLabels;
const labels = original.call(this, chart);
// Filter and customize each label
const filteredLabels = labels.filter(label => {
return !label.text.includes(‘ {
const dataset = chart.data.datasets[label.datasetIndex];
if (dataset && dataset.label) {
if (dataset.label.includes(‘Rush’)) {
label.pointStyle = ‘circle’;
label.pointStyleWidth = 4;
label.fillStyle = ‘white’;
} else if (dataset.label.includes(‘Pass’)) {
label.pointStyle = ‘triangle’;
label.pointStyleWidth = 4;
label.fillStyle = ‘white’;
} else {
label.pointStyle = ‘rect’;
label.pointStyleWidth = 4;
label.fillStyle = ‘white’;
}
}
});
return filteredLabels;
},
boxWidth: 20,
padding: 12
} : {
usePointStyle: false,
boxWidth: 12,
boxHeight: 12,
padding: 12,
generateLabels: function(chart) {
const original = Chart.defaults.plugins.legend.labels.generateLabels;
const labels = original.call(this, chart);
// Filter out reference areas and ensure white fill
const filteredLabels = labels.filter(label => {
return !label.text.includes(‘NCAA Avg SR’) &&
!label.text.includes(’50/50′) &&
!label.text.includes(‘Quarters’);
});
// Ensure white fill for all line chart legend boxes
filteredLabels.forEach((label) => {
label.fillStyle = ‘white’;
});
return filteredLabels;
}
}
} : {
position: ‘top’,
align: ‘start’,
labels: {
usePointStyle: false,
boxWidth: 12,
boxHeight: 12,
padding: 12,
filter: function(legendItem, chartData) {
return !legendItem.text.includes(‘NCAA Avg SR’) &&
!legendItem.text.includes(‘Quarters’) &&
!legendItem.text.includes(’50/50′);
},
generateLabels: function(chart) {
const data = chart.data;
if (data.datasets.length) {
return data.datasets.map((dataset, i) => {
// Handle backgroundColor arrays (like in Overall Team Performance chart)
let fillColor = dataset.backgroundColor;
if (dataset.label === ‘# Plays’) {
fillColor = ‘white’;
} else if (Array.isArray(dataset.backgroundColor)) {
// For datasets with backgroundColor arrays, use the first color for legend
fillColor = dataset.backgroundColor[0];
}
return {
text: dataset.label,
fillStyle: fillColor,
strokeStyle: dataset.label === ‘# Plays’ ? ‘#666’ : dataset.borderColor,
lineWidth: dataset.label === ‘# Plays’ ? 1 : dataset.borderWidth,
hidden: !chart.isDatasetVisible(i),
datasetIndex: i
};
}).filter((item, index) => {
// Apply the same filter logic as above
const dataset = chart.data.datasets[index];
if (!dataset || !dataset.data) return false;
if (dataset.label === ‘# Plays’) return true; // Always show # Plays
if (dataset.label && (dataset.label.includes(‘NCAA Avg SR’) ||
dataset.label.includes(‘Quarters’) ||
dataset.label.includes(’50/50′))) return false;
return dataset.data.some((value) => value > 0);
});
}
return [];
}
}
},
tooltip: ‘down-bars’ === ‘win-probability’ ? {
mode: ‘index’,
intersect: false,
callbacks: {
title: function(tooltipItems) {
if (tooltipItems && tooltipItems[0]) {
return ‘Play ‘ + (tooltipItems[0].dataIndex + 1);
}
return ”;
},
label: function(context) {
const selectedTeamWinProb = context.parsed.y;
const opponentWinProb = 100 – selectedTeamWinProb;
const selectedTeam = context.dataset.selectedTeam || ‘Team’;
const opponentTeam = context.dataset.opponentTeam || ‘Opponent’;
return [
selectedTeam + ‘: ‘ + selectedTeamWinProb.toFixed(1) + ‘%’,
opponentTeam + ‘: ‘ + opponentWinProb.toFixed(1) + ‘%’
];
},
afterLabel: function(context) {
if (context.dataset.playTexts && context.dataset.playTexts[context.dataIndex]) {
return ‘n’ + context.dataset.playTexts[context.dataIndex];
}
return ”;
}
}
} : {
filter: function(tooltipItem) {
if (‘down-bars’.includes(‘play-map’)) {
return !tooltipItem.dataset.label.includes(‘< 0’) &&
!tooltipItem.dataset.label.includes(‘Quarters’) &&
!tooltipItem.dataset.label.includes(‘Drive’);
}
return !tooltipItem.dataset.label.includes(‘NCAA Avg SR’) &&
!tooltipItem.dataset.label.includes(’50/50′) &&
!tooltipItem.dataset.label.includes(‘ ds.label === ‘Win Probability’);
if (wpDataset && wpDataset.segmentColors) {
wpDataset.segment = {
borderColor: function(ctx) {
// Use p1DataIndex (ending point) so the line inherits the destination color
// This makes momentum shifts more visually intuitive
const index = ctx.p1DataIndex;
if (index !== undefined && wpDataset.segmentColors[index]) {
return wpDataset.segmentColors[index];
}
return wpDataset.borderColor || ‘#8B0000’;
}
};
}
}
// Initialize the chart
const ctx = canvas.getContext(‘2d’);
const chart = new Chart(ctx, {
type: ‘bar’,
data: chartData,
options: chartOptions
});
// Store reference to prevent re-initialization
canvas.chartInstance = chart;
console.log(‘CFB Chart initialized successfully’);
} catch (error) {
console.error(‘Error initializing CFB chart:’, error);
// Fallback: show error message in canvas container
const container = document.getElementById(‘cfb-chart-1765138217684-tg2mwe4yg’).parentNode;
if (container) {
container.innerHTML = ‘
‘;
}
}
}
// Start loading scripts sequentially
function startLoading() {
// First, check if scripts are already loaded (multiple embeds on same page)
if (typeof Chart !== ‘undefined’ && typeof ChartDataLabels !== ‘undefined’) {
initChart();
return;
}
// Load Chart.js first
if (typeof Chart === ‘undefined’) {
loadScript(‘https://cdn.jsdelivr.net/npm/chart.js@3.9.1/dist/chart.min.js’, function() {
// Then load ChartDataLabels
if (typeof ChartDataLabels === ‘undefined’) {
loadScript(‘https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2.2.0’, function() {
initChart();
});
} else {
initChart();
}
});
} else if (typeof ChartDataLabels === ‘undefined’) {
// Chart.js loaded but not ChartDataLabels
loadScript(‘https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2.2.0’, function() {
initChart();
});
} else {
initChart();
}
}
// Initialize when DOM is ready
if (document.readyState === ‘loading’) {
document.addEventListener(‘DOMContentLoaded’, startLoading);
} else {
startLoading();
}
})();
Alabama actually won on 1st down efficiency and explosiveness. Isn’t that nuts? Because otherwise, the Tide were completely pantsed on every down. 2nd down was basically “might as well spike the ball” territory, and while 3rd downs had a strong chance at explosiveness, that was Ty’s only play.
Alabama has benefitted from some good playcalling (and good luck) on 4th downs this year — and we’ve been rewarded for some timely conversions, including against Auburn — but it did not hold in this one: 1 for 3 on 4th down means “this team lost.”
.cfb-chart-embed-cfb-chart-1765138232639-ge87ruydd {
font-family: -apple-system, BlinkMacSystemFont, ‘Segoe UI’, ‘Roboto’, sans-serif;
margin: 0;
padding: 0;
}
.cfb-chart-embed-cfb-chart-1765138232639-ge87ruydd .chart-container {
background: white;
border-radius: 12px;
border: 1px solid #e5e5e5;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
overflow: hidden;
}
.cfb-chart-embed-cfb-chart-1765138232639-ge87ruydd .chart-header {
padding: 18px 24px 14px;
border-bottom: 1px solid #e5e5e5;
background: white;
}
.cfb-chart-embed-cfb-chart-1765138232639-ge87ruydd .chart-title {
font-size: 18px;
font-weight: 600;
color: #171717;
margin: 0;
}
.cfb-chart-embed-cfb-chart-1765138232639-ge87ruydd .chart-subtitle {
font-size: 11px;
font-weight: 400;
color: #737373;
margin: 4px 0 0 0;
}
.cfb-chart-embed-cfb-chart-1765138232639-ge87ruydd .chart-content {
padding: 20px 24px 24px !important;
}
.cfb-chart-embed-cfb-chart-1765138232639-ge87ruydd .chart-content { height: 325px; }
@media (max-width: 640px) {
.cfb-chart-embed-cfb-chart-1765138232639-ge87ruydd .chart-content {
padding: 12px 16px 20px !important;
height: 280px !important;
}
.cfb-chart-embed-cfb-chart-1765138232639-ge87ruydd .chart-header {
padding: 12px 16px 12px !important;
}
.cfb-chart-embed-cfb-chart-1765138232639-ge87ruydd .embed-footer-top {
padding: 8px 12px !important;
}
.cfb-chart-embed-cfb-chart-1765138232639-ge87ruydd .data-definitions {
padding: 12px !important;
}
}
.cfb-chart-embed-cfb-chart-1765138232639-ge87ruydd .embed-footer {
border-top: 1px solid #e5e5e5;
font-size: 12px;
color: #737373;
}
.cfb-chart-embed-cfb-chart-1765138232639-ge87ruydd .embed-footer-top {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 16px;
}
.cfb-chart-embed-cfb-chart-1765138232639-ge87ruydd .embed-footer-link {
color: #737373;
text-decoration: none;
font-weight: 500;
}
.cfb-chart-embed-cfb-chart-1765138232639-ge87ruydd .embed-footer-link:hover {
color: #525252;
text-decoration: underline;
}
.cfb-chart-embed-cfb-chart-1765138232639-ge87ruydd .data-definitions-toggle {
background: none;
border: none;
color: #737373;
font-size: 12px;
font-weight: 500;
cursor: pointer;
display: flex;
align-items: center;
gap: 4px;
padding: 0;
}
.cfb-chart-embed-cfb-chart-1765138232639-ge87ruydd .data-definitions-toggle:hover {
color: #525252;
}
.cfb-chart-embed-cfb-chart-1765138232639-ge87ruydd .caret {
transition: transform 0.2s ease;
font-size: 10px;
}
.cfb-chart-embed-cfb-chart-1765138232639-ge87ruydd .caret.expanded {
transform: rotate(180deg);
}
.cfb-chart-embed-cfb-chart-1765138232639-ge87ruydd .data-definitions {
display: none;
padding: 16px;
background: #fafafa;
border-top: 1px solid #e5e5e5;
font-size: 12px;
line-height: 1.4;
}
.cfb-chart-embed-cfb-chart-1765138232639-ge87ruydd .data-definitions.expanded {
display: block;
}
.cfb-chart-embed-cfb-chart-1765138232639-ge87ruydd .data-definitions ul {
margin: 0;
padding-left: 0;
list-style: none;
}
.cfb-chart-embed-cfb-chart-1765138232639-ge87ruydd .data-definitions li {
margin-bottom: 4px;
}
SR and XR by Red Zone
Alabama vs. Georgia • Dec 6, 2025
- Based roughly on the SP+ analytic system
- Successful play: Gains enough needed yards (50% 1st down, 70% on 2nd, 100% on 3rd/4th)
- Success Rate (SR): Percentage of plays that were successful
- Explosiveness Rate (XR): Percentage of plays gaining 15+ yards
- # Plays: Numbers shown in bars represent total play counts
- NCAA Avg: Dashed line shows 42% (roughly NCAA average) success rate
// Toggle data definitions accordion – unique function per embed
function toggleDefinitions_cfb_chart_1765138232639_ge87ruydd() {
const definitions = document.getElementById(‘dataDefinitions_cfb-chart-1765138232639-ge87ruydd’);
const caret = document.getElementById(‘caret_cfb-chart-1765138232639-ge87ruydd’);
if (definitions.classList.contains(‘expanded’)) {
definitions.classList.remove(‘expanded’);
caret.classList.remove(‘expanded’);
} else {
definitions.classList.add(‘expanded’);
caret.classList.add(‘expanded’);
}
}
// Sequential script loading for better reliability
(function() {
‘use strict’;
let retryCount = 0;
const maxRetries = 50; // 5 seconds total
// Load scripts sequentially
function loadScript(url, callback) {
const script = document.createElement(‘script’);
script.src = url;
script.onload = callback;
script.onerror = function() {
console.error(‘Failed to load script:’, url);
showError(‘Failed to load required chart library’);
};
document.head.appendChild(script);
}
function showError(message) {
const canvas = document.getElementById(‘cfb-chart-1765138232639-ge87ruydd’);
if (canvas && canvas.parentNode) {
canvas.parentNode.innerHTML = ‘
‘;
}
}
function initChart() {
retryCount++;
// Check if Chart.js is available
if (typeof Chart === ‘undefined’) {
if (retryCount >= maxRetries) {
showError(‘Chart library failed to load. Please refresh the page.’);
return;
}
setTimeout(initChart, 100);
return;
}
// Check if datalabels plugin is available
if (typeof ChartDataLabels === ‘undefined’) {
if (retryCount >= maxRetries) {
showError(‘Chart plugin failed to load. Please refresh the page.’);
return;
}
setTimeout(initChart, 100);
return;
}
// Check if canvas element exists
const canvas = document.getElementById(‘cfb-chart-1765138232639-ge87ruydd’);
if (!canvas) {
console.warn(‘Canvas element not found yet, retrying…’);
setTimeout(initChart, 100);
return;
}
// Prevent multiple chart instances
if (canvas.chartInstance) {
console.log(‘Chart already initialized’);
return;
}
try {
// Register the datalabels plugin
Chart.register(ChartDataLabels);
// Embed actual chart data directly
const chartData = {
“labels”: [
“Red Zone”,
“Other”
],
“datasets”: [
{
“data”: [
0,
0.09615384615384616
],
“stack”: “Team”,
“label”: “Alabama XR”,
“backgroundColor”: “rgba(101, 0, 20, 0.8)”,
“datalabels”: {
“display”: false
}
},
{
“data”: [
0,
0.3076923076923077
],
“stack”: “Team”,
“label”: “Alabama SR”,
“backgroundColor”: “rgba(175, 40, 60, 0.8)”,
“datalabels”: {
“display”: true
}
},
{
“data”: [
0,
0.07142857142857142
],
“stack”: “Opponent”,
“label”: “Georgia XR”,
“backgroundColor”: “rgba(130, 0, 25, 0.8)”,
“datalabels”: {
“display”: false
}
},
{
“data”: [
0.45454545454545453,
0.3392857142857143
],
“stack”: “Opponent”,
“label”: “Georgia SR”,
“backgroundColor”: “rgba(200, 16, 46, 0.8)”,
“datalabels”: {
“display”: true
}
},
{
“type”: “line”,
“data”: [
0.42,
0.42
],
“label”: “NCAA Avg SR”,
“borderColor”: “#757575”,
“borderWidth”: 2,
“borderDash”: [
3,
3
],
“pointRadius”: 0,
“datalabels”: {
“display”: false
}
},
{
“type”: “line”,
“data”: [
null,
null
],
“label”: “# Plays”,
“backgroundColor”: “rgba(0, 0, 0, 0)”,
“borderColor”: “rgba(0, 0, 0, 0)”,
“borderWidth”: 0,
“pointRadius”: 0,
“showLine”: false,
“fill”: false,
“datalabels”: {
“display”: false
}
}
],
“teamCounts”: [
4,
52
],
“oppCounts”: [
11,
56
],
“currentParams”: {
“year”: 2025,
“week”: 15,
“seasonType”: “regular”,
“team”: “Alabama”,
“gameId”: “401777351”
}
};
// Chart options (WordPress-safe)
const chartOptions = {
responsive: true,
maintainAspectRatio: false,
animation: {
duration: 1 // Minimal animation to trigger layout calculation (fixes label positioning)
},
elements: ‘bar’ === ‘line’ ? ‘red-zone-bars’.includes(‘play-map’) ? {
line: {
tension: 0,
borderWidth: 0
}
} : ‘red-zone-bars’ === ‘win-probability’ ? {
line: {
tension: 0.15,
borderWidth: 2.2,
fill: false
},
point: {
pointRadius: 0,
pointHoverRadius: 4
}
} : {
line: {
tension: 0.25,
borderWidth: 2.2
},
point: {
pointRadius: ‘red-zone-bars’.includes(‘team-lines’) ? 0 : undefined
}
} : {},
plugins: {
datalabels: {
display: function(context) {
// Suppress data labels on line charts
if (‘bar’ === ‘line’) {
return false;
}
return context.dataset.datalabels && context.dataset.datalabels.display === true;
},
formatter: function(value, context) {
// Special handling for Overall Team Performance chart
if (‘red-zone-bars’ === ‘overall-team-performance’ && context.dataset.label === ‘Success Rate (SR)’) {
// Use the stored play count data
if (context.dataset.playCountData && context.dataset.playCountData[context.dataIndex]) {
return context.dataset.playCountData[context.dataIndex];
}
// Fallback to percentage if play count data not available
return Math.round(value * 100) + ‘%’;
}
// Handle bar charts with count data (play-type, quarter, down, etc.)
if (context.dataset.label && context.dataset.label.includes(‘ SR’) &&
(chartData.teamCounts || chartData.oppCounts)) {
// Find the first team SR dataset in the chart to determine team order
const allDatasets = context.chart.data.datasets;
const teamSRDataset = allDatasets.find(d => d.label && d.label.includes(‘ SR’) && !d.label.includes(‘NCAA’));
// If this is the first team’s SR dataset, use teamCounts
if (teamSRDataset && context.dataset.label === teamSRDataset.label && chartData.teamCounts) {
return chartData.teamCounts[context.dataIndex] || 0;
}
// Otherwise, use oppCounts for the second team
else if (chartData.oppCounts) {
return chartData.oppCounts[context.dataIndex] || 0;
}
}
// For player charts, show value only if > 0 (matches non-embedded behavior)
if (‘red-zone-bars’.includes(‘top-rushers’) || ‘red-zone-bars’.includes(‘top-passers’) || ‘red-zone-bars’.includes(‘top-receivers’)) {
// Hide data labels for zero or negative values, show actual value for positive values
return value > 0 ? value : null;
}
// For other charts, show values based on type
if (typeof value === ‘number’) {
// If value is between 0 and 1, treat as percentage
if (value >= 0 && value 0 ? ‘#26262660’ : ‘transparent’;
},
borderColor: function(context) {
const value = context.dataset.data[context.dataIndex];
return value > 0 ? ‘rgba(255, 255, 255, 0.2)’ : ‘transparent’;
},
borderRadius: 4,
align: ‘center’,
anchor: ‘center’
},
legend: ‘red-zone-bars’ === ‘win-probability’ ? {
display: false
} : ‘bar’ === ‘line’ ? {
position: ‘top’,
align: ‘start’,
labels: ‘red-zone-bars’.includes(‘play-map’) ? {
usePointStyle: true,
generateLabels: function(chart) {
// Call the original generateLabels to get default styling
const original = Chart.defaults.plugins.legend.labels.generateLabels;
const labels = original.call(this, chart);
// Filter and customize each label
const filteredLabels = labels.filter(label => {
return !label.text.includes(‘ {
const dataset = chart.data.datasets[label.datasetIndex];
if (dataset && dataset.label) {
if (dataset.label.includes(‘Rush’)) {
label.pointStyle = ‘circle’;
label.pointStyleWidth = 4;
label.fillStyle = ‘white’;
} else if (dataset.label.includes(‘Pass’)) {
label.pointStyle = ‘triangle’;
label.pointStyleWidth = 4;
label.fillStyle = ‘white’;
} else {
label.pointStyle = ‘rect’;
label.pointStyleWidth = 4;
label.fillStyle = ‘white’;
}
}
});
return filteredLabels;
},
boxWidth: 20,
padding: 12
} : {
usePointStyle: false,
boxWidth: 12,
boxHeight: 12,
padding: 12,
generateLabels: function(chart) {
const original = Chart.defaults.plugins.legend.labels.generateLabels;
const labels = original.call(this, chart);
// Filter out reference areas and ensure white fill
const filteredLabels = labels.filter(label => {
return !label.text.includes(‘NCAA Avg SR’) &&
!label.text.includes(’50/50′) &&
!label.text.includes(‘Quarters’);
});
// Ensure white fill for all line chart legend boxes
filteredLabels.forEach((label) => {
label.fillStyle = ‘white’;
});
return filteredLabels;
}
}
} : {
position: ‘top’,
align: ‘start’,
labels: {
usePointStyle: false,
boxWidth: 12,
boxHeight: 12,
padding: 12,
filter: function(legendItem, chartData) {
return !legendItem.text.includes(‘NCAA Avg SR’) &&
!legendItem.text.includes(‘Quarters’) &&
!legendItem.text.includes(’50/50′);
},
generateLabels: function(chart) {
const data = chart.data;
if (data.datasets.length) {
return data.datasets.map((dataset, i) => {
// Handle backgroundColor arrays (like in Overall Team Performance chart)
let fillColor = dataset.backgroundColor;
if (dataset.label === ‘# Plays’) {
fillColor = ‘white’;
} else if (Array.isArray(dataset.backgroundColor)) {
// For datasets with backgroundColor arrays, use the first color for legend
fillColor = dataset.backgroundColor[0];
}
return {
text: dataset.label,
fillStyle: fillColor,
strokeStyle: dataset.label === ‘# Plays’ ? ‘#666’ : dataset.borderColor,
lineWidth: dataset.label === ‘# Plays’ ? 1 : dataset.borderWidth,
hidden: !chart.isDatasetVisible(i),
datasetIndex: i
};
}).filter((item, index) => {
// Apply the same filter logic as above
const dataset = chart.data.datasets[index];
if (!dataset || !dataset.data) return false;
if (dataset.label === ‘# Plays’) return true; // Always show # Plays
if (dataset.label && (dataset.label.includes(‘NCAA Avg SR’) ||
dataset.label.includes(‘Quarters’) ||
dataset.label.includes(’50/50′))) return false;
return dataset.data.some((value) => value > 0);
});
}
return [];
}
}
},
tooltip: ‘red-zone-bars’ === ‘win-probability’ ? {
mode: ‘index’,
intersect: false,
callbacks: {
title: function(tooltipItems) {
if (tooltipItems && tooltipItems[0]) {
return ‘Play ‘ + (tooltipItems[0].dataIndex + 1);
}
return ”;
},
label: function(context) {
const selectedTeamWinProb = context.parsed.y;
const opponentWinProb = 100 – selectedTeamWinProb;
const selectedTeam = context.dataset.selectedTeam || ‘Team’;
const opponentTeam = context.dataset.opponentTeam || ‘Opponent’;
return [
selectedTeam + ‘: ‘ + selectedTeamWinProb.toFixed(1) + ‘%’,
opponentTeam + ‘: ‘ + opponentWinProb.toFixed(1) + ‘%’
];
},
afterLabel: function(context) {
if (context.dataset.playTexts && context.dataset.playTexts[context.dataIndex]) {
return ‘n’ + context.dataset.playTexts[context.dataIndex];
}
return ”;
}
}
} : {
filter: function(tooltipItem) {
if (‘red-zone-bars’.includes(‘play-map’)) {
return !tooltipItem.dataset.label.includes(‘< 0’) &&
!tooltipItem.dataset.label.includes(‘Quarters’) &&
!tooltipItem.dataset.label.includes(‘Drive’);
}
return !tooltipItem.dataset.label.includes(‘NCAA Avg SR’) &&
!tooltipItem.dataset.label.includes(’50/50′) &&
!tooltipItem.dataset.label.includes(‘ ds.label === ‘Win Probability’);
if (wpDataset && wpDataset.segmentColors) {
wpDataset.segment = {
borderColor: function(ctx) {
// Use p1DataIndex (ending point) so the line inherits the destination color
// This makes momentum shifts more visually intuitive
const index = ctx.p1DataIndex;
if (index !== undefined && wpDataset.segmentColors[index]) {
return wpDataset.segmentColors[index];
}
return wpDataset.borderColor || ‘#8B0000’;
}
};
}
}
// Initialize the chart
const ctx = canvas.getContext(‘2d’);
const chart = new Chart(ctx, {
type: ‘bar’,
data: chartData,
options: chartOptions
});
// Store reference to prevent re-initialization
canvas.chartInstance = chart;
console.log(‘CFB Chart initialized successfully’);
} catch (error) {
console.error(‘Error initializing CFB chart:’, error);
// Fallback: show error message in canvas container
const container = document.getElementById(‘cfb-chart-1765138232639-ge87ruydd’).parentNode;
if (container) {
container.innerHTML = ‘
‘;
}
}
}
// Start loading scripts sequentially
function startLoading() {
// First, check if scripts are already loaded (multiple embeds on same page)
if (typeof Chart !== ‘undefined’ && typeof ChartDataLabels !== ‘undefined’) {
initChart();
return;
}
// Load Chart.js first
if (typeof Chart === ‘undefined’) {
loadScript(‘https://cdn.jsdelivr.net/npm/chart.js@3.9.1/dist/chart.min.js’, function() {
// Then load ChartDataLabels
if (typeof ChartDataLabels === ‘undefined’) {
loadScript(‘https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2.2.0’, function() {
initChart();
});
} else {
initChart();
}
});
} else if (typeof ChartDataLabels === ‘undefined’) {
// Chart.js loaded but not ChartDataLabels
loadScript(‘https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2.2.0’, function() {
initChart();
});
} else {
initChart();
}
}
// Initialize when DOM is ready
if (document.readyState === ‘loading’) {
document.addEventListener(‘DOMContentLoaded’, startLoading);
} else {
startLoading();
}
})();
Alabama didn’t even get into the Red Zone the entire game. Just that weird Germie play (where the ref threw an A+ block to open the outside of the field) gave us a score from outside of the 20’s.
Next slide.
.cfb-chart-embed-cfb-chart-1765138243739-9uzacibu3 {
font-family: -apple-system, BlinkMacSystemFont, ‘Segoe UI’, ‘Roboto’, sans-serif;
margin: 0;
padding: 0;
}
.cfb-chart-embed-cfb-chart-1765138243739-9uzacibu3 .chart-container {
background: white;
border-radius: 12px;
border: 1px solid #e5e5e5;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
overflow: hidden;
}
.cfb-chart-embed-cfb-chart-1765138243739-9uzacibu3 .chart-header {
padding: 18px 24px 14px;
border-bottom: 1px solid #e5e5e5;
background: white;
}
.cfb-chart-embed-cfb-chart-1765138243739-9uzacibu3 .chart-title {
font-size: 18px;
font-weight: 600;
color: #171717;
margin: 0;
}
.cfb-chart-embed-cfb-chart-1765138243739-9uzacibu3 .chart-subtitle {
font-size: 11px;
font-weight: 400;
color: #737373;
margin: 4px 0 0 0;
}
.cfb-chart-embed-cfb-chart-1765138243739-9uzacibu3 .chart-content {
padding: 20px 24px 24px !important;
}
.cfb-chart-embed-cfb-chart-1765138243739-9uzacibu3 .chart-content { height: 325px; }
@media (max-width: 640px) {
.cfb-chart-embed-cfb-chart-1765138243739-9uzacibu3 .chart-content {
padding: 12px 16px 20px !important;
height: 280px !important;
}
.cfb-chart-embed-cfb-chart-1765138243739-9uzacibu3 .chart-header {
padding: 12px 16px 12px !important;
}
.cfb-chart-embed-cfb-chart-1765138243739-9uzacibu3 .embed-footer-top {
padding: 8px 12px !important;
}
.cfb-chart-embed-cfb-chart-1765138243739-9uzacibu3 .data-definitions {
padding: 12px !important;
}
}
.cfb-chart-embed-cfb-chart-1765138243739-9uzacibu3 .embed-footer {
border-top: 1px solid #e5e5e5;
font-size: 12px;
color: #737373;
}
.cfb-chart-embed-cfb-chart-1765138243739-9uzacibu3 .embed-footer-top {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 16px;
}
.cfb-chart-embed-cfb-chart-1765138243739-9uzacibu3 .embed-footer-link {
color: #737373;
text-decoration: none;
font-weight: 500;
}
.cfb-chart-embed-cfb-chart-1765138243739-9uzacibu3 .embed-footer-link:hover {
color: #525252;
text-decoration: underline;
}
.cfb-chart-embed-cfb-chart-1765138243739-9uzacibu3 .data-definitions-toggle {
background: none;
border: none;
color: #737373;
font-size: 12px;
font-weight: 500;
cursor: pointer;
display: flex;
align-items: center;
gap: 4px;
padding: 0;
}
.cfb-chart-embed-cfb-chart-1765138243739-9uzacibu3 .data-definitions-toggle:hover {
color: #525252;
}
.cfb-chart-embed-cfb-chart-1765138243739-9uzacibu3 .caret {
transition: transform 0.2s ease;
font-size: 10px;
}
.cfb-chart-embed-cfb-chart-1765138243739-9uzacibu3 .caret.expanded {
transform: rotate(180deg);
}
.cfb-chart-embed-cfb-chart-1765138243739-9uzacibu3 .data-definitions {
display: none;
padding: 16px;
background: #fafafa;
border-top: 1px solid #e5e5e5;
font-size: 12px;
line-height: 1.4;
}
.cfb-chart-embed-cfb-chart-1765138243739-9uzacibu3 .data-definitions.expanded {
display: block;
}
.cfb-chart-embed-cfb-chart-1765138243739-9uzacibu3 .data-definitions ul {
margin: 0;
padding-left: 0;
list-style: none;
}
.cfb-chart-embed-cfb-chart-1765138243739-9uzacibu3 .data-definitions li {
margin-bottom: 4px;
}
Rush Rate: Alabama
Alabama vs. Georgia • Dec 6, 2025
- Based roughly on the SP+ analytic system
- Successful play: Gains enough needed yards (50% 1st down, 70% on 2nd, 100% on 3rd/4th)
- Success Rate (SR): Percentage of plays that were successful
- Explosiveness Rate (XR): Percentage of plays gaining 15+ yards
- Rush Rate: Percentage of offensive plays that are rushing attempts
- Gray area: Represents 50/50 balanced offense
// Toggle data definitions accordion – unique function per embed
function toggleDefinitions_cfb_chart_1765138243739_9uzacibu3() {
const definitions = document.getElementById(‘dataDefinitions_cfb-chart-1765138243739-9uzacibu3’);
const caret = document.getElementById(‘caret_cfb-chart-1765138243739-9uzacibu3’);
if (definitions.classList.contains(‘expanded’)) {
definitions.classList.remove(‘expanded’);
caret.classList.remove(‘expanded’);
} else {
definitions.classList.add(‘expanded’);
caret.classList.add(‘expanded’);
}
}
// Sequential script loading for better reliability
(function() {
‘use strict’;
let retryCount = 0;
const maxRetries = 50; // 5 seconds total
// Load scripts sequentially
function loadScript(url, callback) {
const script = document.createElement(‘script’);
script.src = url;
script.onload = callback;
script.onerror = function() {
console.error(‘Failed to load script:’, url);
showError(‘Failed to load required chart library’);
};
document.head.appendChild(script);
}
function showError(message) {
const canvas = document.getElementById(‘cfb-chart-1765138243739-9uzacibu3’);
if (canvas && canvas.parentNode) {
canvas.parentNode.innerHTML = ‘
‘;
}
}
function initChart() {
retryCount++;
// Check if Chart.js is available
if (typeof Chart === ‘undefined’) {
if (retryCount >= maxRetries) {
showError(‘Chart library failed to load. Please refresh the page.’);
return;
}
setTimeout(initChart, 100);
return;
}
// Check if datalabels plugin is available
if (typeof ChartDataLabels === ‘undefined’) {
if (retryCount >= maxRetries) {
showError(‘Chart plugin failed to load. Please refresh the page.’);
return;
}
setTimeout(initChart, 100);
return;
}
// Check if canvas element exists
const canvas = document.getElementById(‘cfb-chart-1765138243739-9uzacibu3’);
if (!canvas) {
console.warn(‘Canvas element not found yet, retrying…’);
setTimeout(initChart, 100);
return;
}
// Prevent multiple chart instances
if (canvas.chartInstance) {
console.log(‘Chart already initialized’);
return;
}
try {
// Register the datalabels plugin
Chart.register(ChartDataLabels);
// Embed actual chart data directly
const chartData = {
“datasets”: [
{
“label”: “50/50”,
“data”: [
{
“x”: 1,
“y”: 0
},
{
“x”: 1,
“y”: 0.5
},
{
“x”: 56,
“y”: 0.5
},
{
“x”: 56,
“y”: 0
}
],
“backgroundColor”: “rgba(0,0,0,0.03)”,
“borderColor”: “transparent”,
“pointRadius”: 0,
“fill”: true,
“tension”: 0,
“showLine”: true,
“datalabels”: {
“display”: false
}
},
{
“data”: [
{
“x”: 1,
“y”: 1,
“text”: “D.Hill rush middle for 5 yards gain to the ALA24 (#94 X.McLeod)”
},
{
“x”: 2,
“y”: 1,
“text”: “D.Hill rush middle for 2 yards gain to the ALA26 (#6 D.Everette)”
},
{
“x”: 3,
“y”: 1,
“text”: “L.Brooks rush right for 0 yards to the ALA26 (#1 E.Robinson IV)”
},
{
“x”: 4,
“y”: 0.75,
“text”: “T.Simpson pass complete short middle to #1 I.Horton caught at ALA15, for 12 yards to the ALA20 (#20 J.Thomas), 1ST DOWN”
},
{
“x”: 5,
“y”: 0.8,
“text”: “D.Hill rush middle for 2 yards gain to the ALA22 (#94 X.McLeod)”
},
{
“x”: 6,
“y”: 0.8333333333333334,
“text”: “T.Simpson rush middle for 1 yard loss to the ALA21 (#0 G.Harris Jr.)”
},
{
“x”: 7,
“y”: 0.7142857142857143,
“text”: “T.Simpson pass incomplete short middle to #5 G.Bernard thrown to ALA30”
},
{
“x”: 8,
“y”: 0.75,
“text”: “A.Dear rush middle for 2 yards gain to the ALA27 (#5 R.Wilson)”
},
{
“x”: 9,
“y”: 0.6666666666666666,
“text”: “T.Simpson pass complete short right to #4 D.Hill caught at ALA30, for 4 yards to the ALA31 (#9 C.Cole)”
},
{
“x”: 10,
“y”: 0.6,
“text”: “T.Simpson pass complete short left to #2 R.Williams caught at ALA36, for 20 yards to the UGA49, out of bounds at UGA49, 1ST DOWN”
},
{
“x”: 11,
“y”: 0.5454545454545454,
“text”: “T.Simpson pass incomplete short right to #1 I.Horton thrown to UGA32 broken up by #1 E.Robinson IV”
},
{
“x”: 12,
“y”: 0.5,
“text”: “T.Simpson pass complete short middle to #5 G.Bernard caught at UGA47, for 4 yards to the UGA45 (#20 J.Thomas)”
},
{
“x”: 13,
“y”: 0.46153846153846156,
“text”: “T.Simpson pass intercepted by #6 D.Everette at UGA28 #6 D.Everette return 34 yards to the ALA38 (#5 G.Bernard), out of bounds PENALTY UGA Face Mask (#6 D.Everette) 15 yards from ALA42 to UGA43”
},
{
“x”: 14,
“y”: 0.42857142857142855,
“text”: “T.Simpson pass complete short right to #2 R.Williams caught at ALA21, for 13 yards to the ALA38, out of bounds at ALA38, 1ST DOWN. UGA is challenging the ruling on the field – “Runner was out of bounds”. CALL OVERTURNED. (Original Play: (08:39) Shotgun #15 T.Simpson pass complete short right to #2 R.Williams caught at ALA21, for 21 yards to the ALA46 (#20 J.Thomas), out of bounds, 1ST DOWN)”
},
{
“x”: 15,
“y”: 0.4,
“text”: “T.Simpson pass incomplete short right thrown to ALA40 QB hurried by #3 C.Allen”
},
{
“x”: 16,
“y”: 0.375,
“text”: “T.Simpson pass incomplete short right to #4 D.Hill thrown to ALA40 broken up by #33 Q.Johnson”
},
{
“x”: 17,
“y”: 0.35294117647058826,
“text”: “T.Simpson pass incomplete short left to #17 L.Brooks thrown to ALA45”
},
{
“x”: 18,
“y”: 0.3888888888888889,
“text”: “A.Dear rush middle for 3 yards gain to the ALA28 (#3 C.Allen)”
},
{
“x”: 19,
“y”: 0.42105263157894735,
“text”: “R.Williams rush right for 5 yards gain to the ALA33 (#5 R.Wilson), out of bounds”
},
{
“x”: 20,
“y”: 0.4,
“text”: “T.Simpson pass incomplete short left to #4 D.Hill thrown to ALA30”
},
{
“x”: 21,
“y”: 0.38095238095238093,
“text”: “T.Simpson pass complete short middle to #14 M.Pritchett caught at ALA12, for 7 yards to the ALA16 (#5 R.Wilson) PENALTY ALA Personal Foul offsetting UGA Roughing The Passer offsetting. NO PLAY”
},
{
“x”: 22,
“y”: 0.4090909090909091,
“text”: “T.Simpson at ALA08 for loss of 1 yard”
},
{
“x”: 23,
“y”: 0.391304347826087,
“text”: “T.Simpson pass complete short right to #17 L.Brooks caught at ALA24, for 1 yard to the ALA26 (#27 R.Dinkins), out of bounds”
},
{
“x”: 24,
“y”: 0.375,
“text”: “T.Simpson pass incomplete short left to #17 L.Brooks thrown to ALA40 QB hurried by #94 X.McLeod”
},
{
“x”: 25,
“y”: 0.36,
“text”: “T.Simpson sacked for loss of 9 yards to the ALA17 (#20 J.Thomas)”
},
{
“x”: 26,
“y”: 0.38461538461538464,
“text”: “A.Dear rush left for 5 yards gain to the ALA18 (#5 R.Wilson; #20 J.Thomas)”
},
{
“x”: 27,
“y”: 0.4074074074074074,
“text”: “T.Simpson rush left for 5 yards loss to the ALA13, End Of Play”
},
{
“x”: 28,
“y”: 0.39285714285714285,
“text”: “T.Simpson pass complete short right to #14 M.Pritchett caught at ALA09, for 12 yards to the ALA20 (#9 C.Cole; #3 C.Allen), out of bounds”
},
{
“x”: 29,
“y”: 0.3793103448275862,
“text”: “T.Simpson pass complete short left to #4 D.Hill caught at ALA24, for 4 yards to the ALA24, End Of Play”
},
{
“x”: 30,
“y”: 0.4,
“text”: “D.Hill rush middle for 2 yards gain to the ALA26 (#5 R.Wilson; #90 E.Griffin)”
},
{
“x”: 31,
“y”: 0.3870967741935484,
“text”: “T.Simpson pass complete short left to #4 D.Hill caught at ALA26, for 2 yards to the ALA28 (#20 J.Thomas), out of bounds”
},
{
“x”: 32,
“y”: 0.375,
“text”: “T.Simpson pass complete short middle to #81 K.Edwards caught at ALA18, for 21 yards to the ALA30 (#9 C.Cole), 1ST DOWN”
},
{
“x”: 33,
“y”: 0.36363636363636365,
“text”: “T.Simpson pass complete short middle to #4 D.Hill caught at ALA35, for 9 yards to the ALA39 (#9 C.Cole)”
},
{
“x”: 34,
“y”: 0.35294117647058826,
“text”: “T.Simpson sacked for loss of 9 yards to the ALA30 (#33 Q.Johnson, #9 C.Cole) PENALTY UGA Personal Foul (#15 D.Jones) 15 yards from ALA30 to ALA45, 1ST DOWN”
},
{
“x”: 35,
“y”: 0.34285714285714286,
“text”: “T.Simpson pass complete short middle to #81 K.Edwards caught at ALA48, for 13 yards to the UGA42 (#4 K.Bolden; #20 J.Thomas), 1ST DOWN”
},
{
“x”: 36,
“y”: 0.3333333333333333,
“text”: “T.Simpson pass complete short middle to #4 D.Hill caught at UGA38, for 4 yards to the UGA38 (#3 C.Allen)”
},
{
“x”: 37,
“y”: 0.32432432432432434,
“text”: “T.Simpson pass incomplete short right to #4 D.Hill thrown to UGA40”
},
{
“x”: 38,
“y”: 0.3157894736842105,
“text”: “T.Simpson pass incomplete deep middle to #17 L.Brooks thrown to UGA00”
},
{
“x”: 39,
“y”: 0.3076923076923077,
“text”: “T.Simpson pass incomplete deep left to #2 R.Williams thrown to UGA00 broken up by #1 E.Robinson IV”
},
{
“x”: 40,
“y”: 0.3,
“text”: “T.Simpson pass complete short middle to #5 G.Bernard caught at UGA25, for 23 yards to the UGA00 TOUCHDOWN, clock 12:33, 1ST DOWN #31 C.Talty kick attempt good (H: #38 B.Doud, LS: #44 A.Rozier)”
},
{
“x”: 41,
“y”: 0.2926829268292683,
“text”: “T.Simpson pass incomplete short middle to #81 K.Edwards thrown to ALA06 QB hurried by #94 X.McLeod”
},
{
“x”: 42,
“y”: 0.2857142857142857,
“text”: “T.Simpson pass complete short left to #5 G.Bernard caught at ALA09, for 8 yards to the ALA12 (#4 K.Bolden)”
},
{
“x”: 43,
“y”: 0.27906976744186046,
“text”: “T.Simpson pass incomplete short middle to #81 K.Edwards thrown to ALA15 broken up by #3 C.Allen”
},
{
“x”: 44,
“y”: 0.2727272727272727,
“text”: “T.Simpson pass incomplete short right to #5 G.Bernard thrown to ALA17, TURNOVER ON DOWNS”
},
{
“x”: 45,
“y”: 0.26666666666666666,
“text”: “T.Simpson pass complete short left to #5 G.Bernard caught at ALA35, for 16 yards to the ALA41 (#5 R.Wilson; #4 K.Bolden), 1ST DOWN”
},
{
“x”: 46,
“y”: 0.2608695652173913,
“text”: “T.Simpson pass complete short left to #5 G.Bernard caught at ALA49, for 8 yards to the ALA49 (#15 D.Jones)”
},
{
“x”: 47,
“y”: 0.2553191489361702,
“text”: “T.Simpson pass incomplete short left to #5 G.Bernard thrown to UGA40 broken up by #6 D.Everette”
},
{
“x”: 48,
“y”: 0.2708333333333333,
“text”: “T.Simpson rush middle for 1 yard gain to the ALA50 (#3 C.Allen)”
},
{
“x”: 49,
“y”: 0.2653061224489796,
“text”: “T.Simpson pass complete short middle to #81 K.Edwards caught at ALA48, for 8 yards to the UGA42 (#1 E.Robinson IV; #3 C.Allen), 1ST DOWN”
},
{
“x”: 50,
“y”: 0.26,
“text”: “T.Simpson pass incomplete short left to #2 R.Williams thrown to UGA32 broken up by #4 K.Bolden”
},
{
“x”: 51,
“y”: 0.2549019607843137,
“text”: “T.Simpson sacked for loss of 5 yards to the UGA47 (#10 Z.Walker)”
},
{
“x”: 52,
“y”: 0.25,
“text”: “T.Simpson pass complete short middle to #5 G.Bernard caught at UGA44, for 30 yards to the UGA17 lateral to #4 D.Hill for 27 yards gain to the UGA17 (#6 D.Everette), out of bounds, 1ST DOWN”
},
{
“x”: 53,
“y”: 0.24528301886792453,
“text”: “T.Simpson pass incomplete short right to #5 G.Bernard thrown to UGA00”
},
{
“x”: 54,
“y”: 0.24074074074074073,
“text”: “T.Simpson pass incomplete short left to #0 A.Dear thrown to UGA22”
},
{
“x”: 55,
“y”: 0.23636363636363636,
“text”: “T.Simpson pass incomplete short right to #2 R.Williams thrown to UGA08”
},
{
“x”: 56,
“y”: 0.23214285714285715,
“text”: “T.Simpson pass incomplete short right to #5 G.Bernard thrown to UGA00 QB hurried by #19 J.Williams and #91 J.Greene, TURNOVER ON DOWNS”
}
],
“label”: “Alabama Rush Rate”,
“borderColor”: “rgba(101, 0, 20, 0.8)”,
“backgroundColor”: “rgba(245, 229, 233, 0.8)”,
“borderWidth”: 2,
“pointBackgroundColor”: [
“rgba(175, 40, 60, 0.8)”,
“rgba(255,255,255,0.9)”,
“rgba(255,255,255,0.9)”,
“rgba(175, 40, 60, 0.8)”,
“rgba(255,255,255,0.9)”,
“rgba(255,255,255,0.9)”,
“rgba(255,255,255,0.9)”,
“rgba(255,255,255,0.9)”,
“rgba(255,255,255,0.9)”,
“rgba(101, 0, 20, 0.8)”,
“rgba(255,255,255,0.9)”,
“rgba(255,255,255,0.9)”,
“rgba(255,255,255,0.9)”,
“rgba(175, 40, 60, 0.8)”,
“rgba(255,255,255,0.9)”,
“rgba(255,255,255,0.9)”,
“rgba(255,255,255,0.9)”,
“rgba(255,255,255,0.9)”,
“rgba(175, 40, 60, 0.8)”,
“rgba(255,255,255,0.9)”,
“rgba(175, 40, 60, 0.8)”,
“rgba(255,255,255,0.9)”,
“rgba(255,255,255,0.9)”,
“rgba(255,255,255,0.9)”,
“rgba(255,255,255,0.9)”,
“rgba(175, 40, 60, 0.8)”,
“rgba(255,255,255,0.9)”,
“rgba(255,255,255,0.9)”,
“rgba(255,255,255,0.9)”,
“rgba(255,255,255,0.9)”,
“rgba(255,255,255,0.9)”,
“rgba(101, 0, 20, 0.8)”,
“rgba(175, 40, 60, 0.8)”,
“rgba(255,255,255,0.9)”,
“rgba(175, 40, 60, 0.8)”,
“rgba(255,255,255,0.9)”,
“rgba(255,255,255,0.9)”,
“rgba(255,255,255,0.9)”,
“rgba(255,255,255,0.9)”,
“rgba(101, 0, 20, 0.8)”,
“rgba(255,255,255,0.9)”,
“rgba(175, 40, 60, 0.8)”,
“rgba(255,255,255,0.9)”,
“rgba(255,255,255,0.9)”,
“rgba(101, 0, 20, 0.8)”,
“rgba(175, 40, 60, 0.8)”,
“rgba(255,255,255,0.9)”,
“rgba(255,255,255,0.9)”,
“rgba(175, 40, 60, 0.8)”,
“rgba(255,255,255,0.9)”,
“rgba(255,255,255,0.9)”,
“rgba(101, 0, 20, 0.8)”,
“rgba(255,255,255,0.9)”,
“rgba(255,255,255,0.9)”,
“rgba(255,255,255,0.9)”,
“rgba(255,255,255,0.9)”
],
“pointStyle”: [
“circle”,
“circle”,
“circle”,
“triangle”,
“circle”,
“circle”,
“triangle”,
“circle”,
“triangle”,
“triangle”,
“triangle”,
“triangle”,
“triangle”,
“triangle”,
“triangle”,
“triangle”,
“triangle”,
“circle”,
“circle”,
“triangle”,
“triangle”,
“circle”,
“triangle”,
“triangle”,
“triangle”,
“circle”,
“circle”,
“triangle”,
“triangle”,
“circle”,
“triangle”,
“triangle”,
“triangle”,
“triangle”,
“triangle”,
“triangle”,
“triangle”,
“triangle”,
“triangle”,
“triangle”,
“triangle”,
“triangle”,
“triangle”,
“triangle”,
“triangle”,
“triangle”,
“triangle”,
“circle”,
“triangle”,
“triangle”,
“triangle”,
“triangle”,
“triangle”,
“triangle”,
“triangle”,
“triangle”
],
“pointRadius”: [
4,
4,
4,
5.5,
4,
4,
5.5,
4,
5.5,
5.5,
5.5,
5.5,
5.5,
5.5,
5.5,
5.5,
5.5,
4,
4,
5.5,
5.5,
4,
5.5,
5.5,
5.5,
4,
4,
5.5,
5.5,
4,
5.5,
5.5,
5.5,
5.5,
5.5,
5.5,
5.5,
5.5,
5.5,
5.5,
5.5,
5.5,
5.5,
5.5,
5.5,
5.5,
5.5,
4,
5.5,
5.5,
5.5,
5.5,
5.5,
5.5,
5.5,
5.5
],
“pointBorderWidth”: 1,
“pointBorderColor”: “rgba(101, 0, 20, 0.8)”,
“fill”: true
},
{
“label”: “Quarters”,
“data”: [
{
“x”: 1,
“y”: 0
},
{
“x”: 1,
“y”: 1
},
{
“x”: 56,
“y”: 1
},
{
“x”: 56,
“y”: 0
},
{
“x”: 14,
“y”: 0
},
{
“x”: 14,
“y”: 1
},
{
“x”: 56,
“y”: 1
},
{
“x”: 56,
“y”: 0
},
{
“x”: 23,
“y”: 0
},
{
“x”: 23,
“y”: 1
},
{
“x”: 56,
“y”: 1
},
{
“x”: 56,
“y”: 0
},
{
“x”: 33,
“y”: 0
},
{
“x”: 33,
“y”: 1
},
{
“x”: 56,
“y”: 1
},
{
“x”: 56,
“y”: 0
}
],
“borderColor”: “rgba(0,0,0,0.1)”,
“borderWidth”: 1,
“tension”: 0,
“fill”: false,
“pointRadius”: 0,
“showLine”: true,
“datalabels”: {
“display”: false
}
}
],
“currentParams”: {
“year”: 2025,
“week”: 15,
“seasonType”: “regular”,
“team”: “Alabama”,
“gameId”: “401777351”
}
};
// Chart options (WordPress-safe)
const chartOptions = {
responsive: true,
maintainAspectRatio: false,
animation: {
duration: 1 // Minimal animation to trigger layout calculation (fixes label positioning)
},
elements: ‘line’ === ‘line’ ? ‘team-rush-rate’.includes(‘play-map’) ? {
line: {
tension: 0,
borderWidth: 0
}
} : ‘team-rush-rate’ === ‘win-probability’ ? {
line: {
tension: 0.15,
borderWidth: 2.2,
fill: false
},
point: {
pointRadius: 0,
pointHoverRadius: 4
}
} : {
line: {
tension: 0.25,
borderWidth: 2.2
},
point: {
pointRadius: ‘team-rush-rate’.includes(‘team-lines’) ? 0 : undefined
}
} : {},
plugins: {
datalabels: {
display: function(context) {
// Suppress data labels on line charts
if (‘line’ === ‘line’) {
return false;
}
return context.dataset.datalabels && context.dataset.datalabels.display === true;
},
formatter: function(value, context) {
// Special handling for Overall Team Performance chart
if (‘team-rush-rate’ === ‘overall-team-performance’ && context.dataset.label === ‘Success Rate (SR)’) {
// Use the stored play count data
if (context.dataset.playCountData && context.dataset.playCountData[context.dataIndex]) {
return context.dataset.playCountData[context.dataIndex];
}
// Fallback to percentage if play count data not available
return Math.round(value * 100) + ‘%’;
}
// Handle bar charts with count data (play-type, quarter, down, etc.)
if (context.dataset.label && context.dataset.label.includes(‘ SR’) &&
(chartData.teamCounts || chartData.oppCounts)) {
// Find the first team SR dataset in the chart to determine team order
const allDatasets = context.chart.data.datasets;
const teamSRDataset = allDatasets.find(d => d.label && d.label.includes(‘ SR’) && !d.label.includes(‘NCAA’));
// If this is the first team’s SR dataset, use teamCounts
if (teamSRDataset && context.dataset.label === teamSRDataset.label && chartData.teamCounts) {
return chartData.teamCounts[context.dataIndex] || 0;
}
// Otherwise, use oppCounts for the second team
else if (chartData.oppCounts) {
return chartData.oppCounts[context.dataIndex] || 0;
}
}
// For player charts, show value only if > 0 (matches non-embedded behavior)
if (‘team-rush-rate’.includes(‘top-rushers’) || ‘team-rush-rate’.includes(‘top-passers’) || ‘team-rush-rate’.includes(‘top-receivers’)) {
// Hide data labels for zero or negative values, show actual value for positive values
return value > 0 ? value : null;
}
// For other charts, show values based on type
if (typeof value === ‘number’) {
// If value is between 0 and 1, treat as percentage
if (value >= 0 && value 0 ? ‘#26262660’ : ‘transparent’;
},
borderColor: function(context) {
const value = context.dataset.data[context.dataIndex];
return value > 0 ? ‘rgba(255, 255, 255, 0.2)’ : ‘transparent’;
},
borderRadius: 4,
align: ‘center’,
anchor: ‘center’
},
legend: ‘team-rush-rate’ === ‘win-probability’ ? {
display: false
} : ‘line’ === ‘line’ ? {
position: ‘top’,
align: ‘start’,
labels: ‘team-rush-rate’.includes(‘play-map’) ? {
usePointStyle: true,
generateLabels: function(chart) {
// Call the original generateLabels to get default styling
const original = Chart.defaults.plugins.legend.labels.generateLabels;
const labels = original.call(this, chart);
// Filter and customize each label
const filteredLabels = labels.filter(label => {
return !label.text.includes(‘ {
const dataset = chart.data.datasets[label.datasetIndex];
if (dataset && dataset.label) {
if (dataset.label.includes(‘Rush’)) {
label.pointStyle = ‘circle’;
label.pointStyleWidth = 4;
label.fillStyle = ‘white’;
} else if (dataset.label.includes(‘Pass’)) {
label.pointStyle = ‘triangle’;
label.pointStyleWidth = 4;
label.fillStyle = ‘white’;
} else {
label.pointStyle = ‘rect’;
label.pointStyleWidth = 4;
label.fillStyle = ‘white’;
}
}
});
return filteredLabels;
},
boxWidth: 20,
padding: 12
} : {
usePointStyle: false,
boxWidth: 12,
boxHeight: 12,
padding: 12,
generateLabels: function(chart) {
const original = Chart.defaults.plugins.legend.labels.generateLabels;
const labels = original.call(this, chart);
// Filter out reference areas and ensure white fill
const filteredLabels = labels.filter(label => {
return !label.text.includes(‘NCAA Avg SR’) &&
!label.text.includes(’50/50′) &&
!label.text.includes(‘Quarters’);
});
// Ensure white fill for all line chart legend boxes
filteredLabels.forEach((label) => {
label.fillStyle = ‘white’;
});
return filteredLabels;
}
}
} : {
position: ‘top’,
align: ‘start’,
labels: {
usePointStyle: false,
boxWidth: 12,
boxHeight: 12,
padding: 12,
filter: function(legendItem, chartData) {
return !legendItem.text.includes(‘NCAA Avg SR’) &&
!legendItem.text.includes(‘Quarters’) &&
!legendItem.text.includes(’50/50′);
},
generateLabels: function(chart) {
const data = chart.data;
if (data.datasets.length) {
return data.datasets.map((dataset, i) => {
// Handle backgroundColor arrays (like in Overall Team Performance chart)
let fillColor = dataset.backgroundColor;
if (dataset.label === ‘# Plays’) {
fillColor = ‘white’;
} else if (Array.isArray(dataset.backgroundColor)) {
// For datasets with backgroundColor arrays, use the first color for legend
fillColor = dataset.backgroundColor[0];
}
return {
text: dataset.label,
fillStyle: fillColor,
strokeStyle: dataset.label === ‘# Plays’ ? ‘#666’ : dataset.borderColor,
lineWidth: dataset.label === ‘# Plays’ ? 1 : dataset.borderWidth,
hidden: !chart.isDatasetVisible(i),
datasetIndex: i
};
}).filter((item, index) => {
// Apply the same filter logic as above
const dataset = chart.data.datasets[index];
if (!dataset || !dataset.data) return false;
if (dataset.label === ‘# Plays’) return true; // Always show # Plays
if (dataset.label && (dataset.label.includes(‘NCAA Avg SR’) ||
dataset.label.includes(‘Quarters’) ||
dataset.label.includes(’50/50′))) return false;
return dataset.data.some((value) => value > 0);
});
}
return [];
}
}
},
tooltip: ‘team-rush-rate’ === ‘win-probability’ ? {
mode: ‘index’,
intersect: false,
callbacks: {
title: function(tooltipItems) {
if (tooltipItems && tooltipItems[0]) {
return ‘Play ‘ + (tooltipItems[0].dataIndex + 1);
}
return ”;
},
label: function(context) {
const selectedTeamWinProb = context.parsed.y;
const opponentWinProb = 100 – selectedTeamWinProb;
const selectedTeam = context.dataset.selectedTeam || ‘Team’;
const opponentTeam = context.dataset.opponentTeam || ‘Opponent’;
return [
selectedTeam + ‘: ‘ + selectedTeamWinProb.toFixed(1) + ‘%’,
opponentTeam + ‘: ‘ + opponentWinProb.toFixed(1) + ‘%’
];
},
afterLabel: function(context) {
if (context.dataset.playTexts && context.dataset.playTexts[context.dataIndex]) {
return ‘n’ + context.dataset.playTexts[context.dataIndex];
}
return ”;
}
}
} : {
filter: function(tooltipItem) {
if (‘team-rush-rate’.includes(‘play-map’)) {
return !tooltipItem.dataset.label.includes(‘< 0’) &&
!tooltipItem.dataset.label.includes(‘Quarters’) &&
!tooltipItem.dataset.label.includes(‘Drive’);
}
return !tooltipItem.dataset.label.includes(‘NCAA Avg SR’) &&
!tooltipItem.dataset.label.includes(’50/50′) &&
!tooltipItem.dataset.label.includes(‘ ds.label === ‘Win Probability’);
if (wpDataset && wpDataset.segmentColors) {
wpDataset.segment = {
borderColor: function(ctx) {
// Use p1DataIndex (ending point) so the line inherits the destination color
// This makes momentum shifts more visually intuitive
const index = ctx.p1DataIndex;
if (index !== undefined && wpDataset.segmentColors[index]) {
return wpDataset.segmentColors[index];
}
return wpDataset.borderColor || ‘#8B0000’;
}
};
}
}
// Initialize the chart
const ctx = canvas.getContext(‘2d’);
const chart = new Chart(ctx, {
type: ‘line’,
data: chartData,
options: chartOptions
});
// Store reference to prevent re-initialization
canvas.chartInstance = chart;
console.log(‘CFB Chart initialized successfully’);
} catch (error) {
console.error(‘Error initializing CFB chart:’, error);
// Fallback: show error message in canvas container
const container = document.getElementById(‘cfb-chart-1765138243739-9uzacibu3’).parentNode;
if (container) {
container.innerHTML = ‘
‘;
}
}
}
// Start loading scripts sequentially
function startLoading() {
// First, check if scripts are already loaded (multiple embeds on same page)
if (typeof Chart !== ‘undefined’ && typeof ChartDataLabels !== ‘undefined’) {
initChart();
return;
}
// Load Chart.js first
if (typeof Chart === ‘undefined’) {
loadScript(‘https://cdn.jsdelivr.net/npm/chart.js@3.9.1/dist/chart.min.js’, function() {
// Then load ChartDataLabels
if (typeof ChartDataLabels === ‘undefined’) {
loadScript(‘https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2.2.0’, function() {
initChart();
});
} else {
initChart();
}
});
} else if (typeof ChartDataLabels === ‘undefined’) {
// Chart.js loaded but not ChartDataLabels
loadScript(‘https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2.2.0’, function() {
initChart();
});
} else {
initChart();
}
}
// Initialize when DOM is ready
if (document.readyState === ‘loading’) {
document.addEventListener(‘DOMContentLoaded’, startLoading);
} else {
startLoading();
}
})();
Bama actually tried to run the ball early, but veered hard away from it in the first half, before completing the theme by letting it drift through the 4th quarter. That, folks, is what it looks like when a team is losing for the entire game.
.cfb-chart-embed-cfb-chart-1765138252698-f721wlw1f {
font-family: -apple-system, BlinkMacSystemFont, ‘Segoe UI’, ‘Roboto’, sans-serif;
margin: 0;
padding: 0;
}
.cfb-chart-embed-cfb-chart-1765138252698-f721wlw1f .chart-container {
background: white;
border-radius: 12px;
border: 1px solid #e5e5e5;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
overflow: hidden;
}
.cfb-chart-embed-cfb-chart-1765138252698-f721wlw1f .chart-header {
padding: 18px 24px 14px;
border-bottom: 1px solid #e5e5e5;
background: white;
}
.cfb-chart-embed-cfb-chart-1765138252698-f721wlw1f .chart-title {
font-size: 18px;
font-weight: 600;
color: #171717;
margin: 0;
}
.cfb-chart-embed-cfb-chart-1765138252698-f721wlw1f .chart-subtitle {
font-size: 11px;
font-weight: 400;
color: #737373;
margin: 4px 0 0 0;
}
.cfb-chart-embed-cfb-chart-1765138252698-f721wlw1f .chart-content {
padding: 20px 24px 24px !important;
}
.cfb-chart-embed-cfb-chart-1765138252698-f721wlw1f .chart-content { height: 325px; }
@media (max-width: 640px) {
.cfb-chart-embed-cfb-chart-1765138252698-f721wlw1f .chart-content {
padding: 12px 16px 20px !important;
height: 280px !important;
}
.cfb-chart-embed-cfb-chart-1765138252698-f721wlw1f .chart-header {
padding: 12px 16px 12px !important;
}
.cfb-chart-embed-cfb-chart-1765138252698-f721wlw1f .embed-footer-top {
padding: 8px 12px !important;
}
.cfb-chart-embed-cfb-chart-1765138252698-f721wlw1f .data-definitions {
padding: 12px !important;
}
}
.cfb-chart-embed-cfb-chart-1765138252698-f721wlw1f .embed-footer {
border-top: 1px solid #e5e5e5;
font-size: 12px;
color: #737373;
}
.cfb-chart-embed-cfb-chart-1765138252698-f721wlw1f .embed-footer-top {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 16px;
}
.cfb-chart-embed-cfb-chart-1765138252698-f721wlw1f .embed-footer-link {
color: #737373;
text-decoration: none;
font-weight: 500;
}
.cfb-chart-embed-cfb-chart-1765138252698-f721wlw1f .embed-footer-link:hover {
color: #525252;
text-decoration: underline;
}
.cfb-chart-embed-cfb-chart-1765138252698-f721wlw1f .data-definitions-toggle {
background: none;
border: none;
color: #737373;
font-size: 12px;
font-weight: 500;
cursor: pointer;
display: flex;
align-items: center;
gap: 4px;
padding: 0;
}
.cfb-chart-embed-cfb-chart-1765138252698-f721wlw1f .data-definitions-toggle:hover {
color: #525252;
}
.cfb-chart-embed-cfb-chart-1765138252698-f721wlw1f .caret {
transition: transform 0.2s ease;
font-size: 10px;
}
.cfb-chart-embed-cfb-chart-1765138252698-f721wlw1f .caret.expanded {
transform: rotate(180deg);
}
.cfb-chart-embed-cfb-chart-1765138252698-f721wlw1f .data-definitions {
display: none;
padding: 16px;
background: #fafafa;
border-top: 1px solid #e5e5e5;
font-size: 12px;
line-height: 1.4;
}
.cfb-chart-embed-cfb-chart-1765138252698-f721wlw1f .data-definitions.expanded {
display: block;
}
.cfb-chart-embed-cfb-chart-1765138252698-f721wlw1f .data-definitions ul {
margin: 0;
padding-left: 0;
list-style: none;
}
.cfb-chart-embed-cfb-chart-1765138252698-f721wlw1f .data-definitions li {
margin-bottom: 4px;
}
SR and XR by Distance to Go
Alabama vs. Georgia • Dec 6, 2025
- Based roughly on the SP+ analytic system
- Successful play: Gains enough needed yards (50% 1st down, 70% on 2nd, 100% on 3rd/4th)
- Success Rate (SR): Percentage of plays that were successful
- Explosiveness Rate (XR): Percentage of plays gaining 15+ yards
- # Plays: Numbers shown in bars represent total play counts
- NCAA Avg: Dashed line shows 42% (roughly NCAA average) success rate
// Toggle data definitions accordion – unique function per embed
function toggleDefinitions_cfb_chart_1765138252698_f721wlw1f() {
const definitions = document.getElementById(‘dataDefinitions_cfb-chart-1765138252698-f721wlw1f’);
const caret = document.getElementById(‘caret_cfb-chart-1765138252698-f721wlw1f’);
if (definitions.classList.contains(‘expanded’)) {
definitions.classList.remove(‘expanded’);
caret.classList.remove(‘expanded’);
} else {
definitions.classList.add(‘expanded’);
caret.classList.add(‘expanded’);
}
}
// Sequential script loading for better reliability
(function() {
‘use strict’;
let retryCount = 0;
const maxRetries = 50; // 5 seconds total
// Load scripts sequentially
function loadScript(url, callback) {
const script = document.createElement(‘script’);
script.src = url;
script.onload = callback;
script.onerror = function() {
console.error(‘Failed to load script:’, url);
showError(‘Failed to load required chart library’);
};
document.head.appendChild(script);
}
function showError(message) {
const canvas = document.getElementById(‘cfb-chart-1765138252698-f721wlw1f’);
if (canvas && canvas.parentNode) {
canvas.parentNode.innerHTML = ‘
‘;
}
}
function initChart() {
retryCount++;
// Check if Chart.js is available
if (typeof Chart === ‘undefined’) {
if (retryCount >= maxRetries) {
showError(‘Chart library failed to load. Please refresh the page.’);
return;
}
setTimeout(initChart, 100);
return;
}
// Check if datalabels plugin is available
if (typeof ChartDataLabels === ‘undefined’) {
if (retryCount >= maxRetries) {
showError(‘Chart plugin failed to load. Please refresh the page.’);
return;
}
setTimeout(initChart, 100);
return;
}
// Check if canvas element exists
const canvas = document.getElementById(‘cfb-chart-1765138252698-f721wlw1f’);
if (!canvas) {
console.warn(‘Canvas element not found yet, retrying…’);
setTimeout(initChart, 100);
return;
}
// Prevent multiple chart instances
if (canvas.chartInstance) {
console.log(‘Chart already initialized’);
return;
}
try {
// Register the datalabels plugin
Chart.register(ChartDataLabels);
// Embed actual chart data directly
const chartData = {
“labels”: [
“Long (8+)”,
“Medium (4-7)”,
“Short (1-3)”
],
“datasets”: [
{
“data”: [
0.1,
0.125,
0
],
“stack”: “Team”,
“label”: “Alabama XR”,
“backgroundColor”: “rgba(101, 0, 20, 0.8)”,
“datalabels”: {
“display”: false
}
},
{
“data”: [
0.325,
0.25,
0.125
],
“stack”: “Team”,
“label”: “Alabama SR”,
“backgroundColor”: “rgba(175, 40, 60, 0.8)”,
“datalabels”: {
“display”: true
}
},
{
“data”: [
0.07692307692307693,
0,
0
],
“stack”: “Opponent”,
“label”: “Georgia XR”,
“backgroundColor”: “rgba(130, 0, 25, 0.8)”,
“datalabels”: {
“display”: false
}
},
{
“data”: [
0.28846153846153844,
0.16666666666666666,
0.8888888888888888
],
“stack”: “Opponent”,
“label”: “Georgia SR”,
“backgroundColor”: “rgba(200, 16, 46, 0.8)”,
“datalabels”: {
“display”: true
}
},
{
“type”: “line”,
“data”: [
0.42,
0.42,
0.42
],
“label”: “NCAA Avg SR”,
“borderColor”: “#757575”,
“borderWidth”: 2,
“borderDash”: [
3,
3
],
“pointRadius”: 0,
“datalabels”: {
“display”: false
}
},
{
“type”: “line”,
“data”: [
null,
null,
null
],
“label”: “# Plays”,
“backgroundColor”: “rgba(0, 0, 0, 0)”,
“borderColor”: “rgba(0, 0, 0, 0)”,
“borderWidth”: 0,
“pointRadius”: 0,
“showLine”: false,
“fill”: false,
“datalabels”: {
“display”: false
}
}
],
“teamCounts”: [
40,
8,
8
],
“oppCounts”: [
52,
6,
9
],
“currentParams”: {
“year”: 2025,
“week”: 15,
“seasonType”: “regular”,
“team”: “Alabama”,
“gameId”: “401777351”
}
};
// Chart options (WordPress-safe)
const chartOptions = {
responsive: true,
maintainAspectRatio: false,
animation: {
duration: 1 // Minimal animation to trigger layout calculation (fixes label positioning)
},
elements: ‘bar’ === ‘line’ ? ‘distance-bars’.includes(‘play-map’) ? {
line: {
tension: 0,
borderWidth: 0
}
} : ‘distance-bars’ === ‘win-probability’ ? {
line: {
tension: 0.15,
borderWidth: 2.2,
fill: false
},
point: {
pointRadius: 0,
pointHoverRadius: 4
}
} : {
line: {
tension: 0.25,
borderWidth: 2.2
},
point: {
pointRadius: ‘distance-bars’.includes(‘team-lines’) ? 0 : undefined
}
} : {},
plugins: {
datalabels: {
display: function(context) {
// Suppress data labels on line charts
if (‘bar’ === ‘line’) {
return false;
}
return context.dataset.datalabels && context.dataset.datalabels.display === true;
},
formatter: function(value, context) {
// Special handling for Overall Team Performance chart
if (‘distance-bars’ === ‘overall-team-performance’ && context.dataset.label === ‘Success Rate (SR)’) {
// Use the stored play count data
if (context.dataset.playCountData && context.dataset.playCountData[context.dataIndex]) {
return context.dataset.playCountData[context.dataIndex];
}
// Fallback to percentage if play count data not available
return Math.round(value * 100) + ‘%’;
}
// Handle bar charts with count data (play-type, quarter, down, etc.)
if (context.dataset.label && context.dataset.label.includes(‘ SR’) &&
(chartData.teamCounts || chartData.oppCounts)) {
// Find the first team SR dataset in the chart to determine team order
const allDatasets = context.chart.data.datasets;
const teamSRDataset = allDatasets.find(d => d.label && d.label.includes(‘ SR’) && !d.label.includes(‘NCAA’));
// If this is the first team’s SR dataset, use teamCounts
if (teamSRDataset && context.dataset.label === teamSRDataset.label && chartData.teamCounts) {
return chartData.teamCounts[context.dataIndex] || 0;
}
// Otherwise, use oppCounts for the second team
else if (chartData.oppCounts) {
return chartData.oppCounts[context.dataIndex] || 0;
}
}
// For player charts, show value only if > 0 (matches non-embedded behavior)
if (‘distance-bars’.includes(‘top-rushers’) || ‘distance-bars’.includes(‘top-passers’) || ‘distance-bars’.includes(‘top-receivers’)) {
// Hide data labels for zero or negative values, show actual value for positive values
return value > 0 ? value : null;
}
// For other charts, show values based on type
if (typeof value === ‘number’) {
// If value is between 0 and 1, treat as percentage
if (value >= 0 && value 0 ? ‘#26262660’ : ‘transparent’;
},
borderColor: function(context) {
const value = context.dataset.data[context.dataIndex];
return value > 0 ? ‘rgba(255, 255, 255, 0.2)’ : ‘transparent’;
},
borderRadius: 4,
align: ‘center’,
anchor: ‘center’
},
legend: ‘distance-bars’ === ‘win-probability’ ? {
display: false
} : ‘bar’ === ‘line’ ? {
position: ‘top’,
align: ‘start’,
labels: ‘distance-bars’.includes(‘play-map’) ? {
usePointStyle: true,
generateLabels: function(chart) {
// Call the original generateLabels to get default styling
const original = Chart.defaults.plugins.legend.labels.generateLabels;
const labels = original.call(this, chart);
// Filter and customize each label
const filteredLabels = labels.filter(label => {
return !label.text.includes(‘ {
const dataset = chart.data.datasets[label.datasetIndex];
if (dataset && dataset.label) {
if (dataset.label.includes(‘Rush’)) {
label.pointStyle = ‘circle’;
label.pointStyleWidth = 4;
label.fillStyle = ‘white’;
} else if (dataset.label.includes(‘Pass’)) {
label.pointStyle = ‘triangle’;
label.pointStyleWidth = 4;
label.fillStyle = ‘white’;
} else {
label.pointStyle = ‘rect’;
label.pointStyleWidth = 4;
label.fillStyle = ‘white’;
}
}
});
return filteredLabels;
},
boxWidth: 20,
padding: 12
} : {
usePointStyle: false,
boxWidth: 12,
boxHeight: 12,
padding: 12,
generateLabels: function(chart) {
const original = Chart.defaults.plugins.legend.labels.generateLabels;
const labels = original.call(this, chart);
// Filter out reference areas and ensure white fill
const filteredLabels = labels.filter(label => {
return !label.text.includes(‘NCAA Avg SR’) &&
!label.text.includes(’50/50′) &&
!label.text.includes(‘Quarters’);
});
// Ensure white fill for all line chart legend boxes
filteredLabels.forEach((label) => {
label.fillStyle = ‘white’;
});
return filteredLabels;
}
}
} : {
position: ‘top’,
align: ‘start’,
labels: {
usePointStyle: false,
boxWidth: 12,
boxHeight: 12,
padding: 12,
filter: function(legendItem, chartData) {
return !legendItem.text.includes(‘NCAA Avg SR’) &&
!legendItem.text.includes(‘Quarters’) &&
!legendItem.text.includes(’50/50′);
},
generateLabels: function(chart) {
const data = chart.data;
if (data.datasets.length) {
return data.datasets.map((dataset, i) => {
// Handle backgroundColor arrays (like in Overall Team Performance chart)
let fillColor = dataset.backgroundColor;
if (dataset.label === ‘# Plays’) {
fillColor = ‘white’;
} else if (Array.isArray(dataset.backgroundColor)) {
// For datasets with backgroundColor arrays, use the first color for legend
fillColor = dataset.backgroundColor[0];
}
return {
text: dataset.label,
fillStyle: fillColor,
strokeStyle: dataset.label === ‘# Plays’ ? ‘#666’ : dataset.borderColor,
lineWidth: dataset.label === ‘# Plays’ ? 1 : dataset.borderWidth,
hidden: !chart.isDatasetVisible(i),
datasetIndex: i
};
}).filter((item, index) => {
// Apply the same filter logic as above
const dataset = chart.data.datasets[index];
if (!dataset || !dataset.data) return false;
if (dataset.label === ‘# Plays’) return true; // Always show # Plays
if (dataset.label && (dataset.label.includes(‘NCAA Avg SR’) ||
dataset.label.includes(‘Quarters’) ||
dataset.label.includes(’50/50′))) return false;
return dataset.data.some((value) => value > 0);
});
}
return [];
}
}
},
tooltip: ‘distance-bars’ === ‘win-probability’ ? {
mode: ‘index’,
intersect: false,
callbacks: {
title: function(tooltipItems) {
if (tooltipItems && tooltipItems[0]) {
return ‘Play ‘ + (tooltipItems[0].dataIndex + 1);
}
return ”;
},
label: function(context) {
const selectedTeamWinProb = context.parsed.y;
const opponentWinProb = 100 – selectedTeamWinProb;
const selectedTeam = context.dataset.selectedTeam || ‘Team’;
const opponentTeam = context.dataset.opponentTeam || ‘Opponent’;
return [
selectedTeam + ‘: ‘ + selectedTeamWinProb.toFixed(1) + ‘%’,
opponentTeam + ‘: ‘ + opponentWinProb.toFixed(1) + ‘%’
];
},
afterLabel: function(context) {
if (context.dataset.playTexts && context.dataset.playTexts[context.dataIndex]) {
return ‘n’ + context.dataset.playTexts[context.dataIndex];
}
return ”;
}
}
} : {
filter: function(tooltipItem) {
if (‘distance-bars’.includes(‘play-map’)) {
return !tooltipItem.dataset.label.includes(‘< 0’) &&
!tooltipItem.dataset.label.includes(‘Quarters’) &&
!tooltipItem.dataset.label.includes(‘Drive’);
}
return !tooltipItem.dataset.label.includes(‘NCAA Avg SR’) &&
!tooltipItem.dataset.label.includes(’50/50′) &&
!tooltipItem.dataset.label.includes(‘ ds.label === ‘Win Probability’);
if (wpDataset && wpDataset.segmentColors) {
wpDataset.segment = {
borderColor: function(ctx) {
// Use p1DataIndex (ending point) so the line inherits the destination color
// This makes momentum shifts more visually intuitive
const index = ctx.p1DataIndex;
if (index !== undefined && wpDataset.segmentColors[index]) {
return wpDataset.segmentColors[index];
}
return wpDataset.borderColor || ‘#8B0000’;
}
};
}
}
// Initialize the chart
const ctx = canvas.getContext(‘2d’);
const chart = new Chart(ctx, {
type: ‘bar’,
data: chartData,
options: chartOptions
});
// Store reference to prevent re-initialization
canvas.chartInstance = chart;
console.log(‘CFB Chart initialized successfully’);
} catch (error) {
console.error(‘Error initializing CFB chart:’, error);
// Fallback: show error message in canvas container
const container = document.getElementById(‘cfb-chart-1765138252698-f721wlw1f’).parentNode;
if (container) {
container.innerHTML = ‘
‘;
}
}
}
// Start loading scripts sequentially
function startLoading() {
// First, check if scripts are already loaded (multiple embeds on same page)
if (typeof Chart !== ‘undefined’ && typeof ChartDataLabels !== ‘undefined’) {
initChart();
return;
}
// Load Chart.js first
if (typeof Chart === ‘undefined’) {
loadScript(‘https://cdn.jsdelivr.net/npm/chart.js@3.9.1/dist/chart.min.js’, function() {
// Then load ChartDataLabels
if (typeof ChartDataLabels === ‘undefined’) {
loadScript(‘https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2.2.0’, function() {
initChart();
});
} else {
initChart();
}
});
} else if (typeof ChartDataLabels === ‘undefined’) {
// Chart.js loaded but not ChartDataLabels
loadScript(‘https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2.2.0’, function() {
initChart();
});
} else {
initChart();
}
}
// Initialize when DOM is ready
if (document.readyState === ‘loading’) {
document.addEventListener(‘DOMContentLoaded’, startLoading);
} else {
startLoading();
}
})();
Whoa, actually, this one is weird. It’s nothing new that Georgia converts well from short distance — they tend to, though their loss in Athens was an exception — but putting a 90% SR on any metric category is remarkable, but that conversion rate is just crazy.
And it’s even weirder that the Dawgs actually underperformed Alabama on early downs (both SR and XR). Is this short yardage conversion gap — Dawgs almost perfect, Tide almost a dead body — the ‘real’ key in how this turned into an unexpected blowout? Maybe so.
And other oddities
I don’t want to talk about the rusher’s chart, because it’s sad and I don’t want to be sad. Do you want to be sad? Didn’t think so.
I’ll call out some intrigue from the other player charts, though.
.cfb-chart-embed-cfb-chart-1765138264035-fvamqze53 {
font-family: -apple-system, BlinkMacSystemFont, ‘Segoe UI’, ‘Roboto’, sans-serif;
margin: 0;
padding: 0;
}
.cfb-chart-embed-cfb-chart-1765138264035-fvamqze53 .chart-container {
background: white;
border-radius: 12px;
border: 1px solid #e5e5e5;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
overflow: hidden;
}
.cfb-chart-embed-cfb-chart-1765138264035-fvamqze53 .chart-header {
padding: 18px 24px 14px;
border-bottom: 1px solid #e5e5e5;
background: white;
}
.cfb-chart-embed-cfb-chart-1765138264035-fvamqze53 .chart-title {
font-size: 18px;
font-weight: 600;
color: #171717;
margin: 0;
}
.cfb-chart-embed-cfb-chart-1765138264035-fvamqze53 .chart-subtitle {
font-size: 11px;
font-weight: 400;
color: #737373;
margin: 4px 0 0 0;
}
.cfb-chart-embed-cfb-chart-1765138264035-fvamqze53 .chart-content {
padding: 20px 24px 24px !important;
}
.cfb-chart-embed-cfb-chart-1765138264035-fvamqze53 .chart-content.top-passers { height: 280px !important; }
@media (max-width: 640px) {
.cfb-chart-embed-cfb-chart-1765138264035-fvamqze53 .chart-content {
padding: 12px 16px 20px !important;
}
.cfb-chart-embed-cfb-chart-1765138264035-fvamqze53 .chart-header {
padding: 12px 16px 12px !important;
}
.cfb-chart-embed-cfb-chart-1765138264035-fvamqze53 .embed-footer-top {
padding: 8px 12px !important;
}
.cfb-chart-embed-cfb-chart-1765138264035-fvamqze53 .data-definitions {
padding: 12px !important;
}
}
.cfb-chart-embed-cfb-chart-1765138264035-fvamqze53 .embed-footer {
border-top: 1px solid #e5e5e5;
font-size: 12px;
color: #737373;
}
.cfb-chart-embed-cfb-chart-1765138264035-fvamqze53 .embed-footer-top {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 16px;
}
.cfb-chart-embed-cfb-chart-1765138264035-fvamqze53 .embed-footer-link {
color: #737373;
text-decoration: none;
font-weight: 500;
}
.cfb-chart-embed-cfb-chart-1765138264035-fvamqze53 .embed-footer-link:hover {
color: #525252;
text-decoration: underline;
}
.cfb-chart-embed-cfb-chart-1765138264035-fvamqze53 .data-definitions-toggle {
background: none;
border: none;
color: #737373;
font-size: 12px;
font-weight: 500;
cursor: pointer;
display: flex;
align-items: center;
gap: 4px;
padding: 0;
}
.cfb-chart-embed-cfb-chart-1765138264035-fvamqze53 .data-definitions-toggle:hover {
color: #525252;
}
.cfb-chart-embed-cfb-chart-1765138264035-fvamqze53 .caret {
transition: transform 0.2s ease;
font-size: 10px;
}
.cfb-chart-embed-cfb-chart-1765138264035-fvamqze53 .caret.expanded {
transform: rotate(180deg);
}
.cfb-chart-embed-cfb-chart-1765138264035-fvamqze53 .data-definitions {
display: none;
padding: 16px;
background: #fafafa;
border-top: 1px solid #e5e5e5;
font-size: 12px;
line-height: 1.4;
}
.cfb-chart-embed-cfb-chart-1765138264035-fvamqze53 .data-definitions.expanded {
display: block;
}
.cfb-chart-embed-cfb-chart-1765138264035-fvamqze53 .data-definitions ul {
margin: 0;
padding-left: 0;
list-style: none;
}
.cfb-chart-embed-cfb-chart-1765138264035-fvamqze53 .data-definitions li {
margin-bottom: 4px;
}
Top passers
Alabama vs. Georgia • Dec 6, 2025
- Based roughly on the SP+ analytic system
- Successful play: Gains enough needed yards (50% 1st down, 70% on 2nd, 100% on 3rd/4th)
- Success Rate (SR): Percentage of plays that were successful
- Explosiveness Rate (XR): Percentage of plays gaining 15+ yards
// Toggle data definitions accordion – unique function per embed
function toggleDefinitions_cfb_chart_1765138264035_fvamqze53() {
const definitions = document.getElementById(‘dataDefinitions_cfb-chart-1765138264035-fvamqze53’);
const caret = document.getElementById(‘caret_cfb-chart-1765138264035-fvamqze53’);
if (definitions.classList.contains(‘expanded’)) {
definitions.classList.remove(‘expanded’);
caret.classList.remove(‘expanded’);
} else {
definitions.classList.add(‘expanded’);
caret.classList.add(‘expanded’);
}
}
// Sequential script loading for better reliability
(function() {
‘use strict’;
let retryCount = 0;
const maxRetries = 50; // 5 seconds total
// Load scripts sequentially
function loadScript(url, callback) {
const script = document.createElement(‘script’);
script.src = url;
script.onload = callback;
script.onerror = function() {
console.error(‘Failed to load script:’, url);
showError(‘Failed to load required chart library’);
};
document.head.appendChild(script);
}
function showError(message) {
const canvas = document.getElementById(‘cfb-chart-1765138264035-fvamqze53’);
if (canvas && canvas.parentNode) {
canvas.parentNode.innerHTML = ‘
‘;
}
}
function initChart() {
retryCount++;
// Check if Chart.js is available
if (typeof Chart === ‘undefined’) {
if (retryCount >= maxRetries) {
showError(‘Chart library failed to load. Please refresh the page.’);
return;
}
setTimeout(initChart, 100);
return;
}
// Check if datalabels plugin is available
if (typeof ChartDataLabels === ‘undefined’) {
if (retryCount >= maxRetries) {
showError(‘Chart plugin failed to load. Please refresh the page.’);
return;
}
setTimeout(initChart, 100);
return;
}
// Check if canvas element exists
const canvas = document.getElementById(‘cfb-chart-1765138264035-fvamqze53’);
if (!canvas) {
console.warn(‘Canvas element not found yet, retrying…’);
setTimeout(initChart, 100);
return;
}
// Prevent multiple chart instances
if (canvas.chartInstance) {
console.log(‘Chart already initialized’);
return;
}
try {
// Register the datalabels plugin
Chart.register(ChartDataLabels);
// Embed actual chart data directly
const chartData = {
“labels”: [
“T.Simpson”,
“G.Stockton”
],
“datasets”: [
{
“label”: “Explosive”,
“data”: [
5,
3
],
“backgroundColor”: [
“#3c000cCC”,
“#630013CC”
],
“borderColor”: “#374151”,
“borderWidth”: 1
},
{
“label”: “Successful”,
“data”: [
8,
8
],
“backgroundColor”: [
“rgba(175, 40, 60, 0.8)”,
“rgba(200, 16, 46, 0.8)”
],
“borderColor”: “#374151”,
“borderWidth”: 1
},
{
“label”: “Other catches”,
“data”: [
7,
9
],
“backgroundColor”: [
“rgba(245, 229, 233, 0.8)”,
“rgba(248, 228, 233, 0.8)”
],
“borderColor”: “#374151”,
“borderWidth”: 1
},
{
“label”: “Incompletes”,
“data”: [
19,
6
],
“backgroundColor”: “#FFFFFF”,
“borderColor”: “#374151”,
“borderWidth”: 1
},
{
“label”: “Interceptions”,
“data”: [
1,
0
],
“backgroundColor”: “#4B5563”,
“borderColor”: “#374151”,
“borderWidth”: 1
}
],
“currentParams”: {
“year”: 2025,
“week”: 15,
“seasonType”: “regular”,
“team”: “Alabama”,
“gameId”: “401777351”
},
“teamFilter”: “both”
};
// Chart options (WordPress-safe)
const chartOptions = {
responsive: true,
maintainAspectRatio: false,
animation: {
duration: 1 // Minimal animation to trigger layout calculation (fixes label positioning)
},
elements: ‘bar’ === ‘line’ ? ‘top-passers’.includes(‘play-map’) ? {
line: {
tension: 0,
borderWidth: 0
}
} : ‘top-passers’ === ‘win-probability’ ? {
line: {
tension: 0.15,
borderWidth: 2.2,
fill: false
},
point: {
pointRadius: 0,
pointHoverRadius: 4
}
} : {
line: {
tension: 0.25,
borderWidth: 2.2
},
point: {
pointRadius: ‘top-passers’.includes(‘team-lines’) ? 0 : undefined
}
} : {},
plugins: {
datalabels: {
display: function(context) {
// Suppress data labels on line charts
if (‘bar’ === ‘line’) {
return false;
}
return context.dataset.datalabels && context.dataset.datalabels.display === true;
},
formatter: function(value, context) {
// Special handling for Overall Team Performance chart
if (‘top-passers’ === ‘overall-team-performance’ && context.dataset.label === ‘Success Rate (SR)’) {
// Use the stored play count data
if (context.dataset.playCountData && context.dataset.playCountData[context.dataIndex]) {
return context.dataset.playCountData[context.dataIndex];
}
// Fallback to percentage if play count data not available
return Math.round(value * 100) + ‘%’;
}
// Handle bar charts with count data (play-type, quarter, down, etc.)
if (context.dataset.label && context.dataset.label.includes(‘ SR’) &&
(chartData.teamCounts || chartData.oppCounts)) {
// Find the first team SR dataset in the chart to determine team order
const allDatasets = context.chart.data.datasets;
const teamSRDataset = allDatasets.find(d => d.label && d.label.includes(‘ SR’) && !d.label.includes(‘NCAA’));
// If this is the first team’s SR dataset, use teamCounts
if (teamSRDataset && context.dataset.label === teamSRDataset.label && chartData.teamCounts) {
return chartData.teamCounts[context.dataIndex] || 0;
}
// Otherwise, use oppCounts for the second team
else if (chartData.oppCounts) {
return chartData.oppCounts[context.dataIndex] || 0;
}
}
// For player charts, show value only if > 0 (matches non-embedded behavior)
if (‘top-passers’.includes(‘top-rushers’) || ‘top-passers’.includes(‘top-passers’) || ‘top-passers’.includes(‘top-receivers’)) {
// Hide data labels for zero or negative values, show actual value for positive values
return value > 0 ? value : null;
}
// For other charts, show values based on type
if (typeof value === ‘number’) {
// If value is between 0 and 1, treat as percentage
if (value >= 0 && value 0 ? ‘#26262660’ : ‘transparent’;
},
borderColor: function(context) {
const value = context.dataset.data[context.dataIndex];
return value > 0 ? ‘rgba(255, 255, 255, 0.2)’ : ‘transparent’;
},
borderRadius: 4,
align: ‘center’,
anchor: ‘center’
},
legend: ‘top-passers’ === ‘win-probability’ ? {
display: false
} : ‘bar’ === ‘line’ ? {
position: ‘top’,
align: ‘start’,
labels: ‘top-passers’.includes(‘play-map’) ? {
usePointStyle: true,
generateLabels: function(chart) {
// Call the original generateLabels to get default styling
const original = Chart.defaults.plugins.legend.labels.generateLabels;
const labels = original.call(this, chart);
// Filter and customize each label
const filteredLabels = labels.filter(label => {
return !label.text.includes(‘ {
const dataset = chart.data.datasets[label.datasetIndex];
if (dataset && dataset.label) {
if (dataset.label.includes(‘Rush’)) {
label.pointStyle = ‘circle’;
label.pointStyleWidth = 4;
label.fillStyle = ‘white’;
} else if (dataset.label.includes(‘Pass’)) {
label.pointStyle = ‘triangle’;
label.pointStyleWidth = 4;
label.fillStyle = ‘white’;
} else {
label.pointStyle = ‘rect’;
label.pointStyleWidth = 4;
label.fillStyle = ‘white’;
}
}
});
return filteredLabels;
},
boxWidth: 20,
padding: 12
} : {
usePointStyle: false,
boxWidth: 12,
boxHeight: 12,
padding: 12,
generateLabels: function(chart) {
const original = Chart.defaults.plugins.legend.labels.generateLabels;
const labels = original.call(this, chart);
// Filter out reference areas and ensure white fill
const filteredLabels = labels.filter(label => {
return !label.text.includes(‘NCAA Avg SR’) &&
!label.text.includes(’50/50′) &&
!label.text.includes(‘Quarters’);
});
// Ensure white fill for all line chart legend boxes
filteredLabels.forEach((label) => {
label.fillStyle = ‘white’;
});
return filteredLabels;
}
}
} : {
position: ‘top’,
align: ‘start’,
labels: {
usePointStyle: false,
boxWidth: 12,
boxHeight: 12,
padding: 12,
filter: function(legendItem, chartData) {
return !legendItem.text.includes(‘NCAA Avg SR’) &&
!legendItem.text.includes(‘Quarters’) &&
!legendItem.text.includes(’50/50′);
},
generateLabels: function(chart) {
const data = chart.data;
if (data.datasets.length) {
return data.datasets.map((dataset, i) => {
// Handle backgroundColor arrays (like in Overall Team Performance chart)
let fillColor = dataset.backgroundColor;
if (dataset.label === ‘# Plays’) {
fillColor = ‘white’;
} else if (Array.isArray(dataset.backgroundColor)) {
// For datasets with backgroundColor arrays, use the first color for legend
fillColor = dataset.backgroundColor[0];
}
return {
text: dataset.label,
fillStyle: fillColor,
strokeStyle: dataset.label === ‘# Plays’ ? ‘#666’ : dataset.borderColor,
lineWidth: dataset.label === ‘# Plays’ ? 1 : dataset.borderWidth,
hidden: !chart.isDatasetVisible(i),
datasetIndex: i
};
}).filter((item, index) => {
// Apply the same filter logic as above
const dataset = chart.data.datasets[index];
if (!dataset || !dataset.data) return false;
if (dataset.label === ‘# Plays’) return true; // Always show # Plays
if (dataset.label && (dataset.label.includes(‘NCAA Avg SR’) ||
dataset.label.includes(‘Quarters’) ||
dataset.label.includes(’50/50′))) return false;
return dataset.data.some((value) => value > 0);
});
}
return [];
}
}
},
tooltip: ‘top-passers’ === ‘win-probability’ ? {
mode: ‘index’,
intersect: false,
callbacks: {
title: function(tooltipItems) {
if (tooltipItems && tooltipItems[0]) {
return ‘Play ‘ + (tooltipItems[0].dataIndex + 1);
}
return ”;
},
label: function(context) {
const selectedTeamWinProb = context.parsed.y;
const opponentWinProb = 100 – selectedTeamWinProb;
const selectedTeam = context.dataset.selectedTeam || ‘Team’;
const opponentTeam = context.dataset.opponentTeam || ‘Opponent’;
return [
selectedTeam + ‘: ‘ + selectedTeamWinProb.toFixed(1) + ‘%’,
opponentTeam + ‘: ‘ + opponentWinProb.toFixed(1) + ‘%’
];
},
afterLabel: function(context) {
if (context.dataset.playTexts && context.dataset.playTexts[context.dataIndex]) {
return ‘n’ + context.dataset.playTexts[context.dataIndex];
}
return ”;
}
}
} : {
filter: function(tooltipItem) {
if (‘top-passers’.includes(‘play-map’)) {
return !tooltipItem.dataset.label.includes(‘< 0’) &&
!tooltipItem.dataset.label.includes(‘Quarters’) &&
!tooltipItem.dataset.label.includes(‘Drive’);
}
return !tooltipItem.dataset.label.includes(‘NCAA Avg SR’) &&
!tooltipItem.dataset.label.includes(’50/50′) &&
!tooltipItem.dataset.label.includes(‘ ds.label === ‘Win Probability’);
if (wpDataset && wpDataset.segmentColors) {
wpDataset.segment = {
borderColor: function(ctx) {
// Use p1DataIndex (ending point) so the line inherits the destination color
// This makes momentum shifts more visually intuitive
const index = ctx.p1DataIndex;
if (index !== undefined && wpDataset.segmentColors[index]) {
return wpDataset.segmentColors[index];
}
return wpDataset.borderColor || ‘#8B0000’;
}
};
}
}
// Initialize the chart
const ctx = canvas.getContext(‘2d’);
const chart = new Chart(ctx, {
type: ‘bar’,
data: chartData,
options: chartOptions
});
// Store reference to prevent re-initialization
canvas.chartInstance = chart;
console.log(‘CFB Chart initialized successfully’);
} catch (error) {
console.error(‘Error initializing CFB chart:’, error);
// Fallback: show error message in canvas container
const container = document.getElementById(‘cfb-chart-1765138264035-fvamqze53’).parentNode;
if (container) {
container.innerHTML = ‘
‘;
}
}
}
// Start loading scripts sequentially
function startLoading() {
// First, check if scripts are already loaded (multiple embeds on same page)
if (typeof Chart !== ‘undefined’ && typeof ChartDataLabels !== ‘undefined’) {
initChart();
return;
}
// Load Chart.js first
if (typeof Chart === ‘undefined’) {
loadScript(‘https://cdn.jsdelivr.net/npm/chart.js@3.9.1/dist/chart.min.js’, function() {
// Then load ChartDataLabels
if (typeof ChartDataLabels === ‘undefined’) {
loadScript(‘https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2.2.0’, function() {
initChart();
});
} else {
initChart();
}
});
} else if (typeof ChartDataLabels === ‘undefined’) {
// Chart.js loaded but not ChartDataLabels
loadScript(‘https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2.2.0’, function() {
initChart();
});
} else {
initChart();
}
}
// Initialize when DOM is ready
if (document.readyState === ‘loading’) {
document.addEventListener(‘DOMContentLoaded’, startLoading);
} else {
startLoading();
}
})();
Yeah, so Ty Simpson technically did complete more explosive passes and total successful passes than Gunner Stockton. Great job, Ty! (But, honestly, the defense held Stockton QB to a not-great line here).
Problem is, Ty threw a lot more balls than Gunner did, with a whopping 19 incompletions and 1 interception capping the end of his line. Ugh.
.cfb-chart-embed-cfb-chart-1765138274841-8r24cvs0o {
font-family: -apple-system, BlinkMacSystemFont, ‘Segoe UI’, ‘Roboto’, sans-serif;
margin: 0;
padding: 0;
}
.cfb-chart-embed-cfb-chart-1765138274841-8r24cvs0o .chart-container {
background: white;
border-radius: 12px;
border: 1px solid #e5e5e5;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
overflow: hidden;
}
.cfb-chart-embed-cfb-chart-1765138274841-8r24cvs0o .chart-header {
padding: 18px 24px 14px;
border-bottom: 1px solid #e5e5e5;
background: white;
}
.cfb-chart-embed-cfb-chart-1765138274841-8r24cvs0o .chart-title {
font-size: 18px;
font-weight: 600;
color: #171717;
margin: 0;
}
.cfb-chart-embed-cfb-chart-1765138274841-8r24cvs0o .chart-subtitle {
font-size: 11px;
font-weight: 400;
color: #737373;
margin: 4px 0 0 0;
}
.cfb-chart-embed-cfb-chart-1765138274841-8r24cvs0o .chart-content {
padding: 20px 24px 24px !important;
}
.cfb-chart-embed-cfb-chart-1765138274841-8r24cvs0o .chart-content.top-receivers { height: 420px; }
@media (max-width: 640px) {
.cfb-chart-embed-cfb-chart-1765138274841-8r24cvs0o .chart-content {
padding: 12px 16px 20px !important;
}
.cfb-chart-embed-cfb-chart-1765138274841-8r24cvs0o .chart-header {
padding: 12px 16px 12px !important;
}
.cfb-chart-embed-cfb-chart-1765138274841-8r24cvs0o .embed-footer-top {
padding: 8px 12px !important;
}
.cfb-chart-embed-cfb-chart-1765138274841-8r24cvs0o .data-definitions {
padding: 12px !important;
}
}
.cfb-chart-embed-cfb-chart-1765138274841-8r24cvs0o .embed-footer {
border-top: 1px solid #e5e5e5;
font-size: 12px;
color: #737373;
}
.cfb-chart-embed-cfb-chart-1765138274841-8r24cvs0o .embed-footer-top {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 16px;
}
.cfb-chart-embed-cfb-chart-1765138274841-8r24cvs0o .embed-footer-link {
color: #737373;
text-decoration: none;
font-weight: 500;
}
.cfb-chart-embed-cfb-chart-1765138274841-8r24cvs0o .embed-footer-link:hover {
color: #525252;
text-decoration: underline;
}
.cfb-chart-embed-cfb-chart-1765138274841-8r24cvs0o .data-definitions-toggle {
background: none;
border: none;
color: #737373;
font-size: 12px;
font-weight: 500;
cursor: pointer;
display: flex;
align-items: center;
gap: 4px;
padding: 0;
}
.cfb-chart-embed-cfb-chart-1765138274841-8r24cvs0o .data-definitions-toggle:hover {
color: #525252;
}
.cfb-chart-embed-cfb-chart-1765138274841-8r24cvs0o .caret {
transition: transform 0.2s ease;
font-size: 10px;
}
.cfb-chart-embed-cfb-chart-1765138274841-8r24cvs0o .caret.expanded {
transform: rotate(180deg);
}
.cfb-chart-embed-cfb-chart-1765138274841-8r24cvs0o .data-definitions {
display: none;
padding: 16px;
background: #fafafa;
border-top: 1px solid #e5e5e5;
font-size: 12px;
line-height: 1.4;
}
.cfb-chart-embed-cfb-chart-1765138274841-8r24cvs0o .data-definitions.expanded {
display: block;
}
.cfb-chart-embed-cfb-chart-1765138274841-8r24cvs0o .data-definitions ul {
margin: 0;
padding-left: 0;
list-style: none;
}
.cfb-chart-embed-cfb-chart-1765138274841-8r24cvs0o .data-definitions li {
margin-bottom: 4px;
}
Top receivers
Alabama vs. Georgia • Dec 6, 2025
- Based roughly on the SP+ analytic system
- Successful play: Gains enough needed yards (50% 1st down, 70% on 2nd, 100% on 3rd/4th)
- Success Rate (SR): Percentage of plays that were successful
- Explosiveness Rate (XR): Percentage of plays gaining 15+ yards
// Toggle data definitions accordion – unique function per embed
function toggleDefinitions_cfb_chart_1765138274841_8r24cvs0o() {
const definitions = document.getElementById(‘dataDefinitions_cfb-chart-1765138274841-8r24cvs0o’);
const caret = document.getElementById(‘caret_cfb-chart-1765138274841-8r24cvs0o’);
if (definitions.classList.contains(‘expanded’)) {
definitions.classList.remove(‘expanded’);
caret.classList.remove(‘expanded’);
} else {
definitions.classList.add(‘expanded’);
caret.classList.add(‘expanded’);
}
}
// Sequential script loading for better reliability
(function() {
‘use strict’;
let retryCount = 0;
const maxRetries = 50; // 5 seconds total
// Load scripts sequentially
function loadScript(url, callback) {
const script = document.createElement(‘script’);
script.src = url;
script.onload = callback;
script.onerror = function() {
console.error(‘Failed to load script:’, url);
showError(‘Failed to load required chart library’);
};
document.head.appendChild(script);
}
function showError(message) {
const canvas = document.getElementById(‘cfb-chart-1765138274841-8r24cvs0o’);
if (canvas && canvas.parentNode) {
canvas.parentNode.innerHTML = ‘
‘;
}
}
function initChart() {
retryCount++;
// Check if Chart.js is available
if (typeof Chart === ‘undefined’) {
if (retryCount >= maxRetries) {
showError(‘Chart library failed to load. Please refresh the page.’);
return;
}
setTimeout(initChart, 100);
return;
}
// Check if datalabels plugin is available
if (typeof ChartDataLabels === ‘undefined’) {
if (retryCount >= maxRetries) {
showError(‘Chart plugin failed to load. Please refresh the page.’);
return;
}
setTimeout(initChart, 100);
return;
}
// Check if canvas element exists
const canvas = document.getElementById(‘cfb-chart-1765138274841-8r24cvs0o’);
if (!canvas) {
console.warn(‘Canvas element not found yet, retrying…’);
setTimeout(initChart, 100);
return;
}
// Prevent multiple chart instances
if (canvas.chartInstance) {
console.log(‘Chart already initialized’);
return;
}
try {
// Register the datalabels plugin
Chart.register(ChartDataLabels);
// Embed actual chart data directly
const chartData = {
“labels”: [
“G.Bernard”,
“D.Hill”,
“K.Edwards”,
“R.Williams”,
“M.Pritchett”,
“I.Horton”,
“L.Brooks”
],
“datasets”: [
{
“label”: “Explosive catches”,
“data”: [
3,
0,
1,
1,
0,
0,
0
],
“backgroundColor”: [
“#3c000cCC”,
“#3c000cCC”,
“#3c000cCC”,
“#3c000cCC”,
“#3c000cCC”,
“#3c000cCC”,
“#3c000cCC”
],
“borderColor”: “#374151”,
“borderWidth”: 1
},
{
“label”: “Successful catches”,
“data”: [
2,
1,
2,
1,
1,
1,
0
],
“backgroundColor”: [
“rgba(175, 40, 60, 0.8)”,
“rgba(175, 40, 60, 0.8)”,
“rgba(175, 40, 60, 0.8)”,
“rgba(175, 40, 60, 0.8)”,
“rgba(175, 40, 60, 0.8)”,
“rgba(175, 40, 60, 0.8)”,
“rgba(175, 40, 60, 0.8)”
],
“borderColor”: “#374151”,
“borderWidth”: 1
},
{
“label”: “Other catches”,
“data”: [
1,
4,
0,
0,
1,
0,
1
],
“backgroundColor”: [
“rgba(245, 229, 233, 0.8)”,
“rgba(245, 229, 233, 0.8)”,
“rgba(245, 229, 233, 0.8)”,
“rgba(245, 229, 233, 0.8)”,
“rgba(245, 229, 233, 0.8)”,
“rgba(245, 229, 233, 0.8)”,
“rgba(245, 229, 233, 0.8)”
],
“borderColor”: “#374151”,
“borderWidth”: 1
}
],
“currentParams”: {
“year”: 2025,
“week”: 15,
“seasonType”: “regular”,
“team”: “Alabama”,
“gameId”: “401777351”
},
“teamFilter”: “Alabama”
};
// Chart options (WordPress-safe)
const chartOptions = {
responsive: true,
maintainAspectRatio: false,
animation: {
duration: 1 // Minimal animation to trigger layout calculation (fixes label positioning)
},
elements: ‘bar’ === ‘line’ ? ‘top-receivers’.includes(‘play-map’) ? {
line: {
tension: 0,
borderWidth: 0
}
} : ‘top-receivers’ === ‘win-probability’ ? {
line: {
tension: 0.15,
borderWidth: 2.2,
fill: false
},
point: {
pointRadius: 0,
pointHoverRadius: 4
}
} : {
line: {
tension: 0.25,
borderWidth: 2.2
},
point: {
pointRadius: ‘top-receivers’.includes(‘team-lines’) ? 0 : undefined
}
} : {},
plugins: {
datalabels: {
display: function(context) {
// Suppress data labels on line charts
if (‘bar’ === ‘line’) {
return false;
}
return context.dataset.datalabels && context.dataset.datalabels.display === true;
},
formatter: function(value, context) {
// Special handling for Overall Team Performance chart
if (‘top-receivers’ === ‘overall-team-performance’ && context.dataset.label === ‘Success Rate (SR)’) {
// Use the stored play count data
if (context.dataset.playCountData && context.dataset.playCountData[context.dataIndex]) {
return context.dataset.playCountData[context.dataIndex];
}
// Fallback to percentage if play count data not available
return Math.round(value * 100) + ‘%’;
}
// Handle bar charts with count data (play-type, quarter, down, etc.)
if (context.dataset.label && context.dataset.label.includes(‘ SR’) &&
(chartData.teamCounts || chartData.oppCounts)) {
// Find the first team SR dataset in the chart to determine team order
const allDatasets = context.chart.data.datasets;
const teamSRDataset = allDatasets.find(d => d.label && d.label.includes(‘ SR’) && !d.label.includes(‘NCAA’));
// If this is the first team’s SR dataset, use teamCounts
if (teamSRDataset && context.dataset.label === teamSRDataset.label && chartData.teamCounts) {
return chartData.teamCounts[context.dataIndex] || 0;
}
// Otherwise, use oppCounts for the second team
else if (chartData.oppCounts) {
return chartData.oppCounts[context.dataIndex] || 0;
}
}
// For player charts, show value only if > 0 (matches non-embedded behavior)
if (‘top-receivers’.includes(‘top-rushers’) || ‘top-receivers’.includes(‘top-passers’) || ‘top-receivers’.includes(‘top-receivers’)) {
// Hide data labels for zero or negative values, show actual value for positive values
return value > 0 ? value : null;
}
// For other charts, show values based on type
if (typeof value === ‘number’) {
// If value is between 0 and 1, treat as percentage
if (value >= 0 && value 0 ? ‘#26262660’ : ‘transparent’;
},
borderColor: function(context) {
const value = context.dataset.data[context.dataIndex];
return value > 0 ? ‘rgba(255, 255, 255, 0.2)’ : ‘transparent’;
},
borderRadius: 4,
align: ‘center’,
anchor: ‘center’
},
legend: ‘top-receivers’ === ‘win-probability’ ? {
display: false
} : ‘bar’ === ‘line’ ? {
position: ‘top’,
align: ‘start’,
labels: ‘top-receivers’.includes(‘play-map’) ? {
usePointStyle: true,
generateLabels: function(chart) {
// Call the original generateLabels to get default styling
const original = Chart.defaults.plugins.legend.labels.generateLabels;
const labels = original.call(this, chart);
// Filter and customize each label
const filteredLabels = labels.filter(label => {
return !label.text.includes(‘ {
const dataset = chart.data.datasets[label.datasetIndex];
if (dataset && dataset.label) {
if (dataset.label.includes(‘Rush’)) {
label.pointStyle = ‘circle’;
label.pointStyleWidth = 4;
label.fillStyle = ‘white’;
} else if (dataset.label.includes(‘Pass’)) {
label.pointStyle = ‘triangle’;
label.pointStyleWidth = 4;
label.fillStyle = ‘white’;
} else {
label.pointStyle = ‘rect’;
label.pointStyleWidth = 4;
label.fillStyle = ‘white’;
}
}
});
return filteredLabels;
},
boxWidth: 20,
padding: 12
} : {
usePointStyle: false,
boxWidth: 12,
boxHeight: 12,
padding: 12,
generateLabels: function(chart) {
const original = Chart.defaults.plugins.legend.labels.generateLabels;
const labels = original.call(this, chart);
// Filter out reference areas and ensure white fill
const filteredLabels = labels.filter(label => {
return !label.text.includes(‘NCAA Avg SR’) &&
!label.text.includes(’50/50′) &&
!label.text.includes(‘Quarters’);
});
// Ensure white fill for all line chart legend boxes
filteredLabels.forEach((label) => {
label.fillStyle = ‘white’;
});
return filteredLabels;
}
}
} : {
position: ‘top’,
align: ‘start’,
labels: {
usePointStyle: false,
boxWidth: 12,
boxHeight: 12,
padding: 12,
filter: function(legendItem, chartData) {
return !legendItem.text.includes(‘NCAA Avg SR’) &&
!legendItem.text.includes(‘Quarters’) &&
!legendItem.text.includes(’50/50′);
},
generateLabels: function(chart) {
const data = chart.data;
if (data.datasets.length) {
return data.datasets.map((dataset, i) => {
// Handle backgroundColor arrays (like in Overall Team Performance chart)
let fillColor = dataset.backgroundColor;
if (dataset.label === ‘# Plays’) {
fillColor = ‘white’;
} else if (Array.isArray(dataset.backgroundColor)) {
// For datasets with backgroundColor arrays, use the first color for legend
fillColor = dataset.backgroundColor[0];
}
return {
text: dataset.label,
fillStyle: fillColor,
strokeStyle: dataset.label === ‘# Plays’ ? ‘#666’ : dataset.borderColor,
lineWidth: dataset.label === ‘# Plays’ ? 1 : dataset.borderWidth,
hidden: !chart.isDatasetVisible(i),
datasetIndex: i
};
}).filter((item, index) => {
// Apply the same filter logic as above
const dataset = chart.data.datasets[index];
if (!dataset || !dataset.data) return false;
if (dataset.label === ‘# Plays’) return true; // Always show # Plays
if (dataset.label && (dataset.label.includes(‘NCAA Avg SR’) ||
dataset.label.includes(‘Quarters’) ||
dataset.label.includes(’50/50′))) return false;
return dataset.data.some((value) => value > 0);
});
}
return [];
}
}
},
tooltip: ‘top-receivers’ === ‘win-probability’ ? {
mode: ‘index’,
intersect: false,
callbacks: {
title: function(tooltipItems) {
if (tooltipItems && tooltipItems[0]) {
return ‘Play ‘ + (tooltipItems[0].dataIndex + 1);
}
return ”;
},
label: function(context) {
const selectedTeamWinProb = context.parsed.y;
const opponentWinProb = 100 – selectedTeamWinProb;
const selectedTeam = context.dataset.selectedTeam || ‘Team’;
const opponentTeam = context.dataset.opponentTeam || ‘Opponent’;
return [
selectedTeam + ‘: ‘ + selectedTeamWinProb.toFixed(1) + ‘%’,
opponentTeam + ‘: ‘ + opponentWinProb.toFixed(1) + ‘%’
];
},
afterLabel: function(context) {
if (context.dataset.playTexts && context.dataset.playTexts[context.dataIndex]) {
return ‘n’ + context.dataset.playTexts[context.dataIndex];
}
return ”;
}
}
} : {
filter: function(tooltipItem) {
if (‘top-receivers’.includes(‘play-map’)) {
return !tooltipItem.dataset.label.includes(‘< 0’) &&
!tooltipItem.dataset.label.includes(‘Quarters’) &&
!tooltipItem.dataset.label.includes(‘Drive’);
}
return !tooltipItem.dataset.label.includes(‘NCAA Avg SR’) &&
!tooltipItem.dataset.label.includes(’50/50′) &&
!tooltipItem.dataset.label.includes(‘ ds.label === ‘Win Probability’);
if (wpDataset && wpDataset.segmentColors) {
wpDataset.segment = {
borderColor: function(ctx) {
// Use p1DataIndex (ending point) so the line inherits the destination color
// This makes momentum shifts more visually intuitive
const index = ctx.p1DataIndex;
if (index !== undefined && wpDataset.segmentColors[index]) {
return wpDataset.segmentColors[index];
}
return wpDataset.borderColor || ‘#8B0000’;
}
};
}
}
// Initialize the chart
const ctx = canvas.getContext(‘2d’);
const chart = new Chart(ctx, {
type: ‘bar’,
data: chartData,
options: chartOptions
});
// Store reference to prevent re-initialization
canvas.chartInstance = chart;
console.log(‘CFB Chart initialized successfully’);
} catch (error) {
console.error(‘Error initializing CFB chart:’, error);
// Fallback: show error message in canvas container
const container = document.getElementById(‘cfb-chart-1765138274841-8r24cvs0o’).parentNode;
if (container) {
container.innerHTML = ‘
‘;
}
}
}
// Start loading scripts sequentially
function startLoading() {
// First, check if scripts are already loaded (multiple embeds on same page)
if (typeof Chart !== ‘undefined’ && typeof ChartDataLabels !== ‘undefined’) {
initChart();
return;
}
// Load Chart.js first
if (typeof Chart === ‘undefined’) {
loadScript(‘https://cdn.jsdelivr.net/npm/chart.js@3.9.1/dist/chart.min.js’, function() {
// Then load ChartDataLabels
if (typeof ChartDataLabels === ‘undefined’) {
loadScript(‘https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2.2.0’, function() {
initChart();
});
} else {
initChart();
}
});
} else if (typeof ChartDataLabels === ‘undefined’) {
// Chart.js loaded but not ChartDataLabels
loadScript(‘https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2.2.0’, function() {
initChart();
});
} else {
initChart();
}
}
// Initialize when DOM is ready
if (document.readyState === ‘loading’) {
document.addEventListener(‘DOMContentLoaded’, startLoading);
} else {
startLoading();
}
})();
Alabama’s receivers chart looks a lot more sparse than you’d like it to given that volume of passes thrown. (Yep, a lot of incompletions).
But Germie Bernard always seems to find his: his 3 explosives and 2 additional successful catches made him the obvious leader here. Ryan Williams also woke up in the 1st quarter, only to be retired again soon after.
Interestingly, we did get a lot of completions to RB Daniel Hill, which I usually see as a “good” thing, but I think in this game it was more a case of “check-down-itis,” where the QB is scared to throw anything but an easy one to an RB unlikely to break the next tackle. I was very optimistic about Hill when he first started emerging as an unconventional receiver this season, but something seems to have changed.
Our TE group is a mess of injuries, but newbie Marshall Pritchett did catch two, including a successful one. It’s good to know he’s capable, but dang it seems like we’re missing Josh Cuevas.
Isaiah Horton and Lotty Brooks have both shown flashes this year (if in different ways and roles), but neither showed up strong in this one. (I lost count of dropped passes, but I think each of these guys had one, among other teammates).
—
Well. There was a moment there where, honestly, I was trying to find a silver lining in going to a ‘normal’ bowl game: less time watching this team, which frankly is very painful about 75% of the time; and perhaps an opportunity to see/reward some younger players with playing time in a bowl. (I mean, we need to do some work to keep these kids around).
But, the Committee bailed us out. (Bama and the committee have a real “on and off again” relationship that seesaws roughly annually, have you seen a pattern?).
And, so, honestly, I’ll take what we can get here. A Playoff appearance is an important achievement for this coaching staff, a sought-after opportunity for the players, and honestly a recognition (at least for now) of Strength of Schedule as a critical metric of judgement. Some Tide fans might have been fine with seeing this silly team go to the Crab Legs Bowl or whatever, but the kids we’ve recruited (and are recruiting) want to play for a team that competes in real situations.
So, we’ve got the stage that the team wanted, and against one of the weakest opponents (Oklahoma) in the field. Now Grubb and co. just need to do some soul-searching and figure out how to actually (and not just statistically) win this round. Roll Tide.
📊 All charts from this game — which I frankly don’t recommend looking at — are here.