Skip to content

Commit 26664ba

Browse files
committed
Removed tech timings tab
1 parent b91fbd3 commit 26664ba

17 files changed

+52
-501
lines changed

.gitmodules

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[submodule "AoE_Rec_Opening_Analysis"]
22
path = AoE_Rec_Opening_Analysis
33
url = https://github.com/dj0wns/AoE_Rec_Opening_Analysis
4-
[submodule "AoE_Openings/opening_stats/AoE_Rec_Opening_Analysis"]
5-
path = AoE_Openings/opening_stats/AoE_Rec_Opening_Analysis
6-
url = https://github.com/dj0wns/AoE_Rec_Opening_Analysis
4+
[submodule "AoE_Openings/opening_stats/aoe2techtree"]
5+
path = AoE_Openings/opening_stats/aoe2techtree
6+
url = https://github.com/SiegeEngineers/aoe2techtree
This file was deleted.
Submodule aoe2techtree added at 6b5b3b5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Generated by Django 3.2.13 on 2022-05-26 03:18
2+
3+
from django.db import migrations
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('opening_stats', '0012_patches_description'),
10+
]
11+
12+
operations = [
13+
migrations.RemoveField(
14+
model_name='matchplayeractions',
15+
name='match',
16+
),
17+
migrations.RemoveField(
18+
model_name='matchplayeractions',
19+
name='player',
20+
),
21+
migrations.DeleteModel(
22+
name='OpeningEloTechs',
23+
),
24+
migrations.DeleteModel(
25+
name='Techs',
26+
),
27+
migrations.DeleteModel(
28+
name='MatchPlayerActions',
29+
),
30+
]

AoE_Openings/opening_stats/models.py

-36
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,6 @@ class Meta:
2626
models.Index(fields=['stale','query']),
2727
]
2828

29-
class MatchPlayerActions(models.Model):
30-
match = models.ForeignKey('Matches', on_delete=models.CASCADE)
31-
player = models.ForeignKey('Players', on_delete=models.CASCADE)
32-
event_type = models.IntegerField()
33-
event_id = models.IntegerField()
34-
time = models.IntegerField()
35-
duration = models.IntegerField()
36-
37-
class Meta:
38-
db_table = 'match_player_actions'
39-
unique_together = [['match', 'player', 'event_type', 'event_id']]
40-
41-
4229
class Matches(models.Model):
4330
average_elo = models.IntegerField()
4431
map_id = models.IntegerField()
@@ -136,14 +123,6 @@ class Players(models.Model):
136123
class Meta:
137124
db_table = 'players'
138125

139-
#const table for storing specific tech names and ids
140-
class Techs(models.Model):
141-
name = models.TextField()
142-
duration = models.IntegerField()
143-
144-
class Meta:
145-
db_table = 'techs'
146-
147126
#const table for storing specific map names and ids
148127
class Maps(models.Model):
149128
name = models.TextField()
@@ -192,18 +171,3 @@ class OpeningEloWins(models.Model):
192171
class Meta:
193172
db_table = 'opening_elo_wins'
194173
unique_together = [['opening1_id', 'opening2_id', 'map_id', 'ladder_id', 'patch_number', 'elo']]
195-
196-
class OpeningEloTechs(models.Model):
197-
opening_id = models.IntegerField()
198-
tech_id = models.IntegerField()
199-
map_id = models.IntegerField()
200-
ladder_id = models.IntegerField()
201-
patch_number = models.IntegerField()
202-
elo = models.IntegerField()
203-
average_time = models.FloatField(default=0.)
204-
count = models.IntegerField(default=0)
205-
206-
class Meta:
207-
db_table = 'opening_elo_techs'
208-
unique_together = [['opening_id', 'tech_id', 'map_id', 'ladder_id', 'patch_number', 'elo']]
209-

AoE_Openings/opening_stats/serializers.py

+1-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from opening_stats.models import Players, Openings, Matches, MatchPlayerActions, Patches
1+
from opening_stats.models import Players, Openings, Matches, Patches
22
from rest_framework import serializers
33

44
class PlayersSerializer(serializers.ModelSerializer):
@@ -24,14 +24,8 @@ class Meta:
2424
model = Matches
2525
fields = "__all__"
2626

27-
class MatchPlayerActionsSerializer(serializers.ModelSerializer):
28-
class Meta:
29-
model = MatchPlayerActions
30-
fields = "__all__"
31-
3227
class MatchInputSerializer(serializers.Serializer):
3328
matches = MatchesSerializer(many=True)
34-
match_player_actions = MatchPlayerActionsSerializer(many=True)
3529

3630
class TestSerializer(serializers.Serializer):
3731
matches = serializers.CharField(max_length=200)

AoE_Openings/opening_stats/urls.py

-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
path('civ_win_rates/', views.CivWinRates.as_view(), name='civ_win_rates-list'),
1111
path('opening_win_rates/', views.OpeningWinRates.as_view(), name='opening_win_rates-list'),
1212
path('opening_matchups/', views.OpeningMatchups.as_view(), name='opening_matchups-list'),
13-
path('opening_techs/', views.OpeningTechs.as_view(), name='opening_techs-list'),
1413
path('meta_snapshot/', views.MetaSnapshot.as_view(), name='meta_snapshot-list'),
1514
path('last_uploaded_match/', views.LastUploadedMatch.as_view(), name='last_uploaded_match-list'),
1615
path('advanced/', csrf_exempt(views.Advanced.as_view()), name='advanced-list'),

AoE_Openings/opening_stats/utils.py

+3-207
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
import urllib
77

88
from django.db.models import F, Count, Case, When, Q, Sum, Avg, Value, FloatField
9-
from .AoE_Rec_Opening_Analysis.aoe_replay_stats import OpeningType
10-
from opening_stats.models import Matches, Techs, MatchPlayerActions, CivEloWins, OpeningEloWins, OpeningEloTechs, Patches, AdvancedQueryQueue, AdvancedQueryResults
9+
from aoe_opening_data.aoe_replay_stats import OpeningType
10+
from opening_stats.models import Matches, CivEloWins, OpeningEloWins, Patches, AdvancedQueryQueue, AdvancedQueryResults
1111
import django.utils.timezone
1212

1313
ELO_DELTA = 50
@@ -16,11 +16,6 @@
1616

1717
ADVANCED_QUERY_COUNT = 50
1818

19-
Updated_Tech_Names = {
20-
101:'Feudal Age',
21-
102:'Castle Age'
22-
}
23-
2419
#Need to update all bucket tables after modifying these
2520
Basic_Strategies = [
2621
#General Openings
@@ -123,7 +118,7 @@
123118

124119
CIV_IDS_TO_NAMES = {}
125120

126-
with open(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'AoE_Rec_Opening_Analysis', 'aoe2techtree', 'data','data.json')) as json_file:
121+
with open(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'aoe2techtree', 'data','data.json')) as json_file:
127122
aoe_data = json.load(json_file)
128123
for name, value in aoe_data["civ_names"].items():
129124
CIV_IDS_TO_NAMES[int(value) - 10270] = name
@@ -679,7 +674,6 @@ def clear_intermediary_tables():
679674

680675
def clear_main_tables():
681676
Matches.objects.all().delete()
682-
MatchPlayerActions.objects.all().delete()
683677

684678
def update_intermediary_tables():
685679
build_civ_elo_wins()
@@ -890,201 +884,3 @@ def generator():
890884
OpeningEloWins.objects.bulk_create(generator())
891885
end = time.time()
892886
print("build_civ_elo_wins - elapsed time", end - start)
893-
894-
def build_opening_elo_techs_for_match_and_action(match, action, data_dict, previous_match_id, previous_match_openings):
895-
#round down to nearest delta
896-
elo = ELO_DELTA * math.floor(match.average_elo/ELO_DELTA)
897-
if match.id == previous_match_id and action.player_id in previous_match_openings:
898-
player_openings = previous_match_openings
899-
else:
900-
player_openings = {}
901-
#Get players! 1-indexed
902-
for player in range(1,3):
903-
opening_index = 0
904-
player_id = eval(f'match.player{player}_id')
905-
if player_id not in player_openings:
906-
player_openings[player_id] = []
907-
#Get openings!
908-
for opening_info in OPENINGS:
909-
valid_opening = False
910-
#opening inclusions
911-
for inclusion in opening_info[1]:
912-
valid_inclusion = True
913-
if not valid_inclusion:
914-
break
915-
#for each bit in bit set
916-
for i in range(32):
917-
#if true bit
918-
if inclusion & 2**i:
919-
if eval(f'match.player{player}_opening_flag{i}') == False:
920-
valid_inclusion = False
921-
break
922-
#Opening is valid if any inclusions are true
923-
valid_opening |= valid_inclusion
924-
exclusions = opening_info[2]
925-
926-
if not len(exclusions):
927-
exclusions = [OpeningType.Unused.value]
928-
#opening exclusions
929-
for exclusion in exclusions:
930-
if not valid_opening:
931-
break
932-
#for each bit in bit set
933-
for i in range(32):
934-
#if true bit
935-
if exclusion & 2**i:
936-
if eval(f'match.player{player}_opening_flag{i}') == True:
937-
valid_opening = False
938-
break
939-
if valid_opening:
940-
player_openings[player_id].append(opening_index)
941-
opening_index += 1
942-
if not len(player_openings[player_id]):
943-
# Append the unknown opening
944-
player_openings[player_id].append(len(OPENINGS)-1)
945-
#round down to nearest delta
946-
elo = ELO_DELTA * math.floor(match.average_elo/ELO_DELTA)
947-
#get techs for match id
948-
949-
for opening in player_openings[action.player_id]: #1 indexed, remember
950-
key = (opening,
951-
action.event_id,
952-
match.map_id,
953-
match.ladder_id,
954-
match.patch_number,
955-
elo)
956-
if key not in data_dict:
957-
data_dict[key] = {'research_count':0,
958-
"average_time":0}
959-
#multiply average by count and add the new time to keep an average without having to store everything
960-
data_dict[key]['average_time'] =\
961-
((data_dict[key]['average_time'] * data_dict[key]['research_count']) + action.time) /\
962-
(data_dict[key]['research_count']+1)
963-
data_dict[key]['research_count'] += 1
964-
return player_openings
965-
966-
def build_opening_elo_techs_for_mpa_match(match, match_player_action, data_dict, previous_match_id, previous_match_openings):
967-
#round down to nearest delta
968-
elo = ELO_DELTA * math.floor(match.average_elo/ELO_DELTA)
969-
if match.id == previous_match_id and match_player_action.player_id in previous_match_openings:
970-
player_openings = previous_match_openings
971-
else:
972-
player_openings = {}
973-
#Get players! 1-indexed
974-
for player in range(1,3):
975-
opening_index = 0
976-
player_id = eval(f'match.player{player}_id')
977-
if player_id not in player_openings:
978-
player_openings[player_id] = []
979-
#Get openings!
980-
for opening_info in OPENINGS:
981-
valid_opening = False
982-
#opening inclusions
983-
for inclusion in opening_info[1]:
984-
valid_inclusion = True
985-
if not valid_inclusion:
986-
break
987-
#for each bit in bit set
988-
for i in range(32):
989-
#if true bit
990-
if inclusion & 2**i:
991-
if eval(f'match.player{player}_opening_flag{i}') == False:
992-
valid_inclusion = False
993-
break
994-
#Opening is valid if any inclusions are true
995-
valid_opening |= valid_inclusion
996-
exclusions = opening_info[2]
997-
998-
if not len(exclusions):
999-
exclusions = [OpeningType.Unused.value]
1000-
#opening exclusions
1001-
for exclusion in exclusions:
1002-
if not valid_opening:
1003-
break
1004-
#for each bit in bit set
1005-
for i in range(32):
1006-
#if true bit
1007-
if exclusion & 2**i:
1008-
if eval(f'match.player{player}_opening_flag{i}') == True:
1009-
valid_opening = False
1010-
break
1011-
if valid_opening:
1012-
player_openings[player_id].append(opening_index)
1013-
opening_index += 1
1014-
if not len(player_openings[player_id]):
1015-
# Append the unknown opening
1016-
player_openings[player_id].append(len(OPENINGS)-1)
1017-
#round down to nearest delta
1018-
elo = ELO_DELTA * math.floor(match.average_elo/ELO_DELTA)
1019-
#get techs for match id
1020-
1021-
for opening in player_openings[match_player_action.player_id]: #1 indexed, remember
1022-
key = (opening,
1023-
match_player_action.event_id,
1024-
match.map_id,
1025-
match.ladder_id,
1026-
match.patch_number,
1027-
elo)
1028-
if key not in data_dict:
1029-
data_dict[key] = {'research_count':0,
1030-
"average_time":0}
1031-
#multiply average by count and add the new time to keep an average without having to store everything
1032-
data_dict[key]['average_time'] =\
1033-
((data_dict[key]['average_time'] * data_dict[key]['research_count']) + match_player_action.time) /\
1034-
(data_dict[key]['research_count']+1)
1035-
data_dict[key]['research_count'] += 1
1036-
return player_openings
1037-
1038-
# Run this function to build the opening elo techs table for quicker lookups
1039-
def build_opening_elo_techs():
1040-
start = time.time()
1041-
1042-
#Use tuples as key to store data in the interim
1043-
# (opening1_id, opening2_id,map_id,ladder_id,patch_number,elo)
1044-
# ["opening1_victory_count", "opening1_loss_count"]
1045-
data_dict = {}
1046-
1047-
print("Reading from db")
1048-
total = MatchPlayerActions.objects.count()
1049-
print(total)
1050-
count = 0
1051-
techs = [tech.id for tech in Techs.objects.all().iterator()]
1052-
1053-
#optimization to reduce frequency openings are calculated
1054-
previous_match_id = -2
1055-
previous_match_openings = {}
1056-
1057-
for match_player_action in MatchPlayerActions.objects.select_related('match').all().iterator():
1058-
if count % 5000 == 0:
1059-
print (f'({count} / {total}) with {len(data_dict)} elements.')
1060-
gc.collect()
1061-
count += 1
1062-
if match_player_action.event_type != 3 or match_player_action.event_id not in techs:
1063-
continue
1064-
match = match_player_action.match
1065-
if type(match.average_elo) == str:
1066-
#at least one element has a string elo???? throw it away
1067-
continue
1068-
previous_match_openings = build_opening_elo_techs_for_mpa_match(match, match_player_action, data_dict, previous_match_id, previous_match_openings)
1069-
previous_match_id = match.id
1070-
1071-
# Now insert records into db
1072-
print("Creating db objects")
1073-
count = 0
1074-
objects = []
1075-
def generator():
1076-
for k,v in data_dict.items():
1077-
(yield OpeningEloTechs(opening_id=k[0],
1078-
tech_id=k[1],
1079-
map_id=k[2],
1080-
ladder_id=k[3],
1081-
patch_number=k[4],
1082-
elo=k[5],
1083-
average_time=v['average_time'],
1084-
count=v['research_count']))
1085-
1086-
# drop all records and rebuild
1087-
OpeningEloTechs.objects.all().delete()
1088-
OpeningEloTechs.objects.bulk_create(generator(), batch_size=10000)
1089-
end = time.time()
1090-
print("build_opening_elo_techs - elapsed time", end - start)

0 commit comments

Comments
 (0)