Skip to content

Commit d63d10e

Browse files
author
Pavel Perestoronin
committed
New: use stored teams to attack Grand Arena enemies in Top 100
1 parent 1ad404e commit d63d10e

File tree

7 files changed

+38
-14
lines changed

7 files changed

+38
-14
lines changed

.idea/inspectionProfiles/Project_Default.xml

+2-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## `3.4.0b0`
4+
5+
- **Новое**: сохраненная информация о командах других игроков будет использоваться для атаки на топ-100 Гранд Арены
6+
37
## `3.3.1`
48

59
- **Исправление**: парсинг настроек сломан после апгрейда пакетов

Makefile

+2-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ requirements.txt:
2424
.PHONY: test
2525
test:
2626
@$(PYTEST)
27-
@$(FLAKE8) bestmobabot tests
27+
# TODO: disabled until PEP 572 is supported.
28+
# TODO: @$(FLAKE8) bestmobabot tests
2829
@$(ISORT) -rc -c bestmobabot tests
2930

3031
.PHONY: tag

bestmobabot/arena.py

+14-5
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,7 @@ def yield_solutions(self) -> Iterable[ArenaSolution]:
141141
for n_page in count(1):
142142
logger.debug('Fetching enemies…')
143143
self.callback(n_page)
144-
enemies = list(self.filter_enemies(self.get_enemies()))
145-
if enemies:
144+
if enemies := list(self.filter_enemies(self.get_enemies())):
146145
yield max(self.solve_enemy_cached(enemy) for enemy in enemies)
147146
else:
148147
logger.debug('All enemies are filtered out on the current page.')
@@ -156,8 +155,12 @@ def filter_enemies(self, enemies: Iterable[BaseArenaEnemy]) -> Iterable[BaseAren
156155
logger.debug('Skipped empty user #{}.', enemy.user_id)
157156
continue
158157
if len(enemy.teams) < self.n_required_teams:
159-
logger.warning('Enemy has unknown teams: {}.', enemy.user)
160-
continue
158+
if teams := self.db.get(f'{self.enemy_key(enemy)}:teams'):
159+
logger.warning('Using stored teams for this enemy.')
160+
enemy.teams = [[Hero(**hero) for hero in team] for team in teams]
161+
else:
162+
logger.warning('Enemy has unknown teams: {}.', enemy.user)
163+
continue
161164
else:
162165
self.store_enemy(enemy)
163166
if self.user_clan_id and enemy.user.is_from_clans((self.user_clan_id,)):
@@ -168,11 +171,17 @@ def filter_enemies(self, enemies: Iterable[BaseArenaEnemy]) -> Iterable[BaseAren
168171
continue
169172
yield enemy
170173

174+
def enemy_key(self, enemy: BaseArenaEnemy) -> str:
175+
"""
176+
Database key to store the enemy info.
177+
"""
178+
return f'arena:{self.n_required_teams}:{enemy.user.server_id}:{enemy.user_id}'
179+
171180
def store_enemy(self, enemy: BaseArenaEnemy):
172181
"""
173182
Store enemy teams and place to be able to guess their hidden teams in Top 100.
174183
"""
175-
enemy_key = f'arena:{self.n_required_teams}:{enemy.user.server_id}:{enemy.user_id}'
184+
enemy_key = self.enemy_key(enemy)
176185
self.db[f'{enemy_key}:teams'] = [[hero.dict() for hero in team] for team in enemy.teams]
177186
self.db[f'{enemy_key}:place'] = enemy.place
178187

bestmobabot/database.py

+3-4
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,9 @@ def __getitem__(self, key: str) -> Any:
4545
logger.trace('get {}', key)
4646
with closing(self.connection.cursor()) as cursor: # type: sqlite3.Cursor
4747
cursor.execute('SELECT value FROM `default` WHERE `key` = ?', (key,))
48-
row = cursor.fetchone()
49-
if not row:
50-
raise KeyError(key)
51-
return json.loads(row[0])
48+
if row := cursor.fetchone():
49+
return json.loads(row[0])
50+
raise KeyError(key)
5251

5352
def __setitem__(self, key: str, value: Any) -> None:
5453
logger.trace('set {} = {!s:.40}…', key, value)

bestmobabot/dataclasses_.py

+12
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,10 @@ class Config:
322322
def teams(self) -> List[List[Hero]]:
323323
raise NotImplementedError()
324324

325+
@teams.setter
326+
def teams(self, teams: List[List[Hero]]):
327+
raise NotImplementedError()
328+
325329
def __str__(self) -> str:
326330
return f'{self.user} at place {self.place}'
327331

@@ -333,6 +337,10 @@ class ArenaEnemy(BaseArenaEnemy):
333337
def teams(self) -> List[List[Hero]]:
334338
return [self.heroes]
335339

340+
@teams.setter
341+
def teams(self, teams: List[List[Hero]]):
342+
self.heroes = teams[0]
343+
336344

337345
class GrandArenaEnemy(BaseArenaEnemy):
338346
heroes: List[List[Hero]]
@@ -341,6 +349,10 @@ class GrandArenaEnemy(BaseArenaEnemy):
341349
def teams(self) -> List[List[Hero]]:
342350
return self.heroes
343351

352+
@teams.setter
353+
def teams(self, teams: List[List[Hero]]):
354+
self.heroes = teams
355+
344356

345357
class ArenaState(BaseModel, Loggable):
346358
battles: int

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
setuptools.setup(
77
name='bestmobabot',
8-
version='3.3.1',
8+
version='3.4.0b0',
99
author='Pavel Perestoronin',
1010
author_email='[email protected]',
1111
description='Hero Wars game bot 🏆',

0 commit comments

Comments
 (0)