Skip to content

Commit

Permalink
implement check for scoring errors
Browse files Browse the repository at this point in the history
  • Loading branch information
BSalita committed Oct 14, 2023
1 parent 2ce1e5e commit 20c0877
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 6 deletions.
2 changes: 1 addition & 1 deletion acbllib/acbllib.py
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ def get_club_results_details_data(url):
return None # todo: handle team events
data = soup.find('team-result-details')['v-bind:data']
else:
assert False, "Can't find data tag."
return None # "Can't find data tag."
assert data is not None and isinstance(data,str) and len(data), [url, data]

details_data = json.loads(data) # returns dict from json
Expand Down
6 changes: 5 additions & 1 deletion chatlib/chatlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -679,12 +679,16 @@ def augment_df(df,sd_cache_d):
# todo: drop either Tricks or Tricks_Declarer as they are invariant and duplicates
df['Tricks_Declarer'] = df['Tricks'] # synonym for Tricks
df['Score_Declarer'] = df.apply(lambda r: r['Score_'+r['Pair_Declarer_Direction']], axis='columns')
# recompute Score and compare against actual scores to catch scoring errors such as: Board 1 at https://my.acbl.org/club-results/details/878121
df['Computed_Score_Declarer'] = df.apply(lambda r: 0 if r['BidLvl'] is pd.NA else mlBridgeLib.score(r['BidLvl']-1, 'CDHSN'.index(r['BidSuit']), len(r['Dbl']), ('NESW').index(r['Declarer_Direction']), r['Vul_Declarer'], r['Result'],True), axis='columns')
if (df['Score_Declarer'].ne(df['Computed_Score_Declarer'])|df['Score_NS'].ne(-df['Score_EW'])).any():
print('Invalid Scores:\n',df[df['Score_Declarer'].ne(df['Computed_Score_Declarer'])|df['Score_NS'].ne(-df['Score_EW'])][['Board','Contract','BidLvl','BidSuit','Dbl','Declarer_Direction','Vul_Declarer','Score_Declarer','Computed_Score_Declarer','Score_NS','Score_EW','Result']])
df['MPs_Declarer'] = df.apply(lambda r: r['MatchPoints_'+r['Pair_Declarer_Direction']], axis='columns')

df['DDTricks'] = df.apply(lambda r: pd.NA if r['BidLvl'] is pd.NA else r['_'.join(['DD',r['Declarer_Direction'],r['BidSuit']])], axis='columns') # invariant
df['DDTricks_Dummy'] = df.apply(lambda r: pd.NA if r['BidLvl'] is pd.NA else r['_'.join(['DD',r['Direction_Dummy'],r['BidSuit']])], axis='columns') # invariant
# NA for NT. df['DDSLDiff'] = df.apply(lambda r: pd.NA if r['BidLvl'] is pd.NA else r['DDTricks']-r['SL_'+r['Pair_Declarer_Direction']+'_'+r['BidSuit']], axis='columns') # pd.NA or zero?
df['DDScore_NS'] = df.apply(lambda r: 0 if r['BidLvl'] is pd.NA else mlBridgeLib.score(r['BidLvl']-1, 'CDHSN'.index(r['BidSuit']), len(r['Dbl']), ('NSEW').index(r['Declarer_Direction']), mlBridgeLib.DirectionSymToVulBool(r['Vul_Declarer'],r['Declarer_Direction']), r['DDTricks']-r['BidLvl']-6), axis='columns')
df['DDScore_NS'] = df.apply(lambda r: 0 if r['BidLvl'] is pd.NA else mlBridgeLib.score(r['BidLvl']-1, 'CDHSN'.index(r['BidSuit']), len(r['Dbl']), ('NSEW').index(r['Declarer_Direction']), r['Vul_Declarer'], r['DDTricks']-r['BidLvl']-6), axis='columns')
df['DDScore_EW'] = -df['DDScore_NS']
df['DDMPs_NS'] = df.apply(lambda r: mlBridgeLib.MatchPointScoreUpdate(r['DDScore_NS'],matchpoint_ns_d[r['Board']])[r['DDScore_NS']][3],axis='columns')
df['DDMPs_EW'] = df['Board_Top']-df['DDMPs_NS']
Expand Down
14 changes: 13 additions & 1 deletion default.favorites.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
"@Boards_We_Underperformed_ParScore",
"@Single_Dummy_Our_Boards",
"@Single_Dummy_All_Boards",
"@Declarer_Rankings"
"@Declarer_Rankings",
"@Scoring_Errors"
]
},
"Summarize_Briefly": {
Expand Down Expand Up @@ -441,6 +442,17 @@
}
]
},
"Scoring_Errors": {
"title": "Showing Possible Scoring Errors or Adjustments",
"help": "**Scoring errors or adjustments.**",
"prompts": [
{
"failed prompt": "show board, contract, score_declarer, computed_score_declarer, score_ns, score_ew when score_declarer <> computed_score_declarer or score_ns <> -score_ew sort by board.",
"prompt": "",
"sql": "SELECT CONCAT(Pair_Number_NS, ' - ', Player_Name_N, ' - ', Player_Name_S) AS Pair_NS, CONCAT(Pair_Number_EW, ' - ', Player_Name_E, ' - ', Player_Name_W) AS Pair_EW, Board, Contract, Score_Declarer, Computed_Score_Declarer, Score_NS, Score_EW FROM results WHERE Score_Declarer <> Computed_Score_Declarer OR Score_NS <> -Score_EW ORDER BY Board"
}
]
},
"Overall_Rankings_Predictions": {
"title": "Overall Rankings Predictions",
"help": "**Predicted final overall rankings. Predictions made before game starts.**",
Expand Down
6 changes: 3 additions & 3 deletions mlBridgeLib/mlBridgeLib.py
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,7 @@ def DDmakesToScores(ddmakes,vuls):
highest_make_level = tricks-1-tricks_in_a_book
for level in range(max(highest_make_level,0), max_bidding_level):
result = highest_make_level-level
s = score(level, strain, result < 0, 0, v, result)
s = score(level, strain, result < 0, 0, v, result) # double all sets
strainl.append((s,(level,strain),direction,result))
# stable sort by contract then score
sorted_direction = sorted(sorted(strainl,key=lambda k:k[1]),reverse=True,key=lambda k:k[0])
Expand Down Expand Up @@ -616,7 +616,7 @@ def FilterBoards(df, cn=None, vul=None, direction=None, suit=None, contractType=
# adapted (MIT license) from https://github.com/jfklorenz/Bridge-Scoring/blob/master/features/score.js
# ================================================================
# Scoring
def score(level, suit, double, declarer, vulnerability, result):
def score(level, suit, double, declarer, vulnerability, result, declarer_score=False):
assert level in range(0, 7), f'ValueError: level {level} is invalid'
assert suit in range(0, 5), f'ValueError: suit {suit} is invalid' # CDHSN
assert double in range(0, 3), f'ValueError: double {double} is invalid' # ['','X','XX']
Expand Down Expand Up @@ -671,7 +671,7 @@ def score(level, suit, double, declarer, vulnerability, result):
points = -sum([undertricks[vulnerability][double][min(i, 3)]
for i in range(0, -result)])

return points if declarer < 2 else -points # negate points if EW
return points if declarer_score or declarer < 2 else -points # negate points if EW

# ================================================================

Expand Down
2 changes: 2 additions & 0 deletions release_notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@
19. Create a single dataframe for DD, SD, SD Max, Par, and Actual instead of separate dataframes.
20. Does low SD Max correlate to bad bidding/contract?
21. What does low SD but high Pct say about a declarer?
22. Show partnership declarer pct when showing declarer rankings.
23. Show par score pct and sd pcts for boards played by partnership.

## Column Issues
1. Rename any column names?
Expand Down

0 comments on commit 20c0877

Please sign in to comment.