mirror of
https://github.com/veekun/pokedex.git
synced 2024-08-20 18:16:34 +00:00
Add moves to the yaml-to-db importer
This commit is contained in:
parent
956ba7a426
commit
698a211539
2 changed files with 160 additions and 10 deletions
|
@ -2517,7 +2517,9 @@ Move.contest_type = relationship(ContestType,
|
||||||
Move.damage_class = relationship(MoveDamageClass,
|
Move.damage_class = relationship(MoveDamageClass,
|
||||||
innerjoin=True,
|
innerjoin=True,
|
||||||
backref='moves')
|
backref='moves')
|
||||||
Move.flags = association_proxy('move_flags', 'flag')
|
Move.flags = relationship(MoveFlag,
|
||||||
|
secondary=MoveFlagMap.__table__,
|
||||||
|
backref='moves')
|
||||||
Move.flavor_text = relationship(MoveFlavorText,
|
Move.flavor_text = relationship(MoveFlavorText,
|
||||||
order_by=MoveFlavorText.version_group_id, backref='move')
|
order_by=MoveFlavorText.version_group_id, backref='move')
|
||||||
Move.generation = relationship(Generation,
|
Move.generation = relationship(Generation,
|
||||||
|
|
|
@ -2,6 +2,7 @@ import itertools
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from camel import Camel
|
from camel import Camel
|
||||||
|
from sqlalchemy import inspect
|
||||||
from sqlalchemy.orm import Load
|
from sqlalchemy.orm import Load
|
||||||
|
|
||||||
import pokedex.db
|
import pokedex.db
|
||||||
|
@ -30,10 +31,20 @@ for language in session.query(t.Language).all():
|
||||||
db_languages[language.identifier] = language
|
db_languages[language.identifier] = language
|
||||||
session.local_language_id = db_languages['en'].id
|
session.local_language_id = db_languages['en'].id
|
||||||
|
|
||||||
|
db_types = {row.identifier: row for row in session.query(t.Type)}
|
||||||
|
db_targets = {row.identifier: row for row in session.query(t.MoveTarget)}
|
||||||
|
db_damage_classes = {row.identifier: row for row in session.query(t.MoveDamageClass)}
|
||||||
|
db_move_categories = {row.identifier: row for row in session.query(t.MoveMetaCategory)}
|
||||||
|
db_move_ailments = {row.identifier: row for row in session.query(t.MoveMetaAilment)}
|
||||||
|
db_move_flags = {row.identifier: row for row in session.query(t.MoveFlag)}
|
||||||
|
|
||||||
|
# These are by id since move effects don't have identifiers atm
|
||||||
|
db_move_effects = {row.id: row for row in session.query(t.MoveEffect)}
|
||||||
|
|
||||||
# Insert some requisite new stuff if it doesn't already exist
|
# Insert some requisite new stuff if it doesn't already exist
|
||||||
db_sumo_generation = session.query(t.Generation).get(7)
|
db_sumo_generation = session.query(t.Generation).get(7)
|
||||||
if db_sumo_generation:
|
if db_sumo_generation:
|
||||||
db_sumo_version_group = session.query()
|
db_sumo_version_group = session.query(t.VersionGroup).filter_by(identifier='sun-moon').one()
|
||||||
else:
|
else:
|
||||||
# Distinguish simplified and traditional Chinese
|
# Distinguish simplified and traditional Chinese
|
||||||
db_languages['zh'].identifier = 'zh-Hant'
|
db_languages['zh'].identifier = 'zh-Hant'
|
||||||
|
@ -89,6 +100,34 @@ else:
|
||||||
session.flush()
|
session.flush()
|
||||||
|
|
||||||
|
|
||||||
|
def cheap_upsert(db_obj, db_class, new_only, **data):
|
||||||
|
if db_obj:
|
||||||
|
if 'identifier' in new_only and new_only['identifier'] != db_obj.identifier:
|
||||||
|
print(f"- identifier mismatch, yaml {new_only['identifier']!r} vs db {db_obj.identifier!r}")
|
||||||
|
for key, new_value in data.items():
|
||||||
|
old_value = getattr(db_obj, key)
|
||||||
|
if old_value != new_value:
|
||||||
|
print(f"- changing {key} from {old_value!r} to {new_value!r}")
|
||||||
|
setattr(db_obj, key, new_value)
|
||||||
|
else:
|
||||||
|
db_obj = db_class(
|
||||||
|
**new_only,
|
||||||
|
**data,
|
||||||
|
)
|
||||||
|
session.add(db_obj)
|
||||||
|
return db_obj
|
||||||
|
|
||||||
|
|
||||||
|
def update_names(sumo_obj, db_obj):
|
||||||
|
"""Update the database's names as necessary, and add any missing ones"""
|
||||||
|
for lang, name in sumo_obj.name.items():
|
||||||
|
old_name = db_obj.name_map.get(db_languages[lang])
|
||||||
|
if old_name != name:
|
||||||
|
if old_name:
|
||||||
|
print(f"- NOTE: changing {old_name!r} to {name!r} in {lang}")
|
||||||
|
db_obj.name_map[db_languages[lang]] = name
|
||||||
|
|
||||||
|
|
||||||
# Abilities
|
# Abilities
|
||||||
print()
|
print()
|
||||||
print("--- ABILITIES ---")
|
print("--- ABILITIES ---")
|
||||||
|
@ -101,18 +140,11 @@ for (sumo_identifier, sumo_ability), db_ability in itertools.zip_longest(
|
||||||
.filter_by(is_main_series=True)
|
.filter_by(is_main_series=True)
|
||||||
.order_by(t.Ability.id)
|
.order_by(t.Ability.id)
|
||||||
.options(Load(t.Ability).joinedload('names'))
|
.options(Load(t.Ability).joinedload('names'))
|
||||||
.all()
|
|
||||||
):
|
):
|
||||||
print(sumo_identifier)
|
print(sumo_identifier)
|
||||||
if db_ability:
|
if db_ability:
|
||||||
assert sumo_identifier == db_ability.identifier
|
assert sumo_identifier == db_ability.identifier
|
||||||
# Update names and insert new ones
|
update_names(sumo_ability, db_ability)
|
||||||
for lang, name in sumo_ability.name.items():
|
|
||||||
old_name = db_ability.name_map.get(db_languages[lang])
|
|
||||||
if old_name != name:
|
|
||||||
if old_name:
|
|
||||||
print("- hmm! changing", old_name, "to", name, "in", lang)
|
|
||||||
db_ability.name_map[db_languages[lang]] = name
|
|
||||||
else:
|
else:
|
||||||
db_ability = t.Ability(
|
db_ability = t.Ability(
|
||||||
identifier=sumo_identifier,
|
identifier=sumo_identifier,
|
||||||
|
@ -124,6 +156,8 @@ for (sumo_identifier, sumo_ability), db_ability in itertools.zip_longest(
|
||||||
session.add(db_ability)
|
session.add(db_ability)
|
||||||
|
|
||||||
# Flavor text is per-version (group) and thus always new
|
# Flavor text is per-version (group) and thus always new
|
||||||
|
# FIXME uhh no it isn't, not if i've alreayd run this script once lol
|
||||||
|
"""
|
||||||
for lang, flavor_text in sumo_ability.flavor_text.items():
|
for lang, flavor_text in sumo_ability.flavor_text.items():
|
||||||
session.add(t.AbilityFlavorText(
|
session.add(t.AbilityFlavorText(
|
||||||
ability=db_ability,
|
ability=db_ability,
|
||||||
|
@ -131,6 +165,120 @@ for (sumo_identifier, sumo_ability), db_ability in itertools.zip_longest(
|
||||||
language=db_languages[lang],
|
language=db_languages[lang],
|
||||||
flavor_text=flavor_text,
|
flavor_text=flavor_text,
|
||||||
))
|
))
|
||||||
|
"""
|
||||||
|
session.flush()
|
||||||
|
|
||||||
|
|
||||||
|
print()
|
||||||
|
print("--- MOVES ---")
|
||||||
|
with (out / 'moves.yaml').open(encoding='utf8') as f:
|
||||||
|
moves = camel.load(f.read())
|
||||||
|
|
||||||
|
for (sumo_identifier, sumo_move), db_move in itertools.zip_longest(
|
||||||
|
moves.items(),
|
||||||
|
session.query(t.Move)
|
||||||
|
.filter(t.Move.id < 10000)
|
||||||
|
.order_by(t.Move.id)
|
||||||
|
.options(
|
||||||
|
Load(t.Move).joinedload('names'),
|
||||||
|
Load(t.Move).joinedload('meta'),
|
||||||
|
Load(t.Move).subqueryload('flags'),
|
||||||
|
)
|
||||||
|
):
|
||||||
|
print(sumo_identifier)
|
||||||
|
|
||||||
|
# Insert the move effect first, if necessary
|
||||||
|
effect_id = sumo_move.effect + 1
|
||||||
|
if effect_id not in db_move_effects:
|
||||||
|
effect = t.MoveEffect(id=effect_id)
|
||||||
|
effect.short_effect_map[db_languages['en']] = f"XXX new effect for {sumo_identifier}"
|
||||||
|
effect.effect_map[db_languages['en']] = f"XXX new effect for {sumo_identifier}"
|
||||||
|
session.add(effect)
|
||||||
|
db_move_effects[effect_id] = effect
|
||||||
|
|
||||||
|
db_move = cheap_upsert(
|
||||||
|
db_move,
|
||||||
|
t.Move,
|
||||||
|
dict(identifier=sumo_identifier, generation_id=7),
|
||||||
|
type=db_types[sumo_move.type.rpartition('.')[2]],
|
||||||
|
power=None if sumo_move.power in (0, 1) else sumo_move.power,
|
||||||
|
pp=sumo_move.pp,
|
||||||
|
accuracy=None if sumo_move.accuracy == 101 else sumo_move.accuracy,
|
||||||
|
priority=sumo_move.priority,
|
||||||
|
target=db_targets[sumo_move.range.rpartition('.')[2]],
|
||||||
|
damage_class=db_damage_classes[sumo_move.damage_class.rpartition('.')[2]],
|
||||||
|
effect_id=effect_id,
|
||||||
|
effect_chance=sumo_move.effect_chance,
|
||||||
|
)
|
||||||
|
# Check for any changed fields that can go in a changelog
|
||||||
|
# TODO unfortunately, target is not in the changelog
|
||||||
|
state = inspect(db_move)
|
||||||
|
if state.persistent:
|
||||||
|
loggable_changes = {}
|
||||||
|
for field in ('type_id', 'type', 'power', 'pp', 'accuracy', 'effect_id', 'effect_chance'):
|
||||||
|
history = getattr(state.attrs, field).history
|
||||||
|
if history.has_changes():
|
||||||
|
old, = history.deleted
|
||||||
|
if old is not None:
|
||||||
|
loggable_changes[field] = old
|
||||||
|
if loggable_changes:
|
||||||
|
session.add(t.MoveChangelog(
|
||||||
|
move_id=db_move.id,
|
||||||
|
changed_in_version_group_id=db_sumo_version_group.id,
|
||||||
|
**loggable_changes))
|
||||||
|
|
||||||
|
# Names
|
||||||
|
update_names(sumo_move, db_move)
|
||||||
|
|
||||||
|
# Move flags
|
||||||
|
old_flag_set = frozenset(db_move.flags)
|
||||||
|
new_flag_set = frozenset(db_move_flags[flag.rpartition('.')[2]] for flag in sumo_move.flags)
|
||||||
|
for added_flag in new_flag_set - old_flag_set:
|
||||||
|
print(f"- NOTE: adding flag {added_flag.identifier}")
|
||||||
|
db_move.flags.append(added_flag)
|
||||||
|
for removed_flag in old_flag_set - new_flag_set:
|
||||||
|
# These aren't real flags (in the sense of being a rippable part of the
|
||||||
|
# move struct) and I'm not entirely sure why they're in this table
|
||||||
|
if removed_flag.identifier in ('powder', 'bite', 'pulse', 'ballistics', 'mental'):
|
||||||
|
continue
|
||||||
|
print(f"- NOTE: removing flag {removed_flag.identifier}")
|
||||||
|
db_move.flags.remove(removed_flag)
|
||||||
|
|
||||||
|
# Move metadata
|
||||||
|
cheap_upsert(
|
||||||
|
db_move.meta,
|
||||||
|
t.MoveMeta,
|
||||||
|
# FIXME populate stat_chance? but... it's bogus.
|
||||||
|
dict(move=db_move, stat_chance=0),
|
||||||
|
category=db_move_categories[sumo_move.category.rpartition('.')[2]],
|
||||||
|
ailment=db_move_ailments[sumo_move.ailment.rpartition('.')[2]],
|
||||||
|
|
||||||
|
# TODO these should probably be null (or omitted) in the yaml instead of zero
|
||||||
|
min_hits=sumo_move.min_hits or None,
|
||||||
|
max_hits=sumo_move.max_hits or None,
|
||||||
|
min_turns=sumo_move.min_turns or None,
|
||||||
|
max_turns=sumo_move.max_turns or None,
|
||||||
|
|
||||||
|
drain=sumo_move.drain,
|
||||||
|
healing=sumo_move.healing,
|
||||||
|
crit_rate=sumo_move.crit_rate,
|
||||||
|
ailment_chance=sumo_move.ailment_chance,
|
||||||
|
flinch_chance=sumo_move.flinch_chance,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Flavor text is per-version (group) and thus always new
|
||||||
|
# FIXME uhh no it isn't, not if i've already run this script once lol
|
||||||
|
"""
|
||||||
|
for lang, flavor_text in sumo_move.flavor_text.items():
|
||||||
|
session.add(t.MoveFlavorText(
|
||||||
|
move=db_move,
|
||||||
|
version_group=db_sumo_version_group,
|
||||||
|
language=db_languages[lang],
|
||||||
|
flavor_text=flavor_text,
|
||||||
|
))
|
||||||
|
"""
|
||||||
|
session.flush()
|
||||||
|
|
||||||
|
|
||||||
session.commit()
|
session.commit()
|
||||||
print()
|
print()
|
||||||
|
|
Loading…
Reference in a new issue