From eebb4730340f6654e9226ab38e81af34c6b854e3 Mon Sep 17 00:00:00 2001 From: Ophelia Date: Sat, 26 Dec 2020 13:36:44 -0800 Subject: [PATCH 1/6] added score to set_outcome endpoint --- backend/api/views.py | 10 ++++++---- infrastructure/worker/app/game_server.py | 10 ++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/backend/api/views.py b/backend/api/views.py index 420aad26..2f477303 100644 --- a/backend/api/views.py +++ b/backend/api/views.py @@ -1010,14 +1010,16 @@ def set_outcome(self, request, league_id, team, pk=None): return Response({'message': 'Scrimmage does not exist.'}, status.HTTP_404_NOT_FOUND) if 'status' in request.data: - sc_status = request.data['status'] + sc_status = request.data['status'] + sc_score = request.data['score'] + assert sc_score is not None if sc_status == "redwon" or sc_status == "bluewon": scrimmage.status = sc_status # if tournament, then return here if scrimmage.tournament_id is not None: scrimmage.save() - return Response({'status': sc_status}, status.HTTP_200_OK) + return Response({'status': sc_status, 'score': sc_score}, status.HTTP_200_OK) # update rankings using elo # get team info @@ -1051,12 +1053,12 @@ def set_outcome(self, request, league_id, team, pk=None): lost.save() scrimmage.save() - return Response({'status': sc_status}, status.HTTP_200_OK) + return Response({'status': sc_status, 'score': sc_score}, status.HTTP_200_OK) elif sc_status == "error": scrimmage.status = sc_status scrimmage.save() - return Response({'status': sc_status}, status.HTTP_200_OK) + return Response({'status': sc_status, 'score': sc_score}, status.HTTP_200_OK) else: return Response({'message': 'Set scrimmage to pending/queued/cancelled with accept/reject/cancel api calls'}, status.HTTP_400_BAD_REQUEST) else: diff --git a/infrastructure/worker/app/game_server.py b/infrastructure/worker/app/game_server.py index 32848cd4..62661138 100755 --- a/infrastructure/worker/app/game_server.py +++ b/infrastructure/worker/app/game_server.py @@ -11,12 +11,13 @@ from google.cloud import storage -def game_report_result(gametype, gameid, result): +def game_report_result(gametype, gameid, result, score="0-0"): """Sends the result of the run to the API endpoint""" try: auth_token = util.get_api_auth_token() response = requests.patch(url=api_game_update(gametype, gameid), data={ - 'status': result + 'status': result, + 'score': score }, headers={ 'Authorization': 'Bearer {}'.format(auth_token) }) @@ -178,10 +179,11 @@ def game_worker(gameinfo): except: game_log_error(gametype, gameid, 'Could not determine winner') else: + score = "{}-{}".format(wins[0], wins[1]) if wins[0] > wins[1]: - game_report_result(gametype, gameid, GAME_REDWON) + game_report_result(gametype, gameid, GAME_REDWON, score) elif wins[1] > wins[0]: - game_report_result(gametype, gameid, GAME_BLUEWON) + game_report_result(gametype, gameid, GAME_BLUEWON, score) else: game_log_error(gametype, gameid, 'Ended in draw, which should not happen') From 3a556f6df326d9513bb730bae92dce57d9e6252b Mon Sep 17 00:00:00 2001 From: Ophelia Date: Sat, 26 Dec 2020 20:25:47 -0800 Subject: [PATCH 2/6] update db with score val, score is now winscore --- backend/api/models.py | 1 + backend/api/views.py | 10 +++++----- infrastructure/worker/app/game_server.py | 9 ++++----- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/backend/api/models.py b/backend/api/models.py index e7cd9052..e3585595 100644 --- a/backend/api/models.py +++ b/backend/api/models.py @@ -226,6 +226,7 @@ class Scrimmage(models.Model): # Match-running (completed by match runner) status = models.TextField(choices=SCRIMMAGE_STATUS_CHOICES, default='pending') + winscore = models.IntegerField(null=True) replay = models.TextField(blank=True) # Metadata diff --git a/backend/api/views.py b/backend/api/views.py index 2f477303..a03b6cac 100644 --- a/backend/api/views.py +++ b/backend/api/views.py @@ -1011,15 +1011,15 @@ def set_outcome(self, request, league_id, team, pk=None): if 'status' in request.data: sc_status = request.data['status'] - sc_score = request.data['score'] - assert sc_score is not None + sc_winscore = request.data['winscore'] if sc_status == "redwon" or sc_status == "bluewon": scrimmage.status = sc_status + scrimmage.winscore = sc_winscore # if tournament, then return here if scrimmage.tournament_id is not None: scrimmage.save() - return Response({'status': sc_status, 'score': sc_score}, status.HTTP_200_OK) + return Response({'status': sc_status, 'winscore': sc_winscore}, status.HTTP_200_OK) # update rankings using elo # get team info @@ -1053,12 +1053,12 @@ def set_outcome(self, request, league_id, team, pk=None): lost.save() scrimmage.save() - return Response({'status': sc_status, 'score': sc_score}, status.HTTP_200_OK) + return Response({'status': sc_status, 'winscore': sc_winscore}, status.HTTP_200_OK) elif sc_status == "error": scrimmage.status = sc_status scrimmage.save() - return Response({'status': sc_status, 'score': sc_score}, status.HTTP_200_OK) + return Response({'status': sc_status, 'winscore': sc_winscore}, status.HTTP_200_OK) else: return Response({'message': 'Set scrimmage to pending/queued/cancelled with accept/reject/cancel api calls'}, status.HTTP_400_BAD_REQUEST) else: diff --git a/infrastructure/worker/app/game_server.py b/infrastructure/worker/app/game_server.py index 62661138..bbe0fed9 100755 --- a/infrastructure/worker/app/game_server.py +++ b/infrastructure/worker/app/game_server.py @@ -11,13 +11,13 @@ from google.cloud import storage -def game_report_result(gametype, gameid, result, score="0-0"): +def game_report_result(gametype, gameid, result, winscore=None): """Sends the result of the run to the API endpoint""" try: auth_token = util.get_api_auth_token() response = requests.patch(url=api_game_update(gametype, gameid), data={ 'status': result, - 'score': score + 'winscore': winscore }, headers={ 'Authorization': 'Bearer {}'.format(auth_token) }) @@ -179,11 +179,10 @@ def game_worker(gameinfo): except: game_log_error(gametype, gameid, 'Could not determine winner') else: - score = "{}-{}".format(wins[0], wins[1]) if wins[0] > wins[1]: - game_report_result(gametype, gameid, GAME_REDWON, score) + game_report_result(gametype, gameid, GAME_REDWON, wins[0]) elif wins[1] > wins[0]: - game_report_result(gametype, gameid, GAME_BLUEWON, score) + game_report_result(gametype, gameid, GAME_BLUEWON, wins[1]) else: game_log_error(gametype, gameid, 'Ended in draw, which should not happen') From 39bb8efa189f44a97e894b8b82fda43c92ae1150 Mon Sep 17 00:00:00 2001 From: Ophelia Date: Sat, 26 Dec 2020 23:28:14 -0800 Subject: [PATCH 3/6] add score to frontend, migration file --- .../api/migrations/0019_scrimmage_winscore.py | 18 ++++++++++++++++++ backend/api/serializers.py | 2 +- backend/api/views.py | 2 ++ frontend/src/api.js | 9 ++++++++- frontend/src/views/scrimmaging.js | 2 ++ 5 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 backend/api/migrations/0019_scrimmage_winscore.py diff --git a/backend/api/migrations/0019_scrimmage_winscore.py b/backend/api/migrations/0019_scrimmage_winscore.py new file mode 100644 index 00000000..023331de --- /dev/null +++ b/backend/api/migrations/0019_scrimmage_winscore.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.13 on 2020-12-27 02:03 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0018_auto_20200416_2354'), + ] + + operations = [ + migrations.AddField( + model_name='scrimmage', + name='winscore', + field=models.IntegerField(null=True), + ), + ] diff --git a/backend/api/serializers.py b/backend/api/serializers.py index ad05878b..3ae408cb 100644 --- a/backend/api/serializers.py +++ b/backend/api/serializers.py @@ -155,7 +155,7 @@ class ScrimmageSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = Scrimmage fields = ('url', 'id', 'league', 'red_team', 'red_mu', 'blue_team', 'blue_mu', 'ranked', - 'status', 'replay', 'requested_by', 'requested_at', 'started_at', 'updated_at', 'tournament_id') + 'status', 'winscore', 'replay', 'requested_by', 'requested_at', 'started_at', 'updated_at', 'tournament_id') read_only_fields = ('url', 'requested_at', 'started_at', 'updated_at') diff --git a/backend/api/views.py b/backend/api/views.py index a03b6cac..7497a4e8 100644 --- a/backend/api/views.py +++ b/backend/api/views.py @@ -1013,6 +1013,8 @@ def set_outcome(self, request, league_id, team, pk=None): sc_status = request.data['status'] sc_winscore = request.data['winscore'] if sc_status == "redwon" or sc_status == "bluewon": + if sc_winscore < 2: + return Response({'message': 'Winscore invalid: it must be at least 2.'}, status.HTTP_400_BAD_REQUEST) scrimmage.status = sc_status scrimmage.winscore = sc_winscore diff --git a/frontend/src/api.js b/frontend/src/api.js index 6683eb84..e61b5b29 100644 --- a/frontend/src/api.js +++ b/frontend/src/api.js @@ -524,6 +524,14 @@ class Api { s[i].replay = undefined; } + if (s[i].status === 'won'){ + s[i].winscore = `${s[i].winscore} - ${3-s[i].winscore}`; + }else if (s[i].status === 'lost'){ + s[i].winscore = `${3-s[i].winscore} - ${s[i].winscore}`; + }else{ + s[i].winscore = ' - '; + } + s[i].status = s[i].status.charAt(0).toUpperCase() + s[i].status.slice(1); s[i].date = new Date(s[i].updated_at).toLocaleDateString(); @@ -532,7 +540,6 @@ class Api { s[i].team = on_red ? s[i].blue_team : s[i].red_team; s[i].color = on_red ? 'Red' : 'Blue'; - requests.push(s[i]); } callback(requests); }); diff --git a/frontend/src/views/scrimmaging.js b/frontend/src/views/scrimmaging.js index eb3eeeed..b83f5f47 100755 --- a/frontend/src/views/scrimmaging.js +++ b/frontend/src/views/scrimmaging.js @@ -98,6 +98,7 @@ class ScrimmageHistory extends Component { Date Time Status + Score Team Ranked Replay @@ -122,6 +123,7 @@ class ScrimmageHistory extends Component { { s.date } { s.time } { stat_row } + { s.winscore } { s.team } { s.ranked ? "Ranked" : "Unranked"} { s.replay?Watch:N/A } From d5d69cbb1cf218b94b9ffa74f3b6da048132cf84 Mon Sep 17 00:00:00 2001 From: Ophelia Date: Sat, 26 Dec 2020 23:29:40 -0800 Subject: [PATCH 4/6] frontend update --- frontend/src/api.js | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/api.js b/frontend/src/api.js index e61b5b29..a9be7a12 100644 --- a/frontend/src/api.js +++ b/frontend/src/api.js @@ -521,6 +521,7 @@ class Api { else if (s[i].status === 'bluewon') s[i].status = on_red ? 'lost' : 'won'; if (s[i].status !== 'lost' && s[i].status !== 'won') { + s[i].replay = undefined; } From efe6cb434011ebb20224ffb03feef1c1f97dcffa Mon Sep 17 00:00:00 2001 From: Ophelia Date: Sun, 27 Dec 2020 10:06:22 -0800 Subject: [PATCH 5/6] added losescore --- .../api/migrations/0020_scrimmage_losescore.py | 18 ++++++++++++++++++ backend/api/models.py | 1 + backend/api/serializers.py | 2 +- backend/api/views.py | 14 ++++++++------ frontend/src/api.js | 6 +++--- frontend/src/views/scrimmaging.js | 2 +- infrastructure/worker/app/game_server.py | 9 +++++---- 7 files changed, 37 insertions(+), 15 deletions(-) create mode 100644 backend/api/migrations/0020_scrimmage_losescore.py diff --git a/backend/api/migrations/0020_scrimmage_losescore.py b/backend/api/migrations/0020_scrimmage_losescore.py new file mode 100644 index 00000000..366d2d5b --- /dev/null +++ b/backend/api/migrations/0020_scrimmage_losescore.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.13 on 2020-12-27 17:49 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0019_scrimmage_winscore'), + ] + + operations = [ + migrations.AddField( + model_name='scrimmage', + name='losescore', + field=models.IntegerField(null=True), + ), + ] diff --git a/backend/api/models.py b/backend/api/models.py index e3585595..1fa75136 100644 --- a/backend/api/models.py +++ b/backend/api/models.py @@ -227,6 +227,7 @@ class Scrimmage(models.Model): # Match-running (completed by match runner) status = models.TextField(choices=SCRIMMAGE_STATUS_CHOICES, default='pending') winscore = models.IntegerField(null=True) + losescore = models.IntegerField(null=True) replay = models.TextField(blank=True) # Metadata diff --git a/backend/api/serializers.py b/backend/api/serializers.py index 3ae408cb..4f0b9325 100644 --- a/backend/api/serializers.py +++ b/backend/api/serializers.py @@ -155,7 +155,7 @@ class ScrimmageSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = Scrimmage fields = ('url', 'id', 'league', 'red_team', 'red_mu', 'blue_team', 'blue_mu', 'ranked', - 'status', 'winscore', 'replay', 'requested_by', 'requested_at', 'started_at', 'updated_at', 'tournament_id') + 'status', 'winscore', 'losescore', 'replay', 'requested_by', 'requested_at', 'started_at', 'updated_at', 'tournament_id') read_only_fields = ('url', 'requested_at', 'started_at', 'updated_at') diff --git a/backend/api/views.py b/backend/api/views.py index 7497a4e8..f808de8d 100644 --- a/backend/api/views.py +++ b/backend/api/views.py @@ -1011,17 +1011,19 @@ def set_outcome(self, request, league_id, team, pk=None): if 'status' in request.data: sc_status = request.data['status'] - sc_winscore = request.data['winscore'] + sc_winscore = request.data['winscore'] if request.data['winscore'] else None + sc_losescore = request.data['losescore'] if request.data['losescore'] else None if sc_status == "redwon" or sc_status == "bluewon": - if sc_winscore < 2: - return Response({'message': 'Winscore invalid: it must be at least 2.'}, status.HTTP_400_BAD_REQUEST) + if int(sc_winscore) < (float(sc_winscore) + float(sc_losescore))/2.0: + return Response({'message': 'Scores invalid. Winscore must be at least half of total games.'}, status.HTTP_400_BAD_REQUEST) scrimmage.status = sc_status scrimmage.winscore = sc_winscore + scrimmage.losescore = sc_losescore # if tournament, then return here if scrimmage.tournament_id is not None: scrimmage.save() - return Response({'status': sc_status, 'winscore': sc_winscore}, status.HTTP_200_OK) + return Response({'status': sc_status, 'winscore': sc_winscore, 'losescore': sc_losescore}, status.HTTP_200_OK) # update rankings using elo # get team info @@ -1055,12 +1057,12 @@ def set_outcome(self, request, league_id, team, pk=None): lost.save() scrimmage.save() - return Response({'status': sc_status, 'winscore': sc_winscore}, status.HTTP_200_OK) + return Response({'status': sc_status, 'winscore': sc_winscore, 'losescore': sc_losescore}, status.HTTP_200_OK) elif sc_status == "error": scrimmage.status = sc_status scrimmage.save() - return Response({'status': sc_status, 'winscore': sc_winscore}, status.HTTP_200_OK) + return Response({'status': sc_status, 'winscore': sc_winscore, 'losescore': sc_losescore}, status.HTTP_200_OK) else: return Response({'message': 'Set scrimmage to pending/queued/cancelled with accept/reject/cancel api calls'}, status.HTTP_400_BAD_REQUEST) else: diff --git a/frontend/src/api.js b/frontend/src/api.js index a9be7a12..5d2adbc0 100644 --- a/frontend/src/api.js +++ b/frontend/src/api.js @@ -526,11 +526,11 @@ class Api { } if (s[i].status === 'won'){ - s[i].winscore = `${s[i].winscore} - ${3-s[i].winscore}`; + s[i].score = `${s[i].winscore} - ${s[i].losescore}`; }else if (s[i].status === 'lost'){ - s[i].winscore = `${3-s[i].winscore} - ${s[i].winscore}`; + s[i].score = `${s[i].losescore} - ${s[i].winscore}`; }else{ - s[i].winscore = ' - '; + s[i].score = ' - '; } s[i].status = s[i].status.charAt(0).toUpperCase() + s[i].status.slice(1); diff --git a/frontend/src/views/scrimmaging.js b/frontend/src/views/scrimmaging.js index b83f5f47..8985a1e3 100755 --- a/frontend/src/views/scrimmaging.js +++ b/frontend/src/views/scrimmaging.js @@ -123,7 +123,7 @@ class ScrimmageHistory extends Component { { s.date } { s.time } { stat_row } - { s.winscore } + { s.score } { s.team } { s.ranked ? "Ranked" : "Unranked"} { s.replay?Watch:N/A } diff --git a/infrastructure/worker/app/game_server.py b/infrastructure/worker/app/game_server.py index bbe0fed9..425d3d59 100755 --- a/infrastructure/worker/app/game_server.py +++ b/infrastructure/worker/app/game_server.py @@ -11,13 +11,14 @@ from google.cloud import storage -def game_report_result(gametype, gameid, result, winscore=None): +def game_report_result(gametype, gameid, result, winscore=None, losescore=None): """Sends the result of the run to the API endpoint""" try: auth_token = util.get_api_auth_token() response = requests.patch(url=api_game_update(gametype, gameid), data={ 'status': result, - 'winscore': winscore + 'winscore': winscore, + 'losescore': losescore }, headers={ 'Authorization': 'Bearer {}'.format(auth_token) }) @@ -180,9 +181,9 @@ def game_worker(gameinfo): game_log_error(gametype, gameid, 'Could not determine winner') else: if wins[0] > wins[1]: - game_report_result(gametype, gameid, GAME_REDWON, wins[0]) + game_report_result(gametype, gameid, GAME_REDWON, wins[0], wins[1]) elif wins[1] > wins[0]: - game_report_result(gametype, gameid, GAME_BLUEWON, wins[1]) + game_report_result(gametype, gameid, GAME_BLUEWON, wins[1], wins[0]) else: game_log_error(gametype, gameid, 'Ended in draw, which should not happen') From a71dbb05997f8dd83dc194be27c72ce37e495254 Mon Sep 17 00:00:00 2001 From: Ophelia Date: Sun, 27 Dec 2020 10:15:12 -0800 Subject: [PATCH 6/6] correctly handle null/error --- backend/api/views.py | 14 ++++++++++---- backend/backend_script.py | 17 ++++++++++++----- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/backend/api/views.py b/backend/api/views.py index f808de8d..f9338432 100644 --- a/backend/api/views.py +++ b/backend/api/views.py @@ -1008,12 +1008,18 @@ def set_outcome(self, request, league_id, team, pk=None): scrimmage = Scrimmage.objects.all().get(pk=pk) except: return Response({'message': 'Scrimmage does not exist.'}, status.HTTP_404_NOT_FOUND) - + # return Response(request.data, status.HTTP_200_OK) if 'status' in request.data: sc_status = request.data['status'] - sc_winscore = request.data['winscore'] if request.data['winscore'] else None - sc_losescore = request.data['losescore'] if request.data['losescore'] else None if sc_status == "redwon" or sc_status == "bluewon": + + if 'winscore' in request.data and 'losescore' in request.data: + sc_winscore = request.data['winscore'] + sc_losescore = request.data['losescore'] + else: + return Response({'message': 'Must include both winscore and losescore in request.'}, + status.HTTP_400_BAD_REQUEST) + if int(sc_winscore) < (float(sc_winscore) + float(sc_losescore))/2.0: return Response({'message': 'Scores invalid. Winscore must be at least half of total games.'}, status.HTTP_400_BAD_REQUEST) scrimmage.status = sc_status @@ -1062,7 +1068,7 @@ def set_outcome(self, request, league_id, team, pk=None): scrimmage.status = sc_status scrimmage.save() - return Response({'status': sc_status, 'winscore': sc_winscore, 'losescore': sc_losescore}, status.HTTP_200_OK) + return Response({'status': sc_status, 'winscore': None, 'losescore': None}, status.HTTP_200_OK) else: return Response({'message': 'Set scrimmage to pending/queued/cancelled with accept/reject/cancel api calls'}, status.HTTP_400_BAD_REQUEST) else: diff --git a/backend/backend_script.py b/backend/backend_script.py index c5d769e4..7d23e415 100644 --- a/backend/backend_script.py +++ b/backend/backend_script.py @@ -13,13 +13,20 @@ response = requests.post(domain + 'auth/token/', data=data) token = json.loads(response.text)['access'] +# data = { +# 'type': 'tour_scrimmage', +# 'tournament_id': '-1', +# 'player1': '917', +# 'player2': '919' +# } data = { - 'type': 'tour_scrimmage', - 'tournament_id': '-1', - 'player1': '917', - 'player2': '919' + 'status': 'error', + 'winscore': None, + 'losescore': None } headers = {"Authorization": "Bearer " + token} -response = requests.post(domain + 'api/match/enqueue/', data=data, headers=headers) +# response = requests.post(domain + 'api/match/enqueue/', data=data, headers=headers) +response = requests.patch(domain + 'api/0/scrimmage/1/set_outcome/', data=data, headers=headers) + print(response.text)