diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml index 830e2e6..89612ec 100644 --- a/.github/workflows/python-app.yml +++ b/.github/workflows/python-app.yml @@ -36,4 +36,6 @@ jobs: flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - name: Test with pytest run: | - pytest + pip install pytest pytest-cov + pytest tests.py --doctest-modules --junitxml=junit/test-results.xml --cov=com --cov-report=xml --cov-report=html + continue-on-error: true diff --git a/src/ratings_calculator/Profile.py b/src/ratings_calculator/Profile.py new file mode 100644 index 0000000..d5a0c2c --- /dev/null +++ b/src/ratings_calculator/Profile.py @@ -0,0 +1,72 @@ +"""Class to get cfc profile information of the user""" +import json +import requests + + +class CFCProfile: + """User id of the user that we are trying to get data for""" + + # default constructor for ratings calculator + def __init__(self, user_id: int, request=True) -> None: + self.user_id = user_id + self.profile = self.initialize_profile(request) + return + + def initialize_profile(self, request=True) -> dict: + """ + Gets the profile of the user + :param request: boolean indicating whether to use the web to search for this fvalue or not. + :return: json dictionary mapping of the player and its fields + """ + if request: + URL = f"https://server.chess.ca/api/player/v1/{self.user_id}" + page = requests.get(URL) + return page.json() + else: + # open the json file and place the file as the value into the page + filepath = "player_info.json" + f = open(filepath) + data = json.load(f) + return data + + def get_profile(self) -> dict: + """ + Gets the profile of the current user + :return: json dictionary mapping of the player and its fields + """ + return self.profile + + def get_events_played(self) -> int: + """ + Gets the number of events that this user has participated in + :return: events that this user has played in + """ + numEvents = 0 + if self.profile["player"]["events"] == []: + return 0 + else: + return len(self.profile["player"]["events"]) + + def get_last_tournaments(self, num_tournaments: int) -> []: + """ + Gets the number of events that this user has participated in + :param num_tournaments: previous n tournaments to get. + :return: events that this user has played in + """ + + tournament_data = [] + + if num_tournaments > len(self.profile["player"]["events"]): + # if the number of tournaments is greater than the number that exists in the json, take that number + num_tournaments = len(self.profile["player"]["events"]) + + for i in range(num_tournaments): + tournament_data.append(self.profile["player"]["events"][i]) + + return tournament_data + + +class FIDEProfile: + """Gets user id data for FIDE profile""" + + pass diff --git a/src/ratings_calculator/RatingsCalculator.py b/src/ratings_calculator/RatingsCalculator.py new file mode 100644 index 0000000..ba0659f --- /dev/null +++ b/src/ratings_calculator/RatingsCalculator.py @@ -0,0 +1,178 @@ +import math +from csv import reader + + +class RatingsCalculator: + """Ratings Calculator is a class that calculates ratings, cfc-style""" + + # default constructor for ratings calculator + def __init__(self) -> None: + self.expected_scores = self.expected_scores_init() + + return + + def average_rating(self, ratings: list) -> float: + """ + Average ratings of the list of the ratings + :param ratings: a list of ratings + :return: average rating + """ + ave_rating = 0 + for rating in ratings: + ave_rating += rating + return ave_rating / len(ratings) + + def provisional_unrated_players(self, ratings: list, wins: int, losses: int, games_played: int) -> object: + """ + wins is the number of wins, + losses is the number of losses + games_played is the number of games + ratings is the list of opponent's ratings + """ + Rc = self.average_rating(ratings) + # Rp = Rc + 400 (W - L) / N + Rp = Rc + 400 * (wins - losses) / games_played + return Rp + + def established_ratings(self, all_time_high_score: int, old_rating: int, score: float, opponent_ratings: list, + quick=False) -> float: + """ + Returns the established rating from the dictionary of ratings + :param all_time_high_score: the all time high of the player + :param score: the total score from the tournament + :param opponent_ratings: a list of opponent ratings + :param old_rating: the player's old rating + :param quick: if the time control used is between 5 and 14 minutes + :return: returns the established rating of the player + >>> ratingTest = RatingsCalculator() + >>> # expected_dict = ratingTest.expected_scores_init() + >>> ratingTest.established_ratings(1450, 1450, 4, [1237, 1511, 1214, 1441, 1579, 2133]) + 1487 + """ + if score > len(opponent_ratings): + raise Exception("Cannot have higher score than games played") + + # K=32 for players under 2200 and K=16 for players at or over 2200; + # Rn = Ro + 32 (S - Sx) + if old_rating >= 2199: + multiplier = 16 + else: + multiplier = 32 + + # if quick (where time control used is between 5-14 min) + if quick: + multiplier = multiplier // 2 + + # expected_scores_dict = self.expected_scores_init() + + expected_total = self.expected_total_score(old_rating, opponent_ratings) + new_rating = old_rating + multiplier * (score - expected_total) + + if new_rating > all_time_high_score: + all_time_high_valid = 1 + else: + all_time_high_valid = 0 + + multiplier_e = multiplier // 32 # ratio of the multiplier to ratings under 2200. + bonus = self.bonuses(all_time_high_valid, multiplier_e, new_rating, old_rating, len(opponent_ratings)) + sum_of_scores = new_rating + bonus + return sum_of_scores + + def bonuses(self, a: int, k_factor_e: int, r_new: float, r_old: int, n: int) -> int: + """ + Returns the total sum of all bonuses available + :param a: is = 1 if all time high, 0 otherwise + :param k_factor_e: ratio of the player's k factor to the k factor used for players under 2200 + :param r_new: post-event rating + :param r_old: pre-event rating + :param n: number of games played + :return: value of the new rating + >>> ratingTest = RatingsCalculator() + >>> ratingTest.bonuses(0, 1, 1487, 1450, 6) + 1496 + """ + if n < 4: # no bonus points awarded if less than 4 games played + return 0 + + R_MAX_BONUS = 20 # constants set + R_CHANGE_BONUS = 1.75 + R_CHANGE_THRESHOLD = 13 + + bonus1 = a * R_MAX_BONUS * k_factor_e + threshold = R_CHANGE_THRESHOLD * k_factor_e * math.sqrt(n) + + if r_new > (r_old + threshold): + b = 1 + else: + b = 0 + + bonus2 = b * R_CHANGE_BONUS * (r_new - r_old - threshold) * k_factor_e + total_bonus = round(bonus1 + bonus2) + return total_bonus + + def expected_total_score(self, rating: int, opponent_ratings: list): + """ + Returns the expected total score from the tournament + :param rating: is the player's rating + :param opponent_ratings: is the opponent's rating in a lists + >>> ratingTest = RatingsCalculator() + >>> ratingTest.expected_total_score(1450, [1237, 1511, 1214, 1441, 1579, 2133]) + 2.84 + """ + sum_expected = 0 + for opp_rating in opponent_ratings: + if rating >= opp_rating: # your rating is bigger than the opponents + sum_expected += self.find_expected_value(rating - opp_rating, 0) + else: + sum_expected += self.find_expected_value(opp_rating - rating, 1) + + return sum_expected + + def find_expected_value(self, difference: int, lower_val: int): + """ + Returns the expected value of the individual based on whether it is a lower or higher score. + :param lower_val: whether the number is a lower value + :param difference: is the difference in ratings + :return: expected value based on the expected dictionary + """ + expected_dict = self.expected_scores + expected = expected_dict[int(difference)] + if lower_val == 1: + expected = round(1 - expected, 2) + else: + # keep the older value + pass + + return expected + + def expected_scores_init(self) -> dict: + """ + Returns the expected score dictionary + :return: dictionary containing expected scores + """ + # file is recommend to be in the following format: starting rank, Name of Player, CFC ID + # information of the event + file_name = "C:\\Users\\zheng\\PycharmProjects\\ratings-calculator\\ExpectedScores.csv" + expected_scores_higher = {} + + with open(file_name, 'r') as f: + csv_reader = reader(f) + next(csv_reader) + + for row in csv_reader: + # iterate through each row + # print(row) + # if it's the last line + max_diff = 2000 + if row[0][0:3] == "735": + for j in range(735, max_diff): + expected_scores_higher[j] = 1 + else: + row_vals = row[0].split("-") + starting_val = int(row_vals[0]) + end_val = int(row_vals[1]) + + for j in range(starting_val, end_val + 1): + expected_scores_higher[j] = float(row[1]) # the location of the csv file + + return expected_scores_higher diff --git a/src/ratings_calculator/chesscanada.html b/src/ratings_calculator/chesscanada.html new file mode 100644 index 0000000..37bf65d --- /dev/null +++ b/src/ratings_calculator/chesscanada.html @@ -0,0 +1,323 @@ + + + CFC Ratings Calculator + + + + + + + +

+ + + + + + + + + +
+
+ + CFC Ratings Calculator +
+ + + Using the current CFC Ratings formulas as of August 1st, 2012. + + +
+ +

+


+ +

+ To use this calculator, enter your current rating as well as the result and ratings of your opponents. + The calculator will display your new ratings! + + +

+

+ +

+ + + + +
+ Required Information: +

+ Your + current rating
+

+ Enter your opponents' ratings separated by spaces; +/-/= for win/loss/draw. Example: +1600 + -1850 =1725.
+
+ + +

+ +

+

+ + + + +
+ Number of games +

+ Your score +

+ + Your performance + rating +

+ + Your new rating + (no bonus) +

+ + Your new rating + (regular bonus) +

+ Your new rating + (lifetime high bonus) +

+

+ +

+ For new rating, no bonus would mean under normal circumstances. If the regular bonus field is higher, + that will be your new rating. + The lifetime high bonus rating will only be yours if the no bonus rating exceeds your highest ever + rating. Regular Bonus does not apply unless you play at least four games. +

+ Also please note that due to rounding issues, results here may not exactly duplicate your CFC rating. + They should always be within 1 point, however. +


+ +
+ + + + + diff --git a/src/ratings_calculator/main.py b/src/ratings_calculator/main.py index 666228b..9e9e6b4 100644 --- a/src/ratings_calculator/main.py +++ b/src/ratings_calculator/main.py @@ -1,5 +1,4 @@ -import math -from csv import reader +from src.ratings_calculator.RatingsCalculator import RatingsCalculator """ @author Victor Zheng @@ -51,6 +50,24 @@ RChangeThreshold = 13 (a constant). The numerical values in the bonus point equation may be adjusted from time to time by the Rating Auditor as deemed necessary and in consultation with the CFC Executive. + +TODO: From 411.1 Quick Chess, quick ratings will be calculated with 1/2 of the k factor +- this appears to not be in effect? + +TODO: This is not covered by the current calculation: +416. For a player with a pre-event rating below 800. + +TODO: If a player’s post tournament rating (including any participation and bonus points) is less than 200, the player +is entered in the rating list at 200. This applies to both provisional and permanent ratings. + +TODO: Provisional ratings: 3 to 24 games + + +TODO: For players who start a tournament above 2200 and during the event drop below 2200, we currently assume that the +k factor remians the same. + +However, this is not correct as the ratings can change. + """ """ @@ -58,173 +75,6 @@ """ -class RatingsCalculator: - """Ratings Calculator is a class that calculates ratings, cfc-style""" - - # default constructor for ratings calculator - def __init__(self) -> None: - self.expected_scores = self.expected_scores_init() - - return - - def average_rating(self, ratings: list) -> float: - """ - Average ratings of the list of the ratings - :param ratings: a list of ratings - :return: average rating - """ - ave_rating = 0 - for rating in ratings: - ave_rating += rating - return ave_rating / len(ratings) - - def provisional_unrated_players(self, ratings: list, wins: int, losses: int, games_played: int) -> object: - """ - wins is the number of wins, - losses is the number of losses - games_played is the number of games - ratings is the list of opponent's ratings - """ - Rc = self.average_rating(ratings) - # Rp = Rc + 400 (W - L) / N - Rp = Rc + 400 * (wins - losses) / games_played - return Rp - - def established_ratings(self, all_time_high_score: int, old_rating: int, score: float, opponent_ratings: list) -> float: - """ - Returns the established rating from the dictionary of ratings - :param all_time_high_score: the all time high of the player - :param score: the total score from the tournament - :param opponent_ratings: a list of opponent ratings - :param old_rating: the player's old rating - :return: returns the established rating of the player. - >>> ratingTest = RatingsCalculator() - >>> # expected_dict = ratingTest.expected_scores_init() - >>> ratingTest.established_ratings(1450, 1450, 4, [1237, 1511, 1214, 1441, 1579, 2133]) - 1487 - """ - # K=32 for players under 2200 and K=16 for players at or over 2200; - # Rn = Ro + 32 (S - Sx) - if old_rating >= 2199: - multiplier = 16 - else: - multiplier = 32 - - # expected_scores_dict = self.expected_scores_init() - - expected_total = self.expected_total_score(old_rating, opponent_ratings) - new_rating = old_rating + multiplier * (score - expected_total) - - if new_rating > all_time_high_score: - all_time_high_valid = 1 - else: - all_time_high_valid = 0 - - multiplier_e = multiplier // 32 # ratio of the multiplier to ratings under 2200. - bonus = self.bonuses(all_time_high_valid, multiplier_e, new_rating, old_rating, len(opponent_ratings)) - sum_of_scores = new_rating + bonus - return sum_of_scores - - def bonuses(self, a: int, k_factor_e: int, r_new: float, r_old: int, n: int) -> int: - """ - Returns the total sum of all bonuses available - :param a: is = 1 if all time high, 0 otherwise - :param k_factor_e: ratio of the player's k factor to the k factor used for players under 2200 - :param r_new: post-event rating - :param r_old: pre-event rating - :param n: number of games played - :return: value of the new rating - >>> ratingTest = RatingsCalculator() - >>> ratingTest.bonuses(0, 1, 1487, 1450, 6) - 1496 - """ - if n < 4: # no bonus points awarded if less than 4 games played - return 0 - - R_MAX_BONUS = 20 # constants set - R_CHANGE_BONUS = 1.75 - R_CHANGE_THRESHOLD = 13 - - bonus1 = a * R_MAX_BONUS * k_factor_e - threshold = R_CHANGE_THRESHOLD * k_factor_e * math.sqrt(n) - - if r_new > (r_old + threshold): - b = 1 - else: - b = 0 - - bonus2 = b * R_CHANGE_BONUS * (r_new - r_old - threshold) * k_factor_e - total_bonus = round(bonus1 + bonus2) - return total_bonus - - def expected_total_score(self, rating: int, opponent_ratings: list): - """ - Returns the expected total score from the tournament - :param rating: is the player's rating - :param opponent_ratings: is the opponent's rating in a lists - >>> ratingTest = RatingsCalculator() - >>> ratingTest.expected_total_score(1450, [1237, 1511, 1214, 1441, 1579, 2133]) - 2.84 - """ - sum_expected = 0 - for opp_rating in opponent_ratings: - if rating >= opp_rating: # your rating is bigger than the opponents - sum_expected += self.find_expected_value(rating - opp_rating, 0) - else: - sum_expected += self.find_expected_value(opp_rating - rating, 1) - - return sum_expected - - def find_expected_value(self, difference: int, lower_val: int): - """ - Returns the expected value of the individual based on whether it is a lower or higher score. - :param lower_val: whether the number is a lower value - :param difference: is the difference in ratings - :return: expected value based on the expected dictionary - """ - expected_dict = self.expected_scores - expected = expected_dict[int(difference)] - if lower_val == 1: - expected = round(1 - expected, 2) - else: - # keep the older value - pass - - return expected - - def expected_scores_init(self) -> dict: - """ - Returns the expected score dictionary - :return: dictionary containing expected scores - """ - # file is recommend to be in the following format: starting rank, Name of Player, CFC ID - # information of the event - file_name = "C:\\Users\\zheng\\PycharmProjects\\ratings-calculator\\ExpectedScores.csv" - expected_scores_higher = {} - - with open(file_name, 'r') as f: - csv_reader = reader(f) - next(csv_reader) - - for row in csv_reader: - # iterate through each row - # print(row) - # if it's the last line - max_diff = 2000 - if row[0][0:3] == "735": - for j in range(735, max_diff): - expected_scores_higher[j] = 1 - else: - row_vals = row[0].split("-") - starting_val = int(row_vals[0]) - end_val = int(row_vals[1]) - - for j in range(starting_val, end_val + 1): - expected_scores_higher[j] = float(row[1]) # the location of the csv file - - return expected_scores_higher - - if __name__ == "__main__": print("Welcome to Ratings Calculator\n\n" "This project is about calculating more accurate CFC ratings than ever before. \n" @@ -263,7 +113,7 @@ def expected_scores_init(self) -> dict: n = int(numInput) ratings_list = [] - for i in range(1, n+1): + for i in range(1, n + 1): ele = input("Rating of player " + str(i) + ": ") if not ele.isnumeric(): @@ -286,11 +136,14 @@ def expected_scores_init(self) -> dict: all_time_high = int(input("All Time High Rating: ")) # established or provisional rating? (can be removed in the future)) - rating_type = int(input("Rating Type: (1 for established, 0 for provisional: ")) + rating_type = int(input("Rating Type: (1 for established, 0 for provisional): ")) + + # established or provisional rating? (can be removed in the future)) + quickTourney = int(input("Quick Tournament: (1 for quick less than 15 minutes total, 0 for classical): ")) if rating_type == 1: # new_rating = established_ratings(1450, 1450, 4, [1237, 1511, 1214, 1441, 1579, 2133]) - calc_new_rating = ratingsCalc.established_ratings(all_time_high, current_rating, (wins+draws), ratings_list) + calc_new_rating = ratingsCalc.established_ratings(all_time_high, current_rating, (wins + draws), ratings_list) else: calc_new_rating = ratingsCalc.provisional_unrated_players(ratings_list, n, wins, losses) diff --git a/src/ratings_calculator/player_info.json b/src/ratings_calculator/player_info.json new file mode 100644 index 0000000..6cd648c --- /dev/null +++ b/src/ratings_calculator/player_info.json @@ -0,0 +1,1540 @@ +{ + "updated": "2023-12-21", + "player": { + "cfc_id": 150532, + "cfc_expiry": "2024-06-30", + "fide_id": 2620189, + "name_first": "Victor", + "name_last": "Zheng", + "addr_city": "Toronto", + "addr_province": "ON", + "regular_rating": 2073, + "regular_indicator": 2160, + "quick_rating": 2092, + "quick_indicator": 2092, + "events": [ + { + "id": 202312054, + "name": "2023 GTCL Cup U1800", + "date_end": "2023-11-27", + "rating_type": "Q", + "games_played": 5, + "score": 5.0, + "rating_pre": 2002, + "rating_perf": 2202, + "rating_post": 2092, + "rating_indicator": 2092 + }, + { + "id": 202311050, + "name": "2023 ACC Hallowe'en Rapid", + "date_end": "2023-10-30", + "rating_type": "Q", + "games_played": 5, + "score": 4.0, + "rating_pre": 1882, + "rating_perf": 2132, + "rating_post": 2002, + "rating_indicator": 2002 + }, + { + "id": 202310075, + "name": "Hart House October Open - Crown", + "date_end": "2023-10-22", + "rating_type": "R", + "games_played": 5, + "score": 3.0, + "rating_pre": 2014, + "rating_perf": 2211, + "rating_post": 2073, + "rating_indicator": 2160 + }, + { + "id": 202307026, + "name": "2023 Canadian Junior Open", + "date_end": "2023-07-09", + "rating_type": "R", + "games_played": 6, + "score": 3.5, + "rating_pre": 2068, + "rating_perf": 1850, + "rating_post": 2014, + "rating_indicator": 2160 + }, + { + "id": 202306079, + "name": "Cdn Transnational Blitz General", + "date_end": "2023-06-03", + "rating_type": "Q", + "games_played": 14, + "score": 9.0, + "rating_pre": 1856, + "rating_perf": 1843, + "rating_post": 1882, + "rating_indicator": 1882 + }, + { + "id": 202303124, + "name": "5th Ivy League Challenge", + "date_end": "2023-03-26", + "rating_type": "R", + "games_played": 1, + "score": 1.0, + "rating_pre": 2050, + "rating_perf": 2503, + "rating_post": 2068, + "rating_indicator": 2160 + }, + { + "id": 202302001, + "name": "CUCC - Championship Section", + "date_end": "2023-01-29", + "rating_type": "R", + "games_played": 5, + "score": 2.5, + "rating_pre": 2043, + "rating_perf": 2080, + "rating_post": 2050, + "rating_indicator": 2160 + }, + { + "id": 202212022, + "name": "Hart House Holidays Open - Crown", + "date_end": "2022-12-11", + "rating_type": "R", + "games_played": 1, + "score": 0.0, + "rating_pre": 2052, + "rating_perf": 1808, + "rating_post": 2043, + "rating_indicator": 2160 + }, + { + "id": 202212042, + "name": "GTCL Cup Crown", + "date_end": "2022-12-05", + "rating_type": "Q", + "games_played": 5, + "score": 2.0, + "rating_pre": 1818, + "rating_perf": 1943, + "rating_post": 1856, + "rating_indicator": 1856 + }, + { + "id": 202211105, + "name": "Toronto Closed - Reserves", + "date_end": "2022-11-21", + "rating_type": "R", + "games_played": 9, + "score": 3.0, + "rating_pre": 2139, + "rating_perf": 1905, + "rating_post": 2052, + "rating_indicator": 2160 + }, + { + "id": 202209014, + "name": "NAYCC U18 Open", + "date_end": "2022-08-14", + "rating_type": "R", + "games_played": 9, + "score": 4.5, + "rating_pre": 2160, + "rating_perf": 2105, + "rating_post": 2139, + "rating_indicator": 2160 + }, + { + "id": 202205047, + "name": "2022 Ontario Open - U2200", + "date_end": "2022-05-23", + "rating_type": "R", + "games_played": 6, + "score": 5.0, + "rating_pre": 1918, + "rating_perf": 2336, + "rating_post": 2160, + "rating_indicator": 2160 + }, + { + "id": 202002048, + "name": "BC Open Premier", + "date_end": "2020-02-17", + "rating_type": "R", + "games_played": 6, + "score": 2.5, + "rating_pre": 1950, + "rating_perf": 1841, + "rating_post": 1918, + "rating_indicator": 2000 + }, + { + "id": 202001037, + "name": "2020 Victoria Open - Premier", + "date_end": "2020-01-19", + "rating_type": "R", + "games_played": 5, + "score": 3.0, + "rating_pre": 1965, + "rating_perf": 1898, + "rating_post": 1950, + "rating_indicator": 2000 + }, + { + "id": 201911058, + "name": "2019 BC Junior Championship", + "date_end": "2019-11-11", + "rating_type": "R", + "games_played": 5, + "score": 4.0, + "rating_pre": 1942, + "rating_perf": 2051, + "rating_post": 1965, + "rating_indicator": 2000 + }, + { + "id": 201910042, + "name": "New West Fall Open Premier", + "date_end": "2019-10-14", + "rating_type": "R", + "games_played": 6, + "score": 3.0, + "rating_pre": 1979, + "rating_perf": 1818, + "rating_post": 1942, + "rating_indicator": 2000 + }, + { + "id": 201908008, + "name": "New West Summer Open Premier", + "date_end": "2019-08-05", + "rating_type": "R", + "games_played": 6, + "score": 3.0, + "rating_pre": 1976, + "rating_perf": 1985, + "rating_post": 1979, + "rating_indicator": 2000 + }, + { + "id": 201905094, + "name": "Paul Keres Memorial Premier", + "date_end": "2019-05-20", + "rating_type": "R", + "games_played": 6, + "score": 2.0, + "rating_pre": 2000, + "rating_perf": 1904, + "rating_post": 1976, + "rating_indicator": 2000 + }, + { + "id": 201904097, + "name": "GPO 2019 Premier", + "date_end": "2019-04-22", + "rating_type": "R", + "games_played": 6, + "score": 3.0, + "rating_pre": 1961, + "rating_perf": 2038, + "rating_post": 2000, + "rating_indicator": 2000 + }, + { + "id": 201903041, + "name": "2019 BCYCC U16 Open", + "date_end": "2019-03-10", + "rating_type": "R", + "games_played": 4, + "score": 3.0, + "rating_pre": 1978, + "rating_perf": 1601, + "rating_post": 1961, + "rating_indicator": 1978 + }, + { + "id": 201902048, + "name": "2019 BC Open Premier", + "date_end": "2019-02-18", + "rating_type": "R", + "games_played": 6, + "score": 3.0, + "rating_pre": 1951, + "rating_perf": 1984, + "rating_post": 1978, + "rating_indicator": 1978 + }, + { + "id": 201901053, + "name": "2019 Victoria Open Premier", + "date_end": "2019-01-20", + "rating_type": "R", + "games_played": 5, + "score": 3.5, + "rating_pre": 1869, + "rating_perf": 2073, + "rating_post": 1951, + "rating_indicator": 1951 + }, + { + "id": 201811026, + "name": "2018 BC Junior Championship", + "date_end": "2018-11-12", + "rating_type": "R", + "games_played": 5, + "score": 3.0, + "rating_pre": 1876, + "rating_perf": 1799, + "rating_post": 1869, + "rating_indicator": 1876 + }, + { + "id": 201810029, + "name": "New West Open 2018 Premier", + "date_end": "2018-10-08", + "rating_type": "R", + "games_played": 6, + "score": 4.0, + "rating_pre": 1772, + "rating_perf": 2016, + "rating_post": 1876, + "rating_indicator": 1876 + }, + { + "id": 201808026, + "name": "2018 Semiahmoo Open Premier", + "date_end": "2018-08-06", + "rating_type": "R", + "games_played": 6, + "score": 1.0, + "rating_pre": 1808, + "rating_perf": 1666, + "rating_post": 1772, + "rating_indicator": 1852 + }, + { + "id": 201804019, + "name": "Grand Pacific Open U2000", + "date_end": "2018-04-02", + "rating_type": "R", + "games_played": 6, + "score": 4.0, + "rating_pre": 1788, + "rating_perf": 1875, + "rating_post": 1808, + "rating_indicator": 1852 + }, + { + "id": 201802024, + "name": "2018 BC Open Premier", + "date_end": "2018-02-12", + "rating_type": "R", + "games_played": 5, + "score": 1.5, + "rating_pre": 1808, + "rating_perf": 1715, + "rating_post": 1788, + "rating_indicator": 1852 + }, + { + "id": 201711054, + "name": "2017 BC Junior Championship", + "date_end": "2017-11-13", + "rating_type": "R", + "games_played": 5, + "score": 3.0, + "rating_pre": 1814, + "rating_perf": 1764, + "rating_post": 1808, + "rating_indicator": 1852 + }, + { + "id": 201705101, + "name": "Keres Memorial Premier", + "date_end": "2017-05-22", + "rating_type": "R", + "games_played": 5, + "score": 2.0, + "rating_pre": 1819, + "rating_perf": 1819, + "rating_post": 1814, + "rating_indicator": 1852 + }, + { + "id": 201704070, + "name": "11th Grand Pacific Open Premier", + "date_end": "2017-04-17", + "rating_type": "R", + "games_played": 6, + "score": 2.0, + "rating_pre": 1814, + "rating_perf": 1825, + "rating_post": 1819, + "rating_indicator": 1852 + }, + { + "id": 201702066, + "name": "2017 BC Open Premier", + "date_end": "2017-02-13", + "rating_type": "R", + "games_played": 6, + "score": 1.5, + "rating_pre": 1849, + "rating_perf": 1706, + "rating_post": 1814, + "rating_indicator": 1852 + }, + { + "id": 201611047, + "name": "2016 BC Junior Championship", + "date_end": "2016-11-13", + "rating_type": "R", + "games_played": 5, + "score": 2.5, + "rating_pre": 1822, + "rating_perf": 1965, + "rating_post": 1849, + "rating_indicator": 1852 + }, + { + "id": 201608025, + "name": "2016 NAYCC U12", + "date_end": "2016-08-11", + "rating_type": "R", + "games_played": 9, + "score": 5.0, + "rating_pre": 1852, + "rating_perf": 1755, + "rating_post": 1822, + "rating_indicator": 1852 + }, + { + "id": 201606004, + "name": "2016 Paul Keres U2000", + "date_end": "2016-05-23", + "rating_type": "R", + "games_played": 6, + "score": 4.5, + "rating_pre": 1717, + "rating_perf": 1970, + "rating_post": 1852, + "rating_indicator": 1852 + }, + { + "id": 201603087, + "name": "10th Grand Pacific Open Premier", + "date_end": "2016-03-28", + "rating_type": "R", + "games_played": 6, + "score": 1.5, + "rating_pre": 1712, + "rating_perf": 1771, + "rating_post": 1717, + "rating_indicator": 1764 + }, + { + "id": 201602021, + "name": "2016 BC Open U1900", + "date_end": "2016-02-08", + "rating_type": "R", + "games_played": 6, + "score": 4.5, + "rating_pre": 1688, + "rating_perf": 1785, + "rating_post": 1712, + "rating_indicator": 1764 + }, + { + "id": 201511042, + "name": "Vancouver West Open #8", + "date_end": "2015-11-15", + "rating_type": "R", + "games_played": 6, + "score": 3.0, + "rating_pre": 1743, + "rating_perf": 1495, + "rating_post": 1688, + "rating_indicator": 1764 + }, + { + "id": 201509048, + "name": "Vancouver West Open #7", + "date_end": "2015-09-27", + "rating_type": "R", + "games_played": 6, + "score": 2.5, + "rating_pre": 1764, + "rating_perf": 1694, + "rating_post": 1743, + "rating_indicator": 1764 + }, + { + "id": 201505066, + "name": "2015 Paul Keres Memorial U2000", + "date_end": "2015-05-18", + "rating_type": "R", + "games_played": 6, + "score": 3.0, + "rating_pre": 1701, + "rating_perf": 1855, + "rating_post": 1764, + "rating_indicator": 1764 + }, + { + "id": 201504043, + "name": "9th Grand Pacific Open U1900", + "date_end": "2015-04-06", + "rating_type": "R", + "games_played": 6, + "score": 4.0, + "rating_pre": 1539, + "rating_perf": 1837, + "rating_post": 1701, + "rating_indicator": 1701 + }, + { + "id": 201504012, + "name": "BCYCC U12 Open", + "date_end": "2015-03-29", + "rating_type": "R", + "games_played": 5, + "score": 3.0, + "rating_pre": 1494, + "rating_perf": 1606, + "rating_post": 1539, + "rating_indicator": 1539 + }, + { + "id": 201503015, + "name": "Vancouver West Open #4", + "date_end": "2015-03-08", + "rating_type": "R", + "games_played": 6, + "score": 3.0, + "rating_pre": 1371, + "rating_perf": 1780, + "rating_post": 1494, + "rating_indicator": 1494 + }, + { + "id": 201502019, + "name": "2015 BC Open U1900", + "date_end": "2015-02-09", + "rating_type": "R", + "games_played": 6, + "score": 2.0, + "rating_pre": 1365, + "rating_perf": 1391, + "rating_post": 1371, + "rating_indicator": 1481 + }, + { + "id": 201501023, + "name": "West Vancouver Open #3", + "date_end": "2015-01-25", + "rating_type": "R", + "games_played": 5, + "score": 1.5, + "rating_pre": 1428, + "rating_perf": 1182, + "rating_post": 1365, + "rating_indicator": 1481 + }, + { + "id": 201412019, + "name": "Vancouver West Open #2", + "date_end": "2014-12-07", + "rating_type": "R", + "games_played": 6, + "score": 2.5, + "rating_pre": 1427, + "rating_perf": 1529, + "rating_post": 1428, + "rating_indicator": 1481 + }, + { + "id": 201411027, + "name": "2014 BC Junior Championship", + "date_end": "2014-11-09", + "rating_type": "R", + "games_played": 5, + "score": 1.5, + "rating_pre": 1399, + "rating_perf": 1576, + "rating_post": 1427, + "rating_indicator": 1481 + }, + { + "id": 201410050, + "name": "2014 Vancouver West Open", + "date_end": "2014-10-26", + "rating_type": "R", + "games_played": 6, + "score": 3.0, + "rating_pre": 1420, + "rating_perf": 1401, + "rating_post": 1399, + "rating_indicator": 1481 + }, + { + "id": 201408021, + "name": "BC Day Open, 2014", + "date_end": "2014-08-04", + "rating_type": "R", + "games_played": 6, + "score": 2.5, + "rating_pre": 1451, + "rating_perf": 1303, + "rating_post": 1420, + "rating_indicator": 1481 + }, + { + "id": 201405043, + "name": "2014 Keres Memorial - U1600", + "date_end": "2014-05-19", + "rating_type": "R", + "games_played": 6, + "score": 4.5, + "rating_pre": 1463, + "rating_perf": 1376, + "rating_post": 1451, + "rating_indicator": 1481 + }, + { + "id": 201404069, + "name": "8th Grand Pacific Open - U1800", + "date_end": "2014-04-21", + "rating_type": "R", + "games_played": 6, + "score": 3.5, + "rating_pre": 1481, + "rating_perf": 1371, + "rating_post": 1463, + "rating_indicator": 1481 + }, + { + "id": 201402017, + "name": "2014 BC Open - U1800", + "date_end": "2014-02-10", + "rating_type": "R", + "games_played": 6, + "score": 4.5, + "rating_pre": 1324, + "rating_perf": 1617, + "rating_post": 1481, + "rating_indicator": 1481 + }, + { + "id": 201311087, + "name": "2013 November VCS Open", + "date_end": "2013-11-24", + "rating_type": "R", + "games_played": 5, + "score": 2.5, + "rating_pre": 1305, + "rating_perf": 1434, + "rating_post": 1324, + "rating_indicator": 1390 + }, + { + "id": 201311050, + "name": "2013 BCCF Junior Reserves", + "date_end": "2013-11-10", + "rating_type": "R", + "games_played": 5, + "score": 3.5, + "rating_pre": 1334, + "rating_perf": 1075, + "rating_post": 1305, + "rating_indicator": 1390 + }, + { + "id": 201311042, + "name": "2013 October VCS U1600", + "date_end": "2013-10-27", + "rating_type": "R", + "games_played": 5, + "score": 2.5, + "rating_pre": 1390, + "rating_perf": 1062, + "rating_post": 1334, + "rating_indicator": 1390 + }, + { + "id": 201311039, + "name": "2013 Vancouver Open", + "date_end": "2013-10-15", + "rating_type": "R", + "games_played": 6, + "score": 3.0, + "rating_pre": 1178, + "rating_perf": 1799, + "rating_post": 1390, + "rating_indicator": 1390 + }, + { + "id": 201309042, + "name": "2013 Vancouver September U1800", + "date_end": "2013-09-22", + "rating_type": "R", + "games_played": 4, + "score": 3.0, + "rating_pre": 1136, + "rating_perf": 1267, + "rating_post": 1178, + "rating_indicator": 1178 + }, + { + "id": 201308025, + "name": "2013 NAYCC - U10", + "date_end": "2013-08-18", + "rating_type": "R", + "games_played": 9, + "score": 5.0, + "rating_pre": 1016, + "rating_perf": 1227, + "rating_post": 1136, + "rating_indicator": 1136 + }, + { + "id": 201304020, + "name": "VCS April Juniors", + "date_end": "2013-04-14", + "rating_type": "R", + "games_played": 3, + "score": 2.0, + "rating_pre": 1013, + "rating_perf": 1042, + "rating_post": 1016, + "rating_indicator": 1016 + }, + { + "id": 201304001, + "name": "7th Annual Grand Pacific Open U1800", + "date_end": "2013-04-01", + "rating_type": "R", + "games_played": 6, + "score": 2.5, + "rating_pre": 859, + "rating_perf": 1348, + "rating_post": 1013, + "rating_indicator": 1013 + }, + { + "id": 201304057, + "name": "2013 Victoria YCC U10", + "date_end": "2013-03-29", + "rating_type": "Q", + "games_played": 5, + "score": 5.0, + "rating_pre": 745, + "rating_perf": 1267, + "rating_post": 1180, + "rating_indicator": 6 + }, + { + "id": 201302029, + "name": "Vancouver Chess School Feb 2013", + "date_end": "2013-02-17", + "rating_type": "R", + "games_played": 3, + "score": 1.0, + "rating_pre": 872, + "rating_perf": 764, + "rating_post": 859, + "rating_indicator": 872 + }, + { + "id": 201212006, + "name": "2012 BC Junior Ch Reserves", + "date_end": "2012-12-02", + "rating_type": "R", + "games_played": 5, + "score": 2.5, + "rating_pre": 836, + "rating_perf": 948, + "rating_post": 872, + "rating_indicator": 872 + }, + { + "id": 201207018, + "name": "2012 Canadian Youth Ch U8 Open", + "date_end": "2012-07-06", + "rating_type": "R", + "games_played": 7, + "score": 4.0, + "rating_pre": 846, + "rating_perf": 791, + "rating_post": 836, + "rating_indicator": 846 + }, + { + "id": 201204025, + "name": "2012 BCYCC U8 Open", + "date_end": "2012-04-22", + "rating_type": "R", + "games_played": 5, + "score": 4.0, + "rating_pre": 745, + "rating_perf": 987, + "rating_post": 846, + "rating_indicator": 846 + }, + { + "id": 201111017, + "name": "2011 BC Junior Ch Boosters", + "date_end": "2011-11-13", + "rating_type": "R", + "games_played": 5, + "score": 3.0, + "rating_pre": 745, + "rating_perf": 682, + "rating_post": 745, + "rating_indicator": 745 + }, + { + "id": 201110029, + "name": "October Junior Open Intermediate", + "date_end": "2011-10-15", + "rating_type": "R", + "games_played": 4, + "score": 1.0, + "rating_pre": 745, + "rating_perf": 530, + "rating_post": 745, + "rating_indicator": 745 + }, + { + "id": 201105009, + "name": "2011 BCYCC U8 Open", + "date_end": "2011-05-01", + "rating_type": "R", + "games_played": 5, + "score": 3.5, + "rating_pre": 684, + "rating_perf": 966, + "rating_post": 745, + "rating_indicator": 745 + }, + { + "id": 201104018, + "name": "2011 BC Chess Challenge Gr 1", + "date_end": "2011-04-09", + "rating_type": "R", + "games_played": 5, + "score": 4.5, + "rating_pre": 633, + "rating_perf": 869, + "rating_post": 684, + "rating_indicator": 684 + }, + { + "id": 201103046, + "name": "Vancouver Regional Grade K-1", + "date_end": "2011-03-12", + "rating_type": "R", + "games_played": 5, + "score": 4.0, + "rating_pre": 595, + "rating_perf": 731, + "rating_post": 633, + "rating_indicator": 633 + }, + { + "id": 201102045, + "name": "2011 Valentines Scholastic Gr 1", + "date_end": "2011-02-20", + "rating_type": "R", + "games_played": 5, + "score": 3.0, + "rating_pre": 590, + "rating_perf": 585, + "rating_post": 595, + "rating_indicator": 595 + }, + { + "id": 201101029, + "name": "New Year Scholastic Grade K to 1", + "date_end": "2011-01-15", + "rating_type": "R", + "games_played": 4, + "score": 4.0, + "rating_pre": 532, + "rating_perf": 795, + "rating_post": 590, + "rating_indicator": 22 + }, + { + "id": 201010050, + "name": "October Junior Beginner U800", + "date_end": "2010-10-23", + "rating_type": "R", + "games_played": 5, + "score": 2.5, + "rating_pre": 441, + "rating_perf": 768, + "rating_post": 532, + "rating_indicator": 18 + }, + { + "id": 201004029, + "name": "2010 BC Provincials Gr K", + "date_end": "2010-04-11", + "rating_type": "R", + "games_played": 3, + "score": 3.0, + "rating_pre": 293, + "rating_perf": 908, + "rating_post": 441, + "rating_indicator": 13 + }, + { + "id": 201002065, + "name": "Vanc Reg Chess Chall Grade K 1", + "date_end": "2010-02-21", + "rating_type": "R", + "games_played": 5, + "score": 1.0, + "rating_pre": 306, + "rating_perf": 260, + "rating_post": 293, + "rating_indicator": 10 + }, + { + "id": 201001048, + "name": "Sprott Shaw Scholastic Gr K to 2", + "date_end": "2010-01-24", + "rating_type": "R", + "games_played": 5, + "score": 2.0, + "rating_pre": 0, + "rating_perf": 296, + "rating_post": 306, + "rating_indicator": 5 + } + ], + "orgarb": [ + { + "id": 202312038, + "name": "Hart House Holidays Open - Crown", + "date_end": "2023-12-10", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 127516, + "pairings": "SS", + "rating_type": "R", + "n_players": 16, + "n_rounds": 5, + "organizer_name": "Victor Zheng", + "arbiter_name": "Alex T. Ferreira" + }, + { + "id": 202312039, + "name": "Hart House Holidays Open - U1300", + "date_end": "2023-12-10", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 127516, + "pairings": "SS", + "rating_type": "R", + "n_players": 47, + "n_rounds": 5, + "organizer_name": "Victor Zheng", + "arbiter_name": "Alex T. Ferreira" + }, + { + "id": 202312040, + "name": "Hart House Holidays Open - U1600", + "date_end": "2023-12-10", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 127516, + "pairings": "SS", + "rating_type": "R", + "n_players": 44, + "n_rounds": 5, + "organizer_name": "Victor Zheng", + "arbiter_name": "Alex T. Ferreira" + }, + { + "id": 202312041, + "name": "Hart House Holidays Open - U1900", + "date_end": "2023-12-10", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 127516, + "pairings": "SS", + "rating_type": "R", + "n_players": 45, + "n_rounds": 5, + "organizer_name": "Victor Zheng", + "arbiter_name": "Alex T. Ferreira" + }, + { + "id": 202312042, + "name": "Hart House Holidays Open - U2200", + "date_end": "2023-12-10", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 127516, + "pairings": "SS", + "rating_type": "R", + "n_players": 36, + "n_rounds": 5, + "organizer_name": "Victor Zheng", + "arbiter_name": "Alex T. Ferreira" + }, + { + "id": 202312043, + "name": "Hart House Holidays Open Jrs U1100", + "date_end": "2023-12-10", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 111715, + "pairings": "SS", + "rating_type": "R", + "n_players": 11, + "n_rounds": 6, + "organizer_name": "Victor Zheng", + "arbiter_name": "Michael Corrie" + }, + { + "id": 202312044, + "name": "Hart House Holidays Open Jrs U800", + "date_end": "2023-12-10", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 111715, + "pairings": "SS", + "rating_type": "R", + "n_players": 13, + "n_rounds": 6, + "organizer_name": "Victor Zheng", + "arbiter_name": "Michael Corrie" + }, + { + "id": 202311052, + "name": "2023 Hart House Rapid Championship", + "date_end": "2023-11-05", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 150532, + "pairings": "SS", + "rating_type": "Q", + "n_players": 25, + "n_rounds": 6, + "organizer_name": "Victor Zheng", + "arbiter_name": "Victor Zheng" + }, + { + "id": 202311053, + "name": "2023 Hart House Rapid U1200", + "date_end": "2023-11-05", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 150532, + "pairings": "SS", + "rating_type": "Q", + "n_players": 34, + "n_rounds": 6, + "organizer_name": "Victor Zheng", + "arbiter_name": "Victor Zheng" + }, + { + "id": 202311054, + "name": "2023 Hart House Rapid U1800", + "date_end": "2023-11-05", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 150532, + "pairings": "SS", + "rating_type": "Q", + "n_players": 49, + "n_rounds": 6, + "organizer_name": "Victor Zheng", + "arbiter_name": "Victor Zheng" + }, + { + "id": 202308085, + "name": "Hart House Summer Junior U1300", + "date_end": "2023-08-26", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 150532, + "pairings": "SS", + "rating_type": "R", + "n_players": 25, + "n_rounds": 4, + "organizer_name": "Victor Zheng", + "arbiter_name": "Victor Zheng" + }, + { + "id": 202308086, + "name": "Hart House Summer Junior U900", + "date_end": "2023-08-26", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 150532, + "pairings": "SS", + "rating_type": "R", + "n_players": 27, + "n_rounds": 4, + "organizer_name": "Victor Zheng", + "arbiter_name": "Victor Zheng" + }, + { + "id": 202307041, + "name": "Hart House Summer Blitz Premier", + "date_end": "2023-07-15", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 150532, + "pairings": "SS", + "rating_type": "Q", + "n_players": 64, + "n_rounds": 14, + "organizer_name": "Victor Zheng", + "arbiter_name": "Victor Zheng" + }, + { + "id": 202307042, + "name": "Hart House Summer Blitz U1500", + "date_end": "2023-07-15", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 150532, + "pairings": "SS", + "rating_type": "Q", + "n_players": 42, + "n_rounds": 14, + "organizer_name": "Victor Zheng", + "arbiter_name": "Victor Zheng" + }, + { + "id": 202307043, + "name": "Hart House Summer Rapid Premier", + "date_end": "2023-07-15", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 150532, + "pairings": "SS", + "rating_type": "Q", + "n_players": 49, + "n_rounds": 5, + "organizer_name": "Victor Zheng", + "arbiter_name": "Victor Zheng" + }, + { + "id": 202307044, + "name": "Hart House Summer Rapid U1000", + "date_end": "2023-07-15", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 150532, + "pairings": "SS", + "rating_type": "Q", + "n_players": 32, + "n_rounds": 5, + "organizer_name": "Victor Zheng", + "arbiter_name": "Victor Zheng" + }, + { + "id": 202307045, + "name": "Hart House Summer Rapid U1600", + "date_end": "2023-07-15", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 150532, + "pairings": "SS", + "rating_type": "Q", + "n_players": 42, + "n_rounds": 5, + "organizer_name": "Victor Zheng", + "arbiter_name": "Victor Zheng" + }, + { + "id": 202305031, + "name": "Hart House Youth Chess U10", + "date_end": "2023-04-29", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 150532, + "pairings": "SS", + "rating_type": "Q", + "n_players": 25, + "n_rounds": 5, + "organizer_name": "Victor Zheng", + "arbiter_name": "Victor Zheng" + }, + { + "id": 202305032, + "name": "Hart House Youth Chess U12", + "date_end": "2023-04-29", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 150532, + "pairings": "SS", + "rating_type": "Q", + "n_players": 38, + "n_rounds": 5, + "organizer_name": "Victor Zheng", + "arbiter_name": "Victor Zheng" + }, + { + "id": 202305033, + "name": "Hart House Youth Chess U14", + "date_end": "2023-04-29", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 150532, + "pairings": "SS", + "rating_type": "Q", + "n_players": 48, + "n_rounds": 5, + "organizer_name": "Victor Zheng", + "arbiter_name": "Victor Zheng" + }, + { + "id": 202305034, + "name": "Hart House Youth Chess U16", + "date_end": "2023-04-29", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 150532, + "pairings": "SS", + "rating_type": "Q", + "n_players": 10, + "n_rounds": 5, + "organizer_name": "Victor Zheng", + "arbiter_name": "Victor Zheng" + }, + { + "id": 202305035, + "name": "Hart House Youth Chess U18", + "date_end": "2023-04-29", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 150532, + "pairings": "SS", + "rating_type": "Q", + "n_players": 8, + "n_rounds": 5, + "organizer_name": "Victor Zheng", + "arbiter_name": "Victor Zheng" + }, + { + "id": 202305036, + "name": "Hart House Youth Chess U8", + "date_end": "2023-04-29", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 150532, + "pairings": "SS", + "rating_type": "Q", + "n_players": 26, + "n_rounds": 5, + "organizer_name": "Victor Zheng", + "arbiter_name": "Victor Zheng" + }, + { + "id": 202303124, + "name": "5th Ivy League Challenge", + "date_end": "2023-03-26", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 127516, + "pairings": "SS", + "rating_type": "R", + "n_players": 29, + "n_rounds": 5, + "organizer_name": "Victor Zheng", + "arbiter_name": "Alex T. Ferreira" + }, + { + "id": 202303076, + "name": "Hart House Spring Junior Open 2023", + "date_end": "2023-03-18", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 150532, + "pairings": "SS", + "rating_type": "R", + "n_players": 10, + "n_rounds": 4, + "organizer_name": "Victor Zheng", + "arbiter_name": "Victor Zheng" + }, + { + "id": 202303077, + "name": "Hart House Spring Junior U1300", + "date_end": "2023-03-18", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 150532, + "pairings": "SS", + "rating_type": "R", + "n_players": 29, + "n_rounds": 4, + "organizer_name": "Victor Zheng", + "arbiter_name": "Victor Zheng" + }, + { + "id": 202303078, + "name": "Hart House Spring Junior U900", + "date_end": "2023-03-18", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 150532, + "pairings": "SS", + "rating_type": "R", + "n_players": 28, + "n_rounds": 4, + "organizer_name": "Victor Zheng", + "arbiter_name": "Victor Zheng" + }, + { + "id": 202303011, + "name": "GTCL 2023 Bronze Cup", + "date_end": "2023-02-28", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 150532, + "pairings": "SS", + "rating_type": "R", + "n_players": 19, + "n_rounds": 3, + "organizer_name": "Victor Zheng", + "arbiter_name": "Victor Zheng" + }, + { + "id": 202303012, + "name": "GTCL 2023 Gold Cup", + "date_end": "2023-02-28", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 150532, + "pairings": "SS", + "rating_type": "R", + "n_players": 19, + "n_rounds": 3, + "organizer_name": "Victor Zheng", + "arbiter_name": "Victor Zheng" + }, + { + "id": 202303013, + "name": "GTCL 2023 Silver Cup", + "date_end": "2023-02-28", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 150532, + "pairings": "SS", + "rating_type": "R", + "n_players": 16, + "n_rounds": 3, + "organizer_name": "Victor Zheng", + "arbiter_name": "Victor Zheng" + }, + { + "id": 202302081, + "name": "Hart House Reading Week Crown", + "date_end": "2023-02-20", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 127516, + "pairings": "SS", + "rating_type": "R", + "n_players": 25, + "n_rounds": 6, + "organizer_name": "Victor Zheng", + "arbiter_name": "Alex T. Ferreira" + }, + { + "id": 202302082, + "name": "Hart House Reading Week U1000", + "date_end": "2023-02-20", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 127516, + "pairings": "SS", + "rating_type": "R", + "n_players": 28, + "n_rounds": 6, + "organizer_name": "Victor Zheng", + "arbiter_name": "Alex T. Ferreira" + }, + { + "id": 202302083, + "name": "Hart House Reading Week U1300", + "date_end": "2023-02-20", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 127516, + "pairings": "SS", + "rating_type": "R", + "n_players": 50, + "n_rounds": 6, + "organizer_name": "Victor Zheng", + "arbiter_name": "Alex T. Ferreira" + }, + { + "id": 202303001, + "name": "GTCL 2023 Pool B", + "date_end": "2023-02-07", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 150532, + "pairings": "SS", + "rating_type": "R", + "n_players": 33, + "n_rounds": 5, + "organizer_name": "Victor Zheng", + "arbiter_name": "Victor Zheng" + }, + { + "id": 202303002, + "name": "GTCL 2023 Pool A", + "date_end": "2023-02-07", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 150532, + "pairings": "SS", + "rating_type": "R", + "n_players": 37, + "n_rounds": 5, + "organizer_name": "Victor Zheng", + "arbiter_name": "Victor Zheng" + }, + { + "id": 202302020, + "name": "Hart House Weekly Winter Swiss", + "date_end": "2023-01-31", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 150532, + "pairings": "SS", + "rating_type": "R", + "n_players": 16, + "n_rounds": 4, + "organizer_name": "Victor Zheng", + "arbiter_name": "Victor Zheng" + }, + { + "id": 202212022, + "name": "Hart House Holidays Open - Crown", + "date_end": "2022-12-11", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 127516, + "pairings": "SS", + "rating_type": "R", + "n_players": 22, + "n_rounds": 5, + "organizer_name": "Victor Zheng", + "arbiter_name": "Alex T. Ferreira" + }, + { + "id": 202212023, + "name": "Hart House Holidays Open - U1000", + "date_end": "2022-12-11", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 127516, + "pairings": "SS", + "rating_type": "R", + "n_players": 32, + "n_rounds": 5, + "organizer_name": "Victor Zheng", + "arbiter_name": "Alex T. Ferreira" + }, + { + "id": 202212024, + "name": "Hart House Holidays Open - U1300", + "date_end": "2022-12-11", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 127516, + "pairings": "SS", + "rating_type": "R", + "n_players": 39, + "n_rounds": 5, + "organizer_name": "Victor Zheng", + "arbiter_name": "Alex T. Ferreira" + }, + { + "id": 202212025, + "name": "Hart House Holidays Open - U1600", + "date_end": "2022-12-11", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 127516, + "pairings": "SS", + "rating_type": "R", + "n_players": 57, + "n_rounds": 5, + "organizer_name": "Victor Zheng", + "arbiter_name": "Alex T. Ferreira" + }, + { + "id": 202212026, + "name": "Hart House Holidays Open - U1900", + "date_end": "2022-12-11", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 127516, + "pairings": "SS", + "rating_type": "R", + "n_players": 42, + "n_rounds": 5, + "organizer_name": "Victor Zheng", + "arbiter_name": "Alex T. Ferreira" + }, + { + "id": 202212027, + "name": "Hart House Holidays Open - U2200", + "date_end": "2022-12-11", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 127516, + "pairings": "SS", + "rating_type": "R", + "n_players": 24, + "n_rounds": 5, + "organizer_name": "Victor Zheng", + "arbiter_name": "Alex T. Ferreira" + }, + { + "id": 202211086, + "name": "Hart House Rapid & Raffle U1400", + "date_end": "2022-11-12", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 127516, + "pairings": "SS", + "rating_type": "Q", + "n_players": 21, + "n_rounds": 6, + "organizer_name": "Victor Zheng", + "arbiter_name": "Alex T. Ferreira" + }, + { + "id": 202211087, + "name": "Hart House Rapid Raffle Fundraiser", + "date_end": "2022-11-12", + "province": "ON", + "organizer_id": 150532, + "arbiter_id": 127516, + "pairings": "SS", + "rating_type": "Q", + "n_players": 29, + "n_rounds": 6, + "organizer_name": "Victor Zheng", + "arbiter_name": "Alex T. Ferreira" + } + ], + "is_organizer": true, + "is_arbiter": true + }, + "apicode": 0, + "error": "" +} diff --git a/src/ratings_calculator/rating_tests.py b/src/ratings_calculator/rating_tests.py index 7062018..2418855 100644 --- a/src/ratings_calculator/rating_tests.py +++ b/src/ratings_calculator/rating_tests.py @@ -1,14 +1,25 @@ import unittest +from src.ratings_calculator.Profile import CFCProfile +from src.ratings_calculator.RatingsCalculator import RatingsCalculator -from src.ratings_calculator.main import RatingsCalculator + +class TestProfileFunctionality(unittest.TestCase): + def test_name_input_correct(self) -> None: + profile = CFCProfile(150532, False) # for now, input int + profile_dict = profile.get_profile() + self.assertEqual(profile_dict["player"]["name_first"], "Victor") + self.assertEqual(profile_dict["player"]["name_last"], "Zheng") + + tour_data = profile.get_last_tournaments(5) + print(tour_data) class TestBasicFunctionalities(unittest.TestCase): - def test_default_CFC_ratings(self) -> None: + def test_default_CFC_ratings_without_bonus(self) -> None: ratings = RatingsCalculator() - new_rating = ratings.established_ratings(1450, 1450, 4, [1237, 1511, 1214, 1441, 1579, 2133]) + new_rating = ratings.established_ratings(1600, 1450, 4, [1237, 1511, 1214, 1441, 1579, 2133]) print("New Rating is: ", new_rating) - self.assertEqual(new_rating, 1516.12) # add assertion here + self.assertEqual(int(new_rating), 1496) # this is from the handbook def test_null_values(self) -> None: ratings = RatingsCalculator() @@ -18,9 +29,40 @@ def test_null_values(self) -> None: def test_one_game(self) -> None: ratings = RatingsCalculator() - new_rating = ratings.established_ratings(1000, 1000, 1, [1200]) + new_rating = ratings.established_ratings(2160, 2052, 0, [2208]) + print("New Rating is: ", new_rating) + self.assertEqual(round(new_rating), 2043) # add assertion here + + def test_victor_october_open(self) -> None: + # test the calc against perf at october open for 150532 + ratings = RatingsCalculator() + new_rating = ratings.established_ratings(2160, 2014, 3, [2276, 2151, 1972, 2155, 2100]) + print("New Rating is: ", new_rating) + self.assertEqual(round(new_rating), 2073) # add assertion here + + def test_victor_can_junior_open(self) -> None: + # test the calc against perf at october open for 150532 + ratings = RatingsCalculator() + new_rating = ratings.established_ratings(2160, 2068, 2.5, [1949, 1982, 1892, 1843, 1898, 1936]) + print("New Rating is: ", new_rating) + self.assertEqual(round(new_rating), 2014) # add assertion here + + def test_quick_ratings_gtcl_rapid(self) -> None: + # test the calc against perf at october open for 150532 + ratings = RatingsCalculator() + # Can transnational of 14 games + new_rating = ratings.established_ratings(2002, 2002, 5, [1927, 1876, 1899, 1841, 1429], quick=False) + print("New Rating is: ", new_rating) + # within three points + self.assertTrue(abs(round(new_rating) - 2092) <= 3) # add assertion here + + def test_quick_ratings_with_lifetime_high(self) -> None: + # test the calc against perf at october open for 150532 + ratings = RatingsCalculator() + new_rating = ratings.established_ratings(1856, 1856, 9, [1431, 1431, 2024, 2024, 1478, 1478, 1710, 1710, 1938, 1938, 1535, 1535, 1986, 1986], quick=False) print("New Rating is: ", new_rating) - self.assertEqual(new_rating, 1200) # add assertion here + self.assertEqual(round(new_rating), 1882) # add assertion here + # note for this tournament that this should be set to quick as true? if __name__ == '__main__':