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"
|
version = "1.0a1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"requests",
|
"requests",
|
||||||
|
"rich",
|
||||||
]
|
]
|
||||||
requires-python = ">=3.12"
|
requires-python = ">=3.12"
|
||||||
authors = [
|
authors = [
|
||||||
@ -99,3 +100,48 @@ ignore = [
|
|||||||
"ISC001", # single-line-implicit-string-concatenation
|
"ISC001", # single-line-implicit-string-concatenation
|
||||||
"ISC002", # multi-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 time
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from typing import final
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
from rich.progress import Progress, TaskID
|
||||||
|
|
||||||
|
from pogo_scaled_estimators.utilities import format_move_name, format_pokemon_name
|
||||||
|
|
||||||
WEAKNESS = 1.6
|
WEAKNESS = 1.6
|
||||||
DOUBLE_WEAKNESS = WEAKNESS * WEAKNESS
|
DOUBLE_WEAKNESS = WEAKNESS * WEAKNESS
|
||||||
|
|
||||||
|
|
||||||
|
@final
|
||||||
class Calculator:
|
class Calculator:
|
||||||
def __init__(self, attacker_types):
|
def __init__(self, attacker_types: list[str]) -> None:
|
||||||
self.db = sqlite3.connect("ase.db")
|
self.db = sqlite3.connect("ase.db")
|
||||||
# db.set_trace_callback(print)
|
# db.set_trace_callback(print)
|
||||||
|
|
||||||
with contextlib.suppress(sqlite3.OperationalError):
|
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)"
|
"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
|
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")
|
p = Path(f"./{name}.json")
|
||||||
if not p.exists():
|
if not p.exists():
|
||||||
response = requests.get(f"https://fight.pokebattler.com/{name}")
|
response = requests.get(f"https://fight.pokebattler.com/{name}")
|
||||||
with p.open(mode="wb") as fp:
|
with p.open(mode="wb") as fp:
|
||||||
fp.write(response.content)
|
_ = fp.write(response.content)
|
||||||
|
|
||||||
with p.open() as fp:
|
with p.open() as fp:
|
||||||
return json.load(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()
|
raid_bosses = self._raid_bosses()
|
||||||
charged_moves = [
|
charged_moves = [
|
||||||
move["moveId"] for move in self.moves["move"] if "type" in move and move["type"] in self.attacker_types
|
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),
|
(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":
|
if raid_tier == "RAID_LEVEL_MEGA_5":
|
||||||
simplified_raid_tier = "RAID_LEVEL_MEGA"
|
simplified_raid_tier = "RAID_LEVEL_MEGA"
|
||||||
elif raid_tier == "RAID_LEVEL_ULTRA_BEAST":
|
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"])
|
+ 0.35 * sum(estimators["RAID_LEVEL_MEGA"]) / len(estimators["RAID_LEVEL_MEGA"])
|
||||||
)
|
)
|
||||||
fast_move, charged_move = movesets[attacker]
|
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_tiers = []
|
||||||
raid_bosses = {}
|
raid_bosses = {}
|
||||||
|
|
||||||
@ -140,7 +148,7 @@ class Calculator:
|
|||||||
|
|
||||||
return raid_bosses
|
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())
|
pokemon_types = list(self.resists.keys())
|
||||||
defender_type_indices = (
|
defender_type_indices = (
|
||||||
pokemon_types.index(defender_types[0]),
|
pokemon_types.index(defender_types[0]),
|
||||||
@ -164,7 +172,7 @@ class Calculator:
|
|||||||
|
|
||||||
return False
|
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"
|
base_url = "https://fight.pokebattler.com"
|
||||||
query_string = {
|
query_string = {
|
||||||
"sort": "ESTIMATOR",
|
"sort": "ESTIMATOR",
|
||||||
@ -196,16 +204,12 @@ class Calculator:
|
|||||||
)
|
)
|
||||||
estimator = res.fetchone()
|
estimator = res.fetchone()
|
||||||
if estimator is not None:
|
if estimator is not None:
|
||||||
print(
|
self.progress.console.log(
|
||||||
defender,
|
f'{format_pokemon_name(attacker["pokemonId"])} ({format_move_name(attacker_moves["move1"])}/{format_move_name(attacker_moves["move2"])}): {estimator[0]:.2f} (cached)'
|
||||||
attacker["pokemonId"],
|
|
||||||
attacker_moves["move1"],
|
|
||||||
attacker_moves["move2"],
|
|
||||||
estimator[0],
|
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
self.db.execute(
|
_ = self.db.execute(
|
||||||
"INSERT INTO estimators(defender, raid_tier, attacker, level, quick_move, charged_move, estimator, party) VALUES(?, ?, ?, ?, ?, ?, ?, ?)",
|
"INSERT INTO estimators(defender, raid_tier, attacker, level, quick_move, charged_move, estimator, party) VALUES(?, ?, ?, ?, ?, ?, ?, ?)",
|
||||||
(
|
(
|
||||||
defender,
|
defender,
|
||||||
@ -218,21 +222,24 @@ class Calculator:
|
|||||||
party,
|
party,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
print(
|
self.progress.console.log(
|
||||||
defender,
|
f'{format_pokemon_name(attacker["pokemonId"])} ({format_move_name(attacker_moves["move1"])}/{format_move_name(attacker_moves["move2"])}): {attacker_moves["result"]["estimator"]:.2f}'
|
||||||
attacker["pokemonId"],
|
|
||||||
attacker_moves["move1"],
|
|
||||||
attacker_moves["move2"],
|
|
||||||
attacker_moves["result"]["estimator"],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if self._refresh_task is not None:
|
||||||
|
self.progress.update(self._refresh_task, advance=1)
|
||||||
self.db.commit()
|
self.db.commit()
|
||||||
|
|
||||||
def refresh(self, level=40, party=1):
|
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 tier, defenders in self._raid_bosses().items():
|
||||||
for defender in defenders:
|
for defender in defenders:
|
||||||
|
self.progress.update(self._refresh_task, description=f"vs {format_pokemon_name(defender)}...")
|
||||||
try:
|
try:
|
||||||
self.load_estimators(tier, defender, level, party)
|
self.load_estimators(tier, defender, level, party)
|
||||||
except json.decoder.JSONDecodeError:
|
except json.decoder.JSONDecodeError:
|
||||||
time.sleep(30)
|
time.sleep(30)
|
||||||
self.load_estimators(tier, defender, level, party)
|
self.load_estimators(tier, defender, level, party)
|
||||||
time.sleep(30)
|
time.sleep(1)
|
||||||
|
@ -12,10 +12,10 @@ import pogo_scaled_estimators.calculator
|
|||||||
|
|
||||||
def main_cli():
|
def main_cli():
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument("type", nargs="+", help="an attacker type")
|
_ = parser.add_argument("type", nargs="+", help="an attacker type")
|
||||||
parser.add_argument("--level", type=int, default=40)
|
_ = parser.add_argument("--level", type=int, default=40)
|
||||||
parser.add_argument("--party", type=int, default=1)
|
_ = parser.add_argument("--party", type=int, default=1)
|
||||||
parser.add_argument("--refresh", action="store_true", default=False)
|
_ = parser.add_argument("--refresh", action="store_true", default=False)
|
||||||
|
|
||||||
args = parser.parse_args()
|
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