Citizen.set_default_weapon() - eRepublik should return list with all available weapon qualities, but when a battle is just launched, they return only dict with barehands
Citizen.fight() - no longer calls self.set_default_weapon()
Citizen.find_battle_and_fight() - now calls self.set_default_weapon() just before fighting
Citizen.update_war_info() - returns previous battle list if responses 'last_updated' isn't more than 30s old

New:
Citizen.get_battle_for_war(war_id) - returns Battle instance for specific war, if battle is active for given war
This commit is contained in:
Eriks Karls 2020-01-13 10:28:42 +02:00
parent 1c47d169d2
commit 1f07f2e270
2 changed files with 36 additions and 28 deletions

View File

@ -1,20 +1,20 @@
import json
import re
import sys
import warnings
from collections import defaultdict
from datetime import datetime, timedelta
from itertools import product
from json import loads, dumps
from json import dumps, loads
from threading import Event
from time import sleep
from typing import Dict, List, Tuple, Any, Union, Set
from typing import Any, Dict, List, Optional, Set, Tuple, Union
from requests import Response, RequestException
from requests import RequestException, Response
from erepublik.classes import (CitizenAPI, Battle, Reporter, Config, Energy, Details, Politics, MyCompanies,
TelegramBot, ErepublikException, BattleDivision, MyJSONEncoder)
from erepublik.classes import (Battle, BattleDivision, CitizenAPI, Config,
Details, Energy, ErepublikException,
MyCompanies, MyJSONEncoder, Politics, Reporter,
TelegramBot)
from erepublik.utils import *
from erepublik.utils import process_warning
class Citizen(CitizenAPI):
@ -112,6 +112,9 @@ class Citizen(CitizenAPI):
def __str__(self) -> str:
return f"Citizen {self.name}"
def __repr__(self):
return self.__str__()
def __dict__(self):
ret = super().__dict__.copy()
ret.pop('stop_threads', None)
@ -178,7 +181,7 @@ class Citizen(CitizenAPI):
if j['error'] and j["message"] == 'Too many requests':
self.write_log("Made too many requests! Sleeping for 30 seconds.")
self.sleep(30)
except:
except (json.JSONDecodeError, KeyError, TypeError):
pass
if response.status_code >= 400:
self.r = response
@ -559,10 +562,13 @@ class Citizen(CitizenAPI):
if not self.details.current_country:
self.update_citizen_info()
resp_json = self._get_military_campaigns_json_list().json()
if self.__last_war_update_data and self.__last_war_update_data.get('last_updated', 0) + 30 > self.now.timestamp():
resp_json = self.__last_war_update_data
else:
resp_json = self._get_military_campaigns_json_list().json()
if resp_json.get("countries"):
if self.all_battles is None:
self.all_battles = defaultdict(Battle)
self.all_battles = {}
else:
self.all_battles.clear()
@ -638,7 +644,7 @@ class Citizen(CitizenAPI):
def now(self) -> datetime:
"""
Returns aware datetime object localized to US/Pacific (eRepublik time)
:return: datetime.datetime
:return: datetime
"""
return now()
@ -811,6 +817,7 @@ class Citizen(CitizenAPI):
if not self.travel_to_battle(battle_id, country_ids_to_travel):
break
self.set_default_weapon(battle_id)
self.fight(battle_id, side_id)
self.travel_to_residence()
self.collect_weekly_reward()
@ -819,8 +826,7 @@ class Citizen(CitizenAPI):
def fight(self, battle_id: int, side_id: int = None, count: int = None) -> int:
"""Fight in a battle.
Will auto activate booster and travel if allowed to do it and
in the beginning will switch to default weapon (air - bare hands, ground - q7, if count > 30, else bare hands.
Will auto activate booster and travel if allowed to do it.
:param battle_id: int BattleId - battle to fight in
:param side_id: int or None. Battle side to fight in, If side_id not == invader id or not in invader deployed allies list, then defender's side is chosen
:param count: How many hits to do, if not specified self.should_fight() is called.
@ -831,11 +837,10 @@ class Citizen(CitizenAPI):
battle_id = int(battle_id)
if battle_id not in self.all_battles:
self.update_war_info()
battle = self.all_battles[battle_id]
battle = self.all_battles.get(battle_id)
zone_id = battle.div[11 if battle.is_air else self.division].battle_zone_id
if not battle.is_air and self.config.boosters:
self.activate_dmg_booster()
self.set_default_weapon(battle_id)
error_count = 0
ok_to_fight = True
if count is None:
@ -862,7 +867,7 @@ class Citizen(CitizenAPI):
return error_count
def _shoot(self, battle_id: int, inv_side: bool, zone_id: int):
battle = self.all_battles[battle_id]
battle = self.all_battles.get(battle_id)
side_id = battle.invader.id if inv_side else battle.defender.id
if battle.is_air:
response = self._post_military_fight_air(battle_id, side_id, zone_id)
@ -914,7 +919,7 @@ class Citizen(CitizenAPI):
if not isinstance(count, int) or count < 1:
count = 1
has_traveled = False
battle = self.all_battles[battle_id]
battle = self.all_battles.get(battle_id)
if inv_side:
good_countries = [battle.invader.id] + battle.invader.deployed
if self.details.current_country not in good_countries:
@ -946,7 +951,7 @@ class Citizen(CitizenAPI):
:param division_to: int target division to switch to
:return:
"""
battle = self.all_battles[battle_id]
battle = self.all_battles.get(battle_id)
self._post_main_battlefield_change_division(battle_id, battle.div[division_to].battle_zone_id)
def work_ot(self):
@ -2136,8 +2141,10 @@ class Citizen(CitizenAPI):
return self._get_military_show_weapons(battle_id).json()
def set_default_weapon(self, battle_id: int) -> int:
battle = self.all_battles[battle_id]
battle = self.all_battles.get(battle_id)
available_weapons = self._get_military_show_weapons(battle_id).json()
while not isinstance(available_weapons, list):
available_weapons = self._get_military_show_weapons(battle_id).json()
weapon_quality = -1
if not battle.is_air:
for weapon in available_weapons:
@ -2147,7 +2154,12 @@ class Citizen(CitizenAPI):
return self.change_weapon(battle_id, weapon_quality)
def change_weapon(self, battle_id: int, weapon_quality: int) -> int:
battle = self.all_battles[battle_id]
battle = self.all_battles.get(battle_id)
battle_zone = battle.div[11 if battle.is_air else self.division].battle_zone_id
r = self._post_military_change_weapon(battle_id, battle_zone, weapon_quality)
return r.json().get('weaponInfluence')
def get_battle_for_war(self, war_id: int) -> Optional[Battle]:
self.update_war_info()
war_info = self.get_war_status(war_id)
return self.all_battles.get(war_info.get("battle_id"), None)

View File

@ -4,9 +4,9 @@ import hashlib
import random
import threading
import time
from collections import deque, defaultdict
from json import JSONDecodeError, loads, JSONEncoder
from typing import Any, Dict, List, Union, Mapping, Iterable, Tuple
from collections import defaultdict, deque
from json import JSONDecodeError, JSONEncoder, loads
from typing import Any, Dict, Iterable, List, Mapping, Tuple, Union
from requests import Response, Session, post
@ -567,10 +567,6 @@ Class for unifying eRepublik known endpoints and their required/optional paramet
def _get_military_campaigns_json_list(self) -> Response:
return self.get("{}/military/campaignsJson/list".format(self.url))
def _get_military_show_weapons(self, battle_id: int) -> Response:
params = {"_token": self.token, "battleId": battle_id}
return self.get("{}/military/show-weapons".format(self.url), params=params)
def _get_military_unit_data(self, unit_id: int, **kwargs) -> Response:
params = {"groupId": unit_id, "panel": "members", **kwargs}
return self.get("{}/military/military-unit-data/".format(self.url), params=params)