Can u fix scripts
Créé le : 7 novembre 2025
Répondu en utilisant GPT-5 Thinking par Chat01
Créé le : 7 novembre 2025
Répondu en utilisant GPT-5 Thinking par Chat01
Can u fix scripts
Absolutely—happy to fix them.
Drop the script(s) here (or attach files) along with:
If you can, paste like this:
text# script name + language # how you run it # expected vs. actual behavior # code (or a minimal snippet that reproduces it) # error/traceback/output
Meanwhile, a few quick fixes that solve ~80% of issues:
Bash / sh
bashchmod +x your_script.sh && sed -i 's/\r$//' your_script.sh
bash#!/usr/bin/env bash set -euo pipefail; IFS=$'\n\t'
bashshellcheck your_script.sh
Python
bashpython3 -V python3 -m pip install -r requirements.txt python3 your_script.py
bashpython3 -m pip install black ruff black . ruff check .
PowerShell
powershellUnblock-File .\script.ps1 Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
powershellInstall-Module PSScriptAnalyzer -Scope CurrentUser Invoke-ScriptAnalyzer .\script.ps1
Node
bashnode -v rm -rf node_modules package-lock.json && npm ci npm run lint --silent
Common gotchas
#!/usr/bin/env <interp>).dos2unix or the sed line above).$(dirname "$0") in bash, Path(__file__).parent in Python).Send me the script and error, and I’ll fix it inline with a clean, tested patch.
You’re right—the “wrong player” call is coming from Final Bet Summary using an old label. The code enforces the winner with the raw nameA/nameB it received earlier, but everything else uses the resolved names (A/B) pulled from the grid (A2/A11) or named ranges. So if the sheet changed, the final line could still print the older label.
In FINAL_BET_SUMMARY, replace the canonical winner block so it uses the resolved names A/B instead of the raw inputs:
diff- var A_ = nameA, B_ = nameB; - var resolved = __resolvePrimaryPick_fromAdj(A_, B_, pAdjA, oddsA, oddsB, 0.02); + var resolved = __resolvePrimaryPick_fromAdj(A, B, pAdjA, oddsA, oddsB, 0.02); pickSide = resolved.side; pickProb = resolved.prob;
Why this works:
__resolvePrimaryPick_fromAdj expects the current labels for A/B (the same ones used everywhere else in the summary). Passing nameA/nameB lets older overrides sneak in. (fixed_script_betting_lines_fix (1) (1).js) (fixed_script_betting_lines_fix (1) (1).js)nameA/nameB is here. Swap it to A/B. (fixed_script_betting_lines_fix (1) (1).js)pickSide, which will now always be the up-to-date, resolved name. (fixed_script_betting_lines_fix (1) (1).js)tick argument).FINAL_BET_SUMMARY again—the “Match Winner: …” line should now match the model’s current side and names throughout.If you want, send me a quick before/after output and I’ll sanity-check that everything lines up (pick name, odds tag, dog/calc lines, etc.).
My script I attached it keeps picking the wrong player. That is due to it using old stuff in the final bet summary it’s almost correct but putting old stuff in. Same with the match pick, also it’s picking the wrong prop like it’ll say correct props then later it’ll pick a wrong prop
Got it — this is two bugs plus one merge quirk. Here’s how to make the picks stop “reverting” to old names and props.
The summary re-computes the canonical winner using the raw nameA/nameB, not the resolved A/B pulled from the grid/named ranges. That lets old labels leak back in.
Fix (1-line change):
Replace the block below so it passes the resolved names A, B:
diff- // === Canonical winner enforcement (prevents contradictory outputs) === - (function(){ - var A_ = nameA, B_ = nameB; - var resolved = __resolvePrimaryPick_fromAdj(A_, B_, pAdjA, oddsA, oddsB, 0.02); - pickSide = resolved.side; - pickProb = resolved.prob; - })(); + // === Canonical winner enforcement (use resolved names) === + (function(){ + var resolved = __resolvePrimaryPick_fromAdj(A, B, pAdjA, oddsA, oddsB, 0.02); + pickSide = resolved.side; + pickProb = resolved.prob; + })();
(You’ll find that block here.) (fixed_script_betting_lines_fix (1) (1).js)
You push the match-winner pick with key MW, but later you search for key ML when building the “primary” picks. That means the match winner never gets included and props can bubble up oddly.
Fix (rename MW → ML):
diff- pushPick({ - key:'MW', + pushPick({ + key:'ML', label:'Match Winner', text: winner, p: pStar, bucket: buckets.winner });
(Location of the push:) (fixed_script_betting_lines_fix (1) (1).js)
(Location where ML is expected:) (fixed_script_betting_lines_fix (1) (1).js)
When the enhanced summary is merged into the legacy text, the filter removes all bold lines (**...) — which are exactly where your “Best/Second/Third pick” and “Match Winner” show up — and then the legacy block (with older logic/labels) remains. That’s why you see correct props first, then a “wrong” prop later.
Fix (keep bold pick lines from the enhanced block):
Replace the advanced-text filter with one that only drops the decorative header/separators, not bold lines:
diff- var advLines = String(advancedResult).split(/\r?\n/); - var filtered = []; - for (var i = 0; i < advLines.length; i++) { - var line = advLines[i]; - // Skip decorative headings or separators - if (line.trim() === '' || /^=+/.test(line) || /^\*\*/.test(line)) continue; - filtered.push(line); - } + var advLines = String(advancedResult).split(/\r?\n/); + var filtered = advLines.filter(function(line){ + var t = line.trim(); + // Drop only empty lines, big underline separators, and the plain title line + if (t === '' || /^=+/.test(t) || /^Tennis Match Prediction Summary/i.test(t)) return false; + // Keep bold lines like **Best Pick:**, **Leans:**, **Match Winner:** + return true; + });
(Where this merge filter lives.) (fixed_script_betting_lines_fix (1) (1).js)
You push the FS pick in two places. Guard one of them so it only pushes once:
diff- pushPick({ key:'FS', label:'1st-Set O/U', text: (fsPickProb >= 0.5 ? 'Over ' + fsPickLine.toFixed(1) : 'Under ' + fsPickLine.toFixed(1)), p: Math.max(fsPickProb, 1 - fsPickProb), bucket: buckets.fs }); + if (!picks.some(function(x){ return x.key === 'FS'; })) { + pushPick({ key:'FS', label:'1st-Set O/U', text: (fsPickProb >= 0.5 ? 'Over ' + fsPickLine.toFixed(1) : 'Under ' + fsPickLine.toFixed(1)), p: Math.max(fsPickProb, 1 - fsPickProb), bucket: buckets.fs }); + }
(One of the FS pushes is here.) (fixed_script_betting_lines_fix (1) (1).js)
(The other FS push occurs earlier in the props section.) (fixed_script_betting_lines_fix (1) (1).js)
ML key. (fixed_script_betting_lines_fix (1) (1).js) (fixed_script_betting_lines_fix (1) (1).js)If anything still looks off, paste a small sample of your output (top block + the “later” block), and I’ll adjust the filters to nip any remaining legacy lines.
What about the match pick ? Like due to the upset factor it’ll push the wrong moneyline sometimes
You’re right — the upset bump is allowed to shove the blended probability across 50%, which can flip the moneyline side even when the model originally liked the other player. Let’s make the upset logic never change the ML side, only nudge its confidence.
Below are two small patches:
In MATCH_PICK(...), we apply bump directly to pBlendA. Add a “pre-side” anchor and clamp the adjustment so it never crosses 50%. Replace the current bump block with this:
diff- // Apply a small adjustment based on the upset grade. Keep these bumps small so the model remains primary. - var bump = 0; - if (upset.grade === 'UPSET ALERT') bump = 0.02; - else if (upset.grade === 'Upset watch') bump = 0.015; - else if (upset.grade === 'Mild upset lean') bump = 0.01; - if (bump > 0){ - if (pBlendA >= 0.5) pBlendA = Math.max(0, pBlendA - bump); - else pBlendA = Math.min(1, pBlendA + bump); - } + // Upset bump may not flip sides; it can only shrink edge toward 50/50. + var bump = 0; + if (upset.grade === 'UPSET ALERT') bump = 0.02; + else if (upset.grade === 'Upset watch') bump = 0.015; + else if (upset.grade === 'Mild upset lean') bump = 0.01; + var preIsA = (pBlendA >= 0.5); + if (bump > 0){ + if (preIsA) { + // Move toward 0.5001 but never cross it + var room = Math.max(0, pBlendA - 0.5001); + pBlendA = Math.max(0.5001, pBlendA - Math.min(bump, room)); + } else { + // Move toward 0.4999 but never cross it + var room = Math.max(0, 0.4999 - pBlendA); + pBlendA = Math.min(0.4999, pBlendA + Math.min(bump, room)); + } + }
This goes right after _upsetAlert(...) is computed and before the “micro-edge near 50/50” block. (You can see the original upset bump here. (fixed_script_betting_lines_fix (1) (1).js))
In FINAL_BET_SUMMARY(...) there’s a second place where bump gets applied and then pickSide is reassigned based on the bumped value — that’s where the summary can contradict your main pick. Replace that block so the bump can’t cross 50% and we keep the pre-bump side:
diff- var pAdjA = pBlendA; - if (bump > 0){ - if (pBlendA >= 0.5) pAdjA = Math.max(0, pBlendA - bump); - else pAdjA = Math.min(1, pBlendA + bump); - pickSide = (pAdjA >= 0.5 ? A : B); - pickProb = (pAdjA >= 0.5 ? pAdjA : 1 - pAdjA); - } + // Anchor side before bump; allow bump to adjust confidence only + var pAdjA = pBlendA; + var preIsA = (pBlendA >= 0.5); + if (bump > 0){ + if (preIsA){ + var room = Math.max(0, pBlendA - 0.5001); + pAdjA = Math.max(0.5001, pBlendA - Math.min(bump, room)); + } else { + var room = Math.max(0, 0.4999 - pBlendA); + pAdjA = Math.min(0.4999, pBlendA + Math.min(bump, room)); + } + pickSide = preIsA ? A : B; + pickProb = preIsA ? pAdjA : (1 - pAdjA); + }
(This is the exact area where the summary currently reassigns pickSide after bump. (fixed_script_betting_lines_fix (1) (1).js))
You push the winner with key MW, but later the code looks for ML when assembling the primary picks. Rename that key so they match:
diff- pushPick({ - key:'MW', + pushPick({ + key:'ML', label:'Match Winner', text: winner, p: pStar, bucket: buckets.winner });
(Where you push the winner. (fixed_script_betting_lines_fix (1) (1).js))
(Where the primary builder expects ML. (fixed_script_betting_lines_fix (1) (1).js))
This prevents old labels from leaking back in:
diff- var A_ = nameA, B_ = nameB; - var resolved = __resolvePrimaryPick_fromAdj(A_, B_, pAdjA, oddsA, oddsB, 0.02); + var resolved = __resolvePrimaryPick_fromAdj(A, B, pAdjA, oddsA, oddsB, 0.02); pickSide = resolved.side; pickProb = resolved.prob;
(That tiny block lives here in the summary. (fixed_script_betting_lines_fix (1) (1).js))
ML is now consistent. (Patch #3) (fixed_script_betting_lines_fix (1) (1).js)MATCH_PICK and FINAL_BET_SUMMARY on a matchup where baseline is ~51–53%.ML) and matches the header.If you paste a before/after output block, I’ll sanity-check the exact strings to make sure no other merge filters are stepping on the bold lines or pick keys.
Like it’s picking the write props most of the time but sometimes it’s completely wrong
You’re bumping into two things that make the props look “right” up top but “completely wrong” later:
Below are tiny, surgical edits that stop those reversions and make the prop ordering stable.
pushPick)Right now if a prop’s p is NaN/missing, Number(obj.p) || 0 turns into 0, and your rawConf becomes |0 − 0.5| = 0.5 (max edge) — which is why an obviously wrong prop can suddenly be your “Best pick.” (fixed_script_betting_lines_fix (1) (1).js)
Patch:
difffunction pushPick(obj){ - var riskFac = Number(obj.risk || 0); - var rawConf = Math.abs((Number(obj.p) || 0) - 0.5); + var p = Number(obj.p); + // If probability isn't a finite number, don't include this pick at all. + if (!Number.isFinite(p)) return; + var riskFac = Number.isFinite(obj.risk) ? Number(obj.risk) : 0; + if (riskFac < 0) riskFac = 0; if (riskFac > 0.9) riskFac = 0.9; + var rawConf = Math.abs(p - 0.5); var conf = rawConf * (1 - riskFac); obj.conf = conf; picks.push(obj); }
(Insert at the pushPick helper.) (fixed_script_betting_lines_fix (1) (1).js)
The bump is applied in more than one place and can push a 51–49 to 49–51, flipping the ML side. Clamp it so the bump only shrinks confidence toward 50/50 and never crosses it.
Patch in each bump block:
diff- if (bump > 0){ - if (pBlendA >= 0.5) pBlendA = Math.max(0, pBlendA - bump); - else pBlendA = Math.min(1, pBlendA + bump); - } + var preIsA = (pBlendA >= 0.5); + if (bump > 0){ + if (preIsA){ + var room = Math.max(0, pBlendA - 0.5001); + pBlendA = Math.max(0.5001, pBlendA - Math.min(bump, room)); + } else { + var room = Math.max(0, 0.4999 - pBlendA); + pBlendA = Math.min(0.4999, pBlendA + Math.min(bump, room)); + } + }
Apply where the upset bump is used (you have multiple occurrences; clamp them all). Examples shown here: (fixed_script_betting_lines_fix (1) (1).js) (fixed_script_betting_lines_fix (1) (1).js)
nameA/nameB)This prevents old labels leaking back into the summary. Replace the canonical winner enforcement to use A, B. (fixed_script_betting_lines_fix (1) (1).js)
Patch:
diff- var A_ = nameA, B_ = nameB; - var resolved = __resolvePrimaryPick_fromAdj(A_, B_, pAdjA, oddsA, oddsB, 0.02); + var resolved = __resolvePrimaryPick_fromAdj(A, B, pAdjA, oddsA, oddsB, 0.02); pickSide = resolved.side; pickProb = resolved.prob;
This summary section also prints the “Match Winner:” line, so fixing the names here aligns everything that’s printed. (fixed_script_betting_lines_fix (1) (1).js)
You push the ML with key MW, but the primary builder looks for ML. Rename it at the source. (fixed_script_betting_lines_fix (1) (1).js) (fixed_script_betting_lines_fix (1) (1).js)
Patch:
diff- pushPick({ - key:'MW', + pushPick({ + key:'ML', label:'Match Winner', text: winner, p: pStar, bucket: buckets.winner });
You push an FS pick twice; sometimes the second (older) one wins the sort and looks “wrong.” Just guard the second push. (fixed_script_betting_lines_fix (1) (1).js)
Patch:
diff- pushPick({ key:'FS', label:'1st-Set O/U', text: (fsPickProb >= 0.5 ? 'Over ' + fsPickLine.toFixed(1) : 'Under ' + fsPickLine.toFixed(1)), p: Math.max(fsPickProb, 1 - fsPickProb), bucket: buckets.fs }); + if (!picks.some(function(x){ return x.key === 'FS'; })) { + pushPick({ key:'FS', label:'1st-Set O/U', text: (fsPickProb >= 0.5 ? 'Over ' + fsPickLine.toFixed(1) : 'Under ' + fsPickLine.toFixed(1)), p: Math.max(fsPickProb, 1 - fsPickProb), bucket: buckets.fs }); + }
If you want, paste a short “before vs after” of the top block and I’ll double-check the exact strings.
How do I make sure it’s not confusing both players stats? It’s supposed to get stats but it might out the wrong props with the wrong players and it’s not calculating some stats correctly
You’re right: a few spots do mix A/B, which can attach the wrong stats/props to the wrong player. There are two core causes in your file:
'A'/'B', andfirstSrvPct exists, which can cascade into wrong prop math.Here are drop-in fixes (tiny diffs) that stop the mix-ups and fix the stat calc.
'A'/'B') — keep names only for labelsFind function pushPropForPlayer(sideLabel, stats){…} and change it to:
diff- function pushPropForPlayer(sideLabel, stats){ + function pushPropForPlayer(sideCode, displayName, stats){ var m = Math.max(stats.matches || 0, 1); … - var oppSide = (sideLabel === A ? B : A); - var oppSpwAdj = contextAdjustedSPW(oppSide); + var oppCode = (String(sideCode).toUpperCase() === 'A') ? 'B' : 'A'; + var oppSpwAdj = contextAdjustedSPW(oppCode); // expects 'A'/'B' var holdOpp = null; if (Number.isFinite(oppSpwAdj)) { - holdOpp = computeHoldFromSPW(oppSpwAdj, oppSide, 'MATCH'); + holdOpp = computeHoldFromSPW(oppSpwAdj, oppCode, 'MATCH'); // expects 'A'/'B' } if (!Number.isFinite(holdOpp)) holdOpp = 0.5; … - var expReturnGames = (sideLabel === A ? expSrvGamesB : expSrvGamesA); + var expReturnGames = (String(sideCode).toUpperCase() === 'A' ? expSrvGamesB : expSrvGamesA); … - pushPick({ key:'PROP_BP_' + sideLabel, label: sideLabel + ' Breakpoints Won', … }); + pushPick({ key:'PROP_BP_' + sideCode, label: displayName + ' Breakpoints Won', … }); … - var avgGW = (sideLabel === A ? expGamesWonA : (sideLabel === B ? expGamesWonB : null)); + var avgGW = (String(sideCode).toUpperCase() === 'A' ? expGamesWonA : expGamesWonB); … - var pOverGW = _simProbGamesWonOver(lineGW, sideLabel); + var pOverGW = _simProbGamesWonOver(lineGW, sideCode); … - pushPick({ key:'PROP_GW_' + sideLabel, label: sideLabel + ' Games Won', … }); + pushPick({ key:'PROP_GW_' + sideCode, label: displayName + ' Games Won', … });
Why: contextAdjustedSPW and computeHoldFromSPW expect 'A'/'B'. You were passing the player name, which made those functions treat any non-'B' string as 'A', pulling the wrong side’s data (see the current calls that pass names instead of codes (fixed_script_betting_lines_fix (1) (1).js)).
Near where you add player props:
diff- pushPropForPlayer(A, statsA); - pushPropForPlayer(B, statsB); + pushPropForPlayer('A', A, statsA); + pushPropForPlayer('B', B, statsB);
(Where the calls live: (fixed_script_betting_lines_fix (1) (1).js))
diff- function _simProbGamesWonOver(line, side) { - var arr = (side === A ? _simGamesWonA : _simGamesWonB); + function _simProbGamesWonOver(line, sideCode) { + var arr = (String(sideCode).toUpperCase() === 'A' ? _simGamesWonA : _simGamesWonB);
(Current version compares to the name string A instead of a side code, which breaks once you pass 'A'/'B'. Location: (fixed_script_betting_lines_fix (1) (1).js))
firstSrvPct before it exists)In last5Auto(...), the block that computes a weighted SPW:
js// Override serve point win rate using a weighted average... if (Number.isFinite(firstSrvPctVal) && Number.isFinite(fSrvWinRate) && Number.isFinite(sSrvWinRate)) { var wSpw = firstSrvPctVal * fSrvWinRate + (1 - firstSrvPctVal) * sSrvWinRate; if (wSpw > 0 && wSpw < 1) { spwVal = wSpw; } }
currently runs before firstSrvPctVal is set, so it never triggers (always false). Move that block after you define firstSrvPctVal/secSrvPctVal:
diff- // ... computes spwVal - // Override serve point win rate using a weighted average... - if (Number.isFinite(firstSrvPctVal) && Number.isFinite(fSrvWinRate) && Number.isFinite(sSrvWinRate)) { … } // (later) after totalServeAttempts and first/second-serve % var totalServeAttempts = a1 + a2; var firstSrvPctVal = (totalServeAttempts > 0) ? (a1 / totalServeAttempts) : null; var secSrvPctVal = (totalServeAttempts > 0) ? (a2 / totalServeAttempts) : null; + // Now re-compute spwVal as weighted FS/SS win% if all parts exist + if (Number.isFinite(firstSrvPctVal) && Number.isFinite(fSrvWinRate) && Number.isFinite(sSrvWinRate)) { + var wSpw = firstSrvPctVal * fSrvWinRate + (1 - firstSrvPctVal) * sSrvWinRate; + if (wSpw > 0 && wSpw < 1) { spwVal = wSpw; } + }
(You can see the premature use of firstSrvPctVal here, before it’s defined (fixed_script_betting_lines_fix (1) (1).js), and its definition later here (fixed_script_betting_lines_fix (1) (1).js).)
This fixes “not calculating some stats correctly” when props depend on SPW.
Use side codes in all internals: anywhere you branch on side, branch on 'A'/'B' and only use names for output. Double-check any remaining sideLabel === A comparisons and convert to code comparisons.
Row mapping sanity: _rows(side) assumes A is rows 2–6 & B is 12–16 ((fixed_script_betting_lines_fix (1) (1).js)). If your sheet changed, it will silently swap players. Either keep those blocks fixed, or teach _rows to look up named ranges/markers.
'A', stopping silent fallbacks that read the A block for both players (the exact bug here: passing names into contextAdjustedSPW / computeHoldFromSPW (fixed_script_betting_lines_fix (1) (1).js)).firstSrvPct, so props derived from SPW won’t be skewed by a stale/raw value (see order fix above (fixed_script_betting_lines_fix (1) (1).js) (fixed_script_betting_lines_fix (1) (1).js)).If you want, paste the top 15 lines of your output after these patches and I’ll eyeball that ML, aces, DF, and break-point props are attached to the right player.