11 “baffling” charts from the Tide @ Florida State game
Welcome back to college football in 2025. If you can believe it, I’ve been writing this graphing column for coming into my 10th year now. Scream emoji. Old man emoji. Some of you will also remember the great “Charting the Tide” column that existed before this, written by SaxonRBR. Both Saxon and I had the privilege of introducing the column each year with a Tide victory. That’s because Alabama had been winning season openers since 2001 … but … times have changed. Football in general, has changed,
and Alabama football even moreso.
I do want to acknowledge before we get into graphy things that, like all of you, I am also a fan, and I’m also sorely disappointed by this result. I like that advanced metrics and these graphs help us have a different perspective on games, and that they help us attempt to rise above the highlight reels and the emotions of the moment. However, I don’t enjoy occupying the role of countering what are obviously very valid emotions in regards to the Crimson Tide football program.
In the last 14 games, we’ve experienced a lot of pain that Alabama fans had not been used to—at least in terms of frequency, if not depth, of pain. So I want you to know that what I am doing—when I bring a little nuance into the interpretation of this game via the metrics—I’m not trying to sugarcoat things. But yes, for several of Alabama’s losses, including in the last 14 games, these charts haven’t always “agreed” with the result. The team that’s most efficient or that seems to have everything together on most downs doesn’t always win. Often, things come down to 4th down conversions, turnovers, or back-breaking plays—and this game is no different.
That said, the graphing must go on. And funny enough, we have an exciting new graphing workflow this year that’s going to allow us to bring up more charts from more places, and that will even allow you to go see some on your own (at GraphingCollegeFootball.com, I’ll link the game again at the end). I’m excited about those developments, and that they free me up to reintroduce a more free-form format that we tried with this RBR column years ago. It’s just too bad we’re, uh, unveiling it in light of recent performance from the football team.
Most of you know the drill here, but feel free to drop in any comments if you have questions about the metrics. As a brief reminder, success rate (SR) — based on Bill Connelly’s SP+ analytics system — is supposed to measure whether an individual play was successful, that is:
A first down gains 50% of needed yardage
A second down gains 70% of needed yardage
A third or fourth down gains 100% of the needed yardage to get a first down or score
And Explosiveness Rate (XR), is the percentage of plays that gain 15 yards or more. You can also use the little drop-down on each of the chart embeds to see a brief explanation of metrics. Fancy stuff.
First, a little perspective
Sigh. OK, before we get into the game charts for Alabama @ FSU, let’s take a moment to develop some perspective.
// Toggle data definitions accordion - unique function per embed function toggleDefinitions_cfb_chart_1756659562328_wf728ri1e() { const definitions = document.getElementById('dataDefinitions_cfb-chart-1756659562328-wf728ri1e'); const caret = document.getElementById('caret_cfb-chart-1756659562328-wf728ri1e'); if (definitions.classList.contains('expanded')) { definitions.classList.remove('expanded'); caret.classList.remove('expanded'); } else { definitions.classList.add('expanded'); caret.classList.add('expanded'); } } // WordPress-safe chart initialization with defensive checks (function() { 'use strict'; function initChart() { // Check if Chart.js is available if (typeof Chart === 'undefined') { console.warn('Chart.js not loaded yet, retrying...'); setTimeout(initChart, 100); return; } // Check if datalabels plugin is available if (typeof ChartDataLabels === 'undefined') { console.warn('ChartDataLabels plugin not loaded yet, retrying...'); setTimeout(initChart, 100); return; } // Check if canvas element exists const canvas = document.getElementById('cfb-chart-1756659562328-wf728ri1e'); 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": [ "Ohio State", "Virginia Tech" ], "datasets": [ { "label": "Explosiveness Rate (XR)", "data": [ 0.14925373134328357, 0.09210526315789473 ], "backgroundColor": [ "rgba(128, 16, 0, 0.8)", "#7F1D1DCC" ], "stack": "SRXR", "datalabels": { "display": false } }, { "label": "Success Rate (SR)", "data": [ 0.2835820895522388, 0.35526315789473684 ], "backgroundColor": [ "rgba(244, 63, 37, 0.8)", "#9F1239CC" ], "stack": "SRXR", "datalabels": { "display": true }, "playCountData": [ 28, 36 ] }, { "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(244, 63, 37, 0.8)", "explosive": "rgba(128, 16, 0, 0.8)", "light": "rgba(255, 233, 230, 0.8)" }, "opponentColors": { "success": "#9F1239CC", "explosive": "#7F1D1DCC", "light": "#FFE4E1CC", "color": "#9F1239", "colorDark": "#7F1D1D" }, "teamPlayCount": 67, "opponentPlayCount": 76, "currentParams": { "year": 2014, "week": 2, "seasonType": "regular", "team": "Ohio State", "gameId": "400547826" } }; // Chart options (WordPress-safe) const chartOptions = { responsive: true, maintainAspectRatio: false, animation: { duration: 0 // Disable animations to prevent conflicts }, elements: 'bar' === 'line' ? 'overall-team-performance'.includes('play-map') ? { line: { tension: 0, borderWidth: 0 } } : { 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: '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: { 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('< 0') && !tooltipItem.dataset.label.includes('Quarters'); }, callbacks: { label: function(context) { const label = context.dataset.label || ''; let labelText; // Play maps show yards instead of percentages if ('overall-team-performance'.includes('play-map')) { labelText = label + ': ' + context.parsed.y + ' yards'; } else { const value = Math.round(context.parsed.y * 100); labelText = label + ': ' + value + '%'; } // For line charts, include play text if available if ('bar' === 'line' && context.raw && context.raw.text) { return [labelText, context.raw.text]; } return labelText; } } } }, scales: 'bar' === 'line' ? 'overall-team-performance'.includes('play-map') ? { x: { type: 'linear', position: 'bottom', title: { display: true, text: 'Play Number' }, min: 1, ticks: { stepSize: 1, callback: function(value) { return Math.floor(value); } }, grid: { display: false } }, y: { title: { display: true, text: 'Yards Gained' }, min: chartData.minY, max: chartData.maxY } } : { x: { type: 'linear', position: 'bottom', title: { display: true, text: 'overall-team-performance'.includes('team-lines') ? 'Play Number' : 'Team Play Number' }, min: 1, ticks: { stepSize: 1, callback: function(value) { return Math.floor(value); } }, grid: { display: false } }, y: { max: 1, min: 0, ticks: { callback: function(value) { return Math.round(value * 100) + '%'; } } } } : 'overall-team-performance'.includes('drive-metrics') ? { y: { stacked: false, max: 1, ticks: { callback: function(value) { return Math.round(value * 100) + '%'; } } }, y1: { display: false, type: 'linear', position: 'right' } } : ('overall-team-performance'.includes('top-rushers') || 'overall-team-performance'.includes('top-passers') || 'overall-team-performance'.includes('top-receivers')) ? { x: { stacked: true }, y: { stacked: true } } : { y: { max: 1, min: 0, stacked: false, ticks: { callback: function(value) { return Math.round(value * 100) + '%'; } } } } }; // Add indexAxis for player charts if ('overall-team-performance'.includes('top-rushers') || 'overall-team-performance'.includes('top-passers') || 'overall-team-performance'.includes('top-receivers')) { chartOptions.indexAxis = 'y'; } // 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-1756659562328-wf728ri1e').parentNode; if (container) { container.innerHTML = '
Chart failed to load. Please refresh the page.
'; } } } // Initialize when DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initChart); } else { initChart(); } // Also try initialization after a short delay for WordPress compatibility setTimeout(initChart, 500); })();
This is the basic efficiency and explosiveness rundown from the Ohio State vs. Virginia Tech game in 2014. Ohio State lost this game easily, 21-35, and put a huge dent in its perceived resume and ability to get to the very first College Football Playoff (4-team edition). As those around here know quite well, Ohio State very much went to the playoff at the end of it, beat #1 seeded Alabama in the inaugural playoff, and ended up winning the national title pretty comfortably in the title game itself.
In that game, Ohio State outgained Virginia Tech by three yards! They also did acceptably on yards per rush and yards per pass, compared to the opponent. Given that they lost by a few scores, though, you’ll see where things fell apart for the Buckeyes, namely on 3rd downs. There were also some turnovers involved on both ends that made this a bit of a mess and that took away any chances for Ohio State to close the gap.
I don’t really care that much about this game, and I’m sure you don’t either. But it’s important to note that there is strong precedent for good teams to put in poor performances early … and to take time to gel. I would argue that in some ways this OSU loss was worse than the one that we just saw from Alabama-Florida State, especially given the expectations from that Virginia Tech program and given that gap in success rate that Ohio State showed vs Virginia Tech. We’ll get into more of that later.
Fast forward about ten years and Ohio State also had a few losses in 2024, including an embarrassing one to a Michigan squad that was similar to the one that beat Alabama (plus some starters, minus a monsoon). So there’s both distant and recent history for powerhouses crapping the bed and then getting things together enough to make things interesting. I’m not necessarily predicting that that happens to the 2025 Crimson Tide, but a lot of the commentary that I’m seeing post-game is the kind of stuff that isn’t going to help make this season very fun to watch. I choose to hold out some hope and to root for the Tide game-by-game. Maybe we can even get a result like one of Ohio State’s. (Or even Clemson’s last season after a 34-3 spanking by Georgia to start the season).
Alabama also lost their game by two touchdowns. In this case, we did not outgain the opponent in a loss; however, putting up 341 yards against the other team’s 388 is not exactly reminiscent of a blowout. Our yards per rush were weak, and yeah, the yards per pass were too. But Alabama often kept the chains moving enough to keep the game interesting and to put together respectable, if not spectacular, drives.
Alabama also got 18 first downs to Florida State’s 20, which is … interesting in a game that has the fanbase so deep in despair. I think the big problems come where you usually see them: Alabama’s 6 for 17 third downs is not even the worst third-down rate I’ve seen. However, when Florida State is able to deliver a near-50% third-down efficiency, that kills you. The same story goes for fourth down where Alabama’s 2 for 5 is actually about average according to league SR’s, but Florida State’s 2 for 2 are the two daggers that decided this game (including a fourth and one in Florida State’s own territory in the fourth quarter with a one-score game where Alabama could have very well made the play and pushed for a tied game).
Most of the stats in this box score are pretty sad, but to be honest, I think the one that makes me the most sad is the sacks line, with Alabama delivering one against Florida State’s three … against what we kept being told was an excellent Alabama offensive line that was having a really promising camp. Bleh.
// Toggle data definitions accordion - unique function per embed function toggleDefinitions_cfb_chart_1756660255117_59j86svot() { const definitions = document.getElementById('dataDefinitions_cfb-chart-1756660255117-59j86svot'); const caret = document.getElementById('caret_cfb-chart-1756660255117-59j86svot'); if (definitions.classList.contains('expanded')) { definitions.classList.remove('expanded'); caret.classList.remove('expanded'); } else { definitions.classList.add('expanded'); caret.classList.add('expanded'); } } // WordPress-safe chart initialization with defensive checks (function() { 'use strict'; function initChart() { // Check if Chart.js is available if (typeof Chart === 'undefined') { console.warn('Chart.js not loaded yet, retrying...'); setTimeout(initChart, 100); return; } // Check if datalabels plugin is available if (typeof ChartDataLabels === 'undefined') { console.warn('ChartDataLabels plugin not loaded yet, retrying...'); setTimeout(initChart, 100); return; } // Check if canvas element exists const canvas = document.getElementById('cfb-chart-1756660255117-59j86svot'); 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", "Florida State" ], "datasets": [ { "label": "Explosiveness Rate (XR)", "data": [ 0.07042253521126761, 0.09523809523809523 ], "backgroundColor": [ "rgba(101, 0, 20, 0.8)", "#854D0ECC" ], "stack": "SRXR", "datalabels": { "display": false } }, { "label": "Success Rate (SR)", "data": [ 0.38028169014084506, 0.38095238095238093 ], "backgroundColor": [ "rgba(175, 40, 60, 0.8)", "#CA8A04CC" ], "stack": "SRXR", "datalabels": { "display": true }, "playCountData": [ 38, 38 ] }, { "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": "#CA8A04CC", "explosive": "#854D0ECC", "light": "#FEF3C7CC", "color": "#CA8A04", "colorDark": "#854D0E" }, "teamPlayCount": 71, "opponentPlayCount": 63, "currentParams": { "year": 2025, "week": 1, "seasonType": "regular", "team": "Alabama", "gameId": "401752665" } }; // Chart options (WordPress-safe) const chartOptions = { responsive: true, maintainAspectRatio: false, animation: { duration: 0 // Disable animations to prevent conflicts }, elements: 'bar' === 'line' ? 'overall-team-performance'.includes('play-map') ? { line: { tension: 0, borderWidth: 0 } } : { 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: '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: { 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('< 0') && !tooltipItem.dataset.label.includes('Quarters'); }, callbacks: { label: function(context) { const label = context.dataset.label || ''; let labelText; // Play maps show yards instead of percentages if ('overall-team-performance'.includes('play-map')) { labelText = label + ': ' + context.parsed.y + ' yards'; } else { const value = Math.round(context.parsed.y * 100); labelText = label + ': ' + value + '%'; } // For line charts, include play text if available if ('bar' === 'line' && context.raw && context.raw.text) { return [labelText, context.raw.text]; } return labelText; } } } }, scales: 'bar' === 'line' ? 'overall-team-performance'.includes('play-map') ? { x: { type: 'linear', position: 'bottom', title: { display: true, text: 'Play Number' }, min: 1, ticks: { stepSize: 1, callback: function(value) { return Math.floor(value); } }, grid: { display: false } }, y: { title: { display: true, text: 'Yards Gained' }, min: chartData.minY, max: chartData.maxY } } : { x: { type: 'linear', position: 'bottom', title: { display: true, text: 'overall-team-performance'.includes('team-lines') ? 'Play Number' : 'Team Play Number' }, min: 1, ticks: { stepSize: 1, callback: function(value) { return Math.floor(value); } }, grid: { display: false } }, y: { max: 1, min: 0, ticks: { callback: function(value) { return Math.round(value * 100) + '%'; } } } } : 'overall-team-performance'.includes('drive-metrics') ? { y: { stacked: false, max: 1, ticks: { callback: function(value) { return Math.round(value * 100) + '%'; } } }, y1: { display: false, type: 'linear', position: 'right' } } : ('overall-team-performance'.includes('top-rushers') || 'overall-team-performance'.includes('top-passers') || 'overall-team-performance'.includes('top-receivers')) ? { x: { stacked: true }, y: { stacked: true } } : { y: { max: 1, min: 0, stacked: false, ticks: { callback: function(value) { return Math.round(value * 100) + '%'; } } } } }; // Add indexAxis for player charts if ('overall-team-performance'.includes('top-rushers') || 'overall-team-performance'.includes('top-passers') || 'overall-team-performance'.includes('top-receivers')) { chartOptions.indexAxis = 'y'; } // 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-1756660255117-59j86svot').parentNode; if (container) { container.innerHTML = '
Chart failed to load. Please refresh the page.
'; } } } // Initialize when DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initChart); } else { initChart(); } // Also try initialization after a short delay for WordPress compatibility setTimeout(initChart, 500); })();
And here’s the part where I show a chart it says Alabama did fine, even though we lost (what feels like) badly. Alabama ran more plays and delivered, technically speaking, a slightly higher success rate than Florida State. Effectively, you could say that these teams were equally efficient when it comes to success rate.
However, I have long-time readers who have discovered that success rate does correlate with, but it’s not necessarily a guarantee of success. Funny enough, the last time Alabama beat Florida State (2017 season opener), the ‘Noles pulled off the same trick in a loss, with notably higher efficiencies than the Tide. Maybe it was the karmic balance of the universe working against Alabama.
Also, it’s notable that Florida State had three points more in explosiveness rate (10% XR to Alabama’s 7%) which these days does highly correlate with team success. But, Florida State’s 10% is not a high XR. It’s just that Alabama’s explosiveness rate was even lower … abysmal. Just track this dark crimson solid line at the bottom of this next chart:
// Toggle data definitions accordion - unique function per embed function toggleDefinitions_cfb_chart_1756660405610_za0zev8kn() { const definitions = document.getElementById('dataDefinitions_cfb-chart-1756660405610-za0zev8kn'); const caret = document.getElementById('caret_cfb-chart-1756660405610-za0zev8kn'); if (definitions.classList.contains('expanded')) { definitions.classList.remove('expanded'); caret.classList.remove('expanded'); } else { definitions.classList.add('expanded'); caret.classList.add('expanded'); } } // WordPress-safe chart initialization with defensive checks (function() { 'use strict'; function initChart() { // Check if Chart.js is available if (typeof Chart === 'undefined') { console.warn('Chart.js not loaded yet, retrying...'); setTimeout(initChart, 100); return; } // Check if datalabels plugin is available if (typeof ChartDataLabels === 'undefined') { console.warn('ChartDataLabels plugin not loaded yet, retrying...'); setTimeout(initChart, 100); return; } // Check if canvas element exists const canvas = document.getElementById('cfb-chart-1756660405610-za0zev8kn'); 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": "NCAA Avg SR", "data": [ { "x": 1, "y": 0 }, { "x": 1, "y": 0.42 }, { "x": 134, "y": 0.42 }, { "x": 134, "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": 0, "text": "Richard Young run for 6 yds to the ALA 31" }, { "x": 2, "y": 0, "text": "Ty Simpson pass complete to Germie Bernard for 12 yds to the ALA 43 for a 1ST down" }, { "x": 3, "y": 0, "text": "Richard Young run for 3 yds to the ALA 46" }, { "x": 4, "y": 0, "text": "Ty Simpson run for 5 yds to the FSU 49" }, { "x": 5, "y": 0, "text": "Ty Simpson run for 6 yds to the FSU 48" }, { "x": 6, "y": 0, "text": "Richard Young run for 1 yd to the FSU 47 for a 1ST down" }, { "x": 7, "y": 0, "text": "Daniel Hill run for 7 yds to the FSU 40" }, { "x": 8, "y": 0, "text": "Daniel Hill run for a loss of 2 yards to the FSU 42" }, { "x": 9, "y": 0, "text": "Richard Young run for 6 yds to the FSU 36 for a 1ST down" }, { "x": 10, "y": 0, "text": "Kevin Riley run for 13 yds to the FSU 23 for a 1ST down" }, { "x": 11, "y": 0, "text": "Kevin Riley run for 4 yds to the FSU 19" }, { "x": 12, "y": 0, "text": "Ty Simpson pass incomplete to Germie Bernard" }, { "x": 13, "y": 0, "text": "Ty Simpson run for 6 yds to the FSU 13 for a 1ST down" }, { "x": 14, "y": 0, "text": "Ty Simpson pass complete to Ryan Williams for 11 yds to the FSU 2 for a 1ST down" }, { "x": 15, "y": 0, "text": "Richard Young run for no gain to the FSU 2" }, { "x": 16, "y": 0, "text": "Ty Simpson pass complete to Josh Cuevas for 2 yds for a TD (Conor Talty KICK)" }, { "x": 24, "y": 0, "text": "Richard Young run for no gain to the ALA 25" }, { "x": 25, "y": 0.05555555555555555, "text": "Ty Simpson pass complete to Germie Bernard for 29 yds to the FSU 46 for a 1ST down" }, { "x": 26, "y": 0.05263157894736842, "text": "Ty Simpson pass complete to Ryan Williams for 5 yds to the FSU 41" }, { "x": 27, "y": 0.05, "text": "Richard Young run for 3 yds to the FSU 38" }, { "x": 28, "y": 0.047619047619047616, "text": "Ty Simpson pass complete to Germie Bernard for 12 yds to the FSU 26 for a 1ST down" }, { "x": 29, "y": 0.045454545454545456, "text": "Ty Simpson pass complete to Isaiah Horton for 6 yds to the FSU 20" }, { "x": 30, "y": 0.043478260869565216, "text": "Ty Simpson pass complete to Germie Bernard for a loss of 4 yards to the FSU 24" }, { "x": 31, "y": 0.041666666666666664, "text": "Ty Simpson sacked by Deamontae Diggs for a loss of 6 yards to the FSU 35" }, { "x": 40, "y": 0.04, "text": "Ty Simpson pass incomplete to Josh Cuevas" }, { "x": 41, "y": 0.038461538461538464, "text": "Kevin Riley run for 2 yds to the ALA 27" }, { "x": 42, "y": 0.037037037037037035, "text": "Ty Simpson pass incomplete" }, { "x": 51, "y": 0.03571428571428571, "text": "Richard Young run for 6 yds to the ALA 31" }, { "x": 52, "y": 0.034482758620689655, "text": "Richard Young run for 1 yd to the ALA 32" }, { "x": 53, "y": 0.03333333333333333, "text": "Ty Simpson pass complete to Ryan Williams for 8 yds to the ALA 40 for a 1ST down" }, { "x": 54, "y": 0.03225806451612903, "text": "Ty Simpson pass complete to Richard Young for 6 yds to the ALA 46" }, { "x": 55, "y": 0.03125, "text": "Ty Simpson pass incomplete to Germie Bernard" }, { "x": 56, "y": 0.030303030303030304, "text": "Ty Simpson run for no gain to the ALA 46" }, { "x": 67, "y": 0.029411764705882353, "text": "Ty Simpson pass incomplete to Rico Scott" }, { "x": 68, "y": 0.05714285714285714, "text": "Ty Simpson pass complete to Germie Bernard for 30 yds to the FSU 41 for a 1ST down" }, { "x": 69, "y": 0.05555555555555555, "text": "Ty Simpson pass complete to Josh Cuevas for 2 yds to the FSU 39" }, { "x": 70, "y": 0.05405405405405406, "text": "Ty Simpson pass complete to Ryan Williams for 3 yds to the FSU 36" }, { "x": 71, "y": 0.05263157894736842, "text": "Ty Simpson pass incomplete" }, { "x": 72, "y": 0.05128205128205128, "text": "Ty Simpson pass complete to Kevin Riley for 4 yds to the FSU 32" }, { "x": 75, "y": 0.05, "text": "Daniel Hill run for 4 yds to the ALA 29" }, { "x": 76, "y": 0.07317073170731707, "text": "Ty Simpson pass complete to Germie Bernard for 37 yds to the FSU 44 for a 1ST down" }, { "x": 77, "y": 0.07142857142857142, "text": "Ty Simpson pass incomplete to Ryan Williams" }, { "x": 78, "y": 0.06976744186046512, "text": "Dre Washington run for a loss of 1 yard to the FSU 45" }, { "x": 79, "y": 0.09090909090909091, "text": "Ty Simpson pass complete to Germie Bernard for 18 yds to the FSU 27 for a 1ST down" }, { "x": 80, "y": 0.08888888888888889, "text": "Dre Washington run for 2 yds to the FSU 25" }, { "x": 81, "y": 0.08695652173913043, "text": "Ty Simpson pass incomplete to Rico Scott" }, { "x": 82, "y": 0.0851063829787234, "text": "Ty Simpson pass incomplete" }, { "x": 83, "y": 0.08333333333333333, "text": "Ty Simpson pass incomplete to Ryan Williams" }, { "x": 84, "y": 0.08163265306122448, "text": "Ty Simpson pass incomplete to Josh Cuevas" }, { "x": 91, "y": 0.08, "text": "Ty Simpson sacked by Stefon Thompson for a loss of 7 yards to the ALA 13" }, { "x": 92, "y": 0.0784313725490196, "text": "Ty Simpson pass incomplete" }, { "x": 93, "y": 0.07692307692307693, "text": "Ty Simpson run for 6 yds to the ALA 19" }, { "x": 94, "y": 0.07547169811320754, "text": "Germie Bernard run for 3 yds to the FSU 28" }, { "x": 95, "y": 0.07407407407407407, "text": "Ty Simpson pass incomplete" }, { "x": 96, "y": 0.07272727272727272, "text": "Ty Simpson pass incomplete to Germie Bernard" }, { "x": 97, "y": 0.07142857142857142, "text": "Ty Simpson pass incomplete to Ryan Williams" }, { "x": 101, "y": 0.07017543859649122, "text": "Ty Simpson pass complete to Ryan Williams for 3 yds to the ALA 40" }, { "x": 102, "y": 0.08620689655172414, "text": "Ty Simpson pass complete to Josh Cuevas for 27 yds to the FSU 33 for a 1ST down" }, { "x": 103, "y": 0.0847457627118644, "text": "Ty Simpson pass complete to Daniel Hill for 3 yds to the FSU 30" }, { "x": 104, "y": 0.08333333333333333, "text": "Kevin Riley run for 6 yds to the FSU 24" }, { "x": 105, "y": 0.08196721311475409, "text": "Kevin Riley run for 6 yds to the FSU 18 for a 1ST down" }, { "x": 106, "y": 0.08064516129032258, "text": "Ty Simpson pass complete to Germie Bernard for 12 yds to the FSU 6 for a 1ST down" }, { "x": 107, "y": 0.07936507936507936, "text": "Ty Simpson pass complete to Rico Scott for 6 yds for a TD (Conor Talty KICK)" }, { "x": 118, "y": 0.078125, "text": "Ty Simpson pass complete to Daniel Hill for 9 yds to the ALA 34" }, { "x": 119, "y": 0.07692307692307693, "text": "Ty Simpson pass incomplete" }, { "x": 120, "y": 0.07575757575757576, "text": "Ty Simpson pass incomplete" }, { "x": 121, "y": 0.07462686567164178, "text": "Ty Simpson pass complete to Rico Scott for 13 yds to the ALA 42 for a 1ST down" }, { "x": 122, "y": 0.07352941176470588, "text": "Ty Simpson pass incomplete" }, { "x": 123, "y": 0.07246376811594203, "text": "Ty Simpson pass incomplete to Ryan Williams" }, { "x": 124, "y": 0.07142857142857142, "text": "Ty Simpson pass incomplete to Jalen Hale" }, { "x": 125, "y": 0.07042253521126761, "text": "Ty Simpson run for 9 yds to the FSU 49" } ], "label": "Alabama XR", "borderColor": "rgba(101, 0, 20, 0.8)", "borderWidth": 2.2, "fill": false }, { "data": [ { "x": 1, "y": 1, "text": "Richard Young run for 6 yds to the ALA 31" }, { "x": 2, "y": 1, "text": "Ty Simpson pass complete to Germie Bernard for 12 yds to the ALA 43 for a 1ST down" }, { "x": 3, "y": 0.6666666666666666, "text": "Richard Young run for 3 yds to the ALA 46" }, { "x": 4, "y": 0.75, "text": "Ty Simpson run for 5 yds to the FSU 49" }, { "x": 5, "y": 0.6, "text": "Ty Simpson run for 6 yds to the FSU 48" }, { "x": 6, "y": 0.6666666666666666, "text": "Richard Young run for 1 yd to the FSU 47 for a 1ST down" }, { "x": 7, "y": 0.7142857142857143, "text": "Daniel Hill run for 7 yds to the FSU 40" }, { "x": 8, "y": 0.625, "text": "Daniel Hill run for a loss of 2 yards to the FSU 42" }, { "x": 9, "y": 0.6666666666666666, "text": "Richard Young run for 6 yds to the FSU 36 for a 1ST down" }, { "x": 10, "y": 0.7, "text": "Kevin Riley run for 13 yds to the FSU 23 for a 1ST down" }, { "x": 11, "y": 0.6363636363636364, "text": "Kevin Riley run for 4 yds to the FSU 19" }, { "x": 12, "y": 0.5833333333333334, "text": "Ty Simpson pass incomplete to Germie Bernard" }, { "x": 13, "y": 0.6153846153846154, "text": "Ty Simpson run for 6 yds to the FSU 13 for a 1ST down" }, { "x": 14, "y": 0.6428571428571429, "text": "Ty Simpson pass complete to Ryan Williams for 11 yds to the FSU 2 for a 1ST down" }, { "x": 15, "y": 0.6, "text": "Richard Young run for no gain to the FSU 2" }, { "x": 16, "y": 0.625, "text": "Ty Simpson pass complete to Josh Cuevas for 2 yds for a TD (Conor Talty KICK)" }, { "x": 24, "y": 0.5882352941176471, "text": "Richard Young run for no gain to the ALA 25" }, { "x": 25, "y": 0.6111111111111112, "text": "Ty Simpson pass complete to Germie Bernard for 29 yds to the FSU 46 for a 1ST down" }, { "x": 26, "y": 0.631578947368421, "text": "Ty Simpson pass complete to Ryan Williams for 5 yds to the FSU 41" }, { "x": 27, "y": 0.6, "text": "Richard Young run for 3 yds to the FSU 38" }, { "x": 28, "y": 0.6190476190476191, "text": "Ty Simpson pass complete to Germie Bernard for 12 yds to the FSU 26 for a 1ST down" }, { "x": 29, "y": 0.6363636363636364, "text": "Ty Simpson pass complete to Isaiah Horton for 6 yds to the FSU 20" }, { "x": 30, "y": 0.6086956521739131, "text": "Ty Simpson pass complete to Germie Bernard for a loss of 4 yards to the FSU 24" }, { "x": 31, "y": 0.5833333333333334, "text": "Ty Simpson sacked by Deamontae Diggs for a loss of 6 yards to the FSU 35" }, { "x": 40, "y": 0.56, "text": "Ty Simpson pass incomplete to Josh Cuevas" }, { "x": 41, "y": 0.5384615384615384, "text": "Kevin Riley run for 2 yds to the ALA 27" }, { "x": 42, "y": 0.5185185185185185, "text": "Ty Simpson pass incomplete" }, { "x": 51, "y": 0.5357142857142857, "text": "Richard Young run for 6 yds to the ALA 31" }, { "x": 52, "y": 0.5172413793103449, "text": "Richard Young run for 1 yd to the ALA 32" }, { "x": 53, "y": 0.5333333333333333, "text": "Ty Simpson pass complete to Ryan Williams for 8 yds to the ALA 40 for a 1ST down" }, { "x": 54, "y": 0.5483870967741935, "text": "Ty Simpson pass complete to Richard Young for 6 yds to the ALA 46" }, { "x": 55, "y": 0.53125, "text": "Ty Simpson pass incomplete to Germie Bernard" }, { "x": 56, "y": 0.5151515151515151, "text": "Ty Simpson run for no gain to the ALA 46" }, { "x": 67, "y": 0.5, "text": "Ty Simpson pass incomplete to Rico Scott" }, { "x": 68, "y": 0.5142857142857142, "text": "Ty Simpson pass complete to Germie Bernard for 30 yds to the FSU 41 for a 1ST down" }, { "x": 69, "y": 0.5, "text": "Ty Simpson pass complete to Josh Cuevas for 2 yds to the FSU 39" }, { "x": 70, "y": 0.4864864864864865, "text": "Ty Simpson pass complete to Ryan Williams for 3 yds to the FSU 36" }, { "x": 71, "y": 0.47368421052631576, "text": "Ty Simpson pass incomplete" }, { "x": 72, "y": 0.46153846153846156, "text": "Ty Simpson pass complete to Kevin Riley for 4 yds to the FSU 32" }, { "x": 75, "y": 0.45, "text": "Daniel Hill run for 4 yds to the ALA 29" }, { "x": 76, "y": 0.4634146341463415, "text": "Ty Simpson pass complete to Germie Bernard for 37 yds to the FSU 44 for a 1ST down" }, { "x": 77, "y": 0.4523809523809524, "text": "Ty Simpson pass incomplete to Ryan Williams" }, { "x": 78, "y": 0.4418604651162791, "text": "Dre Washington run for a loss of 1 yard to the FSU 45" }, { "x": 79, "y": 0.45454545454545453, "text": "Ty Simpson pass complete to Germie Bernard for 18 yds to the FSU 27 for a 1ST down" }, { "x": 80, "y": 0.4444444444444444, "text": "Dre Washington run for 2 yds to the FSU 25" }, { "x": 81, "y": 0.43478260869565216, "text": "Ty Simpson pass incomplete to Rico Scott" }, { "x": 82, "y": 0.425531914893617, "text": "Ty Simpson pass incomplete" }, { "x": 83, "y": 0.4166666666666667, "text": "Ty Simpson pass incomplete to Ryan Williams" }, { "x": 84, "y": 0.40816326530612246, "text": "Ty Simpson pass incomplete to Josh Cuevas" }, { "x": 91, "y": 0.4, "text": "Ty Simpson sacked by Stefon Thompson for a loss of 7 yards to the ALA 13" }, { "x": 92, "y": 0.39215686274509803, "text": "Ty Simpson pass incomplete" }, { "x": 93, "y": 0.38461538461538464, "text": "Ty Simpson run for 6 yds to the ALA 19" }, { "x": 94, "y": 0.37735849056603776, "text": "Germie Bernard run for 3 yds to the FSU 28" }, { "x": 95, "y": 0.37037037037037035, "text": "Ty Simpson pass incomplete" }, { "x": 96, "y": 0.36363636363636365, "text": "Ty Simpson pass incomplete to Germie Bernard" }, { "x": 97, "y": 0.35714285714285715, "text": "Ty Simpson pass incomplete to Ryan Williams" }, { "x": 101, "y": 0.3508771929824561, "text": "Ty Simpson pass complete to Ryan Williams for 3 yds to the ALA 40" }, { "x": 102, "y": 0.3620689655172414, "text": "Ty Simpson pass complete to Josh Cuevas for 27 yds to the FSU 33 for a 1ST down" }, { "x": 103, "y": 0.3559322033898305, "text": "Ty Simpson pass complete to Daniel Hill for 3 yds to the FSU 30" }, { "x": 104, "y": 0.36666666666666664, "text": "Kevin Riley run for 6 yds to the FSU 24" }, { "x": 105, "y": 0.3770491803278688, "text": "Kevin Riley run for 6 yds to the FSU 18 for a 1ST down" }, { "x": 106, "y": 0.3870967741935484, "text": "Ty Simpson pass complete to Germie Bernard for 12 yds to the FSU 6 for a 1ST down" }, { "x": 107, "y": 0.3968253968253968, "text": "Ty Simpson pass complete to Rico Scott for 6 yds for a TD (Conor Talty KICK)" }, { "x": 118, "y": 0.40625, "text": "Ty Simpson pass complete to Daniel Hill for 9 yds to the ALA 34" }, { "x": 119, "y": 0.4, "text": "Ty Simpson pass incomplete" }, { "x": 120, "y": 0.3939393939393939, "text": "Ty Simpson pass incomplete" }, { "x": 121, "y": 0.40298507462686567, "text": "Ty Simpson pass complete to Rico Scott for 13 yds to the ALA 42 for a 1ST down" }, { "x": 122, "y": 0.39705882352941174, "text": "Ty Simpson pass incomplete" }, { "x": 123, "y": 0.391304347826087, "text": "Ty Simpson pass incomplete to Ryan Williams" }, { "x": 124, "y": 0.38571428571428573, "text": "Ty Simpson pass incomplete to Jalen Hale" }, { "x": 125, "y": 0.38028169014084506, "text": "Ty Simpson run for 9 yds to the FSU 49" } ], "label": "Alabama SR", "borderColor": "rgba(175, 40, 60, 0.8)", "borderWidth": 2.2, "fill": false }, { "data": [ { "x": 17, "y": 0, "text": "Roydell Williams run for 2 yds to the FSU 27" }, { "x": 18, "y": 0, "text": "Tommy Castellanos pass complete to Duce Robinson for 3 yds to the FSU 30" }, { "x": 19, "y": 0, "text": "Tommy Castellanos run for 12 yds to the ALA 48 for a 1ST down" }, { "x": 20, "y": 0, "text": "Gavin Sawchuk run for 5 yds to the FSU 47" }, { "x": 21, "y": 0, "text": "Tommy Castellanos pass complete to Randy Pittman Jr. for 4 yds to the ALA 49" }, { "x": 22, "y": 0.16666666666666666, "text": "Tommy Castellanos pass complete to Squirrel White for 40 yds to the ALA 9 for a 1ST down" }, { "x": 23, "y": 0.14285714285714285, "text": "Tommy Castellanos run for 9 yds for a TD (Jake Weinberg KICK)" }, { "x": 32, "y": 0.125, "text": "Tommy Castellanos pass complete to Gavin Sawchuk for 3 yds to the FSU 38" }, { "x": 33, "y": 0.1111111111111111, "text": "Tommy Castellanos pass complete to Jaylin Lucas for 2 yds to the FSU 40" }, { "x": 34, "y": 0.1, "text": "Tommy Castellanos pass complete to Randy Pittman Jr. for 14 yds to the ALA 46 for a 1ST down" }, { "x": 35, "y": 0.09090909090909091, "text": "Roydell Williams run for 1 yd to the ALA 45" }, { "x": 36, "y": 0.08333333333333333, "text": "Tommy Castellanos run for 5 yds to the ALA 40" }, { "x": 37, "y": 0.07692307692307693, "text": "Tommy Castellanos run for 5 yds to the ALA 35 for a 1ST down" }, { "x": 38, "y": 0.07142857142857142, "text": "Tommy Castellanos run for 3 yds to the ALA 32" }, { "x": 39, "y": 0.13333333333333333, "text": "Micahi Danzy run for 32 yds for a TD (Jake Weinberg KICK)" }, { "x": 43, "y": 0.1875, "text": "Tommy Castellanos pass complete to Duce Robinson for 15 yds to the FSU 36 for a 1ST down" }, { "x": 44, "y": 0.17647058823529413, "text": "Ousmane Kromah run for no gain to the FSU 36" }, { "x": 45, "y": 0.16666666666666666, "text": "Ousmane Kromah run for 14 yds to the 50 yard line for a 1ST down" }, { "x": 46, "y": 0.15789473684210525, "text": "Ousmane Kromah run for 3 yds to the ALA 47" }, { "x": 47, "y": 0.15, "text": "Tommy Castellanos run for 14 yds to the ALA 33 for a 1ST down" }, { "x": 48, "y": 0.14285714285714285, "text": "Roydell Williams run for 2 yds to the ALA 31" }, { "x": 49, "y": 0.13636363636363635, "text": "Tommy Castellanos run for 4 yds to the ALA 27" }, { "x": 50, "y": 0.13043478260869565, "text": "Tommy Castellanos pass incomplete to Duce Robinson" }, { "x": 57, "y": 0.125, "text": "Tommy Castellanos run for 4 yds to the FSU 24" }, { "x": 58, "y": 0.12, "text": "Jaylin Lucas run for 4 yds to the FSU 28" }, { "x": 59, "y": 0.11538461538461539, "text": "Jaylin Lucas run for 5 yds to the FSU 33 for a 1ST down" }, { "x": 60, "y": 0.1111111111111111, "text": "Jaylin Lucas run for 2 yds to the FSU 35" }, { "x": 61, "y": 0.10714285714285714, "text": "Roydell Williams run for no gain to the FSU 35" }, { "x": 62, "y": 0.10344827586206896, "text": "Ousmane Kromah run for 7 yds to the FSU 22" }, { "x": 63, "y": 0.1, "text": "Ousmane Kromah run for 5 yds to the FSU 27 for a 1ST down" }, { "x": 64, "y": 0.0967741935483871, "text": "Tommy Castellanos run for 2 yds to the FSU 29" }, { "x": 65, "y": 0.09375, "text": "Tommy Castellanos pass incomplete" }, { "x": 66, "y": 0.09090909090909091, "text": "Tommy Castellanos pass complete to Ousmane Kromah for 7 yds to the FSU 31" }, { "x": 73, "y": 0.11764705882352941, "text": "Tommy Castellanos pass complete to Jaylin Lucas for 64 yds to the ALA 4 for a 1ST down" }, { "x": 74, "y": 0.11428571428571428, "text": "Caziah Holmes run for 4 yds for a TD (Jake Weinberg KICK)" }, { "x": 85, "y": 0.1111111111111111, "text": "Gavin Sawchuk run for 5 yds to the FSU 30" }, { "x": 86, "y": 0.10810810810810811, "text": "Tommy Castellanos pass incomplete to Duce Robinson" }, { "x": 87, "y": 0.13157894736842105, "text": "Tommy Castellanos run for 6 yds to the ALA 36 for a 1ST down Alabama Penalty, Personal Foul (15 Yards) to the ALA 49 for a 1ST down" }, { "x": 88, "y": 0.1282051282051282, "text": "Roydell Williams run for 5 yds to the ALA 44" }, { "x": 89, "y": 0.125, "text": "Jaylin Lucas run for 1 yd to the ALA 43" }, { "x": 90, "y": 0.12195121951219512, "text": "Tommy Castellanos pass incomplete" }, { "x": 98, "y": 0.11904761904761904, "text": "Ousmane Kromah run for a loss of 1 yard to the FSU 27" }, { "x": 99, "y": 0.11627906976744186, "text": "Gavin Sawchuk run for 2 yds to the FSU 29" }, { "x": 100, "y": 0.11363636363636363, "text": "Tommy Castellanos sacked by Keon Sabb for a loss of 8 yards to the FSU 21" }, { "x": 108, "y": 0.1111111111111111, "text": "Ousmane Kromah run for 3 yds to the FSU 28" }, { "x": 109, "y": 0.10869565217391304, "text": "Tommy Castellanos run for 5 yds to the FSU 33" }, { "x": 110, "y": 0.10638297872340426, "text": "Tommy Castellanos run for 1 yd to the FSU 34" }, { "x": 111, "y": 0.10416666666666667, "text": "Roydell Williams run for 4 yds to the FSU 38 for a 1ST down" }, { "x": 112, "y": 0.10204081632653061, "text": "Tommy Castellanos pass incomplete" }, { "x": 113, "y": 0.1, "text": "Tommy Castellanos run for no gain to the FSU 38" }, { "x": 114, "y": 0.09803921568627451, "text": "Gavin Sawchuk run for 1 yd to the ALA 46" }, { "x": 115, "y": 0.11538461538461539, "text": "Micahi Danzy run for 26 yds to the ALA 20 for a 1ST down" }, { "x": 116, "y": 0.11320754716981132, "text": "Tommy Castellanos run for 6 yds to the ALA 14" }, { "x": 117, "y": 0.1111111111111111, "text": "Gavin Sawchuk run for 14 yds for a TD (Jake Weinberg KICK)" }, { "x": 126, "y": 0.10909090909090909, "text": "Gavin Sawchuk run for 1 yd to the 50 yard line" }, { "x": 127, "y": 0.10714285714285714, "text": "Tommy Castellanos run for 10 yds to the ALA 40 for a 1ST down" }, { "x": 128, "y": 0.10526315789473684, "text": "Caziah Holmes run for 3 yds to the ALA 37" }, { "x": 129, "y": 0.10344827586206896, "text": "Micahi Danzy run for a loss of 2 yards to the ALA 39" }, { "x": 130, "y": 0.1016949152542373, "text": "Jaylin Lucas run for 8 yds to the ALA 31" }, { "x": 131, "y": 0.1, "text": "Jaylin Lucas run for 2 yds to the ALA 29 for a 1ST down" }, { "x": 132, "y": 0.09836065573770492, "text": "TEAM run for a loss of 2 yards to the ALA 31" }, { "x": 133, "y": 0.0967741935483871, "text": "TEAM run for a loss of 2 yards to the ALA 33" }, { "x": 134, "y": 0.09523809523809523, "text": "TEAM run for a loss of 2 yards to the ALA 35" } ], "label": "Florida State XR", "borderColor": "#854D0ECC", "borderWidth": 2.2, "borderDash": [ 4, 4 ], "fill": false }, { "data": [ { "x": 17, "y": 0, "text": "Roydell Williams run for 2 yds to the FSU 27" }, { "x": 18, "y": 0, "text": "Tommy Castellanos pass complete to Duce Robinson for 3 yds to the FSU 30" }, { "x": 19, "y": 0.3333333333333333, "text": "Tommy Castellanos run for 12 yds to the ALA 48 for a 1ST down" }, { "x": 20, "y": 0.25, "text": "Gavin Sawchuk run for 5 yds to the FSU 47" }, { "x": 21, "y": 0.2, "text": "Tommy Castellanos pass complete to Randy Pittman Jr. for 4 yds to the ALA 49" }, { "x": 22, "y": 0.3333333333333333, "text": "Tommy Castellanos pass complete to Squirrel White for 40 yds to the ALA 9 for a 1ST down" }, { "x": 23, "y": 0.42857142857142855, "text": "Tommy Castellanos run for 9 yds for a TD (Jake Weinberg KICK)" }, { "x": 32, "y": 0.375, "text": "Tommy Castellanos pass complete to Gavin Sawchuk for 3 yds to the FSU 38" }, { "x": 33, "y": 0.3333333333333333, "text": "Tommy Castellanos pass complete to Jaylin Lucas for 2 yds to the FSU 40" }, { "x": 34, "y": 0.4, "text": "Tommy Castellanos pass complete to Randy Pittman Jr. for 14 yds to the ALA 46 for a 1ST down" }, { "x": 35, "y": 0.36363636363636365, "text": "Roydell Williams run for 1 yd to the ALA 45" }, { "x": 36, "y": 0.3333333333333333, "text": "Tommy Castellanos run for 5 yds to the ALA 40" }, { "x": 37, "y": 0.38461538461538464, "text": "Tommy Castellanos run for 5 yds to the ALA 35 for a 1ST down" }, { "x": 38, "y": 0.35714285714285715, "text": "Tommy Castellanos run for 3 yds to the ALA 32" }, { "x": 39, "y": 0.4, "text": "Micahi Danzy run for 32 yds for a TD (Jake Weinberg KICK)" }, { "x": 43, "y": 0.4375, "text": "Tommy Castellanos pass complete to Duce Robinson for 15 yds to the FSU 36 for a 1ST down" }, { "x": 44, "y": 0.4117647058823529, "text": "Ousmane Kromah run for no gain to the FSU 36" }, { "x": 45, "y": 0.4444444444444444, "text": "Ousmane Kromah run for 14 yds to the 50 yard line for a 1ST down" }, { "x": 46, "y": 0.42105263157894735, "text": "Ousmane Kromah run for 3 yds to the ALA 47" }, { "x": 47, "y": 0.45, "text": "Tommy Castellanos run for 14 yds to the ALA 33 for a 1ST down" }, { "x": 48, "y": 0.42857142857142855, "text": "Roydell Williams run for 2 yds to the ALA 31" }, { "x": 49, "y": 0.4090909090909091, "text": "Tommy Castellanos run for 4 yds to the ALA 27" }, { "x": 50, "y": 0.391304347826087, "text": "Tommy Castellanos pass incomplete to Duce Robinson" }, { "x": 57, "y": 0.375, "text": "Tommy Castellanos run for 4 yds to the FSU 24" }, { "x": 58, "y": 0.36, "text": "Jaylin Lucas run for 4 yds to the FSU 28" }, { "x": 59, "y": 0.38461538461538464, "text": "Jaylin Lucas run for 5 yds to the FSU 33 for a 1ST down" }, { "x": 60, "y": 0.37037037037037035, "text": "Jaylin Lucas run for 2 yds to the FSU 35" }, { "x": 61, "y": 0.35714285714285715, "text": "Roydell Williams run for no gain to the FSU 35" }, { "x": 62, "y": 0.3793103448275862, "text": "Ousmane Kromah run for 7 yds to the FSU 22" }, { "x": 63, "y": 0.4, "text": "Ousmane Kromah run for 5 yds to the FSU 27 for a 1ST down" }, { "x": 64, "y": 0.3870967741935484, "text": "Tommy Castellanos run for 2 yds to the FSU 29" }, { "x": 65, "y": 0.375, "text": "Tommy Castellanos pass incomplete" }, { "x": 66, "y": 0.36363636363636365, "text": "Tommy Castellanos pass complete to Ousmane Kromah for 7 yds to the FSU 31" }, { "x": 73, "y": 0.38235294117647056, "text": "Tommy Castellanos pass complete to Jaylin Lucas for 64 yds to the ALA 4 for a 1ST down" }, { "x": 74, "y": 0.4, "text": "Caziah Holmes run for 4 yds for a TD (Jake Weinberg KICK)" }, { "x": 85, "y": 0.4166666666666667, "text": "Gavin Sawchuk run for 5 yds to the FSU 30" }, { "x": 86, "y": 0.40540540540540543, "text": "Tommy Castellanos pass incomplete to Duce Robinson" }, { "x": 87, "y": 0.42105263157894735, "text": "Tommy Castellanos run for 6 yds to the ALA 36 for a 1ST down Alabama Penalty, Personal Foul (15 Yards) to the ALA 49 for a 1ST down" }, { "x": 88, "y": 0.4358974358974359, "text": "Roydell Williams run for 5 yds to the ALA 44" }, { "x": 89, "y": 0.425, "text": "Jaylin Lucas run for 1 yd to the ALA 43" }, { "x": 90, "y": 0.4146341463414634, "text": "Tommy Castellanos pass incomplete" }, { "x": 98, "y": 0.40476190476190477, "text": "Ousmane Kromah run for a loss of 1 yard to the FSU 27" }, { "x": 99, "y": 0.3953488372093023, "text": "Gavin Sawchuk run for 2 yds to the FSU 29" }, { "x": 100, "y": 0.38636363636363635, "text": "Tommy Castellanos sacked by Keon Sabb for a loss of 8 yards to the FSU 21" }, { "x": 108, "y": 0.37777777777777777, "text": "Ousmane Kromah run for 3 yds to the FSU 28" }, { "x": 109, "y": 0.391304347826087, "text": "Tommy Castellanos run for 5 yds to the FSU 33" }, { "x": 110, "y": 0.3829787234042553, "text": "Tommy Castellanos run for 1 yd to the FSU 34" }, { "x": 111, "y": 0.3958333333333333, "text": "Roydell Williams run for 4 yds to the FSU 38 for a 1ST down" }, { "x": 112, "y": 0.3877551020408163, "text": "Tommy Castellanos pass incomplete" }, { "x": 113, "y": 0.38, "text": "Tommy Castellanos run for no gain to the FSU 38" }, { "x": 114, "y": 0.37254901960784315, "text": "Gavin Sawchuk run for 1 yd to the ALA 46" }, { "x": 115, "y": 0.38461538461538464, "text": "Micahi Danzy run for 26 yds to the ALA 20 for a 1ST down" }, { "x": 116, "y": 0.39622641509433965, "text": "Tommy Castellanos run for 6 yds to the ALA 14" }, { "x": 117, "y": 0.4074074074074074, "text": "Gavin Sawchuk run for 14 yds for a TD (Jake Weinberg KICK)" }, { "x": 126, "y": 0.4, "text": "Gavin Sawchuk run for 1 yd to the 50 yard line" }, { "x": 127, "y": 0.4107142857142857, "text": "Tommy Castellanos run for 10 yds to the ALA 40 for a 1ST down" }, { "x": 128, "y": 0.40350877192982454, "text": "Caziah Holmes run for 3 yds to the ALA 37" }, { "x": 129, "y": 0.39655172413793105, "text": "Micahi Danzy run for a loss of 2 yards to the ALA 39" }, { "x": 130, "y": 0.3898305084745763, "text": "Jaylin Lucas run for 8 yds to the ALA 31" }, { "x": 131, "y": 0.4, "text": "Jaylin Lucas run for 2 yds to the ALA 29 for a 1ST down" }, { "x": 132, "y": 0.39344262295081966, "text": "TEAM run for a loss of 2 yards to the ALA 31" }, { "x": 133, "y": 0.3870967741935484, "text": "TEAM run for a loss of 2 yards to the ALA 33" }, { "x": 134, "y": 0.38095238095238093, "text": "TEAM run for a loss of 2 yards to the ALA 35" } ], "label": "Florida State SR", "borderColor": "#CA8A04CC", "borderWidth": 2.2, "borderDash": [ 4, 4 ], "fill": false }, { "label": "Quarters", "data": [ { "x": 1, "y": 0 }, { "x": 1, "y": 1 }, { "x": 134, "y": 1 }, { "x": 134, "y": 0 }, { "x": 30, "y": 0 }, { "x": 30, "y": 1 }, { "x": 134, "y": 1 }, { "x": 134, "y": 0 }, { "x": 62, "y": 0 }, { "x": 62, "y": 1 }, { "x": 134, "y": 1 }, { "x": 134, "y": 0 }, { "x": 100, "y": 0 }, { "x": 100, "y": 1 }, { "x": 134, "y": 1 }, { "x": 134, "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": 1, "seasonType": "regular", "team": "Alabama", "gameId": "401752665" } }; // Chart options (WordPress-safe) const chartOptions = { responsive: true, maintainAspectRatio: false, animation: { duration: 0 // Disable animations to prevent conflicts }, elements: 'line' === 'line' ? 'team-lines'.includes('play-map') ? { line: { tension: 0, borderWidth: 0 } } : { line: { tension: 0.25, borderWidth: 2.2 }, point: { pointRadius: 'team-lines'.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-lines' === '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-lines'.includes('top-rushers') || 'team-lines'.includes('top-passers') || 'team-lines'.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: 'line' === 'line' ? { position: 'top', align: 'start', labels: 'team-lines'.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: { filter: function(tooltipItem) { if ('team-lines'.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('< 0') && !tooltipItem.dataset.label.includes('Quarters'); }, callbacks: { label: function(context) { const label = context.dataset.label || ''; let labelText; // Play maps show yards instead of percentages if ('team-lines'.includes('play-map')) { labelText = label + ': ' + context.parsed.y + ' yards'; } else { const value = Math.round(context.parsed.y * 100); labelText = label + ': ' + value + '%'; } // For line charts, include play text if available if ('line' === 'line' && context.raw && context.raw.text) { return [labelText, context.raw.text]; } return labelText; } } } }, scales: 'line' === 'line' ? 'team-lines'.includes('play-map') ? { x: { type: 'linear', position: 'bottom', title: { display: true, text: 'Play Number' }, min: 1, ticks: { stepSize: 1, callback: function(value) { return Math.floor(value); } }, grid: { display: false } }, y: { title: { display: true, text: 'Yards Gained' }, min: chartData.minY, max: chartData.maxY } } : { x: { type: 'linear', position: 'bottom', title: { display: true, text: 'team-lines'.includes('team-lines') ? 'Play Number' : 'Team Play Number' }, min: 1, ticks: { stepSize: 1, callback: function(value) { return Math.floor(value); } }, grid: { display: false } }, y: { max: 1, min: 0, ticks: { callback: function(value) { return Math.round(value * 100) + '%'; } } } } : 'team-lines'.includes('drive-metrics') ? { y: { stacked: false, max: 1, ticks: { callback: function(value) { return Math.round(value * 100) + '%'; } } }, y1: { display: false, type: 'linear', position: 'right' } } : ('team-lines'.includes('top-rushers') || 'team-lines'.includes('top-passers') || 'team-lines'.includes('top-receivers')) ? { x: { stacked: true }, y: { stacked: true } } : { y: { max: 1, min: 0, stacked: false, ticks: { callback: function(value) { return Math.round(value * 100) + '%'; } } } } }; // Add indexAxis for player charts if ('team-lines'.includes('top-rushers') || 'team-lines'.includes('top-passers') || 'team-lines'.includes('top-receivers')) { chartOptions.indexAxis = 'y'; } // 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-1756660405610-za0zev8kn').parentNode; if (container) { container.innerHTML = '
Chart failed to load. Please refresh the page.
'; } } } // Initialize when DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initChart); } else { initChart(); } // Also try initialization after a short delay for WordPress compatibility setTimeout(initChart, 500); })();
Alabama had a solid initial drive, with SR’s up above 60% and maintaining that through the 1st quarter. The problem was … the remaining quarters, where things started showing signs of trouble in the 2nd before really dropping off in the 3rd.
Funny enough, Alabama’s success rate seemed to have an inverse correlation with explosiveness rate, which is not what you expect to see. As the SR dipped in the 2nd and 3rd quarter, we started to actually get a few explosive plays here and there. This SR devolution as especially sharp in the third quarter, when Florida State’s success rate actually maintained well enough (for the whole game, really) simply match Alabama’s just due to Alabama’s declining performance.
Florida State also put up enough explosive plays to keep things not only “interesting,” but to keep the lead for most of this game, which is frustrating … especially when you see how close Alabama got in a few moments to changing what you could call “momentum.”
// Toggle data definitions accordion - unique function per embed function toggleDefinitions_cfb_chart_1756660621381_8487qkgi5() { const definitions = document.getElementById('dataDefinitions_cfb-chart-1756660621381-8487qkgi5'); const caret = document.getElementById('caret_cfb-chart-1756660621381-8487qkgi5'); if (definitions.classList.contains('expanded')) { definitions.classList.remove('expanded'); caret.classList.remove('expanded'); } else { definitions.classList.add('expanded'); caret.classList.add('expanded'); } } // WordPress-safe chart initialization with defensive checks (function() { 'use strict'; function initChart() { // Check if Chart.js is available if (typeof Chart === 'undefined') { console.warn('Chart.js not loaded yet, retrying...'); setTimeout(initChart, 100); return; } // Check if datalabels plugin is available if (typeof ChartDataLabels === 'undefined') { console.warn('ChartDataLabels plugin not loaded yet, retrying...'); setTimeout(initChart, 100); return; } // Check if canvas element exists const canvas = document.getElementById('cfb-chart-1756660621381-8487qkgi5'); 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": 63, "y": 0.5 }, { "x": 63, "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": "Roydell Williams run for 2 yds to the FSU 27" }, { "x": 2, "y": 0.5, "text": "Tommy Castellanos pass complete to Duce Robinson for 3 yds to the FSU 30" }, { "x": 3, "y": 0.6666666666666666, "text": "Tommy Castellanos run for 12 yds to the ALA 48 for a 1ST down" }, { "x": 4, "y": 0.75, "text": "Gavin Sawchuk run for 5 yds to the FSU 47" }, { "x": 5, "y": 0.6, "text": "Tommy Castellanos pass complete to Randy Pittman Jr. for 4 yds to the ALA 49" }, { "x": 6, "y": 0.5, "text": "Tommy Castellanos pass complete to Squirrel White for 40 yds to the ALA 9 for a 1ST down" }, { "x": 7, "y": 0.5714285714285714, "text": "Tommy Castellanos run for 9 yds for a TD (Jake Weinberg KICK)" }, { "x": 8, "y": 0.5, "text": "Tommy Castellanos pass complete to Gavin Sawchuk for 3 yds to the FSU 38" }, { "x": 9, "y": 0.4444444444444444, "text": "Tommy Castellanos pass complete to Jaylin Lucas for 2 yds to the FSU 40" }, { "x": 10, "y": 0.4, "text": "Tommy Castellanos pass complete to Randy Pittman Jr. for 14 yds to the ALA 46 for a 1ST down" }, { "x": 11, "y": 0.45454545454545453, "text": "Roydell Williams run for 1 yd to the ALA 45" }, { "x": 12, "y": 0.5, "text": "Tommy Castellanos run for 5 yds to the ALA 40" }, { "x": 13, "y": 0.5384615384615384, "text": "Tommy Castellanos run for 5 yds to the ALA 35 for a 1ST down" }, { "x": 14, "y": 0.5714285714285714, "text": "Tommy Castellanos run for 3 yds to the ALA 32" }, { "x": 15, "y": 0.6, "text": "Micahi Danzy run for 32 yds for a TD (Jake Weinberg KICK)" }, { "x": 16, "y": 0.5625, "text": "Tommy Castellanos pass complete to Duce Robinson for 15 yds to the FSU 36 for a 1ST down" }, { "x": 17, "y": 0.5882352941176471, "text": "Ousmane Kromah run for no gain to the FSU 36" }, { "x": 18, "y": 0.6111111111111112, "text": "Ousmane Kromah run for 14 yds to the 50 yard line for a 1ST down" }, { "x": 19, "y": 0.631578947368421, "text": "Ousmane Kromah run for 3 yds to the ALA 47" }, { "x": 20, "y": 0.65, "text": "Tommy Castellanos run for 14 yds to the ALA 33 for a 1ST down" }, { "x": 21, "y": 0.6666666666666666, "text": "Roydell Williams run for 2 yds to the ALA 31" }, { "x": 22, "y": 0.6818181818181818, "text": "Tommy Castellanos run for 4 yds to the ALA 27" }, { "x": 23, "y": 0.6521739130434783, "text": "Tommy Castellanos pass incomplete to Duce Robinson" }, { "x": 24, "y": 0.6666666666666666, "text": "Tommy Castellanos run for 4 yds to the FSU 24" }, { "x": 25, "y": 0.68, "text": "Jaylin Lucas run for 4 yds to the FSU 28" }, { "x": 26, "y": 0.6923076923076923, "text": "Jaylin Lucas run for 5 yds to the FSU 33 for a 1ST down" }, { "x": 27, "y": 0.7037037037037037, "text": "Jaylin Lucas run for 2 yds to the FSU 35" }, { "x": 28, "y": 0.7142857142857143, "text": "Roydell Williams run for no gain to the FSU 35" }, { "x": 29, "y": 0.7241379310344828, "text": "Ousmane Kromah run for 7 yds to the FSU 22" }, { "x": 30, "y": 0.7333333333333333, "text": "Ousmane Kromah run for 5 yds to the FSU 27 for a 1ST down" }, { "x": 31, "y": 0.7419354838709677, "text": "Tommy Castellanos run for 2 yds to the FSU 29" }, { "x": 32, "y": 0.71875, "text": "Tommy Castellanos pass incomplete" }, { "x": 33, "y": 0.696969696969697, "text": "Tommy Castellanos pass complete to Ousmane Kromah for 7 yds to the FSU 31" }, { "x": 34, "y": 0.6764705882352942, "text": "Tommy Castellanos pass complete to Jaylin Lucas for 64 yds to the ALA 4 for a 1ST down" }, { "x": 35, "y": 0.6857142857142857, "text": "Caziah Holmes run for 4 yds for a TD (Jake Weinberg KICK)" }, { "x": 36, "y": 0.6944444444444444, "text": "Gavin Sawchuk run for 5 yds to the FSU 30" }, { "x": 37, "y": 0.6756756756756757, "text": "Tommy Castellanos pass incomplete to Duce Robinson" }, { "x": 38, "y": 0.6842105263157895, "text": "Tommy Castellanos run for 6 yds to the ALA 36 for a 1ST down Alabama Penalty, Personal Foul (15 Yards) to the ALA 49 for a 1ST down" }, { "x": 39, "y": 0.6923076923076923, "text": "Roydell Williams run for 5 yds to the ALA 44" }, { "x": 40, "y": 0.7, "text": "Jaylin Lucas run for 1 yd to the ALA 43" }, { "x": 41, "y": 0.6829268292682927, "text": "Tommy Castellanos pass incomplete" }, { "x": 42, "y": 0.6904761904761905, "text": "Ousmane Kromah run for a loss of 1 yard to the FSU 27" }, { "x": 43, "y": 0.6976744186046512, "text": "Gavin Sawchuk run for 2 yds to the FSU 29" }, { "x": 44, "y": 0.6818181818181818, "text": "Tommy Castellanos sacked by Keon Sabb for a loss of 8 yards to the FSU 21" }, { "x": 45, "y": 0.6888888888888889, "text": "Ousmane Kromah run for 3 yds to the FSU 28" }, { "x": 46, "y": 0.6956521739130435, "text": "Tommy Castellanos run for 5 yds to the FSU 33" }, { "x": 47, "y": 0.7021276595744681, "text": "Tommy Castellanos run for 1 yd to the FSU 34" }, { "x": 48, "y": 0.7083333333333334, "text": "Roydell Williams run for 4 yds to the FSU 38 for a 1ST down" }, { "x": 49, "y": 0.6938775510204082, "text": "Tommy Castellanos pass incomplete" }, { "x": 50, "y": 0.7, "text": "Tommy Castellanos run for no gain to the FSU 38" }, { "x": 51, "y": 0.7058823529411765, "text": "Gavin Sawchuk run for 1 yd to the ALA 46" }, { "x": 52, "y": 0.7115384615384616, "text": "Micahi Danzy run for 26 yds to the ALA 20 for a 1ST down" }, { "x": 53, "y": 0.7169811320754716, "text": "Tommy Castellanos run for 6 yds to the ALA 14" }, { "x": 54, "y": 0.7222222222222222, "text": "Gavin Sawchuk run for 14 yds for a TD (Jake Weinberg KICK)" }, { "x": 55, "y": 0.7272727272727273, "text": "Gavin Sawchuk run for 1 yd to the 50 yard line" }, { "x": 56, "y": 0.7321428571428571, "text": "Tommy Castellanos run for 10 yds to the ALA 40 for a 1ST down" }, { "x": 57, "y": 0.7368421052631579, "text": "Caziah Holmes run for 3 yds to the ALA 37" }, { "x": 58, "y": 0.7413793103448276, "text": "Micahi Danzy run for a loss of 2 yards to the ALA 39" }, { "x": 59, "y": 0.7457627118644068, "text": "Jaylin Lucas run for 8 yds to the ALA 31" }, { "x": 60, "y": 0.75, "text": "Jaylin Lucas run for 2 yds to the ALA 29 for a 1ST down" }, { "x": 61, "y": 0.7540983606557377, "text": "TEAM run for a loss of 2 yards to the ALA 31" }, { "x": 62, "y": 0.7580645161290323, "text": "TEAM run for a loss of 2 yards to the ALA 33" }, { "x": 63, "y": 0.7619047619047619, "text": "TEAM run for a loss of 2 yards to the ALA 35" } ], "label": "Florida State Rush Rate", "borderColor": "#854D0ECC", "backgroundColor": "#FEF3C7CC", "borderWidth": 2, "pointBackgroundColor": [ "rgba(255,255,255,0.9)", "rgba(255,255,255,0.9)", "#CA8A04CC", "rgba(255,255,255,0.9)", "rgba(255,255,255,0.9)", "#854D0ECC", "#CA8A04CC", "rgba(255,255,255,0.9)", "rgba(255,255,255,0.9)", "#CA8A04CC", "rgba(255,255,255,0.9)", "rgba(255,255,255,0.9)", "#CA8A04CC", "rgba(255,255,255,0.9)", "#854D0ECC", "#854D0ECC", "rgba(255,255,255,0.9)", "#CA8A04CC", "rgba(255,255,255,0.9)", "#CA8A04CC", "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)", "#CA8A04CC", "rgba(255,255,255,0.9)", "rgba(255,255,255,0.9)", "#CA8A04CC", "#CA8A04CC", "rgba(255,255,255,0.9)", "rgba(255,255,255,0.9)", "rgba(255,255,255,0.9)", "#854D0ECC", "#CA8A04CC", "#CA8A04CC", "rgba(255,255,255,0.9)", "#854D0ECC", "#CA8A04CC", "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(255,255,255,0.9)", "#CA8A04CC", "rgba(255,255,255,0.9)", "#CA8A04CC", "rgba(255,255,255,0.9)", "rgba(255,255,255,0.9)", "rgba(255,255,255,0.9)", "#854D0ECC", "#CA8A04CC", "#CA8A04CC", "rgba(255,255,255,0.9)", "#CA8A04CC", "rgba(255,255,255,0.9)", "rgba(255,255,255,0.9)", "rgba(255,255,255,0.9)", "#CA8A04CC", "rgba(255,255,255,0.9)", "rgba(255,255,255,0.9)", "rgba(255,255,255,0.9)" ], "pointStyle": [ "circle", "triangle", "circle", "circle", "triangle", "triangle", "circle", "triangle", "triangle", "triangle", "circle", "circle", "circle", "circle", "circle", "triangle", "circle", "circle", "circle", "circle", "circle", "circle", "triangle", "circle", "circle", "circle", "circle", "circle", "circle", "circle", "circle", "triangle", "triangle", "triangle", "circle", "circle", "triangle", "circle", "circle", "circle", "triangle", "circle", "circle", "triangle", "circle", "circle", "circle", "circle", "triangle", "circle", "circle", "circle", "circle", "circle", "circle", "circle", "circle", "circle", "circle", "circle", "circle", "circle", "circle" ], "pointRadius": [ 4, 5.5, 4, 4, 5.5, 5.5, 4, 5.5, 5.5, 5.5, 4, 4, 4, 4, 4, 5.5, 4, 4, 4, 4, 4, 4, 5.5, 4, 4, 4, 4, 4, 4, 4, 4, 5.5, 5.5, 5.5, 4, 4, 5.5, 4, 4, 4, 5.5, 4, 4, 5.5, 4, 4, 4, 4, 5.5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 ], "pointBorderWidth": 1, "pointBorderColor": "#854D0ECC", "fill": true }, { "label": "Quarters", "data": [ { "x": 1, "y": 0 }, { "x": 1, "y": 1 }, { "x": 63, "y": 1 }, { "x": 63, "y": 0 }, { "x": 8, "y": 0 }, { "x": 8, "y": 1 }, { "x": 63, "y": 1 }, { "x": 63, "y": 0 }, { "x": 29, "y": 0 }, { "x": 29, "y": 1 }, { "x": 63, "y": 1 }, { "x": 63, "y": 0 }, { "x": 44, "y": 0 }, { "x": 44, "y": 1 }, { "x": 63, "y": 1 }, { "x": 63, "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": 1, "seasonType": "regular", "team": "Alabama", "gameId": "401752665" } }; // Chart options (WordPress-safe) const chartOptions = { responsive: true, maintainAspectRatio: false, animation: { duration: 0 // Disable animations to prevent conflicts }, elements: 'line' === 'line' ? 'opponent-rush-rate'.includes('play-map') ? { line: { tension: 0, borderWidth: 0 } } : { line: { tension: 0.25, borderWidth: 2.2 }, point: { pointRadius: 'opponent-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 ('opponent-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 ('opponent-rush-rate'.includes('top-rushers') || 'opponent-rush-rate'.includes('top-passers') || 'opponent-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: 'line' === 'line' ? { position: 'top', align: 'start', labels: 'opponent-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: { filter: function(tooltipItem) { if ('opponent-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('< 0') && !tooltipItem.dataset.label.includes('Quarters'); }, callbacks: { label: function(context) { const label = context.dataset.label || ''; let labelText; // Play maps show yards instead of percentages if ('opponent-rush-rate'.includes('play-map')) { labelText = label + ': ' + context.parsed.y + ' yards'; } else { const value = Math.round(context.parsed.y * 100); labelText = label + ': ' + value + '%'; } // For line charts, include play text if available if ('line' === 'line' && context.raw && context.raw.text) { return [labelText, context.raw.text]; } return labelText; } } } }, scales: 'line' === 'line' ? 'opponent-rush-rate'.includes('play-map') ? { x: { type: 'linear', position: 'bottom', title: { display: true, text: 'Play Number' }, min: 1, ticks: { stepSize: 1, callback: function(value) { return Math.floor(value); } }, grid: { display: false } }, y: { title: { display: true, text: 'Yards Gained' }, min: chartData.minY, max: chartData.maxY } } : { x: { type: 'linear', position: 'bottom', title: { display: true, text: 'opponent-rush-rate'.includes('team-lines') ? 'Play Number' : 'Team Play Number' }, min: 1, ticks: { stepSize: 1, callback: function(value) { return Math.floor(value); } }, grid: { display: false } }, y: { max: 1, min: 0, ticks: { callback: function(value) { return Math.round(value * 100) + '%'; } } } } : 'opponent-rush-rate'.includes('drive-metrics') ? { y: { stacked: false, max: 1, ticks: { callback: function(value) { return Math.round(value * 100) + '%'; } } }, y1: { display: false, type: 'linear', position: 'right' } } : ('opponent-rush-rate'.includes('top-rushers') || 'opponent-rush-rate'.includes('top-passers') || 'opponent-rush-rate'.includes('top-receivers')) ? { x: { stacked: true }, y: { stacked: true } } : { y: { max: 1, min: 0, stacked: false, ticks: { callback: function(value) { return Math.round(value * 100) + '%'; } } } } }; // Add indexAxis for player charts if ('opponent-rush-rate'.includes('top-rushers') || 'opponent-rush-rate'.includes('top-passers') || 'opponent-rush-rate'.includes('top-receivers')) { chartOptions.indexAxis = 'y'; } // 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-1756660621381-8487qkgi5').parentNode; if (container) { container.innerHTML = '
Chart failed to load. Please refresh the page.
'; } } } // Initialize when DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initChart); } else { initChart(); } // Also try initialization after a short delay for WordPress compatibility setTimeout(initChart, 500); })();
Florida State started out with a surprisingly balanced offense. This hot-headed quarterback, Tommy Castellanos, had created headlines this summer and set himself up for what could have been a classic faceplant. Boy, I was looking forward to it. However, he did well enough in the first quarter with some passing and some running, including two explosive passes in the first half and another one in the third quarter. (And then ran well enough to back up his talk).
Overall, though, you’re seeing what a Malzahn offense (with a mobile QB) was able to do once it learned that Alabama couldn’t stop the run. Florida State’s rushing rate shot up in the 2nd quarter and stayed up throughout the rest of the game.
Honestly, on that big broken play in the 3rd quarter (where our secondary let a wheel route scamper for 64 yards), I almost relate to the guy in the secondary who did not expect to see a pass. I mean … this was like playing Army for a little while, where whenever the team does pass the ball (notably only about ten times in this game) it’s truly a surprise. Turns out that FSU didn’t need to pass the ball very much to make this work, though
// Toggle data definitions accordion - unique function per embed function toggleDefinitions_cfb_chart_1756660727915_38m2mf0ga() { const definitions = document.getElementById('dataDefinitions_cfb-chart-1756660727915-38m2mf0ga'); const caret = document.getElementById('caret_cfb-chart-1756660727915-38m2mf0ga'); if (definitions.classList.contains('expanded')) { definitions.classList.remove('expanded'); caret.classList.remove('expanded'); } else { definitions.classList.add('expanded'); caret.classList.add('expanded'); } } // WordPress-safe chart initialization with defensive checks (function() { 'use strict'; function initChart() { // Check if Chart.js is available if (typeof Chart === 'undefined') { console.warn('Chart.js not loaded yet, retrying...'); setTimeout(initChart, 100); return; } // Check if datalabels plugin is available if (typeof ChartDataLabels === 'undefined') { console.warn('ChartDataLabels plugin not loaded yet, retrying...'); setTimeout(initChart, 100); return; } // Check if canvas element exists const canvas = document.getElementById('cfb-chart-1756660727915-38m2mf0ga'); 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": 71, "y": 0.5 }, { "x": 71, "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": "Richard Young run for 6 yds to the ALA 31" }, { "x": 2, "y": 0.5, "text": "Ty Simpson pass complete to Germie Bernard for 12 yds to the ALA 43 for a 1ST down" }, { "x": 3, "y": 0.6666666666666666, "text": "Richard Young run for 3 yds to the ALA 46" }, { "x": 4, "y": 0.75, "text": "Ty Simpson run for 5 yds to the FSU 49" }, { "x": 5, "y": 0.8, "text": "Ty Simpson run for 6 yds to the FSU 48" }, { "x": 6, "y": 0.8333333333333334, "text": "Richard Young run for 1 yd to the FSU 47 for a 1ST down" }, { "x": 7, "y": 0.8571428571428571, "text": "Daniel Hill run for 7 yds to the FSU 40" }, { "x": 8, "y": 0.875, "text": "Daniel Hill run for a loss of 2 yards to the FSU 42" }, { "x": 9, "y": 0.8888888888888888, "text": "Richard Young run for 6 yds to the FSU 36 for a 1ST down" }, { "x": 10, "y": 0.9, "text": "Kevin Riley run for 13 yds to the FSU 23 for a 1ST down" }, { "x": 11, "y": 0.9090909090909091, "text": "Kevin Riley run for 4 yds to the FSU 19" }, { "x": 12, "y": 0.8333333333333334, "text": "Ty Simpson pass incomplete to Germie Bernard" }, { "x": 13, "y": 0.8461538461538461, "text": "Ty Simpson run for 6 yds to the FSU 13 for a 1ST down" }, { "x": 14, "y": 0.7857142857142857, "text": "Ty Simpson pass complete to Ryan Williams for 11 yds to the FSU 2 for a 1ST down" }, { "x": 15, "y": 0.8, "text": "Richard Young run for no gain to the FSU 2" }, { "x": 16, "y": 0.75, "text": "Ty Simpson pass complete to Josh Cuevas for 2 yds for a TD (Conor Talty KICK)" }, { "x": 17, "y": 0.7647058823529411, "text": "Richard Young run for no gain to the ALA 25" }, { "x": 18, "y": 0.7222222222222222, "text": "Ty Simpson pass complete to Germie Bernard for 29 yds to the FSU 46 for a 1ST down" }, { "x": 19, "y": 0.6842105263157895, "text": "Ty Simpson pass complete to Ryan Williams for 5 yds to the FSU 41" }, { "x": 20, "y": 0.7, "text": "Richard Young run for 3 yds to the FSU 38" }, { "x": 21, "y": 0.6666666666666666, "text": "Ty Simpson pass complete to Germie Bernard for 12 yds to the FSU 26 for a 1ST down" }, { "x": 22, "y": 0.6363636363636364, "text": "Ty Simpson pass complete to Isaiah Horton for 6 yds to the FSU 20" }, { "x": 23, "y": 0.6086956521739131, "text": "Ty Simpson pass complete to Germie Bernard for a loss of 4 yards to the FSU 24" }, { "x": 24, "y": 0.5833333333333334, "text": "Ty Simpson sacked by Deamontae Diggs for a loss of 6 yards to the FSU 35" }, { "x": 25, "y": 0.56, "text": "Ty Simpson pass incomplete to Josh Cuevas" }, { "x": 26, "y": 0.5769230769230769, "text": "Kevin Riley run for 2 yds to the ALA 27" }, { "x": 27, "y": 0.5555555555555556, "text": "Ty Simpson pass incomplete" }, { "x": 28, "y": 0.5714285714285714, "text": "Richard Young run for 6 yds to the ALA 31" }, { "x": 29, "y": 0.5862068965517241, "text": "Richard Young run for 1 yd to the ALA 32" }, { "x": 30, "y": 0.5666666666666667, "text": "Ty Simpson pass complete to Ryan Williams for 8 yds to the ALA 40 for a 1ST down" }, { "x": 31, "y": 0.5483870967741935, "text": "Ty Simpson pass complete to Richard Young for 6 yds to the ALA 46" }, { "x": 32, "y": 0.53125, "text": "Ty Simpson pass incomplete to Germie Bernard" }, { "x": 33, "y": 0.5454545454545454, "text": "Ty Simpson run for no gain to the ALA 46" }, { "x": 34, "y": 0.5294117647058824, "text": "Ty Simpson pass incomplete to Rico Scott" }, { "x": 35, "y": 0.5142857142857142, "text": "Ty Simpson pass complete to Germie Bernard for 30 yds to the FSU 41 for a 1ST down" }, { "x": 36, "y": 0.5, "text": "Ty Simpson pass complete to Josh Cuevas for 2 yds to the FSU 39" }, { "x": 37, "y": 0.4864864864864865, "text": "Ty Simpson pass complete to Ryan Williams for 3 yds to the FSU 36" }, { "x": 38, "y": 0.47368421052631576, "text": "Ty Simpson pass incomplete" }, { "x": 39, "y": 0.46153846153846156, "text": "Ty Simpson pass complete to Kevin Riley for 4 yds to the FSU 32" }, { "x": 40, "y": 0.475, "text": "Daniel Hill run for 4 yds to the ALA 29" }, { "x": 41, "y": 0.4634146341463415, "text": "Ty Simpson pass complete to Germie Bernard for 37 yds to the FSU 44 for a 1ST down" }, { "x": 42, "y": 0.4523809523809524, "text": "Ty Simpson pass incomplete to Ryan Williams" }, { "x": 43, "y": 0.46511627906976744, "text": "Dre Washington run for a loss of 1 yard to the FSU 45" }, { "x": 44, "y": 0.45454545454545453, "text": "Ty Simpson pass complete to Germie Bernard for 18 yds to the FSU 27 for a 1ST down" }, { "x": 45, "y": 0.4666666666666667, "text": "Dre Washington run for 2 yds to the FSU 25" }, { "x": 46, "y": 0.45652173913043476, "text": "Ty Simpson pass incomplete to Rico Scott" }, { "x": 47, "y": 0.44680851063829785, "text": "Ty Simpson pass incomplete" }, { "x": 48, "y": 0.4375, "text": "Ty Simpson pass incomplete to Ryan Williams" }, { "x": 49, "y": 0.42857142857142855, "text": "Ty Simpson pass incomplete to Josh Cuevas" }, { "x": 50, "y": 0.42, "text": "Ty Simpson sacked by Stefon Thompson for a loss of 7 yards to the ALA 13" }, { "x": 51, "y": 0.4117647058823529, "text": "Ty Simpson pass incomplete" }, { "x": 52, "y": 0.4230769230769231, "text": "Ty Simpson run for 6 yds to the ALA 19" }, { "x": 53, "y": 0.4339622641509434, "text": "Germie Bernard run for 3 yds to the FSU 28" }, { "x": 54, "y": 0.42592592592592593, "text": "Ty Simpson pass incomplete" }, { "x": 55, "y": 0.41818181818181815, "text": "Ty Simpson pass incomplete to Germie Bernard" }, { "x": 56, "y": 0.4107142857142857, "text": "Ty Simpson pass incomplete to Ryan Williams" }, { "x": 57, "y": 0.40350877192982454, "text": "Ty Simpson pass complete to Ryan Williams for 3 yds to the ALA 40" }, { "x": 58, "y": 0.39655172413793105, "text": "Ty Simpson pass complete to Josh Cuevas for 27 yds to the FSU 33 for a 1ST down" }, { "x": 59, "y": 0.3898305084745763, "text": "Ty Simpson pass complete to Daniel Hill for 3 yds to the FSU 30" }, { "x": 60, "y": 0.4, "text": "Kevin Riley run for 6 yds to the FSU 24" }, { "x": 61, "y": 0.4098360655737705, "text": "Kevin Riley run for 6 yds to the FSU 18 for a 1ST down" }, { "x": 62, "y": 0.4032258064516129, "text": "Ty Simpson pass complete to Germie Bernard for 12 yds to the FSU 6 for a 1ST down" }, { "x": 63, "y": 0.3968253968253968, "text": "Ty Simpson pass complete to Rico Scott for 6 yds for a TD (Conor Talty KICK)" }, { "x": 64, "y": 0.390625, "text": "Ty Simpson pass complete to Daniel Hill for 9 yds to the ALA 34" }, { "x": 65, "y": 0.38461538461538464, "text": "Ty Simpson pass incomplete" }, { "x": 66, "y": 0.3787878787878788, "text": "Ty Simpson pass incomplete" }, { "x": 67, "y": 0.373134328358209, "text": "Ty Simpson pass complete to Rico Scott for 13 yds to the ALA 42 for a 1ST down" }, { "x": 68, "y": 0.36764705882352944, "text": "Ty Simpson pass incomplete" }, { "x": 69, "y": 0.36231884057971014, "text": "Ty Simpson pass incomplete to Ryan Williams" }, { "x": 70, "y": 0.35714285714285715, "text": "Ty Simpson pass incomplete to Jalen Hale" }, { "x": 71, "y": 0.36619718309859156, "text": "Ty Simpson run for 9 yds to the FSU 49" } ], "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(175, 40, 60, 0.8)", "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(175, 40, 60, 0.8)", "rgba(255,255,255,0.9)", "rgba(175, 40, 60, 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(175, 40, 60, 0.8)", "rgba(255,255,255,0.9)", "rgba(175, 40, 60, 0.8)", "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(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(175, 40, 60, 0.8)", "rgba(255,255,255,0.9)", "rgba(175, 40, 60, 0.8)", "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(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)", "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(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)", "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(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(175, 40, 60, 0.8)", "rgba(175, 40, 60, 0.8)", "rgba(175, 40, 60, 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(255,255,255,0.9)", "rgba(255,255,255,0.9)" ], "pointStyle": [ "circle", "triangle", "circle", "circle", "circle", "circle", "circle", "circle", "circle", "circle", "circle", "triangle", "circle", "triangle", "circle", "triangle", "circle", "triangle", "triangle", "circle", "triangle", "triangle", "triangle", "triangle", "triangle", "circle", "triangle", "circle", "circle", "triangle", "triangle", "triangle", "circle", "triangle", "triangle", "triangle", "triangle", "triangle", "triangle", "circle", "triangle", "triangle", "circle", "triangle", "circle", "triangle", "triangle", "triangle", "triangle", "triangle", "triangle", "circle", "circle", "triangle", "triangle", "triangle", "triangle", "triangle", "triangle", "circle", "circle", "triangle", "triangle", "triangle", "triangle", "triangle", "triangle", "triangle", "triangle", "triangle", "circle" ], "pointRadius": [ 4, 5.5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5.5, 4, 5.5, 4, 5.5, 4, 5.5, 5.5, 4, 5.5, 5.5, 5.5, 5.5, 5.5, 4, 5.5, 4, 4, 5.5, 5.5, 5.5, 4, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 4, 5.5, 5.5, 4, 5.5, 4, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 4, 4, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 4, 4, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 5.5, 4 ], "pointBorderWidth": 1, "pointBorderColor": "rgba(101, 0, 20, 0.8)", "fill": true }, { "label": "Quarters", "data": [ { "x": 1, "y": 0 }, { "x": 1, "y": 1 }, { "x": 71, "y": 1 }, { "x": 71, "y": 0 }, { "x": 23, "y": 0 }, { "x": 23, "y": 1 }, { "x": 71, "y": 1 }, { "x": 71, "y": 0 }, { "x": 34, "y": 0 }, { "x": 34, "y": 1 }, { "x": 71, "y": 1 }, { "x": 71, "y": 0 }, { "x": 57, "y": 0 }, { "x": 57, "y": 1 }, { "x": 71, "y": 1 }, { "x": 71, "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": 1, "seasonType": "regular", "team": "Alabama", "gameId": "401752665" } }; // Chart options (WordPress-safe) const chartOptions = { responsive: true, maintainAspectRatio: false, animation: { duration: 0 // Disable animations to prevent conflicts }, elements: 'line' === 'line' ? 'team-rush-rate'.includes('play-map') ? { line: { tension: 0, borderWidth: 0 } } : { 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: '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: { 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('< 0') && !tooltipItem.dataset.label.includes('Quarters'); }, callbacks: { label: function(context) { const label = context.dataset.label || ''; let labelText; // Play maps show yards instead of percentages if ('team-rush-rate'.includes('play-map')) { labelText = label + ': ' + context.parsed.y + ' yards'; } else { const value = Math.round(context.parsed.y * 100); labelText = label + ': ' + value + '%'; } // For line charts, include play text if available if ('line' === 'line' && context.raw && context.raw.text) { return [labelText, context.raw.text]; } return labelText; } } } }, scales: 'line' === 'line' ? 'team-rush-rate'.includes('play-map') ? { x: { type: 'linear', position: 'bottom', title: { display: true, text: 'Play Number' }, min: 1, ticks: { stepSize: 1, callback: function(value) { return Math.floor(value); } }, grid: { display: false } }, y: { title: { display: true, text: 'Yards Gained' }, min: chartData.minY, max: chartData.maxY } } : { x: { type: 'linear', position: 'bottom', title: { display: true, text: 'team-rush-rate'.includes('team-lines') ? 'Play Number' : 'Team Play Number' }, min: 1, ticks: { stepSize: 1, callback: function(value) { return Math.floor(value); } }, grid: { display: false } }, y: { max: 1, min: 0, ticks: { callback: function(value) { return Math.round(value * 100) + '%'; } } } } : 'team-rush-rate'.includes('drive-metrics') ? { y: { stacked: false, max: 1, ticks: { callback: function(value) { return Math.round(value * 100) + '%'; } } }, y1: { display: false, type: 'linear', position: 'right' } } : ('team-rush-rate'.includes('top-rushers') || 'team-rush-rate'.includes('top-passers') || 'team-rush-rate'.includes('top-receivers')) ? { x: { stacked: true }, y: { stacked: true } } : { y: { max: 1, min: 0, stacked: false, ticks: { callback: function(value) { return Math.round(value * 100) + '%'; } } } } }; // Add indexAxis for player charts if ('team-rush-rate'.includes('top-rushers') || 'team-rush-rate'.includes('top-passers') || 'team-rush-rate'.includes('top-receivers')) { chartOptions.indexAxis = 'y'; } // 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-1756660727915-38m2mf0ga').parentNode; if (container) { container.innerHTML = '
Chart failed to load. Please refresh the page.
'; } } } // Initialize when DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initChart); } else { initChart(); } // Also try initialization after a short delay for WordPress compatibility setTimeout(initChart, 500); })();
Alabama shows an inverse to the Noles chart, after they tried their own #RTDB strategy early on. Lots of Tide rushing, especially in the first drive, and they collected consecutive successful rushes a few times. Somewhere in there things changed, though, and we started mixing it up; the rush rate dropped through the remainder of the 1st quarter … but we were all happy enough, with Alabama briefly holding a 7-0 lead.
Ty Simpson kept passing the ball through the 2nd quarter and going into the 3rd; we were fighting from behind so I guess Grubb felt like we had to lean on our brand new but also not so new QB to bail us out. He tried.
I mean, look at that 3rd quarter: the only three successful plays (filled in shapes) were explosive passes from Ty Simpson … but the rest of those are just empty triangles (unsuccessful passes) and a few empty circles (unsuccessful rushes). That is a very, very bad quarter. So much for a rousing halftime speech.
// Toggle data definitions accordion - unique function per embed function toggleDefinitions_cfb_chart_1756660960382_vf42da1r1() { const definitions = document.getElementById('dataDefinitions_cfb-chart-1756660960382-vf42da1r1'); const caret = document.getElementById('caret_cfb-chart-1756660960382-vf42da1r1'); if (definitions.classList.contains('expanded')) { definitions.classList.remove('expanded'); caret.classList.remove('expanded'); } else { definitions.classList.add('expanded'); caret.classList.add('expanded'); } } // WordPress-safe chart initialization with defensive checks (function() { 'use strict'; function initChart() { // Check if Chart.js is available if (typeof Chart === 'undefined') { console.warn('Chart.js not loaded yet, retrying...'); setTimeout(initChart, 100); return; } // Check if datalabels plugin is available if (typeof ChartDataLabels === 'undefined') { console.warn('ChartDataLabels plugin not loaded yet, retrying...'); setTimeout(initChart, 100); return; } // Check if canvas element exists const canvas = document.getElementById('cfb-chart-1756660960382-vf42da1r1'); 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": [ "Q1", "Q2", "Q3", "Q4" ], "datasets": [ { "data": [ 0.045454545454545456, 0, 0.13043478260869565, 0.06666666666666667 ], "stack": "Team", "label": "Alabama XR", "backgroundColor": "rgba(101, 0, 20, 0.8)", "datalabels": { "display": false } }, { "data": [ 0.6363636363636364, 0.2727272727272727, 0.13043478260869565, 0.4666666666666667 ], "stack": "Team", "label": "Alabama SR", "backgroundColor": "rgba(175, 40, 60, 0.8)", "datalabels": { "display": true } }, { "data": [ 0.14285714285714285, 0.09523809523809523, 0.13333333333333333, 0.05 ], "stack": "Opponent", "label": "Florida State XR", "backgroundColor": "#854D0ECC", "datalabels": { "display": false } }, { "data": [ 0.42857142857142855, 0.3333333333333333, 0.4666666666666667, 0.35 ], "stack": "Opponent", "label": "Florida State SR", "backgroundColor": "#CA8A04CC", "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": [ 22, 11, 23, 15 ], "oppCounts": [ 7, 21, 15, 20 ], "currentParams": { "year": 2025, "week": 1, "seasonType": "regular", "team": "Alabama", "gameId": "401752665" } }; // Chart options (WordPress-safe) const chartOptions = { responsive: true, maintainAspectRatio: false, animation: { duration: 0 // Disable animations to prevent conflicts }, elements: 'bar' === 'line' ? 'quarter-bars'.includes('play-map') ? { line: { tension: 0, borderWidth: 0 } } : { line: { tension: 0.25, borderWidth: 2.2 }, point: { pointRadius: 'quarter-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 ('quarter-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 ('quarter-bars'.includes('top-rushers') || 'quarter-bars'.includes('top-passers') || 'quarter-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: 'bar' === 'line' ? { position: 'top', align: 'start', labels: 'quarter-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: { filter: function(tooltipItem) { if ('quarter-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('< 0') && !tooltipItem.dataset.label.includes('Quarters'); }, callbacks: { label: function(context) { const label = context.dataset.label || ''; let labelText; // Play maps show yards instead of percentages if ('quarter-bars'.includes('play-map')) { labelText = label + ': ' + context.parsed.y + ' yards'; } else { const value = Math.round(context.parsed.y * 100); labelText = label + ': ' + value + '%'; } // For line charts, include play text if available if ('bar' === 'line' && context.raw && context.raw.text) { return [labelText, context.raw.text]; } return labelText; } } } }, scales: 'bar' === 'line' ? 'quarter-bars'.includes('play-map') ? { x: { type: 'linear', position: 'bottom', title: { display: true, text: 'Play Number' }, min: 1, ticks: { stepSize: 1, callback: function(value) { return Math.floor(value); } }, grid: { display: false } }, y: { title: { display: true, text: 'Yards Gained' }, min: chartData.minY, max: chartData.maxY } } : { x: { type: 'linear', position: 'bottom', title: { display: true, text: 'quarter-bars'.includes('team-lines') ? 'Play Number' : 'Team Play Number' }, min: 1, ticks: { stepSize: 1, callback: function(value) { return Math.floor(value); } }, grid: { display: false } }, y: { max: 1, min: 0, ticks: { callback: function(value) { return Math.round(value * 100) + '%'; } } } } : 'quarter-bars'.includes('drive-metrics') ? { y: { stacked: false, max: 1, ticks: { callback: function(value) { return Math.round(value * 100) + '%'; } } }, y1: { display: false, type: 'linear', position: 'right' } } : ('quarter-bars'.includes('top-rushers') || 'quarter-bars'.includes('top-passers') || 'quarter-bars'.includes('top-receivers')) ? { x: { stacked: true }, y: { stacked: true } } : { y: { max: 1, min: 0, stacked: false, ticks: { callback: function(value) { return Math.round(value * 100) + '%'; } } } } }; // Add indexAxis for player charts if ('quarter-bars'.includes('top-rushers') || 'quarter-bars'.includes('top-passers') || 'quarter-bars'.includes('top-receivers')) { chartOptions.indexAxis = 'y'; } // 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-1756660960382-vf42da1r1').parentNode; if (container) { container.innerHTML = '
Chart failed to load. Please refresh the page.
'; } } } // Initialize when DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initChart); } else { initChart(); } // Also try initialization after a short delay for WordPress compatibility setTimeout(initChart, 500); })();
Yep, in the 3rd quarter Alabama posted its highest explosiveness rate for the game. But the wacky context is that we had no other successful plays then, so it was honestly one of the worst quarters I’ve seen from Alabama football—and in the last year and a half I’ve seen some pretty bad Alabama football.
Otherwise … it doesn’t look like that bad of a game! Sure, Alabama came out un-explosive, but we racked up a lot of plays in the 1st quarter and a high success rate. We also had a push late with a higher SR and XR than Florida State in the 4th. The problem in the final frame wasn’t the overall trends—it was just the back-breaking moments, including Florida State converting 4th and 1 on their own side of the field with one score. Those kinds of things just happen—it doesn’t mean that the other plays didn’t happen too, but it sure means that people forget the other plays.
The big moments matter more
Given my dedication to this column, I’m obviously a firm believer that all of the plays matter—that when you’re trying to predict a team’s likelihood to succeed in the future, how successful they are down-by-down matters. That’s why things like success rate are indicative, even when they don’t necessarily deliver wins.
// Toggle data definitions accordion - unique function per embed function toggleDefinitions_cfb_chart_1756661208666_fbn6vrsrc() { const definitions = document.getElementById('dataDefinitions_cfb-chart-1756661208666-fbn6vrsrc'); const caret = document.getElementById('caret_cfb-chart-1756661208666-fbn6vrsrc'); if (definitions.classList.contains('expanded')) { definitions.classList.remove('expanded'); caret.classList.remove('expanded'); } else { definitions.classList.add('expanded'); caret.classList.add('expanded'); } } // WordPress-safe chart initialization with defensive checks (function() { 'use strict'; function initChart() { // Check if Chart.js is available if (typeof Chart === 'undefined') { console.warn('Chart.js not loaded yet, retrying...'); setTimeout(initChart, 100); return; } // Check if datalabels plugin is available if (typeof ChartDataLabels === 'undefined') { console.warn('ChartDataLabels plugin not loaded yet, retrying...'); setTimeout(initChart, 100); return; } // Check if canvas element exists const canvas = document.getElementById('cfb-chart-1756661208666-fbn6vrsrc'); 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, 0.17391304347826086, 0.0625, 0 ], "stack": "Team", "label": "Alabama XR", "backgroundColor": "rgba(101, 0, 20, 0.8)", "datalabels": { "display": false } }, { "data": [ 0.4074074074074074, 0.34782608695652173, 0.375, 0.4 ], "stack": "Team", "label": "Alabama SR", "backgroundColor": "rgba(175, 40, 60, 0.8)", "datalabels": { "display": true } }, { "data": [ 0.07407407407407407, 0.09090909090909091, 0.16666666666666666, 0 ], "stack": "Opponent", "label": "Florida State XR", "backgroundColor": "#854D0ECC", "datalabels": { "display": false } }, { "data": [ 0.3333333333333333, 0.36363636363636365, 0.4166666666666667, 1 ], "stack": "Opponent", "label": "Florida State SR", "backgroundColor": "#CA8A04CC", "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": [ 27, 23, 16, 5 ], "oppCounts": [ 27, 22, 12, 2 ], "currentParams": { "year": 2025, "week": 1, "seasonType": "regular", "team": "Alabama", "gameId": "401752665" } }; // Chart options (WordPress-safe) const chartOptions = { responsive: true, maintainAspectRatio: false, animation: { duration: 0 // Disable animations to prevent conflicts }, elements: 'bar' === 'line' ? 'down-bars'.includes('play-map') ? { line: { tension: 0, borderWidth: 0 } } : { 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: '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: { 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('< 0') && !tooltipItem.dataset.label.includes('Quarters'); }, callbacks: { label: function(context) { const label = context.dataset.label || ''; let labelText; // Play maps show yards instead of percentages if ('down-bars'.includes('play-map')) { labelText = label + ': ' + context.parsed.y + ' yards'; } else { const value = Math.round(context.parsed.y * 100); labelText = label + ': ' + value + '%'; } // For line charts, include play text if available if ('bar' === 'line' && context.raw && context.raw.text) { return [labelText, context.raw.text]; } return labelText; } } } }, scales: 'bar' === 'line' ? 'down-bars'.includes('play-map') ? { x: { type: 'linear', position: 'bottom', title: { display: true, text: 'Play Number' }, min: 1, ticks: { stepSize: 1, callback: function(value) { return Math.floor(value); } }, grid: { display: false } }, y: { title: { display: true, text: 'Yards Gained' }, min: chartData.minY, max: chartData.maxY } } : { x: { type: 'linear', position: 'bottom', title: { display: true, text: 'down-bars'.includes('team-lines') ? 'Play Number' : 'Team Play Number' }, min: 1, ticks: { stepSize: 1, callback: function(value) { return Math.floor(value); } }, grid: { display: false } }, y: { max: 1, min: 0, ticks: { callback: function(value) { return Math.round(value * 100) + '%'; } } } } : 'down-bars'.includes('drive-metrics') ? { y: { stacked: false, max: 1, ticks: { callback: function(value) { return Math.round(value * 100) + '%'; } } }, y1: { display: false, type: 'linear', position: 'right' } } : ('down-bars'.includes('top-rushers') || 'down-bars'.includes('top-passers') || 'down-bars'.includes('top-receivers')) ? { x: { stacked: true }, y: { stacked: true } } : { y: { max: 1, min: 0, stacked: false, ticks: { callback: function(value) { return Math.round(value * 100) + '%'; } } } } }; // Add indexAxis for player charts if ('down-bars'.includes('top-rushers') || 'down-bars'.includes('top-passers') || 'down-bars'.includes('top-receivers')) { chartOptions.indexAxis = 'y'; } // 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-1756661208666-fbn6vrsrc').parentNode; if (container) { container.innerHTML = '
Chart failed to load. Please refresh the page.
'; } } } // Initialize when DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initChart); } else { initChart(); } // Also try initialization after a short delay for WordPress compatibility setTimeout(initChart, 500); })();
That being said, whenever I write this column after a loss, we can usually point to a few places (ones that are also highlighted in traditional metrics). Here you are with the downs chart, where Alabama did better (or at least more efficiently) on 1st downs, respectably on 2nd downs, only slightly underperforming the Noles on 3rd down … and then would you look at that 4th down spike? That’s the difference, even in a 14-point game. It sounds like an exaggeration but it’s hard not to believe it’s true.
// Toggle data definitions accordion - unique function per embed function toggleDefinitions_cfb_chart_1756661280661_khg064tsz() { const definitions = document.getElementById('dataDefinitions_cfb-chart-1756661280661-khg064tsz'); const caret = document.getElementById('caret_cfb-chart-1756661280661-khg064tsz'); if (definitions.classList.contains('expanded')) { definitions.classList.remove('expanded'); caret.classList.remove('expanded'); } else { definitions.classList.add('expanded'); caret.classList.add('expanded'); } } // WordPress-safe chart initialization with defensive checks (function() { 'use strict'; function initChart() { // Check if Chart.js is available if (typeof Chart === 'undefined') { console.warn('Chart.js not loaded yet, retrying...'); setTimeout(initChart, 100); return; } // Check if datalabels plugin is available if (typeof ChartDataLabels === 'undefined') { console.warn('ChartDataLabels plugin not loaded yet, retrying...'); setTimeout(initChart, 100); return; } // Check if canvas element exists const canvas = document.getElementById('cfb-chart-1756661280661-khg064tsz'); 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.08196721311475409 ], "stack": "Team", "label": "Alabama XR", "backgroundColor": "rgba(101, 0, 20, 0.8)", "datalabels": { "display": false } }, { "data": [ 0.5, 0.36065573770491804 ], "stack": "Team", "label": "Alabama SR", "backgroundColor": "rgba(175, 40, 60, 0.8)", "datalabels": { "display": true } }, { "data": [ 0, 0.1016949152542373 ], "stack": "Opponent", "label": "Florida State XR", "backgroundColor": "#854D0ECC", "datalabels": { "display": false } }, { "data": [ 1, 0.3389830508474576 ], "stack": "Opponent", "label": "Florida State SR", "backgroundColor": "#CA8A04CC", "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": [ 10, 61 ], "oppCounts": [ 4, 59 ], "currentParams": { "year": 2025, "week": 1, "seasonType": "regular", "team": "Alabama", "gameId": "401752665" } }; // Chart options (WordPress-safe) const chartOptions = { responsive: true, maintainAspectRatio: false, animation: { duration: 0 // Disable animations to prevent conflicts }, elements: 'bar' === 'line' ? 'red-zone-bars'.includes('play-map') ? { line: { tension: 0, borderWidth: 0 } } : { 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: '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: { 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('< 0') && !tooltipItem.dataset.label.includes('Quarters'); }, callbacks: { label: function(context) { const label = context.dataset.label || ''; let labelText; // Play maps show yards instead of percentages if ('red-zone-bars'.includes('play-map')) { labelText = label + ': ' + context.parsed.y + ' yards'; } else { const value = Math.round(context.parsed.y * 100); labelText = label + ': ' + value + '%'; } // For line charts, include play text if available if ('bar' === 'line' && context.raw && context.raw.text) { return [labelText, context.raw.text]; } return labelText; } } } }, scales: 'bar' === 'line' ? 'red-zone-bars'.includes('play-map') ? { x: { type: 'linear', position: 'bottom', title: { display: true, text: 'Play Number' }, min: 1, ticks: { stepSize: 1, callback: function(value) { return Math.floor(value); } }, grid: { display: false } }, y: { title: { display: true, text: 'Yards Gained' }, min: chartData.minY, max: chartData.maxY } } : { x: { type: 'linear', position: 'bottom', title: { display: true, text: 'red-zone-bars'.includes('team-lines') ? 'Play Number' : 'Team Play Number' }, min: 1, ticks: { stepSize: 1, callback: function(value) { return Math.floor(value); } }, grid: { display: false } }, y: { max: 1, min: 0, ticks: { callback: function(value) { return Math.round(value * 100) + '%'; } } } } : 'red-zone-bars'.includes('drive-metrics') ? { y: { stacked: false, max: 1, ticks: { callback: function(value) { return Math.round(value * 100) + '%'; } } }, y1: { display: false, type: 'linear', position: 'right' } } : ('red-zone-bars'.includes('top-rushers') || 'red-zone-bars'.includes('top-passers') || 'red-zone-bars'.includes('top-receivers')) ? { x: { stacked: true }, y: { stacked: true } } : { y: { max: 1, min: 0, stacked: false, ticks: { callback: function(value) { return Math.round(value * 100) + '%'; } } } } }; // Add indexAxis for player charts if ('red-zone-bars'.includes('top-rushers') || 'red-zone-bars'.includes('top-passers') || 'red-zone-bars'.includes('top-receivers')) { chartOptions.indexAxis = 'y'; } // 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-1756661280661-khg064tsz').parentNode; if (container) { container.innerHTML = '
Chart failed to load. Please refresh the page.
'; } } } // Initialize when DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initChart); } else { initChart(); } // Also try initialization after a short delay for WordPress compatibility setTimeout(initChart, 500); })();
And where the 4th downs trend, you often see similar effects over here on the Red Zone chart. For what it’s worth, Alabama’s offense didn’t do terribly in the Red Zone: a 50% success rate is above league average, and you’re not really expected to get explosive plays in this part of the field though it can happen. Alabama also was more efficient than FSU on the rest of the field between the 20s. (That’s basically my hallmark metric for the Graphing column after Alabama losses; we’re always more efficient between the 20’s than the opponent, but sometimes it just doesn’t matter).
The problem is this Florida State line—once the Noles got inside the 20, there was just no hope for us Gumps: they were seemingly, absolutely going to have success, and they were seemingly absolutely going to score. For all the success that the Alabama defense had early in Florida State drives — and what should have resulted in a few more stops if it weren’t for penalties — they would just fold late in drives. In fact, it looked vaguely like a “break, don’t bend” defense, minus the explosiveness that the offense usually has in that scenario.
// Toggle data definitions accordion - unique function per embed function toggleDefinitions_cfb_chart_1756661469461_mlqtci4np() { const definitions = document.getElementById('dataDefinitions_cfb-chart-1756661469461-mlqtci4np'); const caret = document.getElementById('caret_cfb-chart-1756661469461-mlqtci4np'); if (definitions.classList.contains('expanded')) { definitions.classList.remove('expanded'); caret.classList.remove('expanded'); } else { definitions.classList.add('expanded'); caret.classList.add('expanded'); } } // WordPress-safe chart initialization with defensive checks (function() { 'use strict'; function initChart() { // Check if Chart.js is available if (typeof Chart === 'undefined') { console.warn('Chart.js not loaded yet, retrying...'); setTimeout(initChart, 100); return; } // Check if datalabels plugin is available if (typeof ChartDataLabels === 'undefined') { console.warn('ChartDataLabels plugin not loaded yet, retrying...'); setTimeout(initChart, 100); return; } // Check if canvas element exists const canvas = document.getElementById('cfb-chart-1756661469461-mlqtci4np'); 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.09523809523809523, 0.05, 0 ], "stack": "Team", "label": "Alabama XR", "backgroundColor": "rgba(101, 0, 20, 0.8)", "datalabels": { "display": false } }, { "data": [ 0.3333333333333333, 0.4, 0.5555555555555556 ], "stack": "Team", "label": "Alabama SR", "backgroundColor": "rgba(175, 40, 60, 0.8)", "datalabels": { "display": true } }, { "data": [ 0.09302325581395349, 0.13333333333333333, 0 ], "stack": "Opponent", "label": "Florida State XR", "backgroundColor": "#854D0ECC", "datalabels": { "display": false } }, { "data": [ 0.27906976744186046, 0.5333333333333333, 0.8 ], "stack": "Opponent", "label": "Florida State SR", "backgroundColor": "#CA8A04CC", "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": [ 42, 20, 9 ], "oppCounts": [ 43, 15, 5 ], "currentParams": { "year": 2025, "week": 1, "seasonType": "regular", "team": "Alabama", "gameId": "401752665" } }; // Chart options (WordPress-safe) const chartOptions = { responsive: true, maintainAspectRatio: false, animation: { duration: 0 // Disable animations to prevent conflicts }, elements: 'bar' === 'line' ? 'distance-bars'.includes('play-map') ? { line: { tension: 0, borderWidth: 0 } } : { 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: '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: { 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('< 0') && !tooltipItem.dataset.label.includes('Quarters'); }, callbacks: { label: function(context) { const label = context.dataset.label || ''; let labelText; // Play maps show yards instead of percentages if ('distance-bars'.includes('play-map')) { labelText = label + ': ' + context.parsed.y + ' yards'; } else { const value = Math.round(context.parsed.y * 100); labelText = label + ': ' + value + '%'; } // For line charts, include play text if available if ('bar' === 'line' && context.raw && context.raw.text) { return [labelText, context.raw.text]; } return labelText; } } } }, scales: 'bar' === 'line' ? 'distance-bars'.includes('play-map') ? { x: { type: 'linear', position: 'bottom', title: { display: true, text: 'Play Number' }, min: 1, ticks: { stepSize: 1, callback: function(value) { return Math.floor(value); } }, grid: { display: false } }, y: { title: { display: true, text: 'Yards Gained' }, min: chartData.minY, max: chartData.maxY } } : { x: { type: 'linear', position: 'bottom', title: { display: true, text: 'distance-bars'.includes('team-lines') ? 'Play Number' : 'Team Play Number' }, min: 1, ticks: { stepSize: 1, callback: function(value) { return Math.floor(value); } }, grid: { display: false } }, y: { max: 1, min: 0, ticks: { callback: function(value) { return Math.round(value * 100) + '%'; } } } } : 'distance-bars'.includes('drive-metrics') ? { y: { stacked: false, max: 1, ticks: { callback: function(value) { return Math.round(value * 100) + '%'; } } }, y1: { display: false, type: 'linear', position: 'right' } } : ('distance-bars'.includes('top-rushers') || 'distance-bars'.includes('top-passers') || 'distance-bars'.includes('top-receivers')) ? { x: { stacked: true }, y: { stacked: true } } : { y: { max: 1, min: 0, stacked: false, ticks: { callback: function(value) { return Math.round(value * 100) + '%'; } } } } }; // Add indexAxis for player charts if ('distance-bars'.includes('top-rushers') || 'distance-bars'.includes('top-passers') || 'distance-bars'.includes('top-receivers')) { chartOptions.indexAxis = 'y'; } // 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-1756661469461-mlqtci4np').parentNode; if (container) { container.innerHTML = '
Chart failed to load. Please refresh the page.
'; } } } // Initialize when DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initChart); } else { initChart(); } // Also try initialization after a short delay for WordPress compatibility setTimeout(initChart, 500); })();
Both teams showed similar tendencies towards success when closer to the line to gain. It’s not terribly unusual, but it’s not necessarily guaranteed, either. For Bama, it did fine in short yardage, but unfortunately, FSU did considerably better. The same happened for medium distance, though we did outperform ’em at long distance, which makes sense when only one team has a quarterback who’s doing much passing.
// Toggle data definitions accordion - unique function per embed function toggleDefinitions_cfb_chart_1756661534831_dxk408jku() { const definitions = document.getElementById('dataDefinitions_cfb-chart-1756661534831-dxk408jku'); const caret = document.getElementById('caret_cfb-chart-1756661534831-dxk408jku'); if (definitions.classList.contains('expanded')) { definitions.classList.remove('expanded'); caret.classList.remove('expanded'); } else { definitions.classList.add('expanded'); caret.classList.add('expanded'); } } // WordPress-safe chart initialization with defensive checks (function() { 'use strict'; function initChart() { // Check if Chart.js is available if (typeof Chart === 'undefined') { console.warn('Chart.js not loaded yet, retrying...'); setTimeout(initChart, 100); return; } // Check if datalabels plugin is available if (typeof ChartDataLabels === 'undefined') { console.warn('ChartDataLabels plugin not loaded yet, retrying...'); setTimeout(initChart, 100); return; } // Check if canvas element exists const canvas = document.getElementById('cfb-chart-1756661534831-dxk408jku'); 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": [ "Ty Simpson", "Tommy Castell…" ], "datasets": [ { "label": "Explosive", "data": [ 5, 3 ], "backgroundColor": [ "rgba(101, 0, 20, 0.8)", "#854D0ECC" ], "borderColor": "#374151", "borderWidth": 1 }, { "label": "Successful", "data": [ 12, 1 ], "backgroundColor": [ "rgba(175, 40, 60, 0.8)", "#CA8A04CC" ], "borderColor": "#374151", "borderWidth": 1 }, { "label": "Other catches", "data": [ 6, 5 ], "backgroundColor": [ "rgba(245, 229, 233, 0.8)", "#FEF3C7CC" ], "borderColor": "#374151", "borderWidth": 1 }, { "label": "Incompletes", "data": [ 20, 5 ], "backgroundColor": "#FFFFFF", "borderColor": "#374151", "borderWidth": 1 }, { "label": "Interceptions", "data": [ 0, 0 ], "backgroundColor": "#4B5563", "borderColor": "#374151", "borderWidth": 1 } ], "currentParams": { "year": 2025, "week": 1, "seasonType": "regular", "team": "Alabama", "gameId": "401752665" } }; // Chart options (WordPress-safe) const chartOptions = { responsive: true, maintainAspectRatio: false, animation: { duration: 0 // Disable animations to prevent conflicts }, elements: 'bar' === 'line' ? 'top-passers'.includes('play-map') ? { line: { tension: 0, borderWidth: 0 } } : { 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: '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: { 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('< 0') && !tooltipItem.dataset.label.includes('Quarters'); }, callbacks: { label: function(context) { const label = context.dataset.label || ''; let labelText; // Play maps show yards instead of percentages if ('top-passers'.includes('play-map')) { labelText = label + ': ' + context.parsed.y + ' yards'; } else { const value = Math.round(context.parsed.y * 100); labelText = label + ': ' + value + '%'; } // For line charts, include play text if available if ('bar' === 'line' && context.raw && context.raw.text) { return [labelText, context.raw.text]; } return labelText; } } } }, scales: 'bar' === 'line' ? 'top-passers'.includes('play-map') ? { x: { type: 'linear', position: 'bottom', title: { display: true, text: 'Play Number' }, min: 1, ticks: { stepSize: 1, callback: function(value) { return Math.floor(value); } }, grid: { display: false } }, y: { title: { display: true, text: 'Yards Gained' }, min: chartData.minY, max: chartData.maxY } } : { x: { type: 'linear', position: 'bottom', title: { display: true, text: 'top-passers'.includes('team-lines') ? 'Play Number' : 'Team Play Number' }, min: 1, ticks: { stepSize: 1, callback: function(value) { return Math.floor(value); } }, grid: { display: false } }, y: { max: 1, min: 0, ticks: { callback: function(value) { return Math.round(value * 100) + '%'; } } } } : 'top-passers'.includes('drive-metrics') ? { y: { stacked: false, max: 1, ticks: { callback: function(value) { return Math.round(value * 100) + '%'; } } }, y1: { display: false, type: 'linear', position: 'right' } } : ('top-passers'.includes('top-rushers') || 'top-passers'.includes('top-passers') || 'top-passers'.includes('top-receivers')) ? { x: { stacked: true }, y: { stacked: true } } : { y: { max: 1, min: 0, stacked: false, ticks: { callback: function(value) { return Math.round(value * 100) + '%'; } } } } }; // Add indexAxis for player charts if ('top-passers'.includes('top-rushers') || 'top-passers'.includes('top-passers') || 'top-passers'.includes('top-receivers')) { chartOptions.indexAxis = 'y'; } // 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-1756661534831-dxk408jku').parentNode; if (container) { container.innerHTML = '
Chart failed to load. Please refresh the page.
'; } } } // Initialize when DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initChart); } else { initChart(); } // Also try initialization after a short delay for WordPress compatibility setTimeout(initChart, 500); })();
An interesting Tweet or stat surfaced after the game about the losses that Alabama has taken while an opposing passer has put up very few passes (someone help me out with a link in the comments!). A few of them were from really famous moments in the Saban era (e.g. Cam or Kick Six, aka games where Malzahn was on the sideline somewhere). But several have come in the last 14 games under Kalen DeBoer … and here we are with another one.
You cannot look at this chart and say this opposing passer obviously beat Alabama in the traditional way. Not even the Garcia or the Knight or the Calzada ways. I mean, he only got four successful passes overall. Unfortunately, three of those were explosive, and very importantly so in at least one case.
Alabama’s Ty Simpson did not have a very inspiring line here—20 incomplete passes is not something we’ve seen in a game in a while. In general, we tried to pass the ball a lot to come back into this game, and while Ty did not throw any interceptions (and depending on who you ask, did acceptably well), he did not do enough.
// Toggle data definitions accordion - unique function per embed function toggleDefinitions_cfb_chart_1756661679646_m7haao9ss() { const definitions = document.getElementById('dataDefinitions_cfb-chart-1756661679646-m7haao9ss'); const caret = document.getElementById('caret_cfb-chart-1756661679646-m7haao9ss'); if (definitions.classList.contains('expanded')) { definitions.classList.remove('expanded'); caret.classList.remove('expanded'); } else { definitions.classList.add('expanded'); caret.classList.add('expanded'); } } // WordPress-safe chart initialization with defensive checks (function() { 'use strict'; function initChart() { // Check if Chart.js is available if (typeof Chart === 'undefined') { console.warn('Chart.js not loaded yet, retrying...'); setTimeout(initChart, 100); return; } // Check if datalabels plugin is available if (typeof ChartDataLabels === 'undefined') { console.warn('ChartDataLabels plugin not loaded yet, retrying...'); setTimeout(initChart, 100); return; } // Check if canvas element exists const canvas = document.getElementById('cfb-chart-1756661679646-m7haao9ss'); 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": [ "Richard Young", "Ty Simpson", "Kevin Riley", "Daniel Hill", "Dre Washington", "Germie Bernard", "Tommy Castell…", "Ousmane Kromah", "Roell Williams", "Gavin Sawchuk", "Jaylin Lucas", "Micahi Danzy", "Caziah Holmes" ], "datasets": [ { "label": "Explosive rushes", "data": [ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0 ], "backgroundColor": [ "rgba(101, 0, 20, 0.8)", "rgba(101, 0, 20, 0.8)", "rgba(101, 0, 20, 0.8)", "rgba(101, 0, 20, 0.8)", "rgba(101, 0, 20, 0.8)", "rgba(101, 0, 20, 0.8)", "#854D0ECC", "#854D0ECC", "#854D0ECC", "#854D0ECC", "#854D0ECC", "#854D0ECC", "#854D0ECC" ], "borderColor": "#374151", "borderWidth": 1 }, { "label": "Successful rushes", "data": [ 4, 2, 3, 1, 0, 0, 7, 3, 2, 2, 2, 0, 1 ], "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)", "#CA8A04CC", "#CA8A04CC", "#CA8A04CC", "#CA8A04CC", "#CA8A04CC", "#CA8A04CC", "#CA8A04CC" ], "borderColor": "#374151", "borderWidth": 1 }, { "label": "Unsuccessful rushes", "data": [ 5, 4, 2, 2, 2, 1, 7, 4, 4, 4, 4, 1, 1 ], "backgroundColor": "#FFFFFF", "borderColor": "#374151", "borderWidth": 1 } ], "currentParams": { "year": 2025, "week": 1, "seasonType": "regular", "team": "Alabama", "gameId": "401752665" } }; // Chart options (WordPress-safe) const chartOptions = { responsive: true, maintainAspectRatio: false, animation: { duration: 0 // Disable animations to prevent conflicts }, elements: 'bar' === 'line' ? 'top-rushers'.includes('play-map') ? { line: { tension: 0, borderWidth: 0 } } : { line: { tension: 0.25, borderWidth: 2.2 }, point: { pointRadius: 'top-rushers'.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-rushers' === '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-rushers'.includes('top-rushers') || 'top-rushers'.includes('top-passers') || 'top-rushers'.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: 'bar' === 'line' ? { position: 'top', align: 'start', labels: 'top-rushers'.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: { filter: function(tooltipItem) { if ('top-rushers'.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('< 0') && !tooltipItem.dataset.label.includes('Quarters'); }, callbacks: { label: function(context) { const label = context.dataset.label || ''; let labelText; // Play maps show yards instead of percentages if ('top-rushers'.includes('play-map')) { labelText = label + ': ' + context.parsed.y + ' yards'; } else { const value = Math.round(context.parsed.y * 100); labelText = label + ': ' + value + '%'; } // For line charts, include play text if available if ('bar' === 'line' && context.raw && context.raw.text) { return [labelText, context.raw.text]; } return labelText; } } } }, scales: 'bar' === 'line' ? 'top-rushers'.includes('play-map') ? { x: { type: 'linear', position: 'bottom', title: { display: true, text: 'Play Number' }, min: 1, ticks: { stepSize: 1, callback: function(value) { return Math.floor(value); } }, grid: { display: false } }, y: { title: { display: true, text: 'Yards Gained' }, min: chartData.minY, max: chartData.maxY } } : { x: { type: 'linear', position: 'bottom', title: { display: true, text: 'top-rushers'.includes('team-lines') ? 'Play Number' : 'Team Play Number' }, min: 1, ticks: { stepSize: 1, callback: function(value) { return Math.floor(value); } }, grid: { display: false } }, y: { max: 1, min: 0, ticks: { callback: function(value) { return Math.round(value * 100) + '%'; } } } } : 'top-rushers'.includes('drive-metrics') ? { y: { stacked: false, max: 1, ticks: { callback: function(value) { return Math.round(value * 100) + '%'; } } }, y1: { display: false, type: 'linear', position: 'right' } } : ('top-rushers'.includes('top-rushers') || 'top-rushers'.includes('top-passers') || 'top-rushers'.includes('top-receivers')) ? { x: { stacked: true }, y: { stacked: true } } : { y: { max: 1, min: 0, stacked: false, ticks: { callback: function(value) { return Math.round(value * 100) + '%'; } } } } }; // Add indexAxis for player charts if ('top-rushers'.includes('top-rushers') || 'top-rushers'.includes('top-passers') || 'top-rushers'.includes('top-receivers')) { chartOptions.indexAxis = 'y'; } // 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-1756661679646-m7haao9ss').parentNode; if (container) { container.innerHTML = '
Chart failed to load. Please refresh the page.
'; } } } // Initialize when DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initChart); } else { initChart(); } // Also try initialization after a short delay for WordPress compatibility setTimeout(initChart, 500); })();
Yep, of all the people—all the many (13!) rushers on this chart—only one name stands out, and that’s the quarterback for the Florida State Seminoles. Maybe you could call this a comeuppance from the Jalen Milroe years, delivered from the other sideline instead. Plenty of Tide opponents were on the receiving end up this rush-first QB effect the last two seasons.
The rest is history?
The rest of the charts for this game are available here at GraphingCollegeFootball.com. This site is the result of many years’ work both on this data column, and on data products: it gets you not only these charts but any chart from any college football game from the last 11 years. So feel free to go in there, check out the games, maybe take some screenshots and toss a post into the RBR feed if you find anything noteworthy. I will certainly be plucking a few more charts from this game (and others in Week 1) and adding them there.
As for the 2025 Alabama Crimson Tide, I’m of two minds here. One of them is where I’ve arrived after graphing this game—which is to say, good teams can still have really bad games … especially, apparently, teams coached by this coaching staff. You could argue they’re we’re still in an adjustment period, that we were facing a brand new football team and coaching staff that couldn’t really be scouted; plus, that the opponent had some natural scheme advantages against the Tide that they could take advantage of if they played well (and they played well).
That won’t necessarily be the case for all the teams that we play, or maybe even some of the big teams that we play, so there’s still hope yet that we can have a season that takes us to a playoff, or at least that shows us some signs of progress or some moments of pride. I still want that sixth Iron Bowl win in a row, mind you, no matter who’s on the field or on the sidelines.
The other part of me wants the team to produce that joy in different ways, though. E.g., it does make me wonder if investing in some future talent, like Keelon Russell, would … well, it would certainly not guarantee success (in fact, might even result in an additional loss or two) but might help us train up somebody exciting and create some positive momentum and joy around this program; it’d show recruits that they can get some playing time and win some games even when things aren’t going perfectly for Alabama. Go out there, have fun, make highlights and headlines, and maybe even show up in a few big moments. Spoil someone’s season (besides your own).
Either way, football is back. Alabama loses sometimes, and the next day still happens, so join me in following along this year as we observe some of the most interesting graphs (for better; or often, for worse) from Alabama that we will have seen in years.