Skip to content

Commit 904f8b6

Browse files
committed
handle load of DataContainer from json properly in terms of cls.lab_level, load cls.village
1 parent 76ae7ff commit 904f8b6

File tree

1 file changed

+46
-16
lines changed

1 file changed

+46
-16
lines changed

coc/abc.py

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
SOFTWARE.
2323
"""
2424
import ujson
25-
25+
from pathlib import Path
2626
from typing import AsyncIterator, Any, Dict, Type, Optional, TYPE_CHECKING
2727

2828
from .enums import Resource
@@ -33,6 +33,8 @@
3333
if TYPE_CHECKING:
3434
from .players import Player
3535

36+
BUILDING_FILE_PATH = Path(__file__).parent.joinpath(Path("static/buildings.json"))
37+
3638

3739
class BaseClan:
3840
"""An ABC that implements some common operations on clans, regardless of type.
@@ -150,8 +152,8 @@ def share_link(self) -> str:
150152
class DataContainerMetaClass(type):
151153
def __repr__(cls):
152154
attrs = [
153-
("name", cls.name),
154-
("id", cls.id),
155+
("name", cls.name if "name" in cls.__dict__ else "Unknown"),
156+
("id", cls.id if "id" in cls.__dict__ else "Unknown"),
155157
]
156158
return "<%s %s>" % (cls.__name__, " ".join("%s=%r" % t for t in attrs),)
157159

@@ -187,8 +189,47 @@ def _load_json_meta(cls, troop_meta, id, name, lab_to_townhall):
187189
cls.ground_target = _get_maybe_first(troop_meta, "GroundTargets", default=True)
188190
cls.hitpoints = try_enum(UnitStat, troop_meta.get("Hitpoints"))
189191

192+
# get production building
193+
production_building = troop_meta.get("ProductionBuilding", [None])[0]
194+
if production_building == "Barrack":
195+
cls.is_elixir_troop = True
196+
elif production_building == "Dark Elixir Barrack":
197+
cls.is_dark_troop = True
198+
elif production_building == "SiegeWorkshop":
199+
cls.is_siege_machine = True
200+
elif production_building == "Spell Forge":
201+
cls.is_elixir_spell = True
202+
elif production_building == "Mini Spell Factory":
203+
cls.is_dark_spell = True
204+
205+
# load buildings
206+
with open(BUILDING_FILE_PATH) as fp:
207+
buildings = ujson.load(fp)
208+
209+
# without production_building, it is a hero or pet
210+
if not production_building:
211+
laboratory_levels = troop_meta.get("LaboratoryLevel")
212+
else:
213+
# it is a troop or spell
214+
prod_unit = buildings.get(production_building)
215+
min_prod_unit_level = troop_meta.get("BarrackLevel", [None, ])[0]
216+
# there are some special troops, which have no BarrackLevel attribute
217+
if not min_prod_unit_level:
218+
laboratory_levels = troop_meta.get("LaboratoryLevel")
219+
else:
220+
# get the min th level were we can unlock by the required level of the production building
221+
min_th_level = [th for i, th in enumerate(prod_unit["TownHallLevel"], start=1)
222+
if i == min_prod_unit_level]
223+
# map the min th level to a lab level
224+
[first_lab_level] = [lab_level for lab_level, th_level in lab_to_townhall.items()
225+
if th_level in min_th_level]
226+
# the first_lab_level is the lowest possible (there are some inconsistencies with siege machines)
227+
# To handle them properly, replacing all lab_level lower than first_lab_level with first_lab_level
228+
laboratory_levels = [x if x > first_lab_level else first_lab_level
229+
for x in troop_meta.get("LaboratoryLevel")]
230+
231+
cls.lab_level = try_enum(UnitStat, laboratory_levels)
190232
cls.housing_space = _get_maybe_first(troop_meta, "HousingSpace", default=0)
191-
cls.lab_level = try_enum(UnitStat, troop_meta.get("LaboratoryLevel"))
192233
cls.speed = try_enum(UnitStat, troop_meta.get("Speed"))
193234
cls.level = cls.dps and UnitStat(range(1, len(cls.dps) + 1))
194235

@@ -197,6 +238,7 @@ def _load_json_meta(cls, troop_meta, id, name, lab_to_townhall):
197238
cls.upgrade_resource = Resource(value=troop_meta["UpgradeResource"][0])
198239
cls.upgrade_time = try_enum(UnitStat, [TimeDelta(hours=hours) for hours in troop_meta.get("UpgradeTimeH", [])])
199240
cls._is_home_village = False if troop_meta.get("VillageType") else True
241+
cls.village = "home" if cls._is_home_village else "builderBase"
200242

201243
# spells and troops
202244
cls.training_cost = try_enum(UnitStat, troop_meta.get("TrainingCost"))
@@ -208,18 +250,6 @@ def _load_json_meta(cls, troop_meta, id, name, lab_to_townhall):
208250
cls.required_th_level = try_enum(UnitStat, troop_meta.get("RequiredTownHallLevel"))
209251
cls.regeneration_time = try_enum(UnitStat, [TimeDelta(minutes=value) for value in troop_meta.get("RegenerationTimeMinutes", [])])
210252

211-
production_building = troop_meta.get("ProductionBuilding", [None])[0]
212-
if production_building == "Barrack":
213-
cls.is_elixir_troop = True
214-
elif production_building == "Dark Elixir Barrack":
215-
cls.is_dark_troop = True
216-
elif production_building == "SiegeWorkshop":
217-
cls.is_siege_machine = True
218-
elif production_building == "Spell Forge":
219-
cls.is_elixir_spell = True
220-
elif production_building == "Mini Spell Factory":
221-
cls.is_dark_spell = True
222-
223253
cls.is_loaded = True
224254
return cls
225255

0 commit comments

Comments
 (0)