Skip to content

Commit 79087b1

Browse files
committed
Lost the CSV changes, added the regional evolution data back in
1 parent bfe1e5b commit 79087b1

File tree

2 files changed

+340
-0
lines changed

2 files changed

+340
-0
lines changed

import_regional_evolutions.py

Lines changed: 302 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,302 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Import regional evolution data from CSV and update the pokemon_evolution.csv file
4+
5+
REGIONAL EVOLUTION SYSTEM WITH BUILD PROCESS INTEGRATION
6+
========================================================
7+
8+
This script implements the regional evolution system by updating the pokemon_evolution.csv file
9+
with regional metadata. The system works as follows:
10+
11+
1. CSV STRUCTURE:
12+
- The pokemon_evolution.csv file has been extended with two new columns:
13+
* region_id: References the Region ID where this evolution is restricted to
14+
* base_form_id: References the PokemonSpecies ID of the base form required for evolution
15+
16+
2. BUILD PROCESS INTEGRATION:
17+
- The data/v2/build.py file has been updated to handle these new columns
18+
- The csv_record_to_objects function for PokemonEvolution now includes:
19+
* region_id=int(info[20]) if info[20] != "" else None
20+
* base_form_id=int(info[21]) if info[21] != "" else None
21+
22+
3. DATA FLOW:
23+
- Regional evolution data is scraped from Bulbapedia and stored in regional_evolutions.csv
24+
- This script reads the regional data and updates the main pokemon_evolution.csv file
25+
- When the build process runs (make docker-build-db), it loads all data from CSV files
26+
- The regional evolution data becomes part of the database and persists through rebuilds
27+
28+
4. REGIONAL EVOLUTION EXAMPLES:
29+
- Galarian Meowth → Perrserker (region_id=8, base_form_id=52)
30+
- Hisuian Scyther → Kleavor (region_id=9, base_form_id=123)
31+
- Alolan Rattata → Raticate (region_id=7, base_form_id=19)
32+
33+
5. API INTEGRATION:
34+
- The PokemonEvolution model includes the new fields as ForeignKeys
35+
- Serializers automatically expose regional data through existing API endpoints
36+
- GraphQL metadata files have been updated to include the new fields
37+
38+
6. PERSISTENCE:
39+
- Unlike database-only updates, this approach ensures data survives Docker rebuilds
40+
- The CSV file is the source of truth for all evolution data
41+
- Regional evolution data is now permanently part of the build system
42+
43+
This approach follows the PokeAPI architecture where all data comes from CSV files
44+
and is loaded through the build process, ensuring consistency and persistence.
45+
"""
46+
import os
47+
import sys
48+
import csv
49+
import django
50+
51+
# Setup Django
52+
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.local")
53+
django.setup()
54+
55+
from pokemon_v2.models import (
56+
PokemonEvolution,
57+
PokemonSpecies,
58+
Region,
59+
Item,
60+
Location,
61+
EvolutionTrigger,
62+
Move,
63+
Type,
64+
)
65+
66+
67+
def ensure_csv_columns(csv_file):
68+
"""Ensure the CSV file has the required columns"""
69+
with open(csv_file, "r") as f:
70+
reader = csv.reader(f)
71+
header = next(reader)
72+
73+
# Check if we need to add the new columns
74+
if "region_id" not in header or "base_form_id" not in header:
75+
print("Adding missing columns to CSV...")
76+
77+
# Read all data
78+
with open(csv_file, "r") as f:
79+
reader = csv.reader(f)
80+
rows = list(reader)
81+
82+
# Update header
83+
if "region_id" not in header:
84+
header.append("region_id")
85+
if "base_form_id" not in header:
86+
header.append("base_form_id")
87+
88+
# Add empty columns to all data rows
89+
for i in range(1, len(rows)):
90+
while len(rows[i]) < len(header):
91+
rows[i].append("")
92+
93+
# Write back to file
94+
with open(csv_file, "w", newline="") as f:
95+
writer = csv.writer(f)
96+
writer.writerows(rows)
97+
98+
print("✅ Added missing columns to CSV")
99+
return True # Indicate that columns were added
100+
else:
101+
print("✅ CSV already has required columns")
102+
return False # Indicate that columns already existed
103+
104+
105+
def get_region_id(region_name):
106+
"""Get region ID by name from CSV"""
107+
if not region_name:
108+
return ""
109+
try:
110+
with open("data/v2/csv/regions.csv", "r") as f:
111+
reader = csv.DictReader(f)
112+
for row in reader:
113+
if row["identifier"] == region_name:
114+
return row["id"]
115+
print(f"⚠️ Region '{region_name}' not found in regions.csv")
116+
return ""
117+
except FileNotFoundError:
118+
print("⚠️ regions.csv not found")
119+
return ""
120+
121+
122+
def get_species_id(species_name):
123+
"""Get species ID by name from CSV"""
124+
if not species_name:
125+
return ""
126+
try:
127+
with open("data/v2/csv/pokemon_species.csv", "r") as f:
128+
reader = csv.DictReader(f)
129+
for row in reader:
130+
if row["identifier"] == species_name:
131+
return row["id"]
132+
print(f"⚠️ Species '{species_name}' not found in pokemon_species.csv")
133+
return ""
134+
except FileNotFoundError:
135+
print("⚠️ pokemon_species.csv not found")
136+
return ""
137+
138+
139+
def get_species_name_by_id(species_id):
140+
"""Get species name by ID from CSV"""
141+
if not species_id:
142+
return ""
143+
try:
144+
with open("data/v2/csv/pokemon_species.csv", "r") as f:
145+
reader = csv.DictReader(f)
146+
for row in reader:
147+
if row["id"] == species_id:
148+
return row["identifier"]
149+
return ""
150+
except FileNotFoundError:
151+
return ""
152+
153+
154+
def get_trigger_name_by_id(trigger_id):
155+
"""Get trigger name by ID from CSV"""
156+
if not trigger_id:
157+
return ""
158+
try:
159+
with open("data/v2/csv/evolution_triggers.csv", "r") as f:
160+
reader = csv.DictReader(f)
161+
for row in reader:
162+
if row["id"] == trigger_id:
163+
return row["identifier"]
164+
return ""
165+
except FileNotFoundError:
166+
return ""
167+
168+
169+
def get_evolution_id(evolved_species_name, trigger_name):
170+
"""Get evolution ID by evolved species and trigger"""
171+
try:
172+
evolved_species = PokemonSpecies.objects.get(name=evolved_species_name)
173+
trigger = EvolutionTrigger.objects.get(name=trigger_name)
174+
evolution = PokemonEvolution.objects.get(
175+
evolved_species=evolved_species, evolution_trigger=trigger
176+
)
177+
return evolution.id
178+
except (
179+
PokemonSpecies.DoesNotExist,
180+
EvolutionTrigger.DoesNotExist,
181+
PokemonEvolution.DoesNotExist,
182+
):
183+
print(
184+
f"⚠️ Evolution '{evolved_species_name}' with trigger '{trigger_name}' not found"
185+
)
186+
return None
187+
188+
189+
def update_evolution_csv(regional_csv_file, evolution_csv_file):
190+
"""Update the evolution CSV with regional data"""
191+
print(
192+
f"Updating {evolution_csv_file} with regional data from {regional_csv_file}..."
193+
)
194+
195+
# Read regional data
196+
regional_data = {}
197+
with open(regional_csv_file, "r") as f:
198+
reader = csv.DictReader(f)
199+
for row in reader:
200+
key = f"{row['evolves_to']}_{row['method']}"
201+
regional_data[key] = {
202+
"region": row["region"],
203+
"base_form_id": row["base_form_id"],
204+
}
205+
206+
# Read evolution CSV
207+
with open(evolution_csv_file, "r") as f:
208+
reader = csv.reader(f)
209+
rows = list(reader)
210+
211+
header = rows[0]
212+
213+
# Check if columns exist
214+
if "region_id" not in header:
215+
print("❌ region_id column not found in CSV")
216+
return
217+
if "base_form_id" not in header:
218+
print("❌ base_form_id column not found in CSV")
219+
return
220+
221+
region_col_idx = header.index("region_id")
222+
base_form_col_idx = header.index("base_form_id")
223+
224+
updated_count = 0
225+
226+
# Update each row
227+
for i in range(1, len(rows)):
228+
row = rows[i]
229+
230+
# Ensure row has enough columns
231+
if len(row) < len(header):
232+
# Add empty columns to match header length
233+
missing_columns = len(header) - len(row)
234+
for _ in range(missing_columns):
235+
row.append("")
236+
updated_count += 1
237+
if i <= 3: # Show first few rows
238+
print(f"Row {i}: {len(row)} columns -> {len(header)} columns")
239+
240+
# Get evolution details from CSV
241+
evolved_species_id = row[1] # evolved_species_id column
242+
trigger_id = row[2] # evolution_trigger_id column
243+
244+
# Look up species and trigger names from CSV files
245+
evolved_species_name = get_species_name_by_id(evolved_species_id)
246+
trigger_name = get_trigger_name_by_id(trigger_id)
247+
248+
if evolved_species_name and trigger_name:
249+
# Create key to match regional data
250+
key = f"{evolved_species_name}_{trigger_name}"
251+
252+
if key in regional_data:
253+
# Update with regional data
254+
region_data = regional_data[key]
255+
region_id = get_region_id(region_data["region"])
256+
base_form_id = get_species_id(region_data["base_form_id"])
257+
258+
row[region_col_idx] = region_id
259+
row[base_form_col_idx] = base_form_id
260+
print(f"✅ Updated {evolved_species_name} evolution with regional data")
261+
else:
262+
# Set empty values for the new columns
263+
row[region_col_idx] = ""
264+
row[base_form_col_idx] = ""
265+
266+
# Write updated CSV
267+
with open(evolution_csv_file, "w", newline="") as f:
268+
writer = csv.writer(f)
269+
writer.writerows(rows)
270+
271+
print(f"✅ Updated {updated_count} rows with correct column count")
272+
print(f"✅ CSV file updated: {evolution_csv_file}")
273+
274+
275+
def main():
276+
"""Main function"""
277+
regional_csv_file = "regional_evolutions.csv"
278+
evolution_csv_file = "data/v2/csv/pokemon_evolution.csv"
279+
280+
if not os.path.exists(regional_csv_file):
281+
print(f"❌ Regional CSV file '{regional_csv_file}' not found")
282+
return
283+
284+
if not os.path.exists(evolution_csv_file):
285+
print(f"❌ Evolution CSV file '{evolution_csv_file}' not found")
286+
return
287+
288+
# Ensure CSV has required columns
289+
columns_added = ensure_csv_columns(evolution_csv_file)
290+
291+
# Update evolution CSV with regional data
292+
update_evolution_csv(regional_csv_file, evolution_csv_file)
293+
294+
print("\n🎉 Import completed successfully!")
295+
print(
296+
"The pokemon_evolution.csv file has been updated with regional evolution data."
297+
)
298+
print("You can now rebuild the database to see the changes.")
299+
300+
301+
if __name__ == "__main__":
302+
main()

regional_evolutions.csv

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
pokemon,evolves_to,method,region,level,item,location,base_form_id
2+
meowth,perrserker,level-up,galar,28,,,meowth
3+
linoone,obstagoon,level-up,galar,35,,,linoone
4+
corsola,cursola,trade,galar,20,,,corsola
5+
yamask,runerigus,level-up,galar,,,dusty-bowl-arch,yamask
6+
slowpoke,slowbro,use-item,galar,,galarica-cuff,,slowpoke
7+
slowpoke,slowking,use-item,galar,,galarica-wreath,,slowpoke
8+
ponyta,rapidash,level-up,galar,40,,,ponyta
9+
farfetchd,sirfetchd,level-up,galar,50,,,farfetchd
10+
weezing,weezing,level-up,galar,35,,,weezing
11+
mr-mime,mr-rime,level-up,galar,42,,,mr-mime
12+
darumaka,darmanitan,level-up,galar,35,,,darumaka
13+
stunfisk,stunfisk,level-up,galar,40,,,stunfisk
14+
scyther,kleavor,use-item,hisui,,black-augurite,,scyther
15+
quilava,typhlosion,level-up,hisui,36,,,quilava
16+
dewott,samurott,level-up,hisui,36,,,dewott
17+
petilil,lilligant,use-item,hisui,,sun-stone,,petilil
18+
rufflet,braviary,level-up,hisui,54,,,rufflet
19+
goomy,sliggoo,level-up,hisui,40,,,goomy
20+
sliggoo,goodra,level-up,hisui,50,,,sliggoo
21+
voltorb,electrode,level-up,hisui,30,,,voltorb
22+
growlithe,arcanine,use-item,hisui,,fire-stone,,growlithe
23+
zorua,zoroark,level-up,hisui,30,,,zorua
24+
basculin,basculegion,level-up,hisui,34,,,basculin
25+
qwilfish,overqwil,level-up,hisui,28,,,qwilfish
26+
ursaring,ursaluna,use-item,hisui,,peat-block,,ursaring
27+
stantler,wyrdeer,level-up,hisui,31,,,stantler
28+
sneasel,sneasler,use-item,hisui,,razor-claw,,sneasel
29+
rattata,raticate,level-up,alola,20,,,rattata
30+
sandshrew,sandslash,use-item,alola,,ice-stone,,sandshrew
31+
vulpix,ninetales,use-item,alola,,ice-stone,,vulpix
32+
diglett,dugtrio,level-up,alola,26,,,diglett
33+
meowth,persian,level-up,alola,28,,,meowth
34+
geodude,graveler,level-up,alola,25,,,geodude
35+
graveler,golem,trade,alola,,,,,graveler
36+
grimer,muk,level-up,alola,38,,,grimer
37+
exeggutor,exeggutor,use-item,alola,,leaf-stone,,exeggutor
38+
marowak,marowak,level-up,alola,28,,,marowak

0 commit comments

Comments
 (0)