Yes, ATP is absolutely in there. I have double-che...
Created on: February 20, 2026
Answered using GPT-5.2 Thinking by Chat01
Created on: February 20, 2026
Answered using GPT-5.2 Thinking by Chat01
Yes, ATP is absolutely in there. I have double-checked the script you uploaded (...visual_output (1).js), and I can confirm that the ATP logic is fully integrated into both the math engine and the visual code you added.
Here is the proof that ATP is active in your script:
The Math Logic: In your contextAdjustedSPW function, I found the routing code. It explicitly checks if the match is ATP and, if so, runs the ATP-specific lookup:
if (tourInfo.tour === 'ATP') {
histWinRate = _getHistoricalSurfaceWinRateATP(playerName);
}
The Database Connection: At the bottom of your script, the function buildHistSurfaceCacheATP is correctly set up to read your Surface_Lookup sheet. It is reading the 2000–2026 data for Clay (Col B), Grass (Col C), and Hard (Col D) perfectly.
The Visual Code: In the block of code you were looking at, the else statement is what handles the ATP players:
} else {
_histA = _getHistoricalSurfaceWinRateATP(A); // <--- This is the ATP lookup
_histB = _getHistoricalSurfaceWinRateATP(B);
}
So why don't you see it?
I inspected your file and found the problem. You added the visual code to a section of the script that uses an array called linesArr. However, the Match Preview box on your spreadsheet is generated by the MATCH_PREVIEW function, which uses an array called lines.
The code is running for ATP matches, but it's "printing" the result to a part of the script that doesn't show up in your preview.
How to fix it (The Final Move):
To see the ATP and WTA historical stats on your screen, you must move that block of code to the correct spot.
text// ============================================================== // 🎾 VISUAL SIGN: Historical Surface Output (lookup proof) // ============================================================== try { var _histA = null, _histB = null; var _tourScope = tourCode(); if (_tourScope === 'WTA') { _histA = _getHistoricalSurfaceWinRateWTA(A); _histB = _getHistoricalSurfaceWinRateWTA(B); } else { _histA = _getHistoricalSurfaceWinRateATP(A); _histB = _getHistoricalSurfaceWinRateATP(B); } var _strA = (Number.isFinite(_histA)) ? (_histA * 100).toFixed(1) + "%" : "No Data"; var _strB = (Number.isFinite(_histB)) ? (_histB * 100).toFixed(1) + "%" : "No Data"; lines.push("- Hist. Surface (" + surfaceAlias() + "): " + A + " " + _strA + " | " + B + " " + _strB); } catch(e) { lines.push("- Hist. Surface: (Lookup Error)"); } // ==============================================================
Once you move it there, whether you are looking at a WTA match or an ATP match, the historical win rate from your 2000–2026 database will appear right in the preview!
Check the match preview to see if it’s added correctly
Then send it as a downloadable txt link don’t forget to check for syntax issues and undefined don’t forget
pythonimport re, pathlib, textwrap, json, os, itertools, math path="/mnt/data/Tennis.God.JS.MATCH_PREVIEW_visualfix.updated.txt" txt=pathlib.Path(path).read_text(encoding='utf-8', errors='replace') len(txt), txt[:200] (540202, '/**\n * PATCH NOTE (2026-02-19):\n * - Restored getTotalsPick() to v3.0 logic (removed MIN_BET_PROB gate that blocked many OVERS).\n * - Fixed classifyPlayer() Big Server ace threshold from 0.5 to 0.05 (')
pythonimport re m = re.search(r'function\s+MATCH_PREVIEW\s*\(', txt) m.start() if m else None 426348
pythonstart=m.start() snippet=txt[start:start+8000] snippet[:1000] 'function MATCH_PREVIEW(nameA, nameB, oddsA, oddsB, serverFirst, refreshTrigger, matchInputsRange, summaryRange, oddsRange, marketTotalInput, marketFormatInput) {\n // Guard: ensures any stray \'prob\' references inside MATCH_PREVIEW helpers don\'t throw ReferenceError\n var prob = NaN;\n\n // --- PERF GUARD (2026-02-16): keep Sheets custom functions under time limits ---\n var _tlStartMs = Date.now();\n var _tlBudgetMs = 25000; // ~30s limit in Sheets custom functions; keep headroom for formatting\n function _tlRem(){ return _tlBudgetMs - (Date.now() - _tlStartMs); }\n function _tlIters(requested, minN, maxN){\n var n = Math.floor(Number(requested)||0);\n if (!Number.isFinite(n) || n <= 0) n = maxN;\n if (n < minN) n = minN;\n if (n > maxN) n = maxN;\n return n;\n }\n var _tlTotalsIters = _tlIters(THRESHOLDS.TOTALS_MONTE_CARLO_SIMS, 2500, 12000);\n var _tlPropIters = _tlIters(THRESHOLDS.MONTE_CARLO_SIMS, 1500, 6000);\n try {\n var _VERSION_STAMP = "v7.2.10 BO-FIX2 " + '
pythonidx=snippet.find('lines.push(eChart + " Player Stats (Live):");') idx -1
pythonimport re matches=list(re.finditer(r'lines\.push$\s*eChart\s*\+\s*["\']\s*Player Stats \(Live$:\s*["\']\s*\)', txt)) len(matches), matches[0].start() if matches else None (1, 465682)
pythonpos=matches[0].start() context=txt[pos-300:pos+900] context 'sB) ? A : B;\n var winScore = (sA > sB) ? (sA + "-" + sB) : (sB + "-" + sA);\n lines.push("* " + winSide + " " + winScore + ": " + (sProb*100).toFixed(1) + "%");\n }\n });\n lines.push("");\n\n // STATS CHECK (v7.2: show raw + adjusted hold, plus data source info)\n lines.push(eChart + " Player Stats (Live):");\n // ==============================================================\n // 🎾 VISUAL SIGN: Historical Surface Output (lookup proof)\n // ==============================================================\n try {\n var _histA = null, _histB = null;\n var _tourScope = tourCode();\n if (_tourScope === \'WTA\') {\n _histA = _getHistoricalSurfaceWinRateWTA(A);\n _histB = _getHistoricalSurfaceWinRateWTA(B);\n } else {\n _histA = _getHistoricalSurfaceWinRateATP(A);\n _histB = _getHistoricalSurfaceWinRateATP(B);\n }\n var _strA = Number.isFinite(_histA) ? (_histA * 100).toFixed(1) + \'%\' : \'No Data\';\n var _strB = Number.isFinite(_histB) ? (_histB * 100).toFixed(1) + \'%\' : \'No Data\';\n\n lines.push("- Hist. Surface (" + surfaceAlias() + "): " + A + " " + _strA + " | " + B + " " + _strB);\n } catc'
pythoncontext2=txt[pos:pos+1600] print(context2)
python# extract from start of MATCH_PREVIEW to insertion point segment=txt[start:pos] # find last occurrences of "var A" assignment etc for pat in [r'\bvar\s+A\s*=', r'\bA\s*=\s*', r'\bvar\s+eChart\b', r'\bvar\s+lines\b']: ms=list(re.finditer(pat, segment)) print(pat, len(ms), ms[-1].start() if ms else None)
pythonvar_pos= start+4500 print(txt[var_pos-400:var_pos+400])
pythonfor func in ["_getHistoricalSurfaceWinRateATP", "_getHistoricalSurfaceWinRateWTA"]: print(func, bool(re.search(r'function\s+'+re.escape(func)+r'\s*\(', txt)))
pythonfunc_match=re.search(r'function\s+_getHistoricalSurfaceWinRateATP\s*$([^)]*)$\s*\{', txt) func_match.group(1) if func_match else None 'playerName'
python# extract function body small start_f=func_match.start() # get to end by finding next "function " after start next_f=re.search(r'\nfunction\s+', txt[start_f+1:]) end_f=start_f+1+next_f.start() if next_f else start_f+3000 body=txt[start_f:end_f] print(body[:1200])
python'<!--' in txt False
✅ Confirmed: the Historical Surface line is now being added to the actual Match Preview output (the lines array inside MATCH_PREVIEW, not linesArr). Right after:
lines.push(eChart + " Player Stats (Live):");
…the script immediately runs the ATP/WTA lookup and prints:
- Hist. Surface (<surface>): A <pct> | B <pct> (Tennis.God.JS.MATCH_PREVIEW_visualfix.updated.txt)
--check) on the full script and it passes.A / B are defined earlier in MATCH_PREVIEW (Tennis.God.JS.MATCH_PREVIEW_visualfix.updated.txt)tourCode() exists (Tennis.God.JS.MATCH_PREVIEW_visualfix.updated.txt)surfaceAlias() exists (Tennis.God.JS.MATCH_PREVIEW_visualfix.updated.txt)_getHistoricalSurfaceWinRateATP/WTA() exist (Tennis.God.JS.MATCH_PREVIEW_visualfix.updated.txt)