Skip to content

Commit

Permalink
Add tests for old indoor classifications.
Browse files Browse the repository at this point in the history
  • Loading branch information
jatkinson1000 committed Aug 27, 2023
1 parent 959df2f commit 2e8a857
Show file tree
Hide file tree
Showing 2 changed files with 308 additions and 21 deletions.
40 changes: 19 additions & 21 deletions archeryutils/classifications/agb_old_indoor_classifications.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,28 +111,23 @@ def calculate_agb_old_indoor_classification(
ArcheryGB 2023 Rules of Shooting
ArcheryGB Shooting Administrative Procedures - SAP7 (2023)
"""
# deal with reduced categories:
age_group = "Adult"
if bowstyle.lower() not in ("compound"):
bowstyle = "Recurve"

groupname = cls_funcs.get_groupname(bowstyle, gender, age_group)
group_data = agb_old_indoor_classifications[groupname]

hc_params = hc_eq.HcParams()
# Check score is valid
if score < 0 or score > ALL_INDOOR_ROUNDS[roundname].max_score():
raise ValueError(
f"Invalid score of {score} for a {roundname}. "
f"Should be in range 0-{ALL_INDOOR_ROUNDS[roundname].max_score()}."
)

# Get scores required on this round for each classification
class_scores = [
hc_eq.score_for_round(
ALL_INDOOR_ROUNDS[roundname],
group_data["class_HC"][i],
"AGBold",
hc_params,
round_score_up=True,
)[0]
for i, class_i in enumerate(group_data["classes"])
]
class_scores = agb_old_indoor_classification_scores(
roundname,
bowstyle,
gender,
age_group,
)

groupname = cls_funcs.get_groupname(bowstyle, gender, age_group)
group_data = agb_old_indoor_classifications[groupname]
class_data: Dict[str, Any] = dict(zip(group_data["classes"], class_scores))

# What is the highest classification this score gets?
Expand All @@ -150,8 +145,7 @@ def calculate_agb_old_indoor_classification(
classification_from_score = list(class_data.keys())[0]
return classification_from_score
except IndexError:
# return "UC"
return "unclassified"
return "UC"


def agb_old_indoor_classification_scores(
Expand Down Expand Up @@ -187,6 +181,10 @@ def agb_old_indoor_classification_scores(
ArcheryGB Rules of Shooting
ArcheryGB Shooting Administrative Procedures - SAP7
"""
# enforce compound scoring
if bowstyle.lower() in ("compound"):
roundname = cls_funcs.get_compound_codename(roundname)

# deal with reduced categories:
age_group = "Adult"
if bowstyle.lower() not in ("compound"):
Expand Down
289 changes: 289 additions & 0 deletions archeryutils/classifications/tests/test_agb_old_indoor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,289 @@
"""Tests for old agb indoor classification functions"""
from typing import List
import pytest

from archeryutils import load_rounds
import archeryutils.classifications as class_funcs


ALL_INDOOR_ROUNDS = load_rounds.read_json_to_round_dict(
[
"WA_indoor.json",
"AGB_indoor.json",
]
)


class TestAgbOldIndoorClassificationScores:
"""
Class to test the old_indoor classification scores function.
Methods
-------
test_agb_old_indoor_classification_scores_ages()
test if expected scores returned for different ages
test_agb_old_indoor_classification_scores_genders()
test if expected scores returned for different genders
test_agb_old_indoor_classification_scores_bowstyles()
test if expected scores returned for different bowstyles
test_agb_old_indoor_classification_scores_gent_compound_worcester
test supposed loophole in worcester for gent compound
test_agb_old_indoor_classification_scores_invalid()
test invalid inputs
"""

@pytest.mark.parametrize(
"age_group,scores_expected",
[
(
"adult",
[592, 582, 554, 505, 432, 315, 195, 139],
),
(
"50+",
[592, 582, 554, 505, 432, 315, 195, 139],
),
(
"under21",
[592, 582, 554, 505, 432, 315, 195, 139],
),
(
"Under 18",
[592, 582, 554, 505, 432, 315, 195, 139],
),
(
"Under 12",
[592, 582, 554, 505, 432, 315, 195, 139],
),
],
)
def test_agb_old_indoor_classification_scores_ages(
self,
age_group: str,
scores_expected: List[int],
) -> None:
"""
Check that old_indoor classification returns expected value for a case.
ALl ages should return the same values.
"""
scores = class_funcs.agb_old_indoor_classification_scores(
roundname="portsmouth",
bowstyle="recurve",
gender="male",
age_group=age_group,
)

assert scores == scores_expected

def test_agb_old_indoor_classification_scores_genders(
self,
) -> None:
"""
Check that old_indoor classification returns expected value for a case.
"""
scores = class_funcs.agb_old_indoor_classification_scores(
roundname="portsmouth",
bowstyle="recurve",
gender="female",
age_group="adult",
)

assert scores == [582, 569, 534, 479, 380, 255, 139, 93]

@pytest.mark.parametrize(
"bowstyle,gender,scores_expected",
[
(
"compound",
"male",
[581, 570, 554, 529, 484, 396, 279, 206],
),
(
"compound",
"female",
[570, 562, 544, 509, 449, 347, 206, 160],
),
],
)
def test_agb_old_indoor_classification_scores_bowstyles(
self,
bowstyle: str,
gender: str,
scores_expected: List[int],
) -> None:
"""
Check that old_indoor classification returns expected value for a case.
Also checks that compound scoring is enforced.
"""
scores = class_funcs.agb_old_indoor_classification_scores(
roundname="portsmouth",
bowstyle=bowstyle,
gender=gender,
age_group="adult",
)

assert scores == scores_expected

def test_agb_old_indoor_classification_scores_gent_compound_worcester(
self,
) -> None:
"""
Check gent compound worcester supposed loophole.
"""
scores = class_funcs.agb_old_indoor_classification_scores(
roundname="worcester",
bowstyle="compound",
gender="male",
age_group="adult",
)

assert scores == [300, 299, 289, 264, 226, 162, 96, 65]

@pytest.mark.parametrize(
"bowstyle,gender,age_group",
# Check all systems, different distances, negative and large handicaps.
[
# No invalid bowstyle as anything non-compound returns non-compound.
# No invalid age as only one table for all ages.
(
"recurve",
"invalidgender",
"adult",
),
],
)
def test_agb_old_indoor_classification_scores_invalid(
self,
bowstyle: str,
gender: str,
age_group: str,
) -> None:
"""
Check that old_indoor classification returns expected value for a case.
"""
with pytest.raises(
KeyError,
match=(
f"{age_group.lower().replace(' ','')}_{gender.lower()}_{bowstyle.lower()}"
),
):
_ = class_funcs.agb_old_indoor_classification_scores(
roundname="portsmouth",
bowstyle=bowstyle,
gender=gender,
age_group=age_group,
)


class TestCalculateAgbOldIndoorClassification:
"""
Class to test the old_indoor classification function.
Methods
-------
test_calculate_agb_old_indoor_classification()
test_calculate_agb_old_indoor_classification_invalid_scores()
"""

@pytest.mark.parametrize(
"score,gender,class_expected",
[
(
400,
"male",
"F",
),
(
337,
"female",
"F",
),
(
592,
"male",
"A",
),
(
582,
"female",
"A",
),
(
581,
"male",
"C",
),
(
120,
"male",
"UC",
),
(
1,
"male",
"UC",
),
],
)
def test_calculate_agb_old_indoor_classification(
self,
score: float,
gender: str,
class_expected: str,
) -> None:
"""
Check that old_indoor classification returns expected value for a few cases.
"""
class_returned = class_funcs.calculate_agb_old_indoor_classification(
roundname="portsmouth",
score=score,
bowstyle="recurve",
gender=gender,
age_group="adult",
)

assert class_returned == class_expected

@pytest.mark.parametrize(
"roundname,score",
[
(
"portsmouth",
1000,
),
(
"portsmouth",
601,
),
(
"portsmouth",
-1,
),
(
"portsmouth",
-100,
),
],
)
def test_calculate_agb_old_indoor_classification_invalid_scores(
self,
roundname: str,
score: float,
) -> None:
"""
Check that old_indoor classification fails for inappropriate scores.
"""
with pytest.raises(
ValueError,
match=(
f"Invalid score of {score} for a {roundname}. "
f"Should be in range 0-{ALL_INDOOR_ROUNDS[roundname].max_score()}."
),
):
_ = class_funcs.calculate_agb_old_indoor_classification(
roundname=roundname,
score=score,
bowstyle="barebow",
gender="male",
age_group="adult",
)

0 comments on commit 2e8a857

Please sign in to comment.