Browse Source

- Add in new plan to the site

master
Dan 1 year ago
parent
commit
990f987fa5
  1. 19
      DBEditor/DBEditor.py
  2. 12
      DBEditor/db_controller.py
  3. 135
      DBEditor/plan2.py
  4. 7
      DBEditor/pokemon_db_ui.py
  5. 13
      Site/OriginDex.py
  6. 271
      Site/templates/index.html
  7. 10095
      efficiency_plan.json
  8. BIN
      pokemon_forms.db
  9. 11
      shiftable_forms.json

19
DBEditor/DBEditor.py

@ -96,6 +96,7 @@ class DBEditor(QMainWindow):
event_system.add_listener('gather_encounter_info', self.gather_encounter_info)
event_system.add_listener('reinitialize_database', self.reinitialize_database)
event_system.add_listener('gather_marks_info', self.gather_marks_info)
event_system.add_listener('load_shiftable_forms', self.load_shiftable_forms)
self.conn = sqlite3.connect(':memory:', check_same_thread=False) # Use in-memory database for runtime
self.cursor = self.conn.cursor()
@ -607,6 +608,24 @@ class DBEditor(QMainWindow):
self.logger.info(f"Mark for {form_info[0]} {form_info[1]} is {mark_details[0]} - {mark_details[1]}")
event_system.emit_sync('assign_mark_to_form', (pfic, mark_id))
continue;
def load_shiftable_forms(self, data):
try:
with open('shiftable_forms.json', 'r') as f:
shiftable_forms = json.load(f)
self.logger.info("Starting to load shiftable forms...")
for form in shiftable_forms:
event_system.emit_sync('assign_shiftable_form', (form['from_pfic'], form['to_pfic']))
self.logger.info(f"Successfully loaded {len(shiftable_forms)} shiftable form relationships")
except FileNotFoundError:
self.logger.error("shiftable_forms.json file not found")
except json.JSONDecodeError:
self.logger.error("Error parsing shiftable_forms.json - invalid JSON format")
except Exception as e:
self.logger.error(f"Error loading shiftable forms: {str(e)}")

12
DBEditor/db_controller.py

@ -57,6 +57,7 @@ class DBController:
event_system.add_listener('get_pokemon_form_by_pfic', self.get_pokemon_form_by_pfic)
event_system.add_listener('find_default_form', self.find_default_form)
event_system.add_listener('get_shiftable_forms', self.get_shiftable_forms)
event_system.add_listener('assign_shiftable_form', self.assign_shiftable_form)
def init_database(self):
disk_conn = sqlite3.connect('pokemon_forms.db')
@ -355,7 +356,8 @@ class DBController:
from_pfic TEXT,
to_pfic TEXT,
FOREIGN KEY (from_pfic) REFERENCES pokemon_forms (PFIC),
FOREIGN KEY (to_pfic) REFERENCES pokemon_forms (PFIC)
FOREIGN KEY (to_pfic) REFERENCES pokemon_forms (PFIC),
UNIQUE (from_pfic, to_pfic)
)
''')
@ -606,6 +608,14 @@ class DBController:
pfic = data
self.cursor.execute('SELECT * FROM shiftable_forms WHERE from_pfic = ?', (pfic,))
return self.cursor.fetchall()
def assign_shiftable_form(self, data):
from_pfic, to_pfic = data
self.cursor.execute('''
INSERT OR IGNORE INTO shiftable_forms (from_pfic, to_pfic)
VALUES (?, ?)
''', (from_pfic, to_pfic))
self.conn.commit()
def get_connection(self):
return self.connection_pool.get()

135
DBEditor/plan2.py

@ -52,7 +52,8 @@ class EfficiencyOriginDexPlanner:
for group in generation_groups:
group_plan = self.plan_for_group(group, pokemon_by_gen, game_by_gen, encounter_data, evolution_map, caught_pokemon)
plan.extend(group_plan)
if group_plan:
plan.extend(group_plan)
return plan
@ -145,24 +146,39 @@ class EfficiencyOriginDexPlanner:
for game in selected_games:
game_plan = self.plan_for_game(game, needed_pokemon, encounter_data, evolution_map, caught_pokemon, set(generations), new_evolutions)
if game_plan:
group_plan.extend(game_plan)
# Update game_pokemon to remove exclusive encounters that weren't used
exclusive_groups = self.get_exclusive_groups(game['id'])
used_exclusive_groups = set()
for step in game_plan:
if step.startswith(" Catch:"):
pfic = step.split(":")[1].strip().split(" ")[0]
# Update caught_pokemon and game_pokemon based on the new JSON structure
for plan_entry in game_plan:
for pokemon in plan_entry["pokemon"]:
pfic = pokemon["pfic"]
caught_pokemon.add(pfic)
# Handle evolutions
for evolution in pokemon["evolve_to"]:
caught_pokemon.add(evolution["pfic"])
# Handle breeding
for breeding in pokemon["breed_for"]:
caught_pokemon.add(breeding["pfic"])
# Update game_pokemon to remove exclusive encounters that weren't used
exclusive_groups = self.get_exclusive_groups(game['id'])
used_exclusive_groups = set()
# Track used exclusive groups based on the new structure
for pokemon in plan_entry["pokemon"]:
pfic = pokemon["pfic"]
for group_id, group_encounters in exclusive_groups.items():
if any(ge['pfic'] == pfic for ge in group_encounters):
used_exclusive_groups.add(group_id)
break
for group_id, group_encounters in exclusive_groups.items():
if group_id not in used_exclusive_groups:
for ge in group_encounters:
if ge['pfic'] in game_pokemon[game['id']]:
game_pokemon[game['id']].remove(ge['pfic'])
# Remove unused exclusive encounters
for group_id, group_encounters in exclusive_groups.items():
if group_id not in used_exclusive_groups:
for ge in group_encounters:
if ge['pfic'] in game_pokemon[game['id']]:
game_pokemon[game['id']].remove(ge['pfic'])
group_plan.extend(game_plan)
if not group_plan:
print("Warning: No games were selected or no Pokémon were planned to be caught.")
@ -170,7 +186,10 @@ class EfficiencyOriginDexPlanner:
return group_plan
def plan_for_game(self, game, needed_pokemon, encounter_data, evolution_map, caught_pokemon, target_generations, new_evolutions):
game_plan = []
game_plan = {
"game_name": game['name'],
"pokemon": []
}
to_catch = defaultdict(int)
to_evolve = defaultdict(list)
to_breed = defaultdict(list)
@ -266,23 +285,55 @@ class EfficiencyOriginDexPlanner:
del to_breed[group_encounter['pfic']]
if to_catch or to_evolve or to_breed:
game_plan.append(f"Play {game['name']}:")
if to_catch:
game_plan.append(" Catch:")
for pfic, count in to_catch.items():
game_plan.append(f" - {self.get_pokemon_name(pfic)}: {count} time(s)")
if to_evolve:
game_plan.append(" Evolve:")
for from_pfic, to_pfics in to_evolve.items():
for to_pfic in to_pfics:
game_plan.append(f" - {self.get_pokemon_name(from_pfic)} into {self.get_pokemon_name(to_pfic)}")
if to_breed:
game_plan.append(" Breed:")
for parent_pfic, baby_pfics in to_breed.items():
for baby_pfic in baby_pfics:
game_plan.append(f" - {self.get_pokemon_name(parent_pfic)} to get {self.get_pokemon_name(baby_pfic)}")
return game_plan
for pfic, count in to_catch.items():
pokemon_entry = {
"pfic": pfic,
"name": self.get_pokemon_name(pfic).split(" (")[0],
"form_name": self.get_form_name(pfic),
"catch_count": count,
"evolve_to": [],
"breed_for": []
}
# Add evolution information as flat structure
if pfic in to_evolve:
processed_evolutions = set()
evolution_queue = [(pfic, to_pfic, 1) for to_pfic in to_evolve[pfic]]
while evolution_queue:
from_pfic, to_pfic, count = evolution_queue.pop(0)
if (from_pfic, to_pfic) not in processed_evolutions:
processed_evolutions.add((from_pfic, to_pfic))
evolution = {
"pfic": to_pfic,
"name": self.get_pokemon_name(to_pfic).split(" (")[0],
"form_name": self.get_form_name(to_pfic),
"count": count
}
pokemon_entry["evolve_to"].append(evolution)
# Add next evolution stage to queue if it exists
if to_pfic in evolution_map:
for next_pfic in evolution_map[to_pfic]:
if next_pfic in to_evolve[to_pfic]:
evolution_queue.append((to_pfic, next_pfic, count))
# Add breeding information
if pfic in to_breed:
for baby_pfic in to_breed[pfic]:
breeding = {
"pfic": baby_pfic,
"name": self.get_pokemon_name(baby_pfic).split(" (")[0],
"form_name": self.get_form_name(baby_pfic),
"count": 1
}
pokemon_entry["breed_for"].append(breeding)
game_plan["pokemon"].append(pokemon_entry)
return [game_plan] if game_plan["pokemon"] else []
def plan_evolutions(self, evolution_chains, evolution_map, caught_pokemon):
chains, visit_counts = self.get_evolution_chains(evolution_chains[0][0], evolution_map)
@ -343,17 +394,19 @@ class EfficiencyOriginDexPlanner:
return f"{result['name']} ({result['form_name']})"
return result['name']
def display_plan(self, generation_groups, output_file='efficiency_plan.txt'):
def get_form_name(self, pfic):
cursor = self.conn.cursor()
cursor.execute("SELECT form_name FROM pokemon_forms WHERE PFIC = ?", (pfic,))
result = cursor.fetchone()
return result['form_name'] if result and result['form_name'] else ""
def display_plan(self, generation_groups, output_file='efficiency_plan.json'):
plan = self.generate_efficient_plan(generation_groups)
# Print to console
#for step in plan:
# print(step)
# Write to file
# Write to JSON file
import json
with open(output_file, 'w', encoding='utf-8') as f:
for step in plan:
f.write(f"{step}\n")
json.dump(plan, f, indent=4, ensure_ascii=False)
print(f"\nPlan has been written to {os.path.abspath(output_file)}")

7
DBEditor/pokemon_db_ui.py

@ -311,6 +311,10 @@ class PokemonUI(QWidget): # Change from QMainWindow to QWidget
gather_marks_btn.clicked.connect(self.gather_marks_info)
db_tab_layout.addWidget(gather_marks_btn)
load_shiftable_forms_btn = QPushButton("Load Shiftable Forms")
load_shiftable_forms_btn.clicked.connect(self.load_shiftable_forms)
db_tab_layout.addWidget(load_shiftable_forms_btn)
# Add QTextEdit for progress reporting
self.progress_text = QTextEdit()
self.progress_text.setReadOnly(True)
@ -926,3 +930,6 @@ class PokemonUI(QWidget): # Change from QMainWindow to QWidget
def gather_marks_info(self):
event_system.emit_sync('gather_marks_info')
def load_shiftable_forms(self):
event_system.emit_sync('load_shiftable_forms')

13
Site/OriginDex.py

@ -2,6 +2,7 @@ import sqlite3
from flask import Flask, render_template, jsonify
from collections import defaultdict
import os
import json
app = Flask(__name__)
@ -108,7 +109,17 @@ def load_pokemon_data():
@app.route('/')
def index():
pokemon_list = load_pokemon_data()
return render_template('index.html', grouped_pokemon=pokemon_list)
# Load the efficiency plan
try:
with open('efficiency_plan.json', 'r', encoding='utf-8') as f:
efficiency_plan = json.load(f)
except FileNotFoundError:
efficiency_plan = []
return render_template('index.html',
grouped_pokemon=pokemon_list,
efficiency_plan=efficiency_plan)
@app.route('/pokemon/<string:pfic>')
def pokemon_details(pfic):

271
Site/templates/index.html

@ -56,7 +56,7 @@
justify-content: space-between;
cursor: pointer;
/*width: 120px;*/ /* Fixed width */
height: 169.4px; /* Fixed height */
height: 180px; /* Fixed height */
}
.pokemon-cell.empty {
background-color: #e0e0e0;
@ -79,11 +79,11 @@
background-color: #f9f9f9; /* Light gray background for placeholder */
}
.pokemon-form {
min-height: 2.4em;
line-height: 1.2em;
font-style: italic;
font-size: 0.7em;
margin-top: 5px;
height: 1.4em; /* Allows for 1 line of text */
line-height: 1.4em; /* Vertically centers the text or dashes */
}
.pokemon-number {
color: #777;
@ -194,47 +194,219 @@
.toggle-icon {
float: right;
}
.tabs {
display: flex;
justify-content: center;
margin-bottom: 20px;
gap: 10px;
}
.tab-button {
padding: 10px 20px;
border: none;
background-color: #f0f0f0;
cursor: pointer;
border-radius: 5px;
font-size: 16px;
}
.tab-button.active {
background-color: #4CAF50;
color: white;
}
.tab-content {
display: none;
}
.tab-content.active {
display: block;
}
.efficiency-plan {
background-color: white;
border: 2px solid #ccc;
border-radius: 10px;
margin: 0 10px 30px;
padding: 20px;
position: relative;
width: calc(100% - 20px);
min-width: 1050px;
box-sizing: border-box;
}
.games-accordion {
border: 1px solid #ddd;
border-radius: 5px;
overflow: hidden;
}
.game-section {
border-bottom: 1px solid #ddd;
}
.game-section:last-child {
border-bottom: none;
}
.game-title {
background-color: #f5f5f5;
padding: 15px 20px;
font-weight: bold;
cursor: pointer;
display: flex;
justify-content: space-between;
align-items: center;
transition: background-color 0.3s ease;
}
.game-title:hover {
background-color: #e9e9e9;
}
.game-title.active {
background-color: #e0e0e0;
}
.game-content {
display: none;
padding: 20px;
background-color: white;
}
.game-content.show {
display: block;
}
.pokemon-entry {
margin: 15px 0;
padding: 15px;
background-color: #f9f9f9;
border-radius: 5px;
border: 1px solid #eee;
}
.pokemon-entry h3 {
margin-top: 0;
color: #333;
}
.evolution-list, .breeding-list {
margin: 10px 0;
padding: 10px;
background-color: #fff;
border-radius: 3px;
border: 1px solid #eee;
}
.evolution-list h4, .breeding-list h4 {
margin-top: 0;
color: #666;
}
.evolution-item, .breeding-item {
margin: 5px 0;
padding: 8px 12px;
background-color: #f5f5f5;
border-radius: 3px;
font-size: 0.9em;
}
</style>
</head>
<body>
<div id="main-content">
<h1 style="width: 100%; text-align: center;">OriginDex</h1>
{% for group in grouped_pokemon %}
<div class="pokemon-box">
<div class="box-title">Box {{ '%03d' | format(loop.index) }}</div>
<div class="pokemon-grid">
{% for pokemon in group %}
{% if pokemon %}
<div class="pokemon-cell" onclick="showDetails('{{ pokemon.ID }}', '{{ pokemon.Form }}', '{{ pokemon.pfic }}', event)" data-dex-number="{{ pokemon.ID }}">
<div class="pokemon-name">{{ pokemon.Name }}</div>
<img data-src="{{ url_for('static', filename=pokemon.Image) }}" alt="{{ pokemon.Name }} {{ pokemon.Form }}" class="pokemon-image lazy-load" src="{{ url_for('static', filename='images/placeholder.png') }}">
<div class="pokemon-form">
{% if pokemon.Form != 'Default' %}
{{ pokemon.Form }}
{% else %}
-----
{% endif %}
</div>
<div class="pokemon-info">
<div class="pokeball-container">
<img src="{{ url_for('static', filename='images/pokeball_color.png') }}" alt="Pokeball" class="pokeball-icon grayscale" onclick="togglePokeball(event, this)">
<div class="tabs">
<button class="tab-button active" onclick="switchTab('storage')">Storage</button>
<button class="tab-button" onclick="switchTab('efficiency')">Efficiency Plan</button>
</div>
<div id="storage-tab" class="tab-content active">
{% for group in grouped_pokemon %}
<div class="pokemon-box">
<div class="box-title">Box {{ '%03d' | format(loop.index) }}</div>
<div class="pokemon-grid">
{% for pokemon in group %}
{% if pokemon %}
<div class="pokemon-cell" onclick="showDetails('{{ pokemon.ID }}', '{{ pokemon.Form }}', '{{ pokemon.pfic }}', event)" data-dex-number="{{ pokemon.ID }}">
<div class="pokemon-name">{{ pokemon.Name }}</div>
<img data-src="{{ url_for('static', filename=pokemon.Image) }}" alt="{{ pokemon.Name }} {{ pokemon.Form }}" class="pokemon-image lazy-load" src="{{ url_for('static', filename='images/placeholder.png') }}">
<div class="pokemon-form">
{% if pokemon.Form != 'Default' %}
{{ pokemon.Form }}
{% else %}
-----
{% endif %}
</div>
<div class="pokemon-number">#{{ '%04d'|format(pokemon.ID) }}</div>
{% if pokemon.MarkIcon %}
<div class="origin-mark-container">
<img src="{{ url_for('static', filename=pokemon.MarkIcon) }}" alt="Origin Mark" class="origin-mark" title="{{ pokemon.EarliestGame }}">
<div class="pokemon-info">
<div class="pokeball-container">
<img src="{{ url_for('static', filename='images/pokeball_color.png') }}" alt="Pokeball" class="pokeball-icon grayscale" onclick="togglePokeball(event, this)">
</div>
{% endif %}
<div class="pokemon-number">#{{ '%04d'|format(pokemon.ID) }}</div>
{% if pokemon.MarkIcon %}
<div class="origin-mark-container">
<img src="{{ url_for('static', filename=pokemon.MarkIcon) }}" alt="Origin Mark" class="origin-mark" title="{{ pokemon.EarliestGame }}">
</div>
{% endif %}
</div>
</div>
{% else %}
<div class="pokemon-cell empty"></div>
{% endif %}
{% endfor %}
</div>
</div>
{% endfor %}
</div>
<div id="efficiency-tab" class="tab-content">
<div class="efficiency-plan">
<div class="games-accordion">
{% for game in efficiency_plan %}
<div class="game-section">
<div class="game-title" onclick="toggleGameContent(this)">
{{ game.game_name }}
<span class="toggle-icon"></span>
</div>
<div class="game-content">
{% for pokemon in game.pokemon %}
<div class="pokemon-entry">
<h3>{{ pokemon.name }}{% if pokemon.form_name %} ({{ pokemon.form_name }}){% endif %}</h3>
<p>Catch Count: {{ pokemon.catch_count }}</p>
{% if pokemon.evolve_to %}
<div class="evolution-list">
<h4>Evolves To:</h4>
{% for evolution in pokemon.evolve_to %}
<div class="evolution-item">
{{ evolution.name }}{% if evolution.form_name %} ({{ evolution.form_name }}){% endif %}
- Count: {{ evolution.count }}
</div>
{% endfor %}
</div>
{% endif %}
{% if pokemon.breed_for %}
<div class="breeding-list">
<h4>Breed For:</h4>
{% for breeding in pokemon.breed_for %}
<div class="breeding-item">
{{ breeding.name }}{% if breeding.form_name %} ({{ breeding.form_name }}){% endif %}
- Count: {{ breeding.count }}
</div>
{% endfor %}
</div>
{% endif %}
</div>
{% else %}
<div class="pokemon-cell empty"></div>
{% endif %}
{% endfor %}
</div>
</div>
{% endfor %}
</div>
</div>
{% endfor %}
</div>
</div>
<div id="details-panel"></div>
@ -380,6 +552,43 @@
window.addEventListener("orientationChange", lazyload);
}
});
function toggleGameContent(titleElement) {
const content = titleElement.nextElementSibling;
const icon = titleElement.querySelector('.toggle-icon');
if (content.classList.contains('show')) {
content.classList.remove('show');
icon.textContent = '▼';
} else {
content.classList.add('show');
icon.textContent = '▲';
}
}
function switchTab(tabName) {
// Update tab buttons
document.querySelectorAll('.tab-button').forEach(button => {
button.classList.remove('active');
});
document.querySelector(`[onclick="switchTab('${tabName}')"]`).classList.add('active');
// Update tab content
document.querySelectorAll('.tab-content').forEach(content => {
content.classList.remove('active');
});
document.getElementById(`${tabName}-tab`).classList.add('active');
// Show first game content when switching to efficiency tab
if (tabName === 'efficiency') {
const firstGame = document.querySelector('.game-content');
const firstGameTitle = document.querySelector('.game-title');
if (firstGame && firstGameTitle) {
firstGame.classList.add('show');
firstGameTitle.querySelector('.toggle-icon').textContent = '▲';
}
}
}
</script>
</body>
</html>

10095
efficiency_plan.json

File diff suppressed because it is too large

BIN
pokemon_forms.db

Binary file not shown.

11
shiftable_forms.json

@ -0,0 +1,11 @@
[
{"from_pfic":"0412-04-002-0", "to_pfic":"0412-04-001-0"},
{"from_pfic":"0412-04-003-0", "to_pfic":"0412-04-001-0"},
{"from_pfic":"0641-05-002-0", "to_pfic":"0641-05-001-0"},
{"from_pfic":"0642-05-002-0", "to_pfic":"0642-05-001-0"},
{"from_pfic":"0645-05-002-0", "to_pfic":"0645-05-001-0"},
{"from_pfic":"0647-05-002-0", "to_pfic":"0647-05-001-0"},
{"from_pfic":"0720-06-002-0", "to_pfic":"0720-06-001-0"},
{"from_pfic":"0905-08-002-0", "to_pfic":"0905-08-001-0"},
{"from_pfic":"0492-04-002-0", "to_pfic":"0492-04-001-0"}
]
Loading…
Cancel
Save