Skip to content

Commit 2436be6

Browse files
committed
Track stronghold battles and use resources earned in payout
Resources earned by players are determined from the replay file and stored in the database. In the payout form the number of points to give for each resource earned can be entered and is factored into the gold share calculation. Feature request from #38
1 parent 64fec12 commit 2436be6

File tree

7 files changed

+103
-23
lines changed

7 files changed

+103
-23
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
"""Stronghold support
2+
3+
Revision ID: 2413542ce715
4+
Revises: 398cf0b7b8c8
5+
Create Date: 2014-11-08 18:03:01.861716
6+
7+
"""
8+
9+
# revision identifiers, used by Alembic.
10+
revision = '2413542ce715'
11+
down_revision = '398cf0b7b8c8'
12+
13+
from alembic import op
14+
import sqlalchemy as sa
15+
16+
17+
def upgrade():
18+
op.add_column('battle', sa.Column('stronghold', sa.Boolean(), nullable=True))
19+
op.add_column('player_battle', sa.Column('resources_earned', sa.Integer(), nullable=True))
20+
21+
22+
def downgrade():
23+
op.drop_column('player_battle', 'resources_earned')
24+
op.drop_column('battle', 'stronghold')

whyattend/model.py

+3
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ class BattleAttendance(Base):
9898
player = relationship("Player", backref="battles")
9999
battle = relationship("Battle", backref="attendances")
100100
reserve = Column(Boolean)
101+
resources_earned = Column(Integer)
101102

102103
def __init__(self, player, battle, reserve=False):
103104
self.player = player
@@ -134,6 +135,8 @@ class Battle(Base):
134135
replay_id = Column(Integer, ForeignKey('replay.id'))
135136
replay = relationship("Replay", backref="battle", uselist=False, foreign_keys=[replay_id])
136137

138+
stronghold = Column(Boolean)
139+
137140
battle_group_id = Column(Integer, ForeignKey('battlegroup.id'))
138141
battle_group = relationship("BattleGroup", backref="battles")
139142
# Is this the "final battle" of the group? Exactly one per group should be true

whyattend/replays.py

+28-9
Original file line numberDiff line numberDiff line change
@@ -71,15 +71,28 @@ def players_list(replay_json, team):
7171

7272

7373
def player_won(replay_json):
74-
own_team = replay_json['first']['vehicles'].values()[0]['team']
74+
own_team = get_own_team(replay_json)
7575
return replay_json['second'][0]['common']['winnerTeam'] == own_team
7676

7777

78+
def get_own_team(replay_json):
79+
player_name = replay_json['first']['playerName']
80+
for v in replay_json['first']['vehicles'].itervalues():
81+
if v['name'] == player_name:
82+
return v['team']
83+
84+
7885
def player_team(replay_json):
79-
own_team = replay_json['first']['vehicles'].values()[0]['team']
86+
""" Returns a list of names of the players on the replay recorder's team """
87+
own_team = get_own_team(replay_json)
8088
return [v['name'] for v in replay_json['first']['vehicles'].values() if v['team'] == own_team]
8189

8290

91+
def is_stronghold(replay_json):
92+
""" Returns whether the replay is from a stronghold battle """
93+
return replay_json['first']['battleType'] == 10
94+
95+
8396
def is_cw(replay_json):
8497
"""
8598
Returns whether the replay is probably from a clan war, i.e.
@@ -96,11 +109,11 @@ def is_cw(replay_json):
96109
def guess_clan(replay_json):
97110
""" Attempt to guess the friendly clan name from the replay.
98111
Use is_cw(replay_json) before calling this to confirm it was a clan war.
99-
:param replay_json:
100-
:return:
101112
"""
102-
# first chunk should only contain the own team, so first player's clan is the friendly clan
103-
return replay_json['first']['vehicles'].values()[0]['clanAbbrev']
113+
player_name = replay_json['first']['playerName']
114+
for v in replay_json['first']['vehicles'].itervalues():
115+
if v['name'] == player_name:
116+
return v['clanAbbrev']
104117

105118

106119
def guess_enemy_clan(replay_json):
@@ -110,12 +123,12 @@ def guess_enemy_clan(replay_json):
110123
:param replay_json:
111124
:return:
112125
"""
113-
friendly_team = replay_json['first']['vehicles'].values()[0]['team']
114-
return players_list(replay_json, 1 if friendly_team == 2 else 2)[0]['clanAbbrev']
126+
own_team = get_own_team(replay_json)
127+
return players_list(replay_json, 1 if own_team == 2 else 2)[0]['clanAbbrev']
115128

116129

117130
def score(replay_json):
118-
own_team = replay_json['first']['vehicles'].values()[0]['team']
131+
own_team = get_own_team(replay_json)
119132
own_team_deaths = 0
120133
enemy_team_deaths = 0
121134
for v in replay_json['second'][0]['vehicles'].itervalues():
@@ -127,6 +140,12 @@ def score(replay_json):
127140
return enemy_team_deaths, own_team_deaths
128141

129142

143+
def resources_earned(json_second, player_id):
144+
for v in json_second[0]['vehicles'].itervalues():
145+
if str(v["accountDBID"]) == str(player_id):
146+
return v["fortResource"]
147+
148+
130149
def player_performance(json_second, vehicles, players):
131150
tank_info_by_player_name = {}
132151
for k, v in json_second[1].iteritems():

whyattend/templates/battles/create.html

+8
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ <h2>Add battle</h2>
7575
{% endif %}
7676
<form class="form-horizontal" action="{{url_for('create_battle')}}" method="POST" role="form" enctype="multipart/form-data">
7777

78+
{% if stronghold %}
79+
<p class="alert alert-info">The replay was determined to be from a stronghold battle.</p>
80+
{% endif %}
81+
7882
<div class="form-group">
7983
<label for="date" class="col-lg-2 control-label">Date &amp; Time</label>
8084
<div class="col-lg-10">
@@ -107,6 +111,7 @@ <h2>Add battle</h2>
107111
</div>
108112
</div>
109113

114+
{% if not stronghold %}
110115
<div class="form-group">
111116
<label for="province" class="col-lg-2 control-label">Province(s)</label>
112117
<div class="col-lg-10">
@@ -117,6 +122,7 @@ <h2>Add battle</h2>
117122
</select>
118123
</div>
119124
</div>
125+
{% endif %}
120126

121127
<div class="form-group">
122128
<label for="battle_commander" class="col-lg-2 control-label">Battle commander</label>
@@ -151,6 +157,7 @@ <h2>Add battle</h2>
151157
</div>
152158
</div>
153159

160+
{% if not stronghold %}
154161
<div class="form-group">
155162
<label for="battle_commander" class="col-lg-2 control-label">Battle Group</label>
156163
<div class="col-lg-10">
@@ -177,6 +184,7 @@ <h2>Add battle</h2>
177184
</div>
178185
</div>
179186
</div>
187+
{% endif %}
180188

181189
<div class="form-group">
182190
<label for="description" class="col-lg-2 control-label">Description</label>

whyattend/templates/payout/payout.html

+6-4
Original file line numberDiff line numberDiff line change
@@ -130,19 +130,21 @@
130130
#fromDate { width: 150px; }
131131
#toDate {width: 150px; }
132132
#gold {width: 150px; }
133-
#recruit_factor {width: 50px; }
133+
#recruit_factor {width: 70px; }
134+
#points_per_resource {width: 70px; }
134135
form {margin-bottom: 20px; }
135136
</style>
136137
{% endblock %}
137138
{% block content %}
138139
<h2>Payout <img style="width:32px; height:32px;" src="{{url_for('static', filename='img/clanicons/' + clan + '.png')}}"> </h2>
139140
<h4><a href="{{url_for('reserve_conflicts', clan=clan)}}">Show reserve player conflicts</a></h4>
140-
<form class="form-inline" action="{{url_for('payout_battles', clan=clan)}}" method="GET">
141-
From <input class="form-control" type="datetime" id="fromDate" name="fromDate" placeholder="dd.mm.yyyy">
141+
<form class="form" action="{{url_for('payout_battles', clan=clan)}}" method="GET">
142+
From <input class="form-control" type="datetime" id="fromDate" name="fromDate" placeholder="dd.mm.yyyy">
142143
to <input class="form-control" type="datetime" id="toDate" name="toDate" placeholder="dd.mm.yyyy">
143-
Victories only: <input type="checkbox" name="victories_only" id="victories_only">
144+
Victories only: <input type="checkbox" name="victories_only" id="victories_only"><br/>
144145
Gold: <input id="gold" class="form-control" type="text" name="gold" placeholder="amount of gold" value="0">
145146
Gold/Point factor for recruits: <input id="recruit_factor" class="form-control" type="text" name="recruit_factor" placeholder="Factor for 'gold per point' for recruits" value="1.0">
147+
Points per resource: <input id="points_per_resource" class="form-control" type="text" name="points_per_resource" placeholder="Points per resource" value="0.01">
146148
<h4>Battles in the selected range:</h4>
147149
<table class="table" id="battles">
148150
<thead>

whyattend/templates/payout/payout_battles.html

+6
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
fnShowHide(6);
3636
fnShowHide(7);
3737
fnShowHide(8);
38+
fnShowHide(9);
39+
fnShowHide(10);
3840
};
3941
</script>
4042
{% endblock %}
@@ -78,6 +80,8 @@ <h3>Summary of {{gold}} gold to pay out for {{battles|length}} battle{{'s' if ba
7880
<th># battles drawn</th>
7981
<th># battles lost</th>
8082
<th># battles reserve</th>
83+
<th>Resources</th>
84+
<th>Points from resources</th>
8185
<th>Points</th>
8286
<th>Gold to pay</th>
8387
</tr>
@@ -94,6 +98,8 @@ <h3>Summary of {{gold}} gold to pay out for {{battles|length}} battle{{'s' if ba
9498
<td>{{player_draws[player]}}</td>
9599
<td>{{player_defeats[player]}}</td>
96100
<td>{{player_reserve[player]}}</td>
101+
<td>{{player_resources[player]}}</td>
102+
<td>{{(player_resources[player] * points_per_resource)|round(2)}}</td>
97103
<td>{{player_points[player]}}</td>
98104
<td>{{player_gold[player]}}</td>
99105
</tr>

whyattend/webapp.py

+28-10
Original file line numberDiff line numberDiff line change
@@ -654,7 +654,6 @@ def edit_battle(battle_id):
654654
def create_battle():
655655
"""
656656
Create battle form.
657-
:return:
658657
"""
659658
all_players = Player.query.filter_by(clan=g.player.clan, locked=False).order_by('lower(name)').all()
660659
sorted_players = sorted(all_players, reverse=True, key=lambda p: p.player_role_value())
@@ -670,6 +669,7 @@ def create_battle():
670669
map_name = ''
671670
province = ''
672671
duration = 15 * 60
672+
stronghold = False
673673
battle_commander = None
674674
date = datetime.datetime.now()
675675
battle_groups = BattleGroup.query.filter_by(clan=g.player.clan).order_by('date').all()
@@ -702,13 +702,14 @@ def create_battle():
702702
if g.player in players:
703703
battle_commander = g.player.id
704704
date = datetime.datetime.strptime(replay['first']['dateTime'], '%d.%m.%Y %H:%M:%S')
705+
stronghold = replays.is_stronghold(replay)
705706

706707
if not replay['second']:
707708
flash(u'Error: Uploaded replay file is incomplete (Battle was left before it ended). ' +
708709
u'Can not determine all information automatically.', 'error')
709-
elif not replays.is_cw(replay):
710+
elif not replays.is_cw(replay) and not replays.is_stronghold(replay):
710711
flash(
711-
u'Error: Uploaded replay file is probably not from a clan war '
712+
u'Error: Uploaded replay file is probably not from a clan war or stronghold battle '
712713
u'(Detected different clan tags in one of the team' +
713714
u' or players from the same clan on both sides)', 'error')
714715
else:
@@ -735,7 +736,7 @@ def create_battle():
735736
battle_commander = Player.query.get(int(request.form['battle_commander']))
736737
description = request.form.get('description', '')
737738
duration = request.form.get('duration', 15 * 60)
738-
battle_group = int(request.form['battle_group'])
739+
battle_group = request.form.get('battle_group', -2)
739740
battle_group_title = request.form.get('battle_group_title', '')
740741
battle_group_description = request.form.get('battle_group_description', '')
741742
battle_group_final = request.form.get('battle_group_final', '') == 'on'
@@ -806,6 +807,9 @@ def create_battle():
806807
battle_commander=battle_commander, description=description,
807808
duration=duration)
808809

810+
if replays.is_stronghold(replay):
811+
battle.stronghold = True
812+
809813
if bg:
810814
battle.battle_group_final = battle_group_final
811815
battle.battle_group = bg
@@ -822,12 +826,13 @@ def create_battle():
822826
else:
823827
battle.score_own_team, battle.score_enemy_team = 0, 0
824828

825-
826829
for player_id in players:
827830
player = Player.query.get(player_id)
828831
if not player:
829832
abort(404)
830833
ba = BattleAttendance(player, battle, reserve=False)
834+
if battle.stronghold:
835+
ba.resources_earned = replays.resources_earned(replay['second'], player.wot_id)
831836
db_session.add(ba)
832837

833838
db_session.add(battle)
@@ -843,7 +848,7 @@ def create_battle():
843848
battle_result=battle_result, date=date, battle_groups=battle_groups,
844849
battle_group=battle_group, battle_group_title=battle_group_title, duration=duration,
845850
battle_group_description=battle_group_description, battle_group_final=battle_group_final,
846-
sorted_players=sorted_players, battle_group_id=battle_group_id)
851+
sorted_players=sorted_players, battle_group_id=battle_group_id, stronghold=stronghold)
847852

848853

849854
@app.route('/battles/list/<clan>')
@@ -957,7 +962,9 @@ def battles_list_json(clan):
957962
battles = list(db_session.execute(battles.offset(offset).limit(limit)))
958963

959964
def make_row(battle):
960-
if battle.battle_group_id:
965+
if battle.stronghold:
966+
type = "Stronghold"
967+
elif battle.battle_group_id:
961968
type = '<a href="' + url_for('battle_group_details', group_id=battle.battle_group_id) + '">'
962969
if battle.battle_group_final:
963970
type += 'Final'
@@ -1441,12 +1448,14 @@ def payout_battles(clan):
14411448
gold = int(request.form['gold'])
14421449
victories_only = request.form.get('victories_only', False)
14431450
recruit_factor = request.form['recruit_factor']
1451+
points_per_resource = float(request.form['points_per_resource'])
14441452
else:
14451453
from_date = request.args.get('fromDate')
14461454
to_date = request.args.get('toDate')
14471455
gold = int(request.args.get('gold'))
14481456
victories_only = request.args.get('victories_only', False) == 'on'
14491457
recruit_factor = float(request.args.get('recruit_factor'))
1458+
points_per_resource = float(request.args.get('points_per_resource'))
14501459

14511460
from_date = datetime.datetime.strptime(from_date, '%d.%m.%Y')
14521461
to_date = datetime.datetime.strptime(to_date, '%d.%m.%Y') + datetime.timedelta(days=1)
@@ -1467,6 +1476,8 @@ def payout_battles(clan):
14671476
player_victories = defaultdict(int)
14681477
player_defeats = defaultdict(int)
14691478
player_draws = defaultdict(int)
1479+
player_resources = defaultdict(int)
1480+
14701481
for battle in battles:
14711482
if battle.battle_group and not battle.battle_group_final:
14721483
continue # only finals count
@@ -1478,6 +1489,11 @@ def payout_battles(clan):
14781489
battle_players = battle.get_players()
14791490
battle_reserves = battle.get_reserve_players()
14801491

1492+
if battle.stronghold:
1493+
for ba in battle.attendances:
1494+
player_resources[ba.player] += ba.resources_earned
1495+
continue
1496+
14811497
battle_commander = battle.battle_commander
14821498
if not battle_commander.locked:
14831499
player_fced[battle_commander] += 1
@@ -1506,13 +1522,14 @@ def payout_battles(clan):
15061522

15071523
players = set()
15081524
for p in clan_members:
1509-
if player_played[p] or player_reserve[p] or player_fced[p]:
1525+
if player_played[p] or player_reserve[p] or player_fced[p] or player_resources[p]:
15101526
players.add(p)
15111527

15121528
player_points = dict()
15131529
for p in players:
15141530
player_points[p] = player_fced_win[p] * 6 + player_fced_defeat[p] * 4 + player_fced_draws[p] * 2 + \
1515-
player_victories[p] * 3 + player_defeats[p] * 2 + player_draws[p] * 2 + player_reserve[p]
1531+
player_victories[p] * 3 + player_defeats[p] * 2 + player_draws[p] * 2 + player_reserve[p] + \
1532+
player_resources[p] * points_per_resource
15161533

15171534
total_points = sum(player_points[p] for p in players)
15181535
recruit_points = sum(player_points[p] for p in players if p.is_recruit())
@@ -1531,7 +1548,8 @@ def payout_battles(clan):
15311548
player_gold=player_gold, gold=gold, player_defeats=player_defeats,
15321549
player_fced_win=player_fced_win, victories_only=victories_only, recruit_factor=recruit_factor,
15331550
player_fced_defeat=player_fced_defeat, player_victories=player_victories,
1534-
player_fced_draws=player_fced_draws, player_draws=player_draws, player_points=player_points)
1551+
player_fced_draws=player_fced_draws, player_draws=player_draws, player_points=player_points,
1552+
player_resources=player_resources, points_per_resource=points_per_resource)
15351553

15361554

15371555
@app.route('/players/json')

0 commit comments

Comments
 (0)