WAM/Employ bugfix

Company sorting bugfix
This commit is contained in:
Eriks K 2020-06-16 16:59:56 +03:00
parent 603604213d
commit a825917a98
4 changed files with 83 additions and 60 deletions

View File

@ -5,7 +5,7 @@
__author__ = """Eriks Karls""" __author__ = """Eriks Karls"""
__email__ = 'eriks@72.lv' __email__ = 'eriks@72.lv'
__version__ = '0.20.0' __version__ = '0.20.0'
__commit_id__ = "f83df44" __commit_id__ = "6036042"
from erepublik import classes, utils from erepublik import classes, utils
from erepublik.citizen import Citizen from erepublik.citizen import Citizen

View File

@ -657,6 +657,7 @@ class BaseCitizen(CitizenAPI):
r'CSRF attack detected|meta http-equiv="refresh"|not_authenticated', response.text)) r'CSRF attack detected|meta http-equiv="refresh"|not_authenticated', response.text))
def _report_action(self, action: str, msg: str, **kwargs): def _report_action(self, action: str, msg: str, **kwargs):
kwargs = utils.json.loads(utils.json.dumps(kwargs or {}, cls=MyJSONEncoder))
action = action[:32] action = action[:32]
self.write_log(msg) self.write_log(msg)
if self.reporter.allowed: if self.reporter.allowed:
@ -850,7 +851,7 @@ class CitizenCompanies(BaseCitizen):
if sum(employ_factories.values()) > self.my_companies.work_units: if sum(employ_factories.values()) > self.my_companies.work_units:
employ_factories = {} employ_factories = {}
response = self._post_economy_work("production", wam=wam_list, employ=employ_factories).json() response = self._post_economy_work("production", wam=[c.id for c in wam_list], employ=employ_factories).json()
return response return response
def update_companies(self): def update_companies(self):
@ -1027,7 +1028,7 @@ class CitizenEconomy(CitizenTravel):
ret = self._post_economy_marketplace_actions(**data) ret = self._post_economy_marketplace_actions(**data)
message = (f"Posted market offer for {amount}q{quality} " message = (f"Posted market offer for {amount}q{quality} "
f"{self.get_industry_name(industry)} for price {price}cc") f"{self.get_industry_name(industry)} for price {price}cc")
self._report_action("ECONOMY_SELL_PRODUCTS", message, **ret.json()) self._report_action("ECONOMY_SELL_PRODUCTS", message, kwargs=ret.json())
return ret return ret
def buy_from_market(self, offer: int, amount: int) -> dict: def buy_from_market(self, offer: int, amount: int) -> dict:
@ -1039,7 +1040,7 @@ class CitizenEconomy(CitizenTravel):
self.details.cc = ret.json()['currency'] self.details.cc = ret.json()['currency']
self.details.gold = ret.json()['gold'] self.details.gold = ret.json()['gold']
json_ret.pop("offerUpdate", None) json_ret.pop("offerUpdate", None)
self._report_action("BOUGHT_PRODUCTS", "", **json_ret) self._report_action("BOUGHT_PRODUCTS", "", kwargs=json_ret)
return json_ret return json_ret
def get_market_offers(self, product_name: str, quality: int = None, country_id: int = None) -> Dict[str, OfferItem]: def get_market_offers(self, product_name: str, quality: int = None, country_id: int = None) -> Dict[str, OfferItem]:
@ -1099,7 +1100,7 @@ class CitizenEconomy(CitizenTravel):
if amount * cheapest.price < self.details.cc: if amount * cheapest.price < self.details.cc:
data = dict(offer=cheapest.offer_id, amount=amount, price=cheapest.price, data = dict(offer=cheapest.offer_id, amount=amount, price=cheapest.price,
cost=amount * cheapest.price, quality=cheapest_q, energy=amount * utils.FOOD_ENERGY[cheapest_q]) cost=amount * cheapest.price, quality=cheapest_q, energy=amount * utils.FOOD_ENERGY[cheapest_q])
self._report_action("BUY_FOOD", "", **data) self._report_action("BUY_FOOD", "", kwargs=data)
self.buy_from_market(cheapest.offer_id, amount) self.buy_from_market(cheapest.offer_id, amount)
self.update_inventory() self.update_inventory()
else: else:
@ -1136,11 +1137,11 @@ class CitizenEconomy(CitizenTravel):
self.details.cc = float(response.json().get("ecash").get("value")) self.details.cc = float(response.json().get("ecash").get("value"))
self.details.gold = float(response.json().get("gold").get("value")) self.details.gold = float(response.json().get("gold").get("value"))
if response.json().get('error'): if response.json().get('error'):
self._report_action("BUY_GOLD", "Unable to buy gold!", **response.json()) self._report_action("BUY_GOLD", "Unable to buy gold!", kwargs=response.json())
self.stop_threads.wait() self.stop_threads.wait()
return False return False
else: else:
self._report_action("BUY_GOLD", f"New amount {self.details.cc}cc, {self.details.gold}g", **response.json()) self._report_action("BUY_GOLD", f"New amount {self.details.cc}cc, {self.details.gold}g", kwargs=response.json())
return True return True
def donate_money(self, citizen_id: int = 1620414, amount: float = 0.0, currency: int = 62) -> bool: def donate_money(self, citizen_id: int = 1620414, amount: float = 0.0, currency: int = 62) -> bool:
@ -1177,8 +1178,10 @@ class CitizenEconomy(CitizenTravel):
f"Unable to donate {amount}q{quality} " f"Unable to donate {amount}q{quality} "
f"{self.get_industry_name(industry_id)}, not enough left!", success=False) f"{self.get_industry_name(industry_id)}, not enough left!", success=False)
return 0 return 0
available = re.search(rf"Cannot transfer the items because the user has only (\d+) free slots in (his|her) " available = re.search(
rf"storage.", response.text).group(1) rf"Cannot transfer the items because the user has only (\d+) free slots in (his|her) storage.",
response.text
).group(1)
self._report_action("DONATE_ITEMS", self._report_action("DONATE_ITEMS",
f"Unable to donate {amount}q{quality}{self.get_industry_name(industry_id)}" f"Unable to donate {amount}q{quality}{self.get_industry_name(industry_id)}"
f", receiver has only {available} storage left!", success=False) f", receiver has only {available} storage left!", success=False)
@ -1198,7 +1201,7 @@ class CitizenEconomy(CitizenTravel):
return True return True
else: else:
self._report_action("CONTRIBUTE_CC", f"Unable to contribute {amount}cc to {utils.COUNTRIES[country_id]}'s" self._report_action("CONTRIBUTE_CC", f"Unable to contribute {amount}cc to {utils.COUNTRIES[country_id]}'s"
f" treasury", **r.json()) f" treasury", kwargs=r.json())
return False return False
def contribute_food_to_country(self, amount: int = 0, quality: int = 1, country_id: int = 71) -> bool: def contribute_food_to_country(self, amount: int = 0, quality: int = 1, country_id: int = 71) -> bool:
@ -1215,7 +1218,7 @@ class CitizenEconomy(CitizenTravel):
return True return True
else: else:
self._report_action("CONTRIBUTE_FOOD", f"Unable to contribute {amount}q{quality} food to " self._report_action("CONTRIBUTE_FOOD", f"Unable to contribute {amount}q{quality} food to "
f"{utils.COUNTRIES[country_id]}'s treasury", **r.json()) f"{utils.COUNTRIES[country_id]}'s treasury", kwargs=r.json())
return False return False
def contribute_gold_to_country(self, amount: int, country_id: int = 71) -> bool: def contribute_gold_to_country(self, amount: int, country_id: int = 71) -> bool:
@ -1233,7 +1236,7 @@ class CitizenEconomy(CitizenTravel):
return True return True
else: else:
self._report_action("CONTRIBUTE_GOLD", f"Unable to contribute {amount}g to {utils.COUNTRIES[country_id]}'s" self._report_action("CONTRIBUTE_GOLD", f"Unable to contribute {amount}g to {utils.COUNTRIES[country_id]}'s"
f" treasury", **r.json()) f" treasury", kwargs=r.json())
return False return False
@ -1260,7 +1263,7 @@ class CitizenMedia(BaseCitizen):
return True return True
else: else:
self._report_action("ARTICLE_ENDORSE", f"Unable to endorse article ({article_id}) with {amount}cc", self._report_action("ARTICLE_ENDORSE", f"Unable to endorse article ({article_id}) with {amount}cc",
**resp) kwargs=resp)
return False return False
else: else:
return False return False
@ -1272,7 +1275,7 @@ class CitizenMedia(BaseCitizen):
self._report_action("ARTICLE_VOTE", f"Voted article {article_id}", success=True) self._report_action("ARTICLE_VOTE", f"Voted article {article_id}", success=True)
return True return True
else: else:
self._report_action("ARTICLE_VOTE", f"Unable to vote for article {article_id}", **resp) self._report_action("ARTICLE_VOTE", f"Unable to vote for article {article_id}", kwargs=resp)
return False return False
def get_article_comments(self, article_id: int, page_id: int = 1) -> Dict[str, Any]: def get_article_comments(self, article_id: int, page_id: int = 1) -> Dict[str, Any]:
@ -1292,7 +1295,7 @@ class CitizenMedia(BaseCitizen):
resp = self._post_main_write_article(**data) resp = self._post_main_write_article(**data)
try: try:
article_id = int(resp.history[1].url.split("/")[-3]) article_id = int(resp.history[1].url.split("/")[-3])
self._report_action("ARTICLE_PUBLISH", f"Published new article \"{title}\" ({article_id})", **data) self._report_action("ARTICLE_PUBLISH", f"Published new article \"{title}\" ({article_id})", kwargs=data)
except: # noqa except: # noqa
article_id = 0 article_id = 0
return article_id return article_id
@ -1391,7 +1394,7 @@ class CitizenMilitary(CitizenTravel):
battle_zone = battle.div[11 if battle.is_air else self.division].battle_zone_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, quality) r = self._post_military_change_weapon(battle_id, battle_zone, quality)
influence = r.json().get('weaponInfluence') influence = r.json().get('weaponInfluence')
self._report_action("MILITARY_WEAPON", f"Switched to q{quality} weapon, new influence {influence}", **r.json()) self._report_action("MILITARY_WEAPON", f"Switched to q{quality} weapon, new influence {influence}", kwargs=r.json())
return influence return influence
def check_epic_battles(self): def check_epic_battles(self):
@ -1967,7 +1970,7 @@ class CitizenSocial(BaseCitizen):
if ids is None: if ids is None:
ids = [1620414, ] ids = [1620414, ]
for player_id in ids: for player_id in ids:
self._report_action("SOCIAL_MESSAGE", f"Sent a message to {player_id}", **dict(subject=subject, msg=msg, self._report_action("SOCIAL_MESSAGE", f"Sent a message to {player_id}", kwargs=dict(subject=subject, msg=msg,
id=player_id)) id=player_id))
self._post_main_messages_compose(subject, msg, [player_id]) self._post_main_messages_compose(subject, msg, [player_id])
@ -1977,7 +1980,7 @@ class CitizenSocial(BaseCitizen):
self.r.text, re.S | re.M) self.r.text, re.S | re.M)
r = self._post_main_country_post_create(message, max(post_to_wall_as, key=int) if post_to_wall_as else 0) r = self._post_main_country_post_create(message, max(post_to_wall_as, key=int) if post_to_wall_as else 0)
self._report_action("SOCIAL_WRITE_WALL_COUNTRY", f"Wrote a message to the country wall", msg=message) self._report_action("SOCIAL_WRITE_WALL_COUNTRY", f"Wrote a message to the country wall", kwargs=message)
return r.json() return r.json()
def add_friend(self, player_id: int) -> Response: def add_friend(self, player_id: int) -> Response:
@ -2153,7 +2156,7 @@ class CitizenTasks(BaseCitizen):
def resign_from_employer(self) -> bool: def resign_from_employer(self) -> bool:
r = self.update_job_info() r = self.update_job_info()
if r.json().get("isEmployee"): if r.json().get("isEmployee"):
self._report_action("ECONOMY_RESIGN", f"Resigned from employer!", **r.json()) self._report_action("ECONOMY_RESIGN", f"Resigned from employer!", kwargs=r.json())
self._post_economy_resign() self._post_economy_resign()
return True return True
return False return False
@ -2164,7 +2167,7 @@ class CitizenTasks(BaseCitizen):
extra = ret.json() extra = ret.json()
except: # noqa except: # noqa
extra = {} extra = {}
self._report_action("ECONOMY_TG_CONTRACT", f"Bought TG Contract", **extra) self._report_action("ECONOMY_TG_CONTRACT", f"Bought TG Contract", kwargs=extra)
return ret return ret
def find_new_job(self) -> Response: def find_new_job(self) -> Response:
@ -2179,12 +2182,12 @@ class CitizenTasks(BaseCitizen):
if (not limit or salary * 3 < limit) and salary > data["salary"]: if (not limit or salary * 3 < limit) and salary > data["salary"]:
data.update({"citizen": citizen_id, "salary": salary}) data.update({"citizen": citizen_id, "salary": salary})
self._report_action("ECONOMY_APPLY_FOR_JOB", f"I'm working now for {str(data['citizen'])}", **r.json()) self._report_action("ECONOMY_APPLY_FOR_JOB", f"I'm working now for {str(data['citizen'])}", kwargs=r.json())
return self._post_economy_job_market_apply(**data) return self._post_economy_job_market_apply(**data)
def apply_to_employer(self, employer_id: int, salary: float) -> bool: def apply_to_employer(self, employer_id: int, salary: float) -> bool:
data = dict(citizenId=employer_id, salary=salary) data = dict(citizenId=employer_id, salary=salary)
self._report_action("ECONOMY_APPLY_FOR_JOB", f"I'm working now for #{employer_id}", **data) self._report_action("ECONOMY_APPLY_FOR_JOB", f"I'm working now for #{employer_id}", kwargs=data)
r = self._post_economy_job_market_apply(employer_id, salary) r = self._post_economy_job_market_apply(employer_id, salary)
return bool(r.json().get('status')) return bool(r.json().get('status'))
@ -2438,7 +2441,7 @@ class Citizen(CitizenAnniversary, CitizenCompanies, CitizenEconomy, CitizenLeade
if response is None: if response is None:
return return
if response.get("status"): if response.get("status"):
self._report_action("WORK_AS_MANAGER", f"Worked as manager", **response) self._report_action("WORK_AS_MANAGER", f"Worked as manager", kwargs=response)
if self.config.auto_sell: if self.config.auto_sell:
for kind, data in response.get("result", {}).get("production", {}).items(): for kind, data in response.get("result", {}).get("production", {}).items():
if data and kind in self.config.auto_sell: if data and kind in self.config.auto_sell:
@ -2478,7 +2481,7 @@ class Citizen(CitizenAnniversary, CitizenCompanies, CitizenEconomy, CitizenLeade
self._wam(holding_id) self._wam(holding_id)
else: else:
msg = "I was not able to wam and or employ because:\n{}".format(response) msg = "I was not able to wam and or employ because:\n{}".format(response)
self._report_action("WORK_AS_MANAGER", f"Worked as manager failed: {msg}", **response) self._report_action("WORK_AS_MANAGER", f"Worked as manager failed: {msg}", kwargs=response)
self.write_log(msg) self.write_log(msg)
def work_as_manager(self) -> bool: def work_as_manager(self) -> bool:

View File

@ -3,16 +3,12 @@ import hashlib
import threading import threading
from collections import defaultdict, deque from collections import defaultdict, deque
from decimal import Decimal from decimal import Decimal
from typing import Any, Dict, Iterable, List, NamedTuple, Tuple, Union, Optional from typing import Any, Dict, List, NamedTuple, Tuple, Union, Optional
from requests import Response, Session, post from requests import Response, Session, post
from erepublik import utils from erepublik import utils
from erepublik.utils import json
try:
import simplejson as json
except ImportError:
import json
INDUSTRIES = {1: "Food", 2: "Weapons", 4: "House", 23: "Aircraft", INDUSTRIES = {1: "Food", 2: "Weapons", 4: "House", 23: "Aircraft",
7: "FRM q1", 8: "FRM q2", 9: "FRM q3", 10: "FRM q4", 11: "FRM q5", 7: "FRM q1", 8: "FRM q2", 9: "FRM q3", 10: "FRM q4", 11: "FRM q5",
@ -68,6 +64,12 @@ class Holding:
wrm += company.raw_usage wrm += company.raw_usage
return dict(frm=frm, wrm=wrm) return dict(frm=frm, wrm=wrm)
def __str__(self):
return f"Holding (#{self.id}) with {len(self.companies)} compan{'y' if len(self.companies) % 10 == 1 else 'ies'}"
def __repr__(self):
return str(self)
class Company: class Company:
holding: Holding holding: Holding
@ -90,12 +92,12 @@ class Company:
): ):
self.holding: Holding = holding self.holding: Holding = holding
self.id: int = _id self.id: int = _id
self.quality: int = quality self.industry: int = industry
self.quality: int = self._get_real_quality(quality)
self.is_raw: bool = is_raw self.is_raw: bool = is_raw
self.wam_enabled: bool = wam_enabled self.wam_enabled: bool = wam_enabled
self.can_wam: bool = can_wam self.can_wam: bool = can_wam
self.cannot_wam_reason: str = cannot_wam_reason self.cannot_wam_reason: str = cannot_wam_reason
self.industry: int = industry
self.already_worked: bool = already_worked self.already_worked: bool = already_worked
self.preset_works: int = preset_works self.preset_works: int = preset_works
@ -103,44 +105,63 @@ class Company:
if not self.is_raw: if not self.is_raw:
self.raw_usage = - self.products_made * raw_usage self.raw_usage = - self.products_made * raw_usage
def _get_real_quality(self, quality) -> int:
# 7: "FRM q1", 8: "FRM q2", 9: "FRM q3", 10: "FRM q4", 11: "FRM q5",
# 12: "WRM q1", 13: "WRM q2", 14: "WRM q3", 15: "WRM q4", 16: "WRM q5",
# 18: "HRM q1", 19: "HRM q2", 20: "HRM q3", 21: "HRM q4", 22: "HRM q5",
# 24: "ARM q1", 25: "ARM q2", 26: "ARM q3", 27: "ARM q4", 28: "ARM q5",
if 7 <= self.industry <= 11:
return self.industry % 6
elif 12 <= self.industry <= 16:
return self.industry % 11
elif 18 <= self.industry <= 22:
return self.industry % 17
elif 24 <= self.industry <= 28:
return self.industry % 23
else:
return quality
@property
def _internal_industry(self) -> int:
# 7: "FRM q1", 8: "FRM q2", 9: "FRM q3", 10: "FRM q4", 11: "FRM q5",
# 12: "WRM q1", 13: "WRM q2", 14: "WRM q3", 15: "WRM q4", 16: "WRM q5",
# 18: "HRM q1", 19: "HRM q2", 20: "HRM q3", 21: "HRM q4", 22: "HRM q5",
# 24: "ARM q1", 25: "ARM q2", 26: "ARM q3", 27: "ARM q4", 28: "ARM q5",
if 7 <= self.industry <= 11:
return 7
elif 12 <= self.industry <= 16:
return 12
elif 18 <= self.industry <= 22:
return 18
elif 24 <= self.industry <= 28:
return 24
else:
return self.industry
@property
def _sort_keys(self):
return not self.is_raw, self._internal_industry, -self.quality, self.id
def __hash__(self): def __hash__(self):
return hash((not self.is_raw, self.industry, -self.quality, self.id)) return hash(self._sort_keys)
def __lt__(self, other: "Company"): def __lt__(self, other: "Company"):
return ( return self._sort_keys < other._sort_keys
(not self.is_raw, self.industry, -self.quality, self.id) <
(not other.is_raw, other.industry, -other.quality, other.id)
)
def __le__(self, other: "Company"): def __le__(self, other: "Company"):
return ( return self._sort_keys <= other._sort_keys
(not self.is_raw, self.industry, -self.quality, self.id) <=
(not other.is_raw, other.industry, -other.quality, other.id)
)
def __gt__(self, other: "Company"): def __gt__(self, other: "Company"):
return ( return self._sort_keys > other._sort_keys
(not self.is_raw, self.industry, -self.quality, self.id) >
(not other.is_raw, other.industry, -other.quality, other.id)
)
def __ge__(self, other: "Company"): def __ge__(self, other: "Company"):
return ( return self._sort_keys >= other._sort_keys
(not self.is_raw, self.industry, -self.quality, self.id) >=
(not other.is_raw, other.industry, -other.quality, other.id)
)
def __eq__(self, other: "Company"): def __eq__(self, other: "Company"):
return ( return self._sort_keys == other._sort_keys
(not self.is_raw, self.industry, -self.quality, self.id) ==
(not other.is_raw, other.industry, -other.quality, other.id)
)
def __ne__(self, other: "Company"): def __ne__(self, other: "Company"):
return ( return self._sort_keys != other._sort_keys
(not self.is_raw, self.industry, -self.quality, self.id) !=
(not other.is_raw, other.industry, -other.quality, other.id)
)
def __str__(self): def __str__(self):
name = f"(#{self.id:>9d}) {INDUSTRIES[self.industry]}" name = f"(#{self.id:>9d}) {INDUSTRIES[self.industry]}"

View File

@ -323,8 +323,7 @@ def send_email(name: str, content: List[Any], player=None, local_vars: Mapping[A
if "state_thread" in local_vars: if "state_thread" in local_vars:
local_vars.pop('state_thread', None) local_vars.pop('state_thread', None)
from erepublik.classes import MyJSONEncoder from erepublik.classes import MyJSONEncoder
files.append(('file', ("local_vars.json", json.dumps(local_vars, indent=2, files.append(('file', ("local_vars.json", json.dumps(local_vars, cls=MyJSONEncoder, sort_keys=True), "application/json")))
cls=MyJSONEncoder, sort_keys=True), "application/json")))
if isinstance(player, Citizen): if isinstance(player, Citizen):
files.append(('file', ("instance.json", player.to_json(indent=True), "application/json"))) files.append(('file', ("instance.json", player.to_json(indent=True), "application/json")))
requests.post('https://pasts.72.lv', data=data, files=files) requests.post('https://pasts.72.lv', data=data, files=files)