Begin making the Big Hack look like real software
This commit is contained in:
parent
0e3011c406
commit
5ff176e1e2
@ -7,6 +7,7 @@ name = "pogo-scaled-estimators"
|
||||
version = "1.0a1"
|
||||
dependencies = [
|
||||
"requests",
|
||||
"rich",
|
||||
]
|
||||
requires-python = ">=3.12"
|
||||
authors = [
|
||||
@ -99,3 +100,48 @@ ignore = [
|
||||
"ISC001", # single-line-implicit-string-concatenation
|
||||
"ISC002", # multi-line-implicit-string-concatenation
|
||||
]
|
||||
|
||||
[tool.pyright]
|
||||
include = ["src/glimmer", "tests"]
|
||||
exclude = ["**/__pycache__"]
|
||||
reportMissingImports = true
|
||||
reportMissingTypeStubs = false
|
||||
pythonVersion = "3.12"
|
||||
pythonPlatform = "Linux"
|
||||
typeCheckingMode = "standard"
|
||||
strictListInference = true
|
||||
strictDictionaryInference = true
|
||||
strictSetInference = true
|
||||
reportAssertAlwaysTrue = "error"
|
||||
reportInvalidStringEscapeSequence = "error"
|
||||
reportSelfClsParameterName = "error"
|
||||
reportConstantRedefinition = "error"
|
||||
reportDeprecated = "error"
|
||||
reportDuplicateImport = "error"
|
||||
reportIncompatibleMethodOverride = "error"
|
||||
reportIncompatibleVariableOverride = "error"
|
||||
reportInconsistentConstructor = "error"
|
||||
reportMatchNotExhaustive = "warning"
|
||||
reportOverlappingOverload = "error"
|
||||
reportMissingSuperCall = "error"
|
||||
reportPrivateUsage = "warning"
|
||||
reportTypeCommentUsage = "error"
|
||||
reportUnnecessaryCast = "error"
|
||||
reportUnnecessaryComparison = "error"
|
||||
reportUnnecessaryContains = "error"
|
||||
reportUnnecessaryIsInstance = "error"
|
||||
reportUnusedClass = "warning"
|
||||
reportUnusedImport = "warning"
|
||||
reportUnusedFunction = "warning"
|
||||
reportUnusedVariable = "warning"
|
||||
reportUntypedBaseClass = "error"
|
||||
reportUntypedClassDecorator = "error"
|
||||
reportUntypedFunctionDecorator = "error"
|
||||
reportUntypedNamedTuple = "error"
|
||||
reportCallInDefaultInitializer = "error"
|
||||
reportImplicitOverride = "error"
|
||||
reportPropertyTypeMismatch = "warning"
|
||||
reportShadowedImports = "warning"
|
||||
reportUninitializedInstanceVariable = "warning"
|
||||
reportUnnecessaryTypeIgnoreComment = "warning"
|
||||
reportUnusedCallResult = "warning"
|
||||
|
@ -12,20 +12,25 @@ import sqlite3
|
||||
import time
|
||||
import urllib.parse
|
||||
from pathlib import Path
|
||||
from typing import final
|
||||
|
||||
import requests
|
||||
from rich.progress import Progress, TaskID
|
||||
|
||||
from pogo_scaled_estimators.utilities import format_move_name, format_pokemon_name
|
||||
|
||||
WEAKNESS = 1.6
|
||||
DOUBLE_WEAKNESS = WEAKNESS * WEAKNESS
|
||||
|
||||
|
||||
@final
|
||||
class Calculator:
|
||||
def __init__(self, attacker_types):
|
||||
def __init__(self, attacker_types: list[str]) -> None:
|
||||
self.db = sqlite3.connect("ase.db")
|
||||
# db.set_trace_callback(print)
|
||||
|
||||
with contextlib.suppress(sqlite3.OperationalError):
|
||||
self.db.execute(
|
||||
_ = self.db.execute(
|
||||
"CREATE TABLE estimators(defender, raid_tier, attacker, level, quick_move, charged_move, estimator, party)"
|
||||
)
|
||||
|
||||
@ -36,17 +41,20 @@ class Calculator:
|
||||
|
||||
self.attacker_types = attacker_types
|
||||
|
||||
def _pokebattler_resource(self, name):
|
||||
self.progress = Progress()
|
||||
self._refresh_task: TaskID | None = None
|
||||
|
||||
def _pokebattler_resource(self, name: str) -> dict:
|
||||
p = Path(f"./{name}.json")
|
||||
if not p.exists():
|
||||
response = requests.get(f"https://fight.pokebattler.com/{name}")
|
||||
with p.open(mode="wb") as fp:
|
||||
fp.write(response.content)
|
||||
_ = fp.write(response.content)
|
||||
|
||||
with p.open() as fp:
|
||||
return json.load(fp)
|
||||
|
||||
def calculate(self, level=40, party=1):
|
||||
def calculate(self, level: int = 40, party: int = 1) -> None:
|
||||
raid_bosses = self._raid_bosses()
|
||||
charged_moves = [
|
||||
move["moveId"] for move in self.moves["move"] if "type" in move and move["type"] in self.attacker_types
|
||||
@ -80,7 +88,7 @@ class Calculator:
|
||||
""",
|
||||
(party, party, level),
|
||||
)
|
||||
for raid_tier, _defender, attacker, estimator, fast_move, charged_move in res.fetchall():
|
||||
for raid_tier, _, attacker, estimator, fast_move, charged_move in res.fetchall():
|
||||
if raid_tier == "RAID_LEVEL_MEGA_5":
|
||||
simplified_raid_tier = "RAID_LEVEL_MEGA"
|
||||
elif raid_tier == "RAID_LEVEL_ULTRA_BEAST":
|
||||
@ -100,9 +108,9 @@ class Calculator:
|
||||
+ 0.35 * sum(estimators["RAID_LEVEL_MEGA"]) / len(estimators["RAID_LEVEL_MEGA"])
|
||||
)
|
||||
fast_move, charged_move = movesets[attacker]
|
||||
print(f"{attacker},{ase},{fast_move},{charged_move}")
|
||||
print(f"{attacker},{level},{ase},{fast_move},{charged_move}")
|
||||
|
||||
def _raid_bosses(self):
|
||||
def _raid_bosses(self) -> dict:
|
||||
raid_tiers = []
|
||||
raid_bosses = {}
|
||||
|
||||
@ -140,7 +148,7 @@ class Calculator:
|
||||
|
||||
return raid_bosses
|
||||
|
||||
def _is_weak(self, attacker_type, defender_types):
|
||||
def _is_weak(self, attacker_type: str, defender_types: tuple[str, str]) -> bool:
|
||||
pokemon_types = list(self.resists.keys())
|
||||
defender_type_indices = (
|
||||
pokemon_types.index(defender_types[0]),
|
||||
@ -164,7 +172,7 @@ class Calculator:
|
||||
|
||||
return False
|
||||
|
||||
def load_estimators(self, tier, defender, level, party):
|
||||
def load_estimators(self, tier: str, defender: str, level: int, party: int) -> None:
|
||||
base_url = "https://fight.pokebattler.com"
|
||||
query_string = {
|
||||
"sort": "ESTIMATOR",
|
||||
@ -196,16 +204,12 @@ class Calculator:
|
||||
)
|
||||
estimator = res.fetchone()
|
||||
if estimator is not None:
|
||||
print(
|
||||
defender,
|
||||
attacker["pokemonId"],
|
||||
attacker_moves["move1"],
|
||||
attacker_moves["move2"],
|
||||
estimator[0],
|
||||
self.progress.console.log(
|
||||
f'{format_pokemon_name(attacker["pokemonId"])} ({format_move_name(attacker_moves["move1"])}/{format_move_name(attacker_moves["move2"])}): {estimator[0]:.2f} (cached)'
|
||||
)
|
||||
continue
|
||||
|
||||
self.db.execute(
|
||||
_ = self.db.execute(
|
||||
"INSERT INTO estimators(defender, raid_tier, attacker, level, quick_move, charged_move, estimator, party) VALUES(?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
(
|
||||
defender,
|
||||
@ -218,21 +222,24 @@ class Calculator:
|
||||
party,
|
||||
),
|
||||
)
|
||||
print(
|
||||
defender,
|
||||
attacker["pokemonId"],
|
||||
attacker_moves["move1"],
|
||||
attacker_moves["move2"],
|
||||
attacker_moves["result"]["estimator"],
|
||||
self.progress.console.log(
|
||||
f'{format_pokemon_name(attacker["pokemonId"])} ({format_move_name(attacker_moves["move1"])}/{format_move_name(attacker_moves["move2"])}): {attacker_moves["result"]["estimator"]:.2f}'
|
||||
)
|
||||
|
||||
if self._refresh_task is not None:
|
||||
self.progress.update(self._refresh_task, advance=1)
|
||||
self.db.commit()
|
||||
|
||||
def refresh(self, level=40, party=1):
|
||||
for tier, defenders in self._raid_bosses().items():
|
||||
for defender in defenders:
|
||||
try:
|
||||
self.load_estimators(tier, defender, level, party)
|
||||
except json.decoder.JSONDecodeError:
|
||||
time.sleep(30)
|
||||
self.load_estimators(tier, defender, level, party)
|
||||
time.sleep(30)
|
||||
def refresh(self, level: int = 40, party: int = 1) -> None:
|
||||
with self.progress:
|
||||
total_defenders = sum(len(defenders) for defenders in self._raid_bosses().values())
|
||||
self._refresh_task = self.progress.add_task("Working...", total=(total_defenders * 30))
|
||||
for tier, defenders in self._raid_bosses().items():
|
||||
for defender in defenders:
|
||||
self.progress.update(self._refresh_task, description=f"vs {format_pokemon_name(defender)}...")
|
||||
try:
|
||||
self.load_estimators(tier, defender, level, party)
|
||||
except json.decoder.JSONDecodeError:
|
||||
time.sleep(30)
|
||||
self.load_estimators(tier, defender, level, party)
|
||||
time.sleep(1)
|
||||
|
@ -12,10 +12,10 @@ import pogo_scaled_estimators.calculator
|
||||
|
||||
def main_cli():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("type", nargs="+", help="an attacker type")
|
||||
parser.add_argument("--level", type=int, default=40)
|
||||
parser.add_argument("--party", type=int, default=1)
|
||||
parser.add_argument("--refresh", action="store_true", default=False)
|
||||
_ = parser.add_argument("type", nargs="+", help="an attacker type")
|
||||
_ = parser.add_argument("--level", type=int, default=40)
|
||||
_ = parser.add_argument("--party", type=int, default=1)
|
||||
_ = parser.add_argument("--refresh", action="store_true", default=False)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
|
19
src/pogo_scaled_estimators/utilities.py
Normal file
19
src/pogo_scaled_estimators/utilities.py
Normal file
@ -0,0 +1,19 @@
|
||||
MINIMUM_SPECIAL_NAME_PARTS = 2
|
||||
|
||||
|
||||
def format_pokemon_name(name):
|
||||
parts = [part.capitalize() for part in name.split("_")]
|
||||
if parts[-1] == "Mega" or parts[-1] == "Primal":
|
||||
parts = [parts[-1]] + parts[:-1]
|
||||
if len(parts) > MINIMUM_SPECIAL_NAME_PARTS and parts[-2] == "Mega":
|
||||
parts = [parts[-2]] + parts[:-2] + [parts[-1]]
|
||||
if len(parts) > MINIMUM_SPECIAL_NAME_PARTS and parts[-2] == "Shadow":
|
||||
parts = [parts[-2]] + parts[:-2]
|
||||
return " ".join(parts)
|
||||
|
||||
|
||||
def format_move_name(name):
|
||||
parts = [part.capitalize() for part in name.split("_")]
|
||||
if parts[-1] == "Fast":
|
||||
parts = parts[:-1]
|
||||
return " ".join(parts)
|
Loading…
Reference in New Issue
Block a user