Last active
June 11, 2024 18:00
-
-
Save izxxr/84178a7762ec5e6a8672c871f49fa6cc to your computer and use it in GitHub Desktop.
Calculate the requirements for Pakistan to overcome USA net run rate in T20 World Cup 2024
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Script to calculate the requirements for Pakistan Cricket Team to qualify | |
for super 8 stage of T20 World Cup 2024. | |
This script mainly focuses on calculating the requirements for Pakistan to | |
overcome the USA net run rate (NRR) on the points table in the following way: | |
- In case the opponent team is bowling first, this script can calculate the | |
number of overs required to chase the given target. | |
- In case the opponent team is batting first, this script can calculate the | |
the runs to which opponent team should be restricted to. | |
The formula for calculating the NRR is: | |
NRR = (Runs Scored / Overs Batted) - (Runs Conceded / Overs Bowled) | |
Note that there are a few caveats to this formula: | |
- Overs batted or bowled cannot be a number of UI format i.e. "overs.balls", | |
for example to calculate overs for format O.B. The formula would be: | |
-> O = (6O' + B) / 6 (O: Overs, O': number of overs, B: number of balls) | |
- If a team was all out before their complete overs, the overs | |
bowled would be taken as full overs. For example, if a team is | |
all out in 13 overs, the overs bowled would still be 20 (in case of T20). | |
For calculation methods, see the docstring of calculate_chase_overs() and | |
calculate_score_restriction() functions. | |
Updated 10 June 2024 - after PAK vs CAN: | |
The data used to calculate the requirements is until before Pakistan vs Ireland | |
match on 16 June 2024 and before IND vs USA on 11 June 2024. If using this script | |
after any of these matches of USA or Pakistan, please add the relevant match data | |
to following variables to ensure updated NRR is calculated: | |
- PAK_RUNS_SCORED | |
- PAK_OVERS_BATTED | |
- PAK_RUNS_CONCEDED | |
- PAK_OVERS_BOWLED | |
- USA_RUNS_SCORED | |
- USA_OVERS_BATTED | |
- USA_RUNS_CONCEDED | |
- USA_OVERS_BOWLED | |
Read the comments above each of these variables for information about the | |
respective variable's data. | |
TODO: Verify calculations, there might be an error in calculations somewhere. | |
Written and developed by Izhar Ahmad | |
""" | |
import os | |
def _calc_rr(runs, overs): | |
return runs / overs | |
def _calc_nrr(runs_scored, overs_batted, runs_conceded, overs_bowled): | |
return _calc_rr(runs_scored, overs_batted) - _calc_rr(runs_conceded, overs_bowled) | |
# Runs scored by Pakistan in last matches | |
PAK_RUNS_SCORED = 159 + 113 + 107 | |
# Overs batted by Pakistan in last matches | |
# Caveat: if team was all out before 20 overs, the | |
# overs would still be taken as 20. | |
# Against Canada, 17.3 overs. | |
# 17 * 6 = 102, 102 + 3 = 105 balls | |
# For overs, 105 / 6 | |
PAK_OVERS_BATTED = 20 + 20 + (105 / 6) | |
# Runs scored by opponents in last matches | |
PAK_RUNS_CONCEDED = 159 + 119 + 106 | |
# Overs bowled by Pakistan in last matches | |
# Caveat: if opponent team was all out before 20 overs, the | |
# overs would still be taken as 20. For example, India was | |
# all out in 19 overs but overs bowled in that match would | |
# still be taken as 20. | |
PAK_OVERS_BOWLED = 20 + 20 + 20 | |
# Runs scored by USA in last matches | |
USA_RUNS_SCORED = 197 + 159 | |
# Overs batted by USA in last matches | |
# Caveat: if team was all out before 20 overs, the | |
# overs would still be taken as 20. | |
# Against Canada, 17.4 overs. | |
# 17 * 6 = 102, 102 + 4 = 106 balls | |
# For overs, 106 / 6 | |
USA_OVERS_BATTED = 20 + (106 / 6) | |
# Runs scored by USA opponents | |
USA_RUNS_CONCEDED = 194 + 159 | |
# Overs bowled by USA | |
# Same caveat mentioned above for Pakistan applies here. | |
USA_OVERS_BOWLED = 20 + 20 | |
# Net run rates of respective teams - calculated based on given information | |
# in above variables. | |
USA_NRR = _calc_nrr(USA_RUNS_SCORED, USA_OVERS_BATTED, USA_RUNS_CONCEDED, USA_OVERS_BOWLED) | |
PAK_NRR = _calc_nrr(PAK_RUNS_SCORED, PAK_OVERS_BATTED, PAK_RUNS_CONCEDED, PAK_OVERS_BOWLED) | |
def _fmt_overs(overs): | |
total_balls = round(overs * 6) | |
overs = total_balls // 6 | |
balls = total_balls % 6 | |
if balls == 0: | |
return str(overs) | |
else: | |
return str(overs) + "." + str(balls) | |
def _print_header(team_name, second, xpad=8): | |
padding = xpad * " " | |
print(team_name + padding + second) | |
print(len(team_name) * "-" + padding + len(second) * "-") | |
def _fmt_output(target, overs, team_name, second, xpad=8): | |
target = str(target) | |
left_pad = " " * (len(team_name) // 2) | |
padding = xpad * " " * 2 | |
if len(target) == 1: | |
padding += " " | |
if len(target) == 3: | |
padding = padding[:len(padding) - 1] | |
print(f"{left_pad}{target}" + padding + overs) | |
def calculate_chase_overs(target): | |
"""Calculate the overs required to overcome US NRR while chasing the given target. | |
This is done by following method: | |
A new conceded run rate is calculated. Conceded run rate is | |
the second term in NRR formula. This is done by adding target | |
to previous runs conceded (PAK_RUNS_CONCEDED) and dividing by | |
60 (total overs bowled). | |
The new "scored runs" are calculated by adding "target + 1" to | |
previously scored runs (PAK_RUNS_SCORED). The +1 is done to | |
represent winning scenario. Adding target without +1 indicates | |
a tied match. | |
The new total overs used to overcome the NRR of USA are | |
calculated by formula (derived from NRR formula): | |
OVERS = NEW_SCORED_RUNS / (USA_NRR + NEW_CONCEDED_RR) | |
To get the number of overs for this match that the target | |
must be chased in, the difference is calculated between | |
previously batted overs and new total batted overs. | |
This function returns the overs as a string, in the "UI format." | |
""" | |
conceded_rr_new = _calc_rr(PAK_RUNS_CONCEDED + target, PAK_OVERS_BOWLED + 20) | |
scored_runs_new = PAK_RUNS_SCORED + target + 1 | |
total_overs = (scored_runs_new) / (USA_NRR + conceded_rr_new) | |
required_overs = total_overs - PAK_OVERS_BATTED | |
return _fmt_overs(required_overs) | |
def calculate_score_restriction(pak_score): | |
"""Calculates the score to restrict opponent to for overcoming US NRR if defending target. | |
This is calculated using the following formula: | |
C = P + R - R' - N(O + 20) | |
C: the restricted score | |
P: Pakistan's total in first innings | |
R: runs scored in previous matches by Pakistan | |
R': runs conceeded in previous matches by Pakistan | |
N: NRR of USA | |
O: overs batted by Pakistan | |
This is derived using NRR formula: | |
N = (R / O) - (R' / O') | |
N: NRR of USA | |
R: runs scored in previous matches by Pakistan | |
R': runs conceeded in previous matches by Pakistan | |
O: overs batted | |
O': overs bowled | |
For accounting for next match, | |
- add Pakistan's score of first innings (P) to runs scored | |
- add opponent's score in second innings (C) to runs conceded | |
- add 20 to both overs | |
N = (R + P) / (O + 20) - (R' + C) / (O' + 20) | |
Since we are considering second innings, we can assume | |
that O = O' | |
N = (R + P) / (O + 20) - (R' + C) / (O + 20) | |
N = (R + P - R' - C) / O + 20 | |
N(O + 20) = R + P - R' - C | |
C = P + R - R' - N(O + 20) | |
TODO: Verify O = O' really a correct assumption. | |
""" | |
F = USA_NRR * (PAK_OVERS_BATTED + 20) | |
return round(pak_score + PAK_RUNS_SCORED - PAK_RUNS_CONCEDED - F) | |
ipt = input("Is Pakistan batting first? (yes/no) ") | |
opp_bat_first = ipt == "no" | |
if opp_bat_first: | |
team_name = "Opponent Score" | |
second_col = "Chase in (Overs)" | |
_print_header(team_name, second_col) | |
for target in range(5, 250, 5): | |
overs = calculate_chase_overs(target) | |
_fmt_output(target, overs, team_name, second_col) | |
else: | |
team_name = "Pakistan Score" | |
second_col = "Restrict Opponent To" | |
_print_header(team_name, second_col) | |
for target in range(35, 250, 5): | |
score = calculate_score_restriction(target) | |
_fmt_output(target, str(score), team_name, second_col) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment