diff --git a/.gitignore b/.gitignore
index ff0067e..23c6007 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,4 +3,7 @@ pokemon_database.db
Utilities/venv/
venv/
DBVisualiser/node_modules/
-__pycache__/
\ No newline at end of file
+__pycache__/
+ui_feedback.log
+logs/qt_log.log
+logs/default.log
diff --git a/DBEditor/DBEditor.py b/DBEditor/DBEditor.py
index f3ecce2..dbf3fd9 100644
--- a/DBEditor/DBEditor.py
+++ b/DBEditor/DBEditor.py
@@ -3,294 +3,134 @@ from PyQt6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QH
QLabel, QCheckBox, QPushButton, QFormLayout, QListWidgetItem, QSplitter, QTreeWidget,
QTreeWidgetItem, QDialog, QDialogButtonBox, QComboBox, QMessageBox, QSpinBox, QMenu, QTabWidget,
QTextEdit)
-from PyQt6.QtCore import Qt, QSize
+from PyQt6.QtCore import Qt, QSize, qInstallMessageHandler, QThread, pyqtSignal
from PyQt6.QtGui import QPixmap, QFontMetrics, QColor, QAction
import sqlite3
import json
import os
+import traceback
+import time
+import pdb
+import debugpy
# Add the parent directory to the Python path
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
# Now try to import
+from db_controller import DBController
from pokemon_db_ui import PokemonUI
from DataGatherers.update_location_information import process_pokemon_for_location_data
from DataGatherers.cache_manager import CacheManager
from event_system import event_system
-def parse_pfic(pfic):
- parts = pfic.split('-')
- return tuple(int(part) if part.isdigit() else part for part in parts)
+import logging
+
+class UILogHandler(logging.Handler):
+ def __init__(self):
+ super().__init__()
+
+ def emit(self, record):
+ log_entry = self.format(record) # Format the log message
+ event_system.emit('update_log_display', log_entry)
+
+class PokemonFormGatherer(QThread):
+ progress_signal = pyqtSignal(str)
+ finished_signal = pyqtSignal()
+
+ def run(self):
+ cache = CacheManager()
+ debugpy.debug_this_thread()
+ from DataGatherers.pokemondb_scraper import retrieve_all_pokemon_forms
+ retrieve_all_pokemon_forms(cache, progress_callback=self.progress_signal.emit)
+ self.finished_signal.emit()
+
+class PokemonHomeStatusUpdater(QThread):
+ progress_signal = pyqtSignal(str)
+ finished_signal = pyqtSignal()
+
+ def run(self):
+ cache = CacheManager()
+ debugpy.debug_this_thread()
+ from DataGatherers.update_storable_in_home import update_storable_in_home
+ update_storable_in_home(cache, progress_callback=self.progress_signal.emit)
+ self.finished_signal.emit()
+
+class PokemonEvolutionUpdater(QThread):
+ progress_signal = pyqtSignal(str)
+ finished_signal = pyqtSignal()
+
+ def run(self):
+ time.sleep(0.1)
+ #pdb.set_trace()
+ debugpy.debug_this_thread()
+ cache = CacheManager()
+ from DataGatherers.Update_evolution_information import update_evolution_chains
+ update_evolution_chains(cache, progress_callback=self.progress_signal.emit)
+ self.finished_signal.emit()
+
+class PokemonEncounterUpdater(QThread):
+ progress_signal = pyqtSignal(str)
+ finished_signal = pyqtSignal()
+
+ def run(self):
+ time.sleep(0.1)
+ debugpy.debug_this_thread()
+ cache = CacheManager()
+ from DataGatherers.update_location_information import update_location_information
+ update_location_information(cache, progress_callback=self.progress_signal.emit)
+ self.finished_signal.emit()
class DBEditor(QMainWindow):
def __init__(self):
super().__init__()
+ self.setup_logging()
self.setWindowTitle("Pokémon Database Editor")
self.setGeometry(100, 100, 1000, 600)
- event_system.add_listener('get_pokemon_data', self.load_pokemon_details)
event_system.add_listener('save_changes', self.save_changes)
event_system.add_listener('add_new_encounter', self.add_new_encounter)
- event_system.add_listener('get_pokemon_list', self.send_pokemon_list)
- event_system.add_listener('get_home_storable', self.get_home_storable)
- event_system.add_listener('get_evolution_chain', self.get_evolution_chain)
- event_system.add_listener('get_evolution_parent', self.get_evolution_parent)
+ event_system.add_listener('refresh_pokemon_encounters', self.refresh_pokemon_encounters)
+ event_system.add_listener('gather_pokemon_forms', self.gather_pokemon_forms)
+ event_system.add_listener('gather_home_storage_info', self.gather_home_storage_info)
+ event_system.add_listener('gather_evolution_info', self.gather_evolution_info)
+ event_system.add_listener('gather_encounter_info', self.gather_encounter_info)
+ event_system.add_listener('reinitialize_database', self.reinitialize_database)
self.conn = sqlite3.connect(':memory:', check_same_thread=False) # Use in-memory database for runtime
self.cursor = self.conn.cursor()
self.init_database()
- self.patches = self.load_and_apply_patches()
+ #self.patches = self.load_and_apply_patches()
+ self.patches = {}
- self.encounter_cache = {} # Add this line
self.init_ui()
+
def init_database(self):
- # Create or open the file-based database
- disk_conn = sqlite3.connect('pokemon_forms.db')
- disk_cursor = disk_conn.cursor()
-
- # Create tables in the file-based database
- self.create_games_table(disk_cursor)
- self.create_pokemon_forms_table(disk_cursor)
- self.create_pokemon_storage_table(disk_cursor)
- self.create_evolution_chains_table(disk_cursor)
- self.create_exclusive_encounter_groups_table(disk_cursor)
- self.create_encounters_table(disk_cursor)
- self.create_mark_table(disk_cursor)
-
- # Commit changes to the file-based database
- disk_conn.commit()
-
- # Copy the file-based database to the in-memory database
- disk_conn.backup(self.conn)
-
- # Close the file-based database connection
- disk_conn.close()
-
- # Create tables in the in-memory database (in case they weren't copied)
- self.create_pokemon_forms_table(self.cursor)
- self.create_pokemon_storage_table(self.cursor)
- self.create_evolution_chains_table(self.cursor)
- self.create_exclusive_encounter_groups_table(self.cursor)
- self.create_encounters_table(self.cursor)
-
- # Commit changes to the in-memory database
- self.conn.commit()
+ self.db_controller = DBController()
+ self.db_controller.init_database()
- def create_pokemon_forms_table(self, cursor):
- cursor.execute('''
- CREATE TABLE IF NOT EXISTS pokemon_forms (
- PFIC TEXT PRIMARY KEY,
- name TEXT NOT NULL,
- form_name TEXT,
- national_dex INTEGER NOT NULL,
- generation INTEGER NOT NULL,
- is_baby_form BOOLEAN
- )
- ''')
-
- def create_pokemon_storage_table(self, cursor):
- cursor.execute('''
- CREATE TABLE IF NOT EXISTS pokemon_storage (
- PFIC TEXT PRIMARY KEY,
- storable_in_home BOOLEAN NOT NULL,
- FOREIGN KEY (PFIC) REFERENCES pokemon_forms (PFIC)
- )
- ''')
-
- def create_evolution_chains_table(self, cursor):
- cursor.execute('''
- CREATE TABLE IF NOT EXISTS evolution_chains (
- from_pfic TEXT,
- to_pfic TEXT,
- method TEXT,
- PRIMARY KEY (from_pfic, to_pfic),
- FOREIGN KEY (from_pfic) REFERENCES pokemon_forms (PFIC),
- FOREIGN KEY (to_pfic) REFERENCES pokemon_forms (PFIC)
- )
- ''')
-
- def create_exclusive_encounter_groups_table(self, cursor):
- cursor.execute('''
- CREATE TABLE IF NOT EXISTS exclusive_encounter_groups (
- id INTEGER PRIMARY KEY AUTOINCREMENT,
- group_name TEXT NOT NULL,
- description TEXT
- )
- ''')
-
- def create_encounters_table(self, cursor):
- # First, check if the table exists
- cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='encounters'")
- table_exists = cursor.fetchone() is not None
-
- if not table_exists:
- # If the table doesn't exist, create it with all columns
- cursor.execute('''
- CREATE TABLE encounters (
- id INTEGER PRIMARY KEY AUTOINCREMENT,
- pfic TEXT,
- game TEXT,
- location TEXT,
- day TEXT,
- time TEXT,
- dual_slot TEXT,
- static_encounter BOOLEAN,
- static_encounter_count INTEGER,
- extra_text TEXT,
- stars TEXT,
- fishing BOOLEAN,
- rods TEXT,
- exclusive_group_id INTEGER,
- FOREIGN KEY (pfic) REFERENCES pokemon_forms (PFIC),
- FOREIGN KEY (exclusive_group_id) REFERENCES exclusive_encounter_groups (id)
- )
- ''')
- else:
- # If the table exists, check if the exclusive_group_id column exists
- cursor.execute("PRAGMA table_info(encounters)")
- columns = [column[1] for column in cursor.fetchall()]
-
- if 'exclusive_group_id' not in columns:
- # If the column doesn't exist, add it
- cursor.execute('''
- ALTER TABLE encounters
- ADD COLUMN exclusive_group_id INTEGER
- REFERENCES exclusive_encounter_groups (id)
- ''')
-
- if 'starter' not in columns:
- # If the column doesn't exist, add it
- cursor.execute('''
- ALTER TABLE encounters
- ADD COLUMN starter BOOLEAN
- ''')
-
- def create_mark_table(self, cursor):
-
- cursor.execute('''
- CREATE TABLE IF NOT EXISTS marks (
- id INTEGER PRIMARY KEY,
- name TEXT NOT NULL,
- icon_path TEXT NOT NULL
- )
- ''')
-
- cursor.execute('''
- CREATE TABLE IF NOT EXISTS mark_game_associations (
- mark_id INTEGER,
- game_id INTEGER,
- FOREIGN KEY (mark_id) REFERENCES marks (id),
- FOREIGN KEY (game_id) REFERENCES games (id),
- PRIMARY KEY (mark_id, game_id)
- )
- ''')
-
- marks = [
- ("Game Boy", "images/marks/GB_icon_HOME.png", ["Red", "Blue", "Yellow", "Gold", "Silver", "Crystal", "Ruby", "Sapphire", "Emerald", "FireRed", "LeafGreen"]),
- ("Kalos", "images/marks/Blue_pentagon_HOME.png", ["X", "Y", "Omega Ruby", "Alpha Sapphire"]),
- ("Alola", "images/marks/Black_clover_HOME.png", ["Sun", "Moon", "Ultra Sun", "Ultra Moon"]),
- ("Let's Go", "images/marks/Let's_Go_icon_HOME.png", ["Let's Go Pikachu", "Let's Go Eevee"]),
- ("Galar", "images/marks/Galar_symbol_HOME.png", ["Sword", "Shield"]),
- ("Sinnoh", "images/marks/BDSP_icon_HOME.png", ["Brilliant Diamond", "Shining Pearl"]),
- ("Hisui", "images/marks/Arceus_mark_HOME.png", ["Legends Arceus"]),
- ("Paldea", "images/marks/Paldea_icon_HOME.png", ["Scarlet", "Violet"]),
- ]
-
- for mark in marks:
- cursor.execute('''
- INSERT OR IGNORE INTO marks (name, icon_path)
- VALUES (?, ?)
- ''', (mark[0], mark[1]))
-
- mark_id = cursor.lastrowid
-
- for game_name in mark[2]:
- cursor.execute('''
- INSERT OR IGNORE INTO mark_game_associations (mark_id, game_id)
- SELECT ?, id FROM games WHERE name = ?
- ''', (mark_id, game_name))
-
- def create_games_table(self, cursor):
-
- cursor.execute('''
- CREATE TABLE IF NOT EXISTS games (
- id INTEGER PRIMARY KEY,
- name TEXT NOT NULL,
- generation INTEGER NOT NULL
- )
- ''')
-
- cursor.execute('''
- CREATE TABLE IF NOT EXISTS alternate_game_names (
- id INTEGER PRIMARY KEY,
- game_id INTEGER NOT NULL,
- alternate_name TEXT NOT NULL,
- FOREIGN KEY (game_id) REFERENCES games (id),
- UNIQUE (alternate_name COLLATE NOCASE)
- )
- ''')
-
- games = [
- ("Red", 1, ["Red Version"]),
- ("Blue", 1, ["Blue Version"]),
- ("Yellow", 1, ["Yellow Version"]),
- ("Gold", 2, ["Gold Version"]),
- ("Silver", 2, ["Silver Version"]),
- ("Crystal", 2, ["Crystal Version"]),
- ("Ruby", 3, ["Ruby Version"]),
- ("Sapphire", 3, ["Sapphire Version"]),
- ("Emerald", 3, ["Emerald Version"]),
- ("FireRed", 3, ["Fire Red", "Fire-Red"]),
- ("LeafGreen", 3, ["Leaf Green", "Leaf-Green"]),
- ("Diamond", 4, ["Diamond Version"]),
- ("Pearl", 4, ["Pearl Version"]),
- ("Platinum", 4, ["Platinum Version"]),
- ("HeartGold", 4, ["Heart Gold", "Heart-Gold"]),
- ("SoulSilver", 4, ["Soul Silver", "Soul-Silver"]),
- ("Black", 5, ["Black Version"]),
- ("White", 5, ["White Version"]),
- ("Black 2", 5, ["Black Version 2", "Black-2"]),
- ("White 2", 5, ["White Version 2", "White-2"]),
- ("X", 6, ["X Version"]),
- ("Y", 6, ["Y Version"]),
- ("Omega Ruby", 6, ["Omega Ruby Version", "Omega-Ruby"]),
- ("Alpha Sapphire", 6, ["Alpha Sapphire Version", "Alpha-Sapphire"]),
- ("Sun", 7, ["Sun Version"]),
- ("Moon", 7, ["Moon Version"]),
- ("Ultra Sun", 7, ["Ultra Sun Version", "Ultra-Sun"]),
- ("Ultra Moon", 7, ["Ultra Moon Version", "Ultra-Moon"]),
- ("Let's Go Pikachu", 7, ["Let's Go, Pikachu!", "Lets Go Pikachu"]),
- ("Let's Go Eevee", 7, ["Let's Go, Eevee!", "Lets Go Eevee"]),
- ("Sword", 8, ["Sword Version"]),
- ("Shield", 8, ["Shield Version"]),
- ("Expansion Pass", 8, ["Expansion Pass (Sword)", "Expansion Pass (Shield)"]),
- ("Brilliant Diamond", 8, ["Brilliant Diamond Version", "Brilliant-Diamond"]),
- ("Shining Pearl", 8, ["Shining Pearl Version", "Shining-Pearl"]),
- ("Legends Arceus", 8, ["Legends: Arceus", "Legends-Arceus"]),
- ("Scarlet", 9, ["Scarlet Version"]),
- ("Violet", 9, ["Violet Version"]),
- ("The Teal Mask", 9, ["The Teal Mask Version", "The Teal Mask (Scarlet)", "The Teal Mask (Violet)"]),
- ("The Hidden Treasure of Area Zero", 9, ["The Hidden Treasure of Area Zero Version", "The Hidden Treasure of Area Zero (Scarlet)", "The Hidden Treasure of Area Zero (Violet)"]),
-
- ("Pokémon Home", 98, ["Pokémon HOME"]),
- ("Pokémon Go", 99, ["Pokémon GO"]),
- ]
-
- for game in games:
- cursor.execute('''
- INSERT OR IGNORE INTO games (name, generation)
- VALUES (?, ?)
- ''', (game[0], game[1]))
-
- game_id = cursor.lastrowid
-
- # Insert alternate names
- for alt_name in game[2]:
- cursor.execute('''
- INSERT OR IGNORE INTO alternate_game_names (game_id, alternate_name)
- VALUES (?, ?)
- ''', (game_id, alt_name))
+ def setup_logging(self):
+ # Create the logger with the name 'ui_feedback'
+ self.logger = logging.getLogger('ui_feedback')
+ self.logger.setLevel(logging.DEBUG) # Set the logging level
+
+ # Create handlers
+ console_handler = logging.StreamHandler() # Log to the console
+ file_handler = logging.FileHandler('ui_feedback.log') # Log to a file
+ ui_handler = UILogHandler()
+
+ # Create formatters and add them to handlers
+ formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
+ console_handler.setFormatter(formatter)
+ file_handler.setFormatter(formatter)
+ ui_handler.setFormatter(formatter)
+
+ # Add the handler to the logger
+ self.logger.addHandler(ui_handler)
+
+ # Add handlers to the logger
+ self.logger.addHandler(console_handler)
+ self.logger.addHandler(file_handler)
def load_and_apply_patches(self):
try:
@@ -333,16 +173,6 @@ class DBEditor(QMainWindow):
with open('patches.json', 'w') as f:
json.dump(self.patches, f)
- def load_pokemon_details(self, pfic):
- self.cursor.execute('''
- SELECT pf.name, pf.form_name, pf.national_dex, pf.generation, ps.storable_in_home
- FROM pokemon_forms pf
- LEFT JOIN pokemon_storage ps ON pf.PFIC = ps.PFIC
- WHERE pf.PFIC = ?
- ''', (pfic,))
-
- return self.cursor.fetchone()
-
def save_changes(self, data):
# Your existing code to save changes
pass
@@ -351,18 +181,6 @@ class DBEditor(QMainWindow):
# Your existing code to add a new encounter
pass
- def send_pokemon_list(self, callback):
- # Fetch pokemon list from database
- self.cursor.execute('''
- SELECT pf.PFIC, pf.name, pf.form_name, pf.national_dex
- FROM pokemon_forms pf
- ''')
- pokemon_data = self.cursor.fetchall()
-
- # Sort the pokemon_data based on PFIC
- pokemon_data.sort(key=lambda x: parse_pfic(x[0]))
- callback(pokemon_data)
-
def init_ui(self):
# Create a central widget for the main window
central_widget = QWidget()
@@ -373,12 +191,6 @@ class DBEditor(QMainWindow):
self.pokemon_ui = PokemonUI(self)
main_layout.addWidget(self.pokemon_ui)
- def get_home_storable(self, pfic):
- self.cursor.execute('SELECT storable_in_home FROM pokemon_storage WHERE PFIC = ?', (pfic,))
- result = self.cursor.fetchone()
- home_storable = result[0] if result else False
- return home_storable
-
def update_home_storable(self):
if hasattr(self, 'current_pfic'):
storable_in_home = self.home_checkbox.isChecked()
@@ -440,131 +252,10 @@ class DBEditor(QMainWindow):
# Refresh the evolution chain display
# self.load_evolution_chain(self.current_pfic)
-
- def get_evolution_chain(self, pfic):
- def follow_chain(start_pfic, visited=None):
- if visited is None:
- visited = set()
-
- chain = []
- stack = [(start_pfic, None)]
-
- while stack:
- current_pfic, method = stack.pop()
- if current_pfic in visited:
- continue
-
- visited.add(current_pfic)
- self.cursor.execute('SELECT name, form_name FROM pokemon_forms WHERE PFIC = ?', (current_pfic,))
- name, form_name = self.cursor.fetchone()
-
- chain.append((current_pfic, name, form_name, method))
-
- # Get previous evolutions
- self.cursor.execute('SELECT from_pfic, method FROM evolution_chains WHERE to_pfic = ?', (current_pfic,))
- prev_evolutions = self.cursor.fetchall()
- for prev_pfic, prev_method in prev_evolutions:
- if prev_pfic not in visited:
- stack.append((prev_pfic, prev_method))
-
- # Get next evolutions
- self.cursor.execute('SELECT to_pfic, method FROM evolution_chains WHERE from_pfic = ?', (current_pfic,))
- next_evolutions = self.cursor.fetchall()
- for next_pfic, next_method in next_evolutions:
- if next_pfic not in visited:
- stack.append((next_pfic, next_method))
-
- return chain
-
- return follow_chain(pfic)
- def get_evolution_parent(self, pfic):
- self.cursor.execute('SELECT from_pfic FROM evolution_chains WHERE to_pfic = ?', (pfic,))
- return self.cursor.fetchone()
-
def closeEvent(self, event):
self.conn.close()
- event.accept()
-
- def load_encounter_locations(self, pfic):
- self.locations_tree.clear()
- self.cursor.execute('''
- SELECT game, location, day, time, dual_slot, static_encounter_count, static_encounter, extra_text, stars, rods, fishing
- FROM encounters
- WHERE pfic = ?
- ORDER BY game, location
- ''', (pfic,))
- encounters = self.cursor.fetchall()
-
- game_items = {}
- for encounter in encounters:
- game, location, day, time, dual_slot, static_encounter_count, static_encounter, extra_text, stars, rods, fishing = encounter
-
- if game not in game_items:
- game_item = QTreeWidgetItem([game])
- game_items[game] = game_item
- # Use generation for sorting, default to 0 if not found
- game_item.setData(0, Qt.ItemDataRole.UserRole, self.game_generations.get(game, 0))
-
- location_item = QTreeWidgetItem([location])
- details = []
- if day:
- details.append(f"Day: {day}")
- if time:
- details.append(f"Time: {time}")
- if dual_slot:
- details.append(f"Dual Slot: {dual_slot}")
- if static_encounter:
- details.append(f"Static Encounter (Count: {static_encounter_count})")
- if extra_text:
- details.append(f"Extra: {extra_text}")
- if stars:
- details.append(f"Stars: {stars}")
- if fishing:
- details.append(f"Fishing")
- if rods:
- details.append(f"Rods: {rods}")
-
- location_item.setText(1, ", ".join(details))
- game_items[game].addChild(location_item)
-
- # Sort game items by generation and add them to the tree
- sorted_game_items = sorted(game_items.values(), key=lambda x: x.data(0, Qt.ItemDataRole.UserRole))
- self.locations_tree.addTopLevelItems(sorted_game_items)
- self.locations_tree.expandAll()
-
- # Update the cache for this Pokémon
- self.encounter_cache[pfic] = len(encounters) > 0
-
- # After updating the locations tree
- self.update_pokemon_list_highlights()
-
- # Add this as a class attribute in the DBEditor class
- game_generations = {
- "Red": 1, "Blue": 1, "Yellow": 1,
- "Gold": 2, "Silver": 2, "Crystal": 2,
- "Ruby": 3, "Sapphire": 3, "Emerald": 3, "FireRed": 3, "LeafGreen": 3,
- "Diamond": 4, "Pearl": 4, "Platinum": 4, "HeartGold": 4, "SoulSilver": 4,
- "Black": 5, "White": 5, "Black 2": 5, "White 2": 5,
- "X": 6, "Y": 6, "Omega Ruby": 6, "Alpha Sapphire": 6,
- "Sun": 7, "Moon": 7, "Ultra Sun": 7, "Ultra Moon": 7,
- "Sword": 8, "Shield": 8, "Brilliant Diamond": 8, "Shining Pearl": 8, "Expansion Pass": 8,
- "Legends: Arceus": 8,
- "Scarlet": 9, "Violet": 9, "The Teal Mask": 9, "The Hidden Treasure of Area Zero": 9, "The Hidden Treasure of Area Zero (Scarlet)": 9, "The Hidden Treasure of Area Zero (Violet)": 9, "The Teal Mask (Scarlet)": 9, "The Teal Mask (Violet)": 9,
- "Pokémon Go": 0, "Pokémon Home": 0
- }
-
- def update_encounter_cache(self):
- self.cursor.execute('''
- SELECT DISTINCT pfic
- FROM encounters
- ''')
- pokemon_with_encounters = set(row[0] for row in self.cursor.fetchall())
-
- #for i in range(self.pokemon_list.count()):
- # item = self.pokemon_list.item(i)
- # pfic = item.data(Qt.ItemDataRole.UserRole)
- # self.encounter_cache[pfic] = pfic in pokemon_with_encounters
+ event.accept()
def check_pokemon_has_encounters(self, pfic):
return self.encounter_cache.get(pfic, False)
@@ -606,16 +297,24 @@ class DBEditor(QMainWindow):
name_edit = QLineEdit()
description_edit = QLineEdit()
+ game_combo = QComboBox()
layout.addRow("Group Name:", name_edit)
layout.addRow("Description:", description_edit)
+ layout.addRow("Game:", game_combo)
+
+ # Populate game combo box
+ self.cursor.execute('SELECT id, name FROM games ORDER BY name')
+ for game_id, game_name in self.cursor.fetchall():
+ game_combo.addItem(game_name, game_id)
if item:
group_id = item.data(Qt.ItemDataRole.UserRole)
- self.cursor.execute('SELECT group_name, description FROM exclusive_encounter_groups WHERE id = ?', (group_id,))
- group_name, description = self.cursor.fetchone()
+ self.cursor.execute('SELECT group_name, description, game_id FROM exclusive_encounter_groups WHERE id = ?', (group_id,))
+ group_name, description, game_id = self.cursor.fetchone()
name_edit.setText(group_name)
description_edit.setText(description)
+ game_combo.setCurrentIndex(game_combo.findData(game_id))
buttons = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel)
buttons.accepted.connect(dialog.accept)
@@ -625,13 +324,14 @@ class DBEditor(QMainWindow):
if dialog.exec() == QDialog.DialogCode.Accepted:
name = name_edit.text()
description = description_edit.text()
+ game_id = game_combo.currentData()
if item:
- self.cursor.execute('UPDATE exclusive_encounter_groups SET group_name = ?, description = ? WHERE id = ?', (name, description, group_id))
- item.setText(f"{name} - {description}")
+ self.cursor.execute('UPDATE exclusive_encounter_groups SET group_name = ?, description = ?, game_id = ? WHERE id = ?', (name, description, game_id, group_id))
+ item.setText(f"{name} - {description} ({game_combo.currentText()})")
else:
- self.cursor.execute('INSERT INTO exclusive_encounter_groups (group_name, description) VALUES (?, ?)', (name, description))
+ self.cursor.execute('INSERT INTO exclusive_encounter_groups (group_name, description, game_id) VALUES (?, ?, ?)', (name, description, game_id))
group_id = self.cursor.lastrowid
- new_item = QListWidgetItem(f"{name} - {description}")
+ new_item = QListWidgetItem(f"{name} - {description} ({game_combo.currentText()})")
new_item.setData(Qt.ItemDataRole.UserRole, group_id)
group_list.addItem(new_item)
self.conn.commit()
@@ -646,35 +346,15 @@ class DBEditor(QMainWindow):
self.conn.commit()
group_list.takeItem(group_list.row(item))
- def show_pokemon_context_menu(self, position):
- item = self.pokemon_list.itemAt(position)
- if item is not None:
- context_menu = QMenu(self)
- refresh_action = QAction("Refresh Encounters", self)
- refresh_action.triggered.connect(lambda: self.refresh_pokemon_encounters(item))
- context_menu.addAction(refresh_action)
- context_menu.exec(self.pokemon_list.viewport().mapToGlobal(position))
-
- def refresh_pokemon_encounters(self, item):
- pfic = item.data(Qt.ItemDataRole.UserRole)
- self.cursor.execute('''
- SELECT name, form_name, national_dex
- FROM pokemon_forms
- WHERE PFIC = ?
- ''', (pfic,))
- pokemon_data = self.cursor.fetchone()
+ def refresh_pokemon_encounters(self, pfic):
+ pokemon_data = event_system.call_sync('get_pokemon_data', pfic)
+
if pokemon_data:
- name, form, national_dex = pokemon_data
-
- # Import the necessary function and classes
- #from DataGatherers.update_location_information import process_pokemon_for_location_data
-
- import json
+ name, form_name, national_dex, generation, storable_in_home, is_baby_form = pokemon_data
# Create a temporary connection for this operation
temp_conn = sqlite3.connect('pokemon_forms.db')
-
- # Load default forms
+
try:
with open('./DataGatherers/DefaultForms.json', 'r') as f:
default_forms = json.load(f)
@@ -684,73 +364,98 @@ class DBEditor(QMainWindow):
# Create a cache manager instance
cache = CacheManager()
- # Delete existing encounters for this Pokémon
- self.cursor.execute('DELETE FROM encounters WHERE pfic = ?', (pfic,))
- self.conn.commit()
+ event_system.emit_sync('clear_encounters_for_pokemon', pfic)
# Process the Pokémon data
- process_pokemon_for_location_data(pfic, name, form, national_dex, default_forms, cache, temp_conn)
+ process_pokemon_for_location_data(pfic, name, form_name, national_dex, default_forms, cache, temp_conn)
- temp_conn.backup(self.conn)
+ event_system.emit_sync('refresh_in_memory_db', temp_conn)
# Close the temporary connection
temp_conn.close()
- # Refresh the encounter locations in the UI
- self.load_encounter_locations(pfic)
-
- # Update the encounter cache and highlights
- self.update_encounter_cache()
- self.update_pokemon_list_highlights()
-
- print(f"Refreshed encounters for {name} {form if form else ''}")
-
- def gather_pokemon_forms(self):
- self.progress_text.clear() # Clear previous progress text
- self.progress_text.append("Starting to gather Pokémon forms...")
- # Implement the logic to gather Pokémon forms
- # Update progress as you go, for example:
- self.progress_text.append("Processed 100 Pokémon...")
- self.progress_text.append("Processed 200 Pokémon...")
- # ...
- self.progress_text.append("Finished gathering Pokémon forms.")
-
- def gather_home_storage_info(self):
- self.progress_text.clear()
- self.progress_text.append("Starting to gather Home storage information...")
- # Implement the logic
- # ...
-
- def gather_evolution_info(self):
- self.progress_text.clear()
- self.progress_text.append("Starting to gather evolution information...")
- # Implement the logic
- # ...
-
- def gather_encounter_info(self):
- self.progress_text.clear()
- self.progress_text.append("Starting to gather encounter information...")
- # Implement the logic
- # ...
-
- def reinitialize_database(self):
+ event_system.emit_sync('refresh_pokemon_details_panel', pfic)
+
+ print(f"Refreshed encounters for {name} {form_name if form_name else ''}")
+
+ def gather_pokemon_forms(self, data):
+ event_system.emit_sync('clear_log_display')
+ self.logger.info("Starting to gather Pokémon forms...")
+
+ self.form_gatherer = PokemonFormGatherer()
+ self.form_gatherer.progress_signal.connect(self.update_progress)
+ self.form_gatherer.finished_signal.connect(self.gathering_finished)
+ self.form_gatherer.start()
+
+ def update_progress(self, message):
+ self.logger.info(message)
+
+ def gathering_finished(self):
+ self.logger.info("Finished gathering Pokémon forms.")
+
+ def gather_home_storage_info(self, data):
+ event_system.emit_sync('clear_log_display')
+ self.logger.info("Starting to gather Home storage information...")
+ self.home_storage_updater = PokemonHomeStatusUpdater()
+ self.home_storage_updater.progress_signal.connect(self.update_progress)
+ self.home_storage_updater.finished_signal.connect(self.updating_home_storage_finished)
+ self.home_storage_updater.start()
+
+ def updating_home_storage_finished(self):
+ self.logger.info("Finished updating Home storage information.")
+
+ def gather_evolution_info(self, data):
+ event_system.call_sync('clear_log_display')
+ self.logger.info("Starting to gather evolution information...")
+ self.evolution_updater = PokemonEvolutionUpdater()
+ self.evolution_updater.progress_signal.connect(self.update_progress)
+ self.evolution_updater.finished_signal.connect(self.updating_evolution_info_finished)
+ self.evolution_updater.start()
+
+ def updating_evolution_info_finished(self):
+ self.logger.info("Finished updating evolution information.")
+
+
+ def gather_encounter_info(self, data):
+ event_system.call_sync('clear_log_display')
+ self.logger.info("Starting to gather encounter information...")
+ self.encounter_updater = PokemonEncounterUpdater()
+ self.encounter_updater.progress_signal.connect(self.update_progress)
+ self.encounter_updater.finished_signal.connect(self.updating_encounter_info_finished)
+ self.encounter_updater.start()
+
+ def updating_encounter_info_finished(self):
+ self.logger.info("Finished updating encounter information.")
+
+ def reinitialize_database(self, data):
reply = QMessageBox.question(self, 'Confirm Action',
'Are you sure you want to clear and reinitialize the database? This action cannot be undone.',
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No, QMessageBox.StandardButton.No)
if reply == QMessageBox.StandardButton.Yes:
- self.progress_text.clear()
- self.progress_text.append("Starting database reinitialization...")
+ self.logger.info("Starting database reinitialization...")
# Implement the logic to clear and reinitialize the database
self.conn.close()
os.remove('pokemon_forms.db') # Remove the existing database file
self.conn = sqlite3.connect('pokemon_forms.db')
self.cursor = self.conn.cursor()
self.init_database() # Reinitialize the database structure
- self.progress_text.append("Database reinitialized successfully.")
+ self.logger.info("Database reinitialized successfully.")
QMessageBox.information(self, 'Database Reinitialized', 'The database has been cleared and reinitialized.')
+
+
+def qt_message_handler(mode, context, message):
+ print(f"Qt Message: {mode} {context} {message}")
+
+def exception_hook(exctype, value, tb):
+ print(''.join(traceback.format_exception(exctype, value, tb)))
+ sys.exit(1)
+
+sys.excepthook = exception_hook
+
if __name__ == '__main__':
app = QApplication(sys.argv)
+ qInstallMessageHandler(qt_message_handler)
editor = DBEditor()
editor.show()
- sys.exit(app.exec())
\ No newline at end of file
+ sys.exit(app.exec())
diff --git a/DBEditor/db_controller.py b/DBEditor/db_controller.py
new file mode 100644
index 0000000..09831f2
--- /dev/null
+++ b/DBEditor/db_controller.py
@@ -0,0 +1,382 @@
+import sqlite3
+import sys
+import os
+
+from event_system import event_system
+
+def parse_pfic(pfic):
+ parts = pfic.split('-')
+ return tuple(int(part) if part.isdigit() else part for part in parts)
+
+class DBController:
+ def __init__(self):
+ self.conn = sqlite3.connect(':memory:', check_same_thread=False) # Use in-memory database for runtime
+ self.cursor = self.conn.cursor()
+
+ event_system.add_listener('get_pokemon_data', self.load_pokemon_details)
+ event_system.add_listener('get_pokemon_list', self.send_pokemon_list)
+ event_system.add_listener('get_home_storable', self.get_home_storable)
+ event_system.add_listener('get_evolution_chain', self.get_evolution_chain)
+ event_system.add_listener('get_evolution_parent', self.get_evolution_parent)
+ event_system.add_listener('get_encounter_locations', self.get_encounter_locations)
+ event_system.add_listener('get_game_generation', self.get_game_generation)
+ event_system.add_listener('get_pokemon_with_encounters', self.get_pokemon_with_encounters)
+ event_system.add_listener('refresh_in_memory_db', self.refresh_in_memory_db)
+ event_system.add_listener('clear_encounters_for_pokemon', self.clear_encounters_for_pokemon)
+ event_system.add_listener('get_game_id_for_name', self.get_game_id_for_name)
+
+ def init_database(self):
+ disk_conn = sqlite3.connect('pokemon_forms.db')
+ disk_cursor = disk_conn.cursor()
+
+ # Create tables in the file-based database
+ self.create_games_table(disk_cursor)
+ self.create_pokemon_forms_table(disk_cursor)
+ self.create_pokemon_storage_table(disk_cursor)
+ self.create_evolution_chains_table(disk_cursor)
+ self.create_exclusive_encounter_groups_table(disk_cursor)
+ self.create_encounters_table(disk_cursor)
+ self.create_mark_table(disk_cursor)
+
+ # Commit changes to the file-based database
+ disk_conn.commit()
+
+ # Copy the file-based database to the in-memory database
+ disk_conn.backup(self.conn)
+
+ # Close the file-based database connection
+ disk_conn.close()
+
+ def create_pokemon_forms_table(self, cursor):
+ cursor.execute('''
+ CREATE TABLE IF NOT EXISTS pokemon_forms (
+ PFIC TEXT PRIMARY KEY,
+ name TEXT NOT NULL,
+ form_name TEXT,
+ national_dex INTEGER NOT NULL,
+ generation INTEGER NOT NULL,
+ is_baby_form BOOLEAN
+ )
+ ''')
+
+ def create_pokemon_storage_table(self, cursor):
+ cursor.execute('''
+ CREATE TABLE IF NOT EXISTS pokemon_storage (
+ PFIC TEXT PRIMARY KEY,
+ storable_in_home BOOLEAN NOT NULL,
+ FOREIGN KEY (PFIC) REFERENCES pokemon_forms (PFIC)
+ )
+ ''')
+
+ def create_evolution_chains_table(self, cursor):
+ cursor.execute('''
+ CREATE TABLE IF NOT EXISTS evolution_chains (
+ from_pfic TEXT,
+ to_pfic TEXT,
+ method TEXT,
+ PRIMARY KEY (from_pfic, to_pfic),
+ FOREIGN KEY (from_pfic) REFERENCES pokemon_forms (PFIC),
+ FOREIGN KEY (to_pfic) REFERENCES pokemon_forms (PFIC)
+ )
+ ''')
+
+ def create_exclusive_encounter_groups_table(self, cursor):
+ cursor.execute('''
+ CREATE TABLE IF NOT EXISTS exclusive_encounter_groups (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ group_name TEXT NOT NULL,
+ description TEXT,
+ game_id INTEGER,
+ FOREIGN KEY (game_id) REFERENCES games (id)
+ )
+ ''')
+
+ def create_encounter_exclusive_group_table(self, cursor):
+ cursor.execute('''
+ CREATE TABLE IF NOT EXISTS encounter_exclusive_groups (
+ encounter_id INTEGER,
+ group_id INTEGER,
+ FOREIGN KEY (encounter_id) REFERENCES encounters (id),
+ FOREIGN KEY (group_id) REFERENCES exclusive_encounter_groups (id),
+ PRIMARY KEY (encounter_id, group_id)
+ )
+ ''')
+
+ def create_encounters_table(self, cursor):
+ cursor.execute('''
+ CREATE TABLE IF NOT EXISTS encounters (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ pfic TEXT,
+ game_id INTEGER,
+ location TEXT,
+ day TEXT,
+ time TEXT,
+ dual_slot TEXT,
+ static_encounter BOOLEAN,
+ static_encounter_count INTEGER,
+ extra_text TEXT,
+ stars TEXT,
+ fishing BOOLEAN,
+ rods TEXT,
+ starter BOOLEAN,
+ FOREIGN KEY (pfic) REFERENCES pokemon_forms (PFIC),
+ FOREIGN KEY (game_id) REFERENCES games (id)
+ )
+ ''')
+
+ def create_mark_table(self, cursor):
+ cursor.execute('''
+ CREATE TABLE IF NOT EXISTS marks (
+ id INTEGER PRIMARY KEY,
+ name TEXT NOT NULL UNIQUE,
+ icon_path TEXT NOT NULL
+ )
+ ''')
+
+ cursor.execute('''
+ CREATE TABLE IF NOT EXISTS mark_game_associations (
+ mark_id INTEGER,
+ game_id INTEGER,
+ FOREIGN KEY (mark_id) REFERENCES marks (id),
+ FOREIGN KEY (game_id) REFERENCES games (id),
+ PRIMARY KEY (mark_id, game_id)
+ )
+ ''')
+
+ marks = [
+ ("Game Boy", "images/marks/GB_icon_HOME.png", ["Red", "Blue", "Yellow", "Gold", "Silver", "Crystal"]),
+ ("Kalos", "images/marks/Blue_pentagon_HOME.png", ["X", "Y", "Omega Ruby", "Alpha Sapphire"]),
+ ("Alola", "images/marks/Black_clover_HOME.png", ["Sun", "Moon", "Ultra Sun", "Ultra Moon"]),
+ ("Let's Go", "images/marks/Let's_Go_icon_HOME.png", ["Let's Go Pikachu", "Let's Go Eevee"]),
+ ("Galar", "images/marks/Galar_symbol_HOME.png", ["Sword", "Shield"]),
+ ("Sinnoh", "images/marks/BDSP_icon_HOME.png", ["Brilliant Diamond", "Shining Pearl"]),
+ ("Hisui", "images/marks/Arceus_mark_HOME.png", ["Legends Arceus"]),
+ ("Paldea", "images/marks/Paldea_icon_HOME.png", ["Scarlet", "Violet"]),
+ ]
+
+ # Check if marks already exist
+ cursor.execute('SELECT COUNT(*) FROM marks')
+ marks_count = cursor.fetchone()[0]
+
+ if marks_count == 0:
+ for mark in marks:
+ cursor.execute('''
+ INSERT OR IGNORE INTO marks (name, icon_path)
+ VALUES (?, ?)
+ ''', (mark[0], mark[1]))
+
+ mark_id = cursor.lastrowid
+
+ for game_name in mark[2]:
+ cursor.execute('''
+ INSERT OR IGNORE INTO mark_game_associations (mark_id, game_id)
+ SELECT ?, id FROM games WHERE name = ?
+ ''', (mark_id, game_name))
+
+ def create_games_table(self, cursor):
+
+ cursor.execute('''
+ CREATE TABLE IF NOT EXISTS games (
+ id INTEGER PRIMARY KEY,
+ name TEXT NOT NULL,
+ generation INTEGER NOT NULL
+ )
+ ''')
+
+ cursor.execute('''
+ CREATE TABLE IF NOT EXISTS alternate_game_names (
+ id INTEGER PRIMARY KEY,
+ game_id INTEGER NOT NULL,
+ alternate_name TEXT NOT NULL,
+ FOREIGN KEY (game_id) REFERENCES games (id),
+ UNIQUE (alternate_name COLLATE NOCASE)
+ )
+ ''')
+
+ games = [
+ ("Red", 1, ["Red Version"]),
+ ("Blue", 1, ["Blue Version"]),
+ ("Yellow", 1, ["Yellow Version"]),
+ ("Gold", 2, ["Gold Version"]),
+ ("Silver", 2, ["Silver Version"]),
+ ("Crystal", 2, ["Crystal Version"]),
+ ("Ruby", 3, ["Ruby Version"]),
+ ("Sapphire", 3, ["Sapphire Version"]),
+ ("Emerald", 3, ["Emerald Version"]),
+ ("FireRed", 3, ["Fire Red", "Fire-Red"]),
+ ("LeafGreen", 3, ["Leaf Green", "Leaf-Green"]),
+ ("Diamond", 4, ["Diamond Version"]),
+ ("Pearl", 4, ["Pearl Version"]),
+ ("Platinum", 4, ["Platinum Version"]),
+ ("HeartGold", 4, ["Heart Gold", "Heart-Gold"]),
+ ("SoulSilver", 4, ["Soul Silver", "Soul-Silver"]),
+ ("Black", 5, ["Black Version"]),
+ ("White", 5, ["White Version"]),
+ ("Black 2", 5, ["Black Version 2", "Black-2"]),
+ ("White 2", 5, ["White Version 2", "White-2"]),
+ ("X", 6, ["X Version"]),
+ ("Y", 6, ["Y Version"]),
+ ("Omega Ruby", 6, ["Omega Ruby Version", "Omega-Ruby"]),
+ ("Alpha Sapphire", 6, ["Alpha Sapphire Version", "Alpha-Sapphire"]),
+ ("Sun", 7, ["Sun Version"]),
+ ("Moon", 7, ["Moon Version"]),
+ ("Ultra Sun", 7, ["Ultra Sun Version", "Ultra-Sun"]),
+ ("Ultra Moon", 7, ["Ultra Moon Version", "Ultra-Moon"]),
+ ("Let's Go Pikachu", 7, ["Let's Go, Pikachu!", "Lets Go Pikachu"]),
+ ("Let's Go Eevee", 7, ["Let's Go, Eevee!", "Lets Go Eevee"]),
+ ("Sword", 8, ["Sword Version"]),
+ ("Shield", 8, ["Shield Version"]),
+ ("Expansion Pass", 8, ["Expansion Pass (Sword)", "Expansion Pass (Shield)"]),
+ ("Brilliant Diamond", 8, ["Brilliant Diamond Version", "Brilliant-Diamond"]),
+ ("Shining Pearl", 8, ["Shining Pearl Version", "Shining-Pearl"]),
+ ("Legends Arceus", 8, ["Legends: Arceus", "Legends-Arceus"]),
+ ("Scarlet", 9, ["Scarlet Version"]),
+ ("Violet", 9, ["Violet Version"]),
+ ("The Teal Mask", 9, ["The Teal Mask Version", "The Teal Mask (Scarlet)", "The Teal Mask (Violet)"]),
+ ("The Hidden Treasure of Area Zero", 9, ["The Hidden Treasure of Area Zero Version", "The Hidden Treasure of Area Zero (Scarlet)", "The Hidden Treasure of Area Zero (Violet)"]),
+
+ ("Pokémon Home", 98, ["Pokémon HOME"]),
+ ("Pokémon Go", 99, ["Pokémon GO"]),
+ ]
+
+ for game in games:
+ cursor.execute('''
+ INSERT OR IGNORE INTO games (name, generation)
+ VALUES (?, ?)
+ ''', (game[0], game[1]))
+
+ game_id = cursor.lastrowid
+
+ # Insert alternate names
+ for alt_name in game[2]:
+ cursor.execute('''
+ INSERT OR IGNORE INTO alternate_game_names (game_id, alternate_name)
+ VALUES (?, ?)
+ ''', (game_id, alt_name))
+
+ def load_pokemon_details(self, pfic):
+ self.cursor.execute('''
+ SELECT pf.name, pf.form_name, pf.national_dex, pf.generation, ps.storable_in_home, pf.is_baby_form
+ FROM pokemon_forms pf
+ LEFT JOIN pokemon_storage ps ON pf.PFIC = ps.PFIC
+ WHERE pf.PFIC = ?
+ ''', (pfic,))
+
+ return self.cursor.fetchone()
+
+ def send_pokemon_list(self, data):
+ # Fetch pokemon list from database
+ self.cursor.execute('''
+ SELECT pf.PFIC, pf.name, pf.form_name, pf.national_dex
+ FROM pokemon_forms pf
+ ''')
+ pokemon_data = self.cursor.fetchall()
+
+ # Sort the pokemon_data based on PFIC
+ pokemon_data.sort(key=lambda x: parse_pfic(x[0]))
+ return pokemon_data
+
+ def get_home_storable(self, pfic):
+ self.cursor.execute('SELECT storable_in_home FROM pokemon_storage WHERE PFIC = ?', (pfic,))
+ result = self.cursor.fetchone()
+ home_storable = result[0] if result else False
+ return home_storable
+
+ def get_evolution_chain(self, pfic):
+ def follow_chain(start_pfic, visited=None):
+ if visited is None:
+ visited = set()
+
+ chain = []
+ stack = [(start_pfic, None)]
+
+ while stack:
+ current_pfic, method = stack.pop()
+ if current_pfic in visited:
+ continue
+
+ visited.add(current_pfic)
+ self.cursor.execute('SELECT name, form_name FROM pokemon_forms WHERE PFIC = ?', (current_pfic,))
+ name, form_name = self.cursor.fetchone()
+
+ chain.append((current_pfic, name, form_name, method))
+
+ # Get previous evolutions
+ self.cursor.execute('SELECT from_pfic, method FROM evolution_chains WHERE to_pfic = ?', (current_pfic,))
+ prev_evolutions = self.cursor.fetchall()
+ for prev_pfic, prev_method in prev_evolutions:
+ if prev_pfic not in visited:
+ stack.append((prev_pfic, prev_method))
+
+ # Get next evolutions
+ self.cursor.execute('SELECT to_pfic, method FROM evolution_chains WHERE from_pfic = ?', (current_pfic,))
+ next_evolutions = self.cursor.fetchall()
+ for next_pfic, next_method in next_evolutions:
+ if next_pfic not in visited:
+ stack.append((next_pfic, next_method))
+
+ return chain
+
+ return follow_chain(pfic)
+
+ def get_evolution_parent(self, pfic):
+ self.cursor.execute('SELECT from_pfic FROM evolution_chains WHERE to_pfic = ?', (pfic,))
+ return self.cursor.fetchone()
+
+ def get_encounter_locations(self, pfic):
+ self.cursor.execute('''
+ SELECT g.name, e.location, e.day, e.time, e.dual_slot, e.static_encounter_count, e.static_encounter, e.extra_text, e.stars, e.rods, e.fishing
+ FROM encounters e
+ JOIN games g ON e.game_id = g.id
+ WHERE e.pfic = ?
+ ORDER BY g.name, e.location
+ ''', (pfic,))
+ return self.cursor.fetchall()
+
+ def get_game_generation(self, game):
+ self.cursor.execute('''
+ SELECT g.generation
+ FROM games g
+ LEFT JOIN alternate_game_names agn ON g.id = agn.game_id
+ WHERE g.name = ? OR agn.alternate_name = ?
+ LIMIT 1
+ ''', (game, game))
+ result = self.cursor.fetchone()
+ return result[0] if result else None
+
+ def get_game_id_for_name(self, game):
+ # First, try to find the game in the main games table
+ self.cursor.execute('''
+ SELECT id
+ FROM games
+ WHERE name = ?
+ ''', (game,))
+ result = self.cursor.fetchone()
+
+ if result:
+ return result[0]
+
+ # If not found, check the alternate_game_names table
+ self.cursor.execute('''
+ SELECT game_id
+ FROM alternate_game_names
+ WHERE alternate_name = ?
+ ''', (game,))
+ result = self.cursor.fetchone()
+
+ return result[0] if result else None
+
+ def get_pokemon_with_encounters(self, data):
+ self.cursor.execute('''
+ SELECT DISTINCT pfic
+ FROM encounters
+ ''')
+ pokemon_with_encounters = set(row[0] for row in self.cursor.fetchall())
+ return pokemon_with_encounters
+
+ def refresh_in_memory_db(self, temp_conn):
+ temp_conn.backup(self.conn)
+
+ def clear_encounters_for_pokemon(self, pfic):
+ self.cursor.execute('DELETE FROM encounters WHERE pfic = ?', (pfic,))
+ self.conn.commit()
diff --git a/DBEditor/event_system.py b/DBEditor/event_system.py
index da891db..339d8df 100644
--- a/DBEditor/event_system.py
+++ b/DBEditor/event_system.py
@@ -20,35 +20,28 @@ class EventSystem:
with self.lock:
self.listeners[event_type].remove(callback)
- def emit(self, event_type, data=None, callback=None):
- self.event_queue.put((event_type, data, callback))
+ def emit(self, event_type, data=None):
+ self.event_queue.put((event_type, data))
def emit_sync(self, event_type, data=None):
- results = []
- with self.lock:
- for listener in self.listeners[event_type]:
- result = listener(data)
- results.append(result)
- return results
+ #with self.lock:
+ for listener in self.listeners[event_type]:
+ listener(data)
def call_sync(self, event_type, data=None):
- with self.lock:
- if event_type in self.listeners and self.listeners[event_type]:
- # Call only the first registered listener
- return self.listeners[event_type][0](data)
+ #with self.lock:
+ if event_type in self.listeners and self.listeners[event_type]:
+ # Call only the first registered listener
+ return self.listeners[event_type][0](data)
return None
def _process_events(self):
while not self._stop_event.is_set():
try:
- event_type, data, callback = self.event_queue.get(timeout=0.1)
- results = []
+ event_type, data = self.event_queue.get(timeout=0.1)
with self.lock:
for listener in self.listeners[event_type]:
- result = listener(data)
- results.append(result)
- if callback:
- callback(results)
+ listener(data)
except Empty:
pass
diff --git a/DBEditor/plan.py b/DBEditor/plan.py
new file mode 100644
index 0000000..88ee68d
--- /dev/null
+++ b/DBEditor/plan.py
@@ -0,0 +1,269 @@
+import sqlite3
+from collections import defaultdict
+
+class OriginDexPlanner:
+ def __init__(self, db_path):
+ self.conn = sqlite3.connect(db_path)
+ self.conn.row_factory = sqlite3.Row
+
+ def get_game_data(self):
+ """Fetch game and pokemon information from the database."""
+ cursor = self.conn.cursor()
+ cursor.execute("SELECT * FROM games")
+ games = cursor.fetchall()
+
+ cursor.execute("SELECT * FROM pokemon_forms WHERE name IN ('Elekid', 'Electabuzz', 'Electivire')")
+ pokemon_forms = cursor.fetchall()
+
+ cursor.execute("SELECT * FROM encounters")
+ encounters = cursor.fetchall()
+
+ exclusive_encounters = []
+ cursor.execute("SELECT * FROM evolution_chains WHERE from_pfic IN (SELECT PFIC FROM pokemon_forms WHERE name IN ('Elekid', 'Electabuzz', 'Electivire'))")
+ evolutions = cursor.fetchall()
+
+ return games, pokemon_forms, encounters, exclusive_encounters, evolutions
+
+ def build_pokemon_data(self):
+ """Construct data dictionaries to store relationships between the Pokemon and encounters."""
+ games, pokemon_forms, encounters, exclusive_encounters, evolutions = self.get_game_data()
+
+ pokemon_by_gen = defaultdict(list)
+ game_by_gen = defaultdict(list)
+ encounter_data = defaultdict(list)
+
+ for game in games:
+ game_by_gen[game['generation']].append(game)
+
+ for pokemon in pokemon_forms:
+ pokemon_by_gen[pokemon['generation']].append(pokemon)
+
+ # Build a dict of encounters, mapping game_id to Pokemon encountered in it
+ for encounter in encounters:
+ encounter_data[encounter['game_id']].append(encounter)
+
+ evolution_map = defaultdict(list)
+ for evolution in evolutions:
+ from_pfic = evolution['from_pfic']
+ to_pfic = evolution['to_pfic']
+ # Lookup generation from pokemon_forms table
+ cursor = self.conn.cursor()
+ cursor.execute("SELECT generation FROM pokemon_forms WHERE PFIC = ?", (to_pfic,))
+ to_generation = cursor.fetchone()['generation']
+ evolution_map[from_pfic].append((to_pfic, to_generation))
+
+ exclusive_group_map = defaultdict(list)
+ for exclusive_encounter in exclusive_encounters:
+ exclusive_group_map[exclusive_encounter['group_id']].append(exclusive_encounter['encounter_id'])
+
+ return pokemon_by_gen, game_by_gen, encounter_data, evolution_map, exclusive_group_map
+
+ def generate_plan(self, generations_to_group_list=None):
+ """Generate a game plan to catch all Pokemon in their origin generation."""
+ if generations_to_group_list is None:
+ generations_to_group_list = []
+
+ pokemon_by_gen, game_by_gen, encounter_data, evolution_map, exclusive_group_map = self.build_pokemon_data()
+
+ plan = []
+ pokemon_to_catch = defaultdict(list)
+ caught_pokemon = set()
+ pokemon_names = {}
+
+ # Handle multiple sets of grouped generations
+ grouped_generations_sets = [set(generations) for generations in generations_to_group_list]
+ for grouped_generations in grouped_generations_sets:
+ grouped_games = []
+ grouped_pokemon_list = []
+ for gen in grouped_generations:
+ if gen in game_by_gen:
+ grouped_games.extend(game_by_gen[gen])
+ grouped_pokemon_list.extend(pokemon_by_gen[gen])
+
+ if grouped_games:
+ plan.extend(self.generate_plan_for_generation(grouped_games, grouped_pokemon_list, encounter_data, evolution_map, exclusive_group_map, pokemon_names, caught_pokemon, game_by_gen))
+
+ # Loop through each generation, generating a plan for each game
+ for gen in sorted(game_by_gen.keys()):
+ # Skip generations that have been grouped
+ if any(gen in grouped_generations for grouped_generations in grouped_generations_sets):
+ continue
+ games = game_by_gen[gen]
+ pokemon_list = pokemon_by_gen[gen]
+
+ plan.extend(self.generate_plan_for_generation(games, pokemon_list, encounter_data, evolution_map, exclusive_group_map, pokemon_names, caught_pokemon, game_by_gen))
+
+ return plan
+
+ def generate_plan_for_generation(self, games, pokemon_list, encounter_data, evolution_map, exclusive_group_map, pokemon_names, caught_pokemon, game_by_gen):
+ """Generate a game plan for a specific generation or group of generations."""
+ plan = []
+ pokemon_to_catch = defaultdict(list)
+ pokemon_to_breed = defaultdict(list)
+ catchable_pokemon = set()
+
+ # Create a set of baby Pokémon PFICs
+ baby_pokemon = set(pokemon['PFIC'] for pokemon in pokemon_list if pokemon['is_baby_form'])
+
+ # Identify unique evolution chains and the starting point
+ for pokemon in pokemon_list:
+ pfic = pokemon['PFIC']
+ pokemon_names[pfic] = f'{pokemon["name"]} ({pokemon["form_name"] if pokemon["form_name"] is not None else ""})'
+ if pfic not in evolution_map: # Not evolved from anything
+ catchable_pokemon.add(pfic)
+ else:
+ catchable_pokemon.add(pfic)
+ # Add all evolution stages to catchable list if they belong to the current or previous generations
+ current = pfic
+ current_generation = pokemon['generation']
+ while current in evolution_map:
+ next_pfic, next_generation = evolution_map[current][0]
+ if any(p['PFIC'] == next_pfic for p in pokemon_list):
+ if next_generation <= current_generation:
+ catchable_pokemon.add(next_pfic)
+ current = next_pfic
+
+ # Determine the best game to catch the most Pokemon
+ best_game = None
+ max_catchable = 0
+ game_catchable_pokemon = defaultdict(set)
+ for game in games:
+ game_id = game['id']
+ encounters = encounter_data[game_id]
+
+ # Track how many unique Pokemon are available in this game
+ for encounter in encounters:
+ pfic = encounter['pfic']
+ if pfic in catchable_pokemon:
+ game_catchable_pokemon[game_id].add(pfic)
+
+ # Update the best game if this game has more catchable Pokemon
+ if len(game_catchable_pokemon[game_id]) > max_catchable:
+ max_catchable = len(game_catchable_pokemon[game_id])
+ best_game = game
+
+ # Use the best game to catch as many unique Pokemon as possible
+ remaining_games = [game for game in games if game != best_game]
+ if best_game:
+ game_id = best_game['id']
+ game_name = best_game['name']
+ encounters = encounter_data[game_id]
+
+ for encounter in encounters:
+ pfic = encounter['pfic']
+ if pfic in catchable_pokemon and pfic not in caught_pokemon:
+ evolution_chain = self.get_full_evolution_chain(pfic, evolution_map)
+ base_pokemon = evolution_chain[0]
+ if base_pokemon not in caught_pokemon:
+ # Calculate the number of Pokemon needed for the full evolution chain
+ count = len(evolution_chain)
+ if encounter['static_encounter']:
+ count = min(count, encounter['static_encounter_count'] or 1)
+
+ if base_pokemon in baby_pokemon:
+ # For baby Pokémon, catch the first non-baby evolution and breed for the baby
+ non_baby_pokemon = next((p for p in evolution_chain if p not in baby_pokemon), None)
+ if non_baby_pokemon:
+ pokemon_to_catch[game_name].append({'pfic': non_baby_pokemon, 'count': 1})
+ pokemon_to_breed[game_name].append({'pfic': base_pokemon, 'count': 1})
+ else:
+ pokemon_to_catch[game_name].append({'pfic': base_pokemon, 'count': count})
+
+ caught_pokemon.update(evolution_chain)
+
+ # Account for exclusive encounters
+ exclusive_group_ids = [group['group_id'] for group in exclusive_group_map if group['encounter_id'] == encounter['id']]
+ if exclusive_group_ids:
+ other_options = exclusive_group_map[exclusive_group_ids[0]]
+ if len(other_options) > 1:
+ # Pick one of the options, mark the rest to catch in another game
+ catchable_pokemon.remove(pfic)
+ else:
+ continue
+
+ # Use remaining games to catch any remaining Pokemon
+ for game in remaining_games:
+ game_id = game['id']
+ game_name = game['name']
+ encounters = encounter_data[game_id]
+
+ for encounter in encounters:
+ pfic = encounter['pfic']
+ if pfic in catchable_pokemon and pfic not in caught_pokemon:
+ evolution_chain = self.get_full_evolution_chain(pfic, evolution_map)
+ base_pokemon = evolution_chain[0]
+ if base_pokemon not in caught_pokemon:
+ # Calculate the number of Pokemon needed for the full evolution chain
+ count = len(evolution_chain)
+ if encounter['static_encounter']:
+ count = min(count, encounter['static_encounter_count'] or 1)
+
+ if base_pokemon in baby_pokemon:
+ # For baby Pokémon, catch the first non-baby evolution and breed for the baby
+ non_baby_pokemon = next((p for p in evolution_chain if p not in baby_pokemon), None)
+ if non_baby_pokemon:
+ pokemon_to_catch[game_name].append({'pfic': non_baby_pokemon, 'count': 1})
+ pokemon_to_breed[game_name].append({'pfic': base_pokemon, 'count': 1})
+ else:
+ pokemon_to_catch[game_name].append({'pfic': base_pokemon, 'count': count})
+
+ caught_pokemon.update(evolution_chain)
+
+ # Handle new evolutions or forms added in later generations
+ for pfic in list(caught_pokemon):
+ if pfic in evolution_map:
+ for new_evolution, new_generation in evolution_map[pfic]:
+ # Check if the new evolution is from a later generation
+ full_evolution_chain = self.get_full_evolution_chain(pfic, evolution_map)
+ current_generation = min((pokemon['generation'] for pokemon in pokemon_list if pokemon['PFIC'] in full_evolution_chain), default=None)
+ if new_generation and current_generation and new_generation > current_generation:
+ # Add the baby/base form to be caught in the new generation if required
+ base_pokemon = full_evolution_chain[0]
+ new_gen_games = game_by_gen[new_generation]
+ for game in new_gen_games:
+ game_id = game['id']
+ game_name = game['name']
+ encounters = encounter_data[game_id]
+ for encounter in encounters:
+ if encounter['pfic'] == base_pokemon and base_pokemon not in caught_pokemon:
+ if base_pokemon in baby_pokemon:
+ non_baby_pokemon = next((p for p in full_evolution_chain if p not in baby_pokemon), None)
+ if non_baby_pokemon:
+ pokemon_to_catch[game_name].append({'pfic': non_baby_pokemon, 'count': 1})
+ pokemon_to_breed[game_name].append({'pfic': base_pokemon, 'count': 1})
+ else:
+ pokemon_to_catch[game_name].append({'pfic': base_pokemon, 'count': 1})
+ caught_pokemon.add(base_pokemon)
+ break
+
+ # Generate the plan for this generation or group of generations
+ for game_name in set(list(pokemon_to_catch.keys()) + list(pokemon_to_breed.keys())):
+ plan.append(f"Play {game_name}:")
+ if game_name in pokemon_to_catch:
+ plan.append(f" Catch {len(pokemon_to_catch[game_name])} unique Pokemon:")
+ for pokemon in pokemon_to_catch[game_name]:
+ plan.append(f" - {pokemon_names[pokemon['pfic']]}: {pokemon['count']} times")
+
+ if game_name in pokemon_to_breed:
+ plan.append(f" Breed {len(pokemon_to_breed[game_name])} Pokemon:")
+ for pokemon in pokemon_to_breed[game_name]:
+ plan.append(f" - {pokemon_names[pokemon['pfic']]}: {pokemon['count']} times")
+
+ return plan
+
+ def get_full_evolution_chain(self, pfic, evolution_map):
+ """Get the full evolution chain for a given PFIC."""
+ chain = [pfic]
+ while pfic in evolution_map:
+ pfic = evolution_map[pfic][0][0]
+ chain.append(pfic)
+ return chain
+
+ def display_plan(self, generations_to_group_list=None):
+ plan = self.generate_plan(generations_to_group_list)
+ for step in plan:
+ print(step)
+
+# Example usage
+planner = OriginDexPlanner('pokemon_forms.db')
+planner.display_plan(generations_to_group_list=[[1, 2], [3, 4, 5, 6]])
\ No newline at end of file
diff --git a/DBEditor/plan2.py b/DBEditor/plan2.py
new file mode 100644
index 0000000..d1a158d
--- /dev/null
+++ b/DBEditor/plan2.py
@@ -0,0 +1,262 @@
+import sqlite3
+import os
+from collections import defaultdict
+
+class EfficiencyOriginDexPlanner:
+ def __init__(self, db_path):
+ self.conn = sqlite3.connect(db_path)
+ self.conn.row_factory = sqlite3.Row
+
+ def get_all_data(self):
+ cursor = self.conn.cursor()
+ cursor.execute("SELECT * FROM games ORDER BY generation, id")
+ games = cursor.fetchall()
+
+ cursor.execute("SELECT * FROM pokemon_forms ORDER BY generation, national_dex")
+ pokemon_forms = cursor.fetchall()
+
+ cursor.execute("SELECT * FROM encounters")
+ encounters = cursor.fetchall()
+
+ cursor.execute("SELECT * FROM evolution_chains")
+ evolutions = cursor.fetchall()
+
+ return games, pokemon_forms, encounters, evolutions
+
+ def build_data_structures(self):
+ games, pokemon_forms, encounters, evolutions = self.get_all_data()
+
+ pokemon_by_gen = defaultdict(list)
+ game_by_gen = defaultdict(list)
+ encounter_data = defaultdict(list)
+ evolution_map = defaultdict(list)
+
+ for game in games:
+ game_by_gen[game['generation']].append(game)
+
+ for pokemon in pokemon_forms:
+ pokemon_by_gen[pokemon['generation']].append(pokemon)
+
+ for encounter in encounters:
+ encounter_data[encounter['game_id']].append(encounter)
+
+ for evolution in evolutions:
+ evolution_map[evolution['from_pfic']].append(evolution['to_pfic'])
+
+ return pokemon_by_gen, game_by_gen, encounter_data, evolution_map
+
+ def generate_efficient_plan(self, generation_groups):
+ pokemon_by_gen, game_by_gen, encounter_data, evolution_map = self.build_data_structures()
+ plan = []
+ caught_pokemon = set()
+
+ 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)
+
+ return plan
+
+ def plan_for_group(self, generations, pokemon_by_gen, game_by_gen, encounter_data, evolution_map, caught_pokemon):
+ group_plan = []
+ needed_pokemon = set()
+ games_in_group = []
+
+ for gen in generations:
+ needed_pokemon.update(pokemon['PFIC'] for pokemon in pokemon_by_gen[gen])
+ games_in_group.extend(game_by_gen[gen])
+
+ # Check for new evolutions of already caught Pokémon
+ new_evolutions = set()
+ for pfic in caught_pokemon:
+ if pfic in evolution_map:
+ for evolved_pfic in evolution_map[pfic]:
+ if self.get_pokemon_generation(evolved_pfic) in generations and evolved_pfic not in caught_pokemon:
+ new_evolutions.add(pfic)
+ needed_pokemon.add(evolved_pfic)
+ print(f"New evolution: {self.get_pokemon_name(pfic)} into {self.get_pokemon_name(evolved_pfic)}")
+
+ games_in_group.sort(key=lambda g: len([e for e in encounter_data[g['id']] if e['pfic'] in needed_pokemon]), reverse=True)
+
+ for game in games_in_group:
+ 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)
+
+ return group_plan
+
+ def plan_for_game(self, game, needed_pokemon, encounter_data, evolution_map, caught_pokemon, target_generations, new_evolutions):
+ game_plan = []
+ to_catch = defaultdict(int)
+ to_evolve = defaultdict(list)
+ to_breed = defaultdict(list)
+ planned_evolutions = defaultdict(int)
+ processed_chains = set()
+
+ # First, handle new evolutions for already caught Pokémon
+ for pfic in new_evolutions:
+ evolution_chains, visit_counts, baby_forms = self.get_evolution_chains(pfic, evolution_map, target_generations)
+
+ new_evolutions_count = sum(1 for chain in evolution_chains for pokemon in chain if pokemon not in caught_pokemon)
+
+ if new_evolutions_count > 0:
+ if any(encounter['pfic'] == pfic for encounter in encounter_data[game['id']]):
+ to_catch[pfic] += new_evolutions_count - planned_evolutions[pfic]
+ planned_evolutions[pfic] += new_evolutions_count
+
+ for chain in evolution_chains:
+ if len(chain) > 1:
+ for i in range(len(chain) - 1):
+ from_pfic, to_pfic = chain[i], chain[i+1]
+ if to_pfic not in caught_pokemon:
+ to_evolve[from_pfic].append(to_pfic)
+ caught_pokemon.add(to_pfic)
+ needed_pokemon.discard(to_pfic)
+
+ # Then proceed with the regular planning
+ for encounter in encounter_data[game['id']]:
+ if encounter['pfic'] in needed_pokemon and encounter['pfic'] not in caught_pokemon:
+ evolution_chains, visit_counts, baby_forms = self.get_evolution_chains(encounter['pfic'], evolution_map, target_generations)
+ base_form = evolution_chains[0][0]
+
+ if base_form not in caught_pokemon:
+ chain_key = tuple(sorted(set(pokemon for chain in evolution_chains for pokemon in chain)))
+ if chain_key not in processed_chains:
+ processed_chains.add(chain_key)
+
+ num_to_catch = max(0, visit_counts[base_form] - planned_evolutions[base_form])
+ if num_to_catch > 0:
+ to_catch[encounter['pfic']] += num_to_catch
+ planned_evolutions[base_form] += num_to_catch
+
+ for chain in evolution_chains:
+ if len(chain) > 1:
+ for i in range(len(chain) - 1):
+ from_pfic, to_pfic = chain[i], chain[i+1]
+ if from_pfic not in baby_forms:
+ if not self.is_final_evolution(to_pfic, evolution_map) or (self.is_final_evolution(to_pfic, evolution_map) and not self.is_in_to_evolve(to_pfic, to_evolve)):
+ to_evolve[from_pfic].append(to_pfic)
+ else:
+ to_catch[encounter['pfic']] += -1
+ planned_evolutions[base_form] += -1
+
+ if from_pfic in baby_forms and from_pfic not in encounter_data[game['id']]:
+ if to_pfic not in to_breed or from_pfic not in to_breed[to_pfic]:
+ to_breed[to_pfic].append(from_pfic)
+
+ caught_pokemon.update(pfic for chain in evolution_chains for pfic in chain)
+ needed_pokemon.difference_update(pfic for chain in evolution_chains for pfic in chain)
+
+ 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
+
+ def plan_evolutions(self, evolution_chains, evolution_map, caught_pokemon):
+ chains, visit_counts = self.get_evolution_chains(evolution_chains[0][0], evolution_map)
+ evolution_plan = []
+ needed_counts = defaultdict(int)
+
+ # Count how many of each Pokémon we need based on visit counts
+ for pfic, count in visit_counts.items():
+ if pfic not in caught_pokemon:
+ needed_counts[pfic] = count
+
+ # Plan evolutions
+ for chain in chains:
+ for i in range(len(chain) - 1):
+ from_pfic, to_pfic = chain[i], chain[i+1]
+ if needed_counts[to_pfic] > 0:
+ evolution_plan.append((from_pfic, to_pfic))
+ needed_counts[to_pfic] -= 1
+ needed_counts[from_pfic] -= 1
+
+ return evolution_plan, needed_counts
+
+ def get_evolution_chains(self, pfic, evolution_map, target_generations):
+ visited = defaultdict(int)
+ unique_paths = set()
+ baby_forms = set()
+
+ def dfs(current_pfic, path):
+ path_tuple = tuple(path)
+ if path_tuple in unique_paths:
+ return
+
+ unique_paths.add(path_tuple)
+ for pfic in path:
+ visited[pfic] += 1
+ if self.is_baby_pokemon(pfic):
+ baby_forms.add(pfic)
+
+ if current_pfic in evolution_map:
+ for next_pfic in evolution_map[current_pfic]:
+ if self.get_pokemon_generation(next_pfic) in target_generations:
+ dfs(next_pfic, path + [next_pfic])
+
+ dfs(pfic, [pfic])
+ chains = [list(path) for path in unique_paths]
+
+ # Adjust visit counts for baby Pokémon
+ for baby in baby_forms:
+ visited[baby] = 1
+
+ return chains, visited, baby_forms
+
+ def get_pokemon_name(self, pfic):
+ cursor = self.conn.cursor()
+ cursor.execute("SELECT name, form_name FROM pokemon_forms WHERE PFIC = ?", (pfic,))
+ result = cursor.fetchone()
+ if result['form_name']:
+ return f"{result['name']} ({result['form_name']})"
+ return result['name']
+
+ def display_plan(self, generation_groups, output_file='efficiency_plan.txt'):
+ plan = self.generate_efficient_plan(generation_groups)
+
+ # Print to console
+ for step in plan:
+ print(step)
+
+ # Write to file
+ with open(output_file, 'w', encoding='utf-8') as f:
+ for step in plan:
+ f.write(f"{step}\n")
+
+ print(f"\nPlan has been written to {os.path.abspath(output_file)}")
+
+ def is_baby_pokemon(self, pfic):
+ cursor = self.conn.cursor()
+ cursor.execute("SELECT is_baby_form FROM pokemon_forms WHERE PFIC = ?", (pfic,))
+ result = cursor.fetchone()
+ return result['is_baby_form'] if result else False
+
+ def get_pokemon_generation(self, pfic):
+ cursor = self.conn.cursor()
+ cursor.execute("SELECT generation FROM pokemon_forms WHERE PFIC = ?", (pfic,))
+ result = cursor.fetchone()
+ return result['generation'] if result else None
+
+ def is_final_evolution(self, pfic, evolution_map):
+ return pfic not in evolution_map
+
+ def is_in_to_evolve(self, pfic, to_evolve):
+ return any(pfic in to_pfics for to_pfics in to_evolve.values())
+
+# Example usage
+planner = EfficiencyOriginDexPlanner('pokemon_forms.db')
+planner.display_plan([[1, 2], [3, 4, 5, 6], [7], [8], [9]])
+
diff --git a/DBEditor/pokemon_db_ui.py b/DBEditor/pokemon_db_ui.py
index 3208cca..c743ac8 100644
--- a/DBEditor/pokemon_db_ui.py
+++ b/DBEditor/pokemon_db_ui.py
@@ -5,14 +5,18 @@ from PyQt6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QH
QLabel, QCheckBox, QPushButton, QFormLayout, QListWidgetItem, QSplitter, QTreeWidget,
QTreeWidgetItem, QDialog, QDialogButtonBox, QComboBox, QMessageBox, QSpinBox, QMenu, QTabWidget,
QTextEdit)
-from PyQt6.QtCore import Qt, QSize
+from PyQt6.QtCore import Qt, QSize, QTimer, QMetaObject
from PyQt6.QtGui import QPixmap, QFontMetrics, QColor, QAction
+from collections import deque
+
from event_system import event_system
+import logging
class EvolutionEditDialog(QDialog):
def __init__(self, parent=None, from_pfic=None, to_pfic=None, method=None):
super().__init__(parent)
+
self.setWindowTitle("Edit Evolution")
self.setModal(True)
@@ -59,8 +63,34 @@ class EvolutionEditDialog(QDialog):
class PokemonUI(QWidget): # Change from QMainWindow to QWidget
def __init__(self, parent=None):
super().__init__(parent)
+
+ self.log_queue = deque() # Queue to store log messages
+ self.log_timer = QTimer(self)
+ self.log_timer.timeout.connect(self.process_log_queue)
+ self.log_timer.start(100)
+
+ event_system.add_listener('refresh_pokemon_details_panel', self.refresh)
+ event_system.add_listener('update_log_display', self.queue_log_message)
+ event_system.add_listener('clear_log_display', self.clear_log_display)
+
+ self.logger = logging.getLogger('ui_feedback')
+
+ self.encounter_cache = {}
+ self.evolution_load_timer = QTimer()
+ self.evolution_load_timer.setSingleShot(True)
+ self.evolution_load_timer.timeout.connect(self._load_evolution_chain)
+ self.current_evolution_pfic = None
self.init_ui()
self.request_pokemon_list()
+ self.logger.info("Initializing PokemonUI")
+
+ def queue_log_message(self, message):
+ self.log_queue.append(message)
+
+ def process_log_queue(self):
+ while self.log_queue:
+ message = self.log_queue.popleft()
+ self.update_log_display(message)
def init_ui(self):
main_layout = QVBoxLayout(self) # Use self directly instead of a central widget
@@ -86,7 +116,7 @@ class PokemonUI(QWidget): # Change from QMainWindow to QWidget
self.pokemon_list = QListWidget()
self.pokemon_list.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
- #self.pokemon_list.customContextMenuRequested.connect(self.show_pokemon_context_menu)
+ self.pokemon_list.customContextMenuRequested.connect(self.show_pokemon_context_menu)
self.pokemon_list.currentItemChanged.connect(self.on_pokemon_selected)
left_layout.addWidget(self.pokemon_list)
@@ -103,9 +133,10 @@ class PokemonUI(QWidget): # Change from QMainWindow to QWidget
main_tab_layout.addLayout(left_layout, 1)
# Right side: Edit panel
- right_layout = QHBoxLayout()
+ right_layout = QVBoxLayout()
# Left side of right panel: Text information
+ info_layout = QHBoxLayout()
text_layout = QVBoxLayout()
self.edit_form = QFormLayout()
self.name_label = QLabel()
@@ -124,54 +155,59 @@ class PokemonUI(QWidget): # Change from QMainWindow to QWidget
text_layout.addLayout(self.edit_form)
+ # Right side of right panel: Image
+ image_layout = QVBoxLayout()
+ self.image_label = QLabel()
+ self.image_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
+ self.image_label.setFixedSize(150, 150)
+ image_layout.addWidget(self.image_label)
+ image_layout.addStretch(1)
+
+ info_layout.addLayout(text_layout)
+ info_layout.addLayout(image_layout)
+
+ second_half_layout = QVBoxLayout()
# Evolution chain tree
self.evolution_tree = QTreeWidget()
self.evolution_tree.setHeaderLabels(["Pokémon", "Evolution Method"])
self.evolution_tree.setColumnWidth(0, 200)
- text_layout.addWidget(self.evolution_tree)
+ second_half_layout.addWidget(self.evolution_tree)
# Add Locations tree
self.locations_tree = QTreeWidget()
self.locations_tree.setHeaderLabels(["Game/Location", "Details"])
self.locations_tree.setColumnWidth(0, 200)
self.locations_tree.itemDoubleClicked.connect(self.edit_encounter)
- text_layout.addWidget(QLabel("Locations:"))
- text_layout.addWidget(self.locations_tree)
+ second_half_layout.addWidget(QLabel("Locations:"))
+ second_half_layout.addWidget(self.locations_tree)
# Add New Encounter button
self.add_encounter_button = QPushButton("Add New Encounter")
self.add_encounter_button.clicked.connect(self.add_new_encounter)
- text_layout.addWidget(self.add_encounter_button)
+ second_half_layout.addWidget(self.add_encounter_button)
# Move buttons to the bottom
- text_layout.addStretch(1)
-
- self.save_button = QPushButton("Save Changes")
- self.save_button.clicked.connect(self.save_changes)
- text_layout.addWidget(self.save_button)
-
- self.export_button = QPushButton("Export Database")
- self.export_button.clicked.connect(self.export_database)
- text_layout.addWidget(self.export_button)
+ second_half_layout.addStretch(1)
# Add New Evolution button
self.add_evolution_button = QPushButton("Add New Evolution")
self.add_evolution_button.clicked.connect(self.add_new_evolution)
- text_layout.addWidget(self.add_evolution_button)
+ second_half_layout.addWidget(self.add_evolution_button)
- # Right side of right panel: Image
- image_layout = QVBoxLayout()
- self.image_label = QLabel()
- self.image_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
- self.image_label.setFixedSize(200, 200)
- image_layout.addWidget(self.image_label)
- image_layout.addStretch(1)
-
- right_layout.addLayout(text_layout)
- right_layout.addLayout(image_layout)
+ right_layout.addLayout(info_layout)
+ right_layout.addLayout(second_half_layout)
main_tab_layout.addLayout(right_layout, 1)
+
+ self.save_button = QPushButton("Save Changes")
+ self.save_button.clicked.connect(self.save_changes)
+ main_layout.addWidget(self.save_button)
+
+ self.export_button = QPushButton("Export Database")
+ self.export_button.clicked.connect(self.export_database)
+ main_layout.addWidget(self.export_button)
+
# Database Operations tab
db_tab = QWidget()
db_tab_layout = QVBoxLayout(db_tab)
@@ -179,19 +215,19 @@ class PokemonUI(QWidget): # Change from QMainWindow to QWidget
# Add buttons to the Database Operations tab
gather_forms_btn = QPushButton("Gather Pokémon Forms")
- #gather_forms_btn.clicked.connect(self.gather_pokemon_forms)
+ gather_forms_btn.clicked.connect(self.gather_pokemon_forms)
db_tab_layout.addWidget(gather_forms_btn)
gather_home_btn = QPushButton("Gather Home Storage Info")
- #gather_home_btn.clicked.connect(self.gather_home_storage_info)
+ gather_home_btn.clicked.connect(self.gather_home_storage_info)
db_tab_layout.addWidget(gather_home_btn)
gather_evolutions_btn = QPushButton("Gather Evolution Information")
- #gather_evolutions_btn.clicked.connect(self.gather_evolution_info)
+ gather_evolutions_btn.clicked.connect(self.gather_evolution_info)
db_tab_layout.addWidget(gather_evolutions_btn)
gather_encounters_btn = QPushButton("Gather Encounter Information")
- #gather_encounters_btn.clicked.connect(self.gather_encounter_info)
+ gather_encounters_btn.clicked.connect(self.gather_encounter_info)
db_tab_layout.addWidget(gather_encounters_btn)
# Add QTextEdit for progress reporting
@@ -203,28 +239,40 @@ class PokemonUI(QWidget): # Change from QMainWindow to QWidget
db_tab_layout.addStretch(1) # Add stretch to separate the last button
reinit_db_btn = QPushButton("Clear and Reinitialize Database")
- #reinit_db_btn.clicked.connect(self.reinitialize_database)
+ reinit_db_btn.clicked.connect(self.reinitialize_database)
db_tab_layout.addWidget(reinit_db_btn)
+ encounter_tab = QWidget()
+ encounter_tab_layout = QVBoxLayout(encounter_tab)
+ self.tab_widget.addTab(encounter_tab, "Manage Encounters")
+
def on_pokemon_selected(self, item):
pfic = item.data(Qt.ItemDataRole.UserRole)
- pokemon_data = event_system.emit_sync('get_pokemon_data', data=pfic)
+ self.refresh_pokemon_details_panel(pfic)
+
+ def refresh(self, pfic):
+ self.refresh_pokemon_details_panel(pfic)
+ self.update_encounter_cache()
+ self.update_pokemon_list_highlights()
+
+ def refresh_pokemon_details_panel(self, pfic):
+ pokemon_data = event_system.call_sync('get_pokemon_data', data=pfic)
if pokemon_data:
- name, form_name, national_dex, generation, storable_in_home = pokemon_data[0]
+ name, form_name, national_dex, generation, storable_in_home, is_baby_form = pokemon_data
self.name_label.setText(name)
self.form_name_label.setText(form_name if form_name else "")
self.national_dex_label.setText(str(national_dex))
self.generation_label.setText(str(generation))
self.home_checkbox.setChecked(bool(storable_in_home))
#self.home_checkbox.stateChanged.connect(self.update_home_storable)
- self.is_baby_form_checkbox.setChecked(bool(False))
+ self.is_baby_form_checkbox.setChecked(bool(is_baby_form))
# Load and display the image
image_path = f"images-new/{pfic}.png"
if os.path.exists(image_path):
pixmap = QPixmap(image_path)
- self.image_label.setPixmap(pixmap.scaled(200, 200, Qt.AspectRatioMode.KeepAspectRatio, Qt.TransformationMode.SmoothTransformation))
+ self.image_label.setPixmap(pixmap.scaled(150, 150, Qt.AspectRatioMode.KeepAspectRatio, Qt.TransformationMode.SmoothTransformation))
else:
self.image_label.setText("Image not found")
@@ -232,15 +280,33 @@ class PokemonUI(QWidget): # Change from QMainWindow to QWidget
self.load_evolution_chain(pfic)
# Load and display encounter locations
- #self.load_encounter_locations(pfic)
+ self.load_encounter_locations(pfic)
self.current_pfic = pfic
self.add_evolution_button.setEnabled(True) # Enable the button when a Pokémon is selected
def load_evolution_chain(self, pfic):
- self.evolution_tree.clear()
+ self.current_evolution_pfic = pfic
+ if self.evolution_load_timer.isActive():
+ self.evolution_load_timer.stop()
+ self.evolution_load_timer.start(50) # 50ms delay
+
+ def _load_evolution_chain(self):
+ if not hasattr(self, 'evolution_tree') or self.evolution_tree is None:
+ print("Evolution tree widget not initialized")
+ return
+
+ pfic = self.current_evolution_pfic
+ if pfic is None:
+ return
+
+ try:
+ self.evolution_tree.clear()
+ except RuntimeError:
+ print("Error clearing evolution tree. Widget might have been deleted.")
+ return
- evolution_chain = event_system.emit_sync('get_evolution_chain', data=pfic)[0]
+ evolution_chain = event_system.call_sync('get_evolution_chain', data=pfic)
# Create a dictionary to store tree items
tree_items = {}
@@ -261,7 +327,7 @@ class PokemonUI(QWidget): # Change from QMainWindow to QWidget
item = tree_items[current_pfic]
# Find the parent of this item
- parent_pfic = event_system.emit_sync('get_evolution_parent', data=current_pfic)[0]
+ parent_pfic = event_system.call_sync('get_evolution_parent', data=current_pfic)
if parent_pfic:
parent_item = tree_items.get(parent_pfic[0])
@@ -282,6 +348,58 @@ class PokemonUI(QWidget): # Change from QMainWindow to QWidget
# Connect double-click signal
#self.evolution_tree.itemDoubleClicked.connect(self.edit_evolution)
+ def load_encounter_locations(self, pfic):
+ self.locations_tree.clear()
+
+ encounters = event_system.call_sync('get_encounter_locations', data=pfic)
+
+ game_items = {}
+ for encounter in encounters:
+ game, location, day, time, dual_slot, static_encounter_count, static_encounter, extra_text, stars, rods, fishing = encounter
+
+ if game not in game_items:
+ #print(f'finding generation for {game}')
+ game_item = QTreeWidgetItem([game])
+ game_items[game] = game_item
+
+ generation = event_system.call_sync('get_game_generation', data=game)
+ # Use generation for sorting, default to 0 if not found
+ game_item.setData(0, Qt.ItemDataRole.UserRole, generation)
+ #print(f'generation for {game} is {generation}')
+
+ location_item = QTreeWidgetItem([location])
+ details = []
+ if day:
+ details.append(f"Day: {day}")
+ if time:
+ details.append(f"Time: {time}")
+ if dual_slot:
+ details.append(f"Dual Slot: {dual_slot}")
+ if static_encounter:
+ details.append(f"Static Encounter (Count: {static_encounter_count})")
+ if extra_text:
+ details.append(f"Extra: {extra_text}")
+ if stars:
+ details.append(f"Stars: {stars}")
+ if fishing:
+ details.append(f"Fishing")
+ if rods:
+ details.append(f"Rods: {rods}")
+
+ location_item.setText(1, ", ".join(details))
+ game_items[game].addChild(location_item)
+
+ # Sort game items by generation and add them to the tree
+ sorted_game_items = sorted(game_items.values(), key=lambda x: x.data(0, Qt.ItemDataRole.UserRole))
+ self.locations_tree.addTopLevelItems(sorted_game_items)
+ self.locations_tree.expandAll()
+
+ # Update the cache for this Pokémon
+ self.encounter_cache[pfic] = len(encounters) > 0
+
+ # After updating the locations tree
+ self.update_pokemon_list_highlights()
+
def on_save_button_clicked(self):
# Gather data from UI elements
data = {
@@ -292,7 +410,8 @@ class PokemonUI(QWidget): # Change from QMainWindow to QWidget
event_system.emit('save_changes', data)
def request_pokemon_list(self):
- event_system.emit('get_pokemon_list', self.update_pokemon_list)
+ pokemon_data = event_system.call_sync('get_pokemon_list')
+ self.update_pokemon_list(pokemon_data)
def update_pokemon_list(self, pokemon_data):
self.pokemon_list.clear()
@@ -305,7 +424,7 @@ class PokemonUI(QWidget): # Change from QMainWindow to QWidget
item.setData(Qt.ItemDataRole.UserRole, pfic)
self.pokemon_list.addItem(item)
- #self.update_encounter_cache()
+ self.update_encounter_cache()
self.update_pokemon_list_highlights()
self.adjust_list_width()
self.filter_pokemon_list()
@@ -345,6 +464,14 @@ class PokemonUI(QWidget): # Change from QMainWindow to QWidget
def toggle_highlight_mode(self):
self.update_pokemon_list_highlights()
+ def update_encounter_cache(self):
+ pokemon_with_encounters = event_system.call_sync('get_pokemon_with_encounters')
+ for i in range(self.pokemon_list.count()):
+ item = self.pokemon_list.item(i)
+ pfic = item.data(Qt.ItemDataRole.UserRole)
+ self.encounter_cache[pfic] = pfic in pokemon_with_encounters
+
+
def update_pokemon_list_highlights(self):
highlight_mode = self.highlight_no_encounters.isChecked()
for i in range(self.pokemon_list.count()):
@@ -396,24 +523,20 @@ class PokemonUI(QWidget): # Change from QMainWindow to QWidget
layout.addRow("Fishing:", fishing_check)
layout.addRow("Rods:", rods_edit)
+ layout.addRow("Exclusive Group:", QLabel())
exclusive_group_combo = QComboBox()
- exclusive_group_combo.addItem("None", None)
- self.cursor.execute('SELECT id, group_name FROM exclusive_encounter_groups')
- for group_id, group_name in self.cursor.fetchall():
- exclusive_group_combo.addItem(group_name, group_id)
-
- layout.addRow("Exclusive Group:", exclusive_group_combo)
+ layout.addRow(exclusive_group_combo)
# Fetch current values
self.cursor.execute('''
- SELECT day, time, dual_slot, static_encounter_count, static_encounter, extra_text, stars, fishing, rods, exclusive_group_id
+ SELECT day, time, dual_slot, static_encounter_count, static_encounter, extra_text, stars, fishing, rods
FROM encounters
WHERE pfic = ? AND game = ? AND location = ?
''', (self.current_pfic, game, location))
current_values = self.cursor.fetchone()
if current_values:
- day, time, dual_slot, static_encounter_count, static_encounter, extra_text, stars, fishing, rods, exclusive_group_id = current_values
+ day, time, dual_slot, static_encounter_count, static_encounter, extra_text, stars, fishing, rods = current_values
day_edit.setText(day or "")
time_edit.setText(time or "")
dual_slot_edit.setText(dual_slot or "")
@@ -453,11 +576,11 @@ class PokemonUI(QWidget): # Change from QMainWindow to QWidget
UPDATE encounters
SET game = ?, location = ?, day = ?, time = ?, dual_slot = ?,
static_encounter = ?, static_encounter_count = ?, extra_text = ?,
- stars = ?, fishing = ?, rods = ?, exclusive_group_id = ?
+ stars = ?, fishing = ?, rods = ?
WHERE pfic = ? AND game = ? AND location = ?
''', (new_game, new_location, new_day, new_time, new_dual_slot,
new_static_encounter, new_static_encounter_count, new_extra_text,
- new_stars, new_fishing, new_rods, new_exclusive_group_id,
+ new_stars, new_fishing, new_rods,
self.current_pfic, game, location))
self.conn.commit()
@@ -524,14 +647,15 @@ class PokemonUI(QWidget): # Change from QMainWindow to QWidget
stars = stars_edit.text() or None
fishing = fishing_check.isChecked()
rods = rods_edit.text() or None
- exclusive_group_id = exclusive_group_combo.currentData()
+
+ game_id = event_system.call_sync('get_game_id_for_name', game)
# Insert new encounter into the database
self.cursor.execute('''
INSERT INTO encounters
- (pfic, game, location, day, time, dual_slot, static_encounter, static_encounter_count, extra_text, stars, fishing, rods, exclusive_group_id)
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
- ''', (self.current_pfic, game, location, day, time, dual_slot, static_encounter, static_encounter_count, extra_text, stars, fishing, rods, exclusive_group_id))
+ (pfic, game_id, location, day, time, dual_slot, static_encounter, static_encounter_count, extra_text, stars, fishing, rods)
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+ ''', (self.current_pfic, game_id, location, day, time, dual_slot, static_encounter, static_encounter_count, extra_text, stars, fishing, rods))
self.conn.commit()
# Update the cache
@@ -582,4 +706,48 @@ class PokemonUI(QWidget): # Change from QMainWindow to QWidget
self.save_patches()
# Refresh the evolution chain display
- self.load_evolution_chain(self.current_pfic)
\ No newline at end of file
+ self.load_evolution_chain(self.current_pfic)
+
+ def show_pokemon_context_menu(self, position):
+ item = self.pokemon_list.itemAt(position)
+ if item is not None:
+ context_menu = QMenu(self)
+ refresh_action = QAction("Refresh Encounters", self)
+ refresh_action.triggered.connect(lambda: self.refresh_pokemon_encounters(item))
+ context_menu.addAction(refresh_action)
+ context_menu.exec(self.pokemon_list.viewport().mapToGlobal(position))
+
+ def refresh_pokemon_encounters(self, item):
+ pfic = item.data(Qt.ItemDataRole.UserRole)
+ event_system.emit_sync('refresh_pokemon_encounters', pfic)
+
+ def update_log_display(self, message):
+ if self.progress_text is not None:
+ self.progress_text.append(message)
+ #QMetaObject.invokeMethod(self.progress_text, "append", Qt.ConnectionType.QueuedConnection, message)
+ # Scroll to the bottom
+ scrollbar = self.progress_text.verticalScrollBar()
+ scrollbar.setValue(scrollbar.maximum())
+
+ def clear_log_display(self, data):
+ if self.progress_text is not None:
+ self.progress_text.clear()
+ # Reset scroll to top
+ scrollbar = self.progress_text.verticalScrollBar()
+ scrollbar.setValue(scrollbar.minimum())
+
+ def gather_pokemon_forms(self):
+ event_system.emit_sync('gather_pokemon_forms')
+
+ def gather_home_storage_info(self):
+ event_system.emit_sync('gather_home_storage_info')
+
+ def gather_evolution_info(self):
+ event_system.emit_sync('gather_evolution_info')
+
+ def reinitialize_database(self):
+ event_system.emit_sync('reinitialize_database')
+
+ def gather_encounter_info(self):
+ event_system.emit_sync('gather_encounter_info')
+
diff --git a/DBVisualiser/index.html b/DBVisualiser/index.html
deleted file mode 100644
index 666470d..0000000
--- a/DBVisualiser/index.html
+++ /dev/null
@@ -1,87 +0,0 @@
-
-
-
- Pokémon Database Visualizer
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ×
-
Edit Pokémon
-
-
-
-
-
\ No newline at end of file
diff --git a/DBVisualiser/main.js b/DBVisualiser/main.js
deleted file mode 100644
index ee1bb9a..0000000
--- a/DBVisualiser/main.js
+++ /dev/null
@@ -1,200 +0,0 @@
-const { app, BrowserWindow, ipcMain } = require('electron');
-const path = require('path');
-const sqlite3 = require('sqlite3').verbose();
-
-app.commandLine.appendSwitch('remote-debugging-port', '9222');
-
-let mainWindow;
-let db;
-
-function createWindow() {
- mainWindow = new BrowserWindow({
- width: 1200,
- height: 800,
- webPreferences: {
- nodeIntegration: true,
- contextIsolation: false
- }
- });
-
- mainWindow.loadFile('index.html');
-
- db = new sqlite3.Database('../pokemon_forms.db', (err) => {
- if (err) {
- console.error('Database opening error: ', err);
- }
- });
-}
-
-app.whenReady().then(createWindow);
-
-app.on('window-all-closed', () => {
- if (process.platform !== 'darwin') {
- app.quit();
- }
-});
-
-app.on('activate', () => {
- if (BrowserWindow.getAllWindows().length === 0) {
- createWindow();
- }
-});
-
-ipcMain.on('load-forms-data', (event) => {
- db.all(`
- SELECT pf.PFIC, pf.name, pf.form_name, pf.national_dex, pf.generation, ps.storable_in_home
- FROM pokemon_forms pf
- LEFT JOIN pokemon_storage ps ON pf.PFIC = ps.PFIC
- `, (err, rows) => {
- if (err) {
- console.error('Error fetching data: ', err);
- event.reply('forms-data-response', { error: err.message });
- } else {
- event.reply('forms-data-response', { data: rows });
- }
- });
-});
-
-ipcMain.on('search-evolution', (event, searchTerm) => {
- db.all(`
- SELECT DISTINCT name, PFIC
- FROM pokemon_forms
- WHERE LOWER(name) LIKE ?
- `, [`%${searchTerm.toLowerCase()}%`], (err, rows) => {
- if (err) {
- console.error('Error searching evolution: ', err);
- event.reply('evolution-search-response', { error: err.message });
- } else {
- event.reply('evolution-search-response', { data: rows });
- }
- });
-});
-
-ipcMain.on('get-evolution-chain', (event, pfic) => {
- function getEvolutions(currentPfic) {
- return new Promise((resolve, reject) => {
- db.all(`
- SELECT ec.to_pfic as pfic, pf.name, pf.form_name, ec.method, ec.from_pfic
- FROM evolution_chains ec
- JOIN pokemon_forms pf ON ec.to_pfic = pf.PFIC
- WHERE ec.from_pfic = ?
- `, [currentPfic], (err, rows) => {
- if (err) {
- reject(err);
- } else {
- resolve(rows);
- }
- });
- });
- }
-
- async function buildChain(pfic) {
- const pokemon = await new Promise((resolve, reject) => {
- db.get(`SELECT PFIC as pfic, name, form_name FROM pokemon_forms WHERE PFIC = ?`, [pfic], (err, row) => {
- if (err) reject(err);
- else resolve(row);
- });
- });
-
- if (!pokemon) return null;
-
- const evolutions = await getEvolutions(pfic);
- pokemon.evolutions = await Promise.all(evolutions.map(evo => buildChain(evo.pfic)));
-
- return pokemon;
- }
-
- buildChain(pfic)
- .then(chain => {
- event.reply('evolution-chain-response', { data: chain });
- })
- .catch(err => {
- console.error('Error building evolution chain:', err);
- event.reply('evolution-chain-response', { error: err.message });
- });
-});
-
-ipcMain.on('edit-pokemon', (event, data) => {
- // Implement the logic to update the Pokémon in the database
- console.log('Editing Pokémon:', data);
- // Update the database and send a response back to the renderer
-});
-
-ipcMain.on('remove-pokemon', (event, data) => {
- // Implement the logic to remove the Pokémon from the evolution chain in the database
- console.log('Removing Pokémon:', data);
- // Update the database and send a response back to the renderer
-});
-
-ipcMain.on('add-stage', (event, data) => {
- // Implement the logic to add a new stage to the evolution chain in the database
- console.log('Adding new stage:', data);
- // Update the database and send a response back to the renderer
-});
-
-ipcMain.on('save-evolution-changes', (event, data) => {
- // Implement the logic to save all changes to the evolution chain in the database
- console.log('Saving evolution changes:', data);
-
- // Here you would update the database with the new evolution chain data
- // This is a placeholder implementation
- setTimeout(() => {
- event.reply('save-evolution-changes-response', { success: true });
- }, 1000);
-
- // If there's an error, you would reply with:
- // event.reply('save-evolution-changes-response', { error: 'Error message' });
-});
-
-// Add more IPC handlers for other database operations
-
-// Add this IPC handler
-ipcMain.on('load-all-pokemon', (event) => {
- db.all(`
- SELECT PFIC, name, form_name
- FROM pokemon_forms
- ORDER BY
- CAST(SUBSTR(PFIC, 1, 4) AS INTEGER), -- National Dex number
- CAST(SUBSTR(PFIC, 6, 2) AS INTEGER), -- Region code
- CAST(SUBSTR(PFIC, 9, 3) AS INTEGER), -- Form index
- CAST(SUBSTR(PFIC, 13, 1) AS INTEGER) -- Gender code
- `, (err, rows) => {
- if (err) {
- console.error('Error fetching all Pokémon:', err);
- event.reply('all-pokemon-response', { error: err.message });
- } else {
- event.reply('all-pokemon-response', { data: rows });
- }
- });
-});
-
-ipcMain.on('get-pokemon-details', (event, pfic) => {
- db.get(`
- SELECT pf.PFIC, pf.name, pf.form_name, pf.national_dex, pf.generation, ps.storable_in_home
- FROM pokemon_forms pf
- LEFT JOIN pokemon_storage ps ON pf.PFIC = ps.PFIC
- WHERE pf.PFIC = ?
- `, [pfic], (err, row) => {
- if (err) {
- console.error('Error fetching Pokémon details:', err);
- event.reply('pokemon-details-response', { error: err.message });
- } else {
- event.reply('pokemon-details-response', { data: row });
- }
- });
-});
-
-ipcMain.on('update-storable-in-home', (event, data) => {
- db.run(`
- UPDATE pokemon_storage
- SET storable_in_home = ?
- WHERE PFIC = ?
- `, [data.storable ? 1 : 0, data.pfic], (err) => {
- if (err) {
- console.error('Error updating storable in home:', err);
- event.reply('update-storable-in-home-response', { error: err.message });
- } else {
- event.reply('update-storable-in-home-response', { success: true });
- }
- });
-});
\ No newline at end of file
diff --git a/DBVisualiser/package-lock.json b/DBVisualiser/package-lock.json
deleted file mode 100644
index 0dc455f..0000000
--- a/DBVisualiser/package-lock.json
+++ /dev/null
@@ -1,5193 +0,0 @@
-{
- "name": "dbvisualiser",
- "version": "1.0.0",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {
- "": {
- "name": "dbvisualiser",
- "version": "1.0.0",
- "license": "ISC",
- "dependencies": {
- "electron": "^32.1.2",
- "electron-builder": "^25.1.7",
- "sqlite3": "^5.1.7"
- }
- },
- "node_modules/@develar/schema-utils": {
- "version": "2.6.5",
- "resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz",
- "integrity": "sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==",
- "license": "MIT",
- "dependencies": {
- "ajv": "^6.12.0",
- "ajv-keywords": "^3.4.1"
- },
- "engines": {
- "node": ">= 8.9.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/webpack"
- }
- },
- "node_modules/@electron/asar": {
- "version": "3.2.13",
- "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.2.13.tgz",
- "integrity": "sha512-pY5z2qQSwbFzJsBdgfJIzXf5ElHTVMutC2dxh0FD60njknMu3n1NnTABOcQwbb5/v5soqE79m9UjaJryBf3epg==",
- "license": "MIT",
- "dependencies": {
- "@types/glob": "^7.1.0",
- "commander": "^5.0.0",
- "glob": "^7.1.6",
- "minimatch": "^3.0.4"
- },
- "bin": {
- "asar": "bin/asar.js"
- },
- "engines": {
- "node": ">=10.12.0"
- }
- },
- "node_modules/@electron/asar/node_modules/brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "node_modules/@electron/asar/node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/@electron/get": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz",
- "integrity": "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==",
- "license": "MIT",
- "dependencies": {
- "debug": "^4.1.1",
- "env-paths": "^2.2.0",
- "fs-extra": "^8.1.0",
- "got": "^11.8.5",
- "progress": "^2.0.3",
- "semver": "^6.2.0",
- "sumchecker": "^3.0.1"
- },
- "engines": {
- "node": ">=12"
- },
- "optionalDependencies": {
- "global-agent": "^3.0.0"
- }
- },
- "node_modules/@electron/notarize": {
- "version": "2.5.0",
- "resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-2.5.0.tgz",
- "integrity": "sha512-jNT8nwH1f9X5GEITXaQ8IF/KdskvIkOFfB2CvwumsveVidzpSc+mvhhTMdAGSYF3O+Nq49lJ7y+ssODRXu06+A==",
- "license": "MIT",
- "dependencies": {
- "debug": "^4.1.1",
- "fs-extra": "^9.0.1",
- "promise-retry": "^2.0.1"
- },
- "engines": {
- "node": ">= 10.0.0"
- }
- },
- "node_modules/@electron/notarize/node_modules/fs-extra": {
- "version": "9.1.0",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
- "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
- "license": "MIT",
- "dependencies": {
- "at-least-node": "^1.0.0",
- "graceful-fs": "^4.2.0",
- "jsonfile": "^6.0.1",
- "universalify": "^2.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/@electron/notarize/node_modules/jsonfile": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
- "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
- "license": "MIT",
- "dependencies": {
- "universalify": "^2.0.0"
- },
- "optionalDependencies": {
- "graceful-fs": "^4.1.6"
- }
- },
- "node_modules/@electron/notarize/node_modules/universalify": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
- "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
- "license": "MIT",
- "engines": {
- "node": ">= 10.0.0"
- }
- },
- "node_modules/@electron/osx-sign": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.3.1.tgz",
- "integrity": "sha512-BAfviURMHpmb1Yb50YbCxnOY0wfwaLXH5KJ4+80zS0gUkzDX3ec23naTlEqKsN+PwYn+a1cCzM7BJ4Wcd3sGzw==",
- "license": "BSD-2-Clause",
- "dependencies": {
- "compare-version": "^0.1.2",
- "debug": "^4.3.4",
- "fs-extra": "^10.0.0",
- "isbinaryfile": "^4.0.8",
- "minimist": "^1.2.6",
- "plist": "^3.0.5"
- },
- "bin": {
- "electron-osx-flat": "bin/electron-osx-flat.js",
- "electron-osx-sign": "bin/electron-osx-sign.js"
- },
- "engines": {
- "node": ">=12.0.0"
- }
- },
- "node_modules/@electron/osx-sign/node_modules/fs-extra": {
- "version": "10.1.0",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
- "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
- "license": "MIT",
- "dependencies": {
- "graceful-fs": "^4.2.0",
- "jsonfile": "^6.0.1",
- "universalify": "^2.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@electron/osx-sign/node_modules/isbinaryfile": {
- "version": "4.0.10",
- "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz",
- "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==",
- "license": "MIT",
- "engines": {
- "node": ">= 8.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/gjtorikian/"
- }
- },
- "node_modules/@electron/osx-sign/node_modules/jsonfile": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
- "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
- "license": "MIT",
- "dependencies": {
- "universalify": "^2.0.0"
- },
- "optionalDependencies": {
- "graceful-fs": "^4.1.6"
- }
- },
- "node_modules/@electron/osx-sign/node_modules/universalify": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
- "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
- "license": "MIT",
- "engines": {
- "node": ">= 10.0.0"
- }
- },
- "node_modules/@electron/rebuild": {
- "version": "3.6.1",
- "resolved": "https://registry.npmjs.org/@electron/rebuild/-/rebuild-3.6.1.tgz",
- "integrity": "sha512-f6596ZHpEq/YskUd8emYvOUne89ij8mQgjYFA5ru25QwbrRO+t1SImofdDv7kKOuWCmVOuU5tvfkbgGxIl3E/w==",
- "license": "MIT",
- "dependencies": {
- "@malept/cross-spawn-promise": "^2.0.0",
- "chalk": "^4.0.0",
- "debug": "^4.1.1",
- "detect-libc": "^2.0.1",
- "fs-extra": "^10.0.0",
- "got": "^11.7.0",
- "node-abi": "^3.45.0",
- "node-api-version": "^0.2.0",
- "node-gyp": "^9.0.0",
- "ora": "^5.1.0",
- "read-binary-file-arch": "^1.0.6",
- "semver": "^7.3.5",
- "tar": "^6.0.5",
- "yargs": "^17.0.1"
- },
- "bin": {
- "electron-rebuild": "lib/cli.js"
- },
- "engines": {
- "node": ">=12.13.0"
- }
- },
- "node_modules/@electron/rebuild/node_modules/fs-extra": {
- "version": "10.1.0",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
- "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
- "license": "MIT",
- "dependencies": {
- "graceful-fs": "^4.2.0",
- "jsonfile": "^6.0.1",
- "universalify": "^2.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@electron/rebuild/node_modules/jsonfile": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
- "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
- "license": "MIT",
- "dependencies": {
- "universalify": "^2.0.0"
- },
- "optionalDependencies": {
- "graceful-fs": "^4.1.6"
- }
- },
- "node_modules/@electron/rebuild/node_modules/semver": {
- "version": "7.6.3",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
- "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/@electron/rebuild/node_modules/universalify": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
- "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
- "license": "MIT",
- "engines": {
- "node": ">= 10.0.0"
- }
- },
- "node_modules/@electron/universal": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-2.0.1.tgz",
- "integrity": "sha512-fKpv9kg4SPmt+hY7SVBnIYULE9QJl8L3sCfcBsnqbJwwBwAeTLokJ9TRt9y7bK0JAzIW2y78TVVjvnQEms/yyA==",
- "license": "MIT",
- "dependencies": {
- "@electron/asar": "^3.2.7",
- "@malept/cross-spawn-promise": "^2.0.0",
- "debug": "^4.3.1",
- "dir-compare": "^4.2.0",
- "fs-extra": "^11.1.1",
- "minimatch": "^9.0.3",
- "plist": "^3.1.0"
- },
- "engines": {
- "node": ">=16.4"
- }
- },
- "node_modules/@electron/universal/node_modules/fs-extra": {
- "version": "11.2.0",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz",
- "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==",
- "license": "MIT",
- "dependencies": {
- "graceful-fs": "^4.2.0",
- "jsonfile": "^6.0.1",
- "universalify": "^2.0.0"
- },
- "engines": {
- "node": ">=14.14"
- }
- },
- "node_modules/@electron/universal/node_modules/jsonfile": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
- "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
- "license": "MIT",
- "dependencies": {
- "universalify": "^2.0.0"
- },
- "optionalDependencies": {
- "graceful-fs": "^4.1.6"
- }
- },
- "node_modules/@electron/universal/node_modules/minimatch": {
- "version": "9.0.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
- "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^2.0.1"
- },
- "engines": {
- "node": ">=16 || 14 >=14.17"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/@electron/universal/node_modules/universalify": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
- "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
- "license": "MIT",
- "engines": {
- "node": ">= 10.0.0"
- }
- },
- "node_modules/@gar/promisify": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz",
- "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==",
- "license": "MIT"
- },
- "node_modules/@isaacs/cliui": {
- "version": "8.0.2",
- "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
- "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
- "license": "ISC",
- "dependencies": {
- "string-width": "^5.1.2",
- "string-width-cjs": "npm:string-width@^4.2.0",
- "strip-ansi": "^7.0.1",
- "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
- "wrap-ansi": "^8.1.0",
- "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@isaacs/cliui/node_modules/ansi-regex": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
- "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-regex?sponsor=1"
- }
- },
- "node_modules/@isaacs/cliui/node_modules/ansi-styles": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
- "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/@isaacs/cliui/node_modules/emoji-regex": {
- "version": "9.2.2",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
- "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
- "license": "MIT"
- },
- "node_modules/@isaacs/cliui/node_modules/string-width": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
- "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
- "license": "MIT",
- "dependencies": {
- "eastasianwidth": "^0.2.0",
- "emoji-regex": "^9.2.2",
- "strip-ansi": "^7.0.1"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/@isaacs/cliui/node_modules/strip-ansi": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
- "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^6.0.1"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/strip-ansi?sponsor=1"
- }
- },
- "node_modules/@isaacs/cliui/node_modules/wrap-ansi": {
- "version": "8.1.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
- "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^6.1.0",
- "string-width": "^5.0.1",
- "strip-ansi": "^7.0.1"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
- }
- },
- "node_modules/@malept/cross-spawn-promise": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-2.0.0.tgz",
- "integrity": "sha512-1DpKU0Z5ThltBwjNySMC14g0CkbyhCaz9FkhxqNsZI6uAPJXFS8cMXlBKo26FJ8ZuW6S9GCMcR9IO5k2X5/9Fg==",
- "funding": [
- {
- "type": "individual",
- "url": "https://github.com/sponsors/malept"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/subscription/pkg/npm-.malept-cross-spawn-promise?utm_medium=referral&utm_source=npm_fund"
- }
- ],
- "license": "Apache-2.0",
- "dependencies": {
- "cross-spawn": "^7.0.1"
- },
- "engines": {
- "node": ">= 12.13.0"
- }
- },
- "node_modules/@malept/flatpak-bundler": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/@malept/flatpak-bundler/-/flatpak-bundler-0.4.0.tgz",
- "integrity": "sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==",
- "license": "MIT",
- "dependencies": {
- "debug": "^4.1.1",
- "fs-extra": "^9.0.0",
- "lodash": "^4.17.15",
- "tmp-promise": "^3.0.2"
- },
- "engines": {
- "node": ">= 10.0.0"
- }
- },
- "node_modules/@malept/flatpak-bundler/node_modules/fs-extra": {
- "version": "9.1.0",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
- "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
- "license": "MIT",
- "dependencies": {
- "at-least-node": "^1.0.0",
- "graceful-fs": "^4.2.0",
- "jsonfile": "^6.0.1",
- "universalify": "^2.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/@malept/flatpak-bundler/node_modules/jsonfile": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
- "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
- "license": "MIT",
- "dependencies": {
- "universalify": "^2.0.0"
- },
- "optionalDependencies": {
- "graceful-fs": "^4.1.6"
- }
- },
- "node_modules/@malept/flatpak-bundler/node_modules/universalify": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
- "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
- "license": "MIT",
- "engines": {
- "node": ">= 10.0.0"
- }
- },
- "node_modules/@npmcli/fs": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz",
- "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==",
- "license": "ISC",
- "dependencies": {
- "@gar/promisify": "^1.1.3",
- "semver": "^7.3.5"
- },
- "engines": {
- "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
- }
- },
- "node_modules/@npmcli/fs/node_modules/semver": {
- "version": "7.6.3",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
- "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/@npmcli/move-file": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz",
- "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==",
- "deprecated": "This functionality has been moved to @npmcli/fs",
- "license": "MIT",
- "dependencies": {
- "mkdirp": "^1.0.4",
- "rimraf": "^3.0.2"
- },
- "engines": {
- "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
- }
- },
- "node_modules/@pkgjs/parseargs": {
- "version": "0.11.0",
- "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
- "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">=14"
- }
- },
- "node_modules/@sindresorhus/is": {
- "version": "4.6.0",
- "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz",
- "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==",
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sindresorhus/is?sponsor=1"
- }
- },
- "node_modules/@szmarczak/http-timer": {
- "version": "4.0.6",
- "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz",
- "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==",
- "license": "MIT",
- "dependencies": {
- "defer-to-connect": "^2.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/@tootallnate/once": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
- "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==",
- "license": "MIT",
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/@types/cacheable-request": {
- "version": "6.0.3",
- "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz",
- "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==",
- "license": "MIT",
- "dependencies": {
- "@types/http-cache-semantics": "*",
- "@types/keyv": "^3.1.4",
- "@types/node": "*",
- "@types/responselike": "^1.0.0"
- }
- },
- "node_modules/@types/debug": {
- "version": "4.1.12",
- "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz",
- "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==",
- "license": "MIT",
- "dependencies": {
- "@types/ms": "*"
- }
- },
- "node_modules/@types/fs-extra": {
- "version": "9.0.13",
- "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz",
- "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==",
- "license": "MIT",
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/@types/glob": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz",
- "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==",
- "license": "MIT",
- "dependencies": {
- "@types/minimatch": "*",
- "@types/node": "*"
- }
- },
- "node_modules/@types/http-cache-semantics": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz",
- "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==",
- "license": "MIT"
- },
- "node_modules/@types/keyv": {
- "version": "3.1.4",
- "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz",
- "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==",
- "license": "MIT",
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/@types/minimatch": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz",
- "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==",
- "license": "MIT"
- },
- "node_modules/@types/ms": {
- "version": "0.7.34",
- "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz",
- "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==",
- "license": "MIT"
- },
- "node_modules/@types/node": {
- "version": "20.16.10",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz",
- "integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==",
- "license": "MIT",
- "dependencies": {
- "undici-types": "~6.19.2"
- }
- },
- "node_modules/@types/plist": {
- "version": "3.0.5",
- "resolved": "https://registry.npmjs.org/@types/plist/-/plist-3.0.5.tgz",
- "integrity": "sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@types/node": "*",
- "xmlbuilder": ">=11.0.1"
- }
- },
- "node_modules/@types/responselike": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz",
- "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==",
- "license": "MIT",
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/@types/verror": {
- "version": "1.10.10",
- "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.10.tgz",
- "integrity": "sha512-l4MM0Jppn18hb9xmM6wwD1uTdShpf9Pn80aXTStnK1C94gtPvJcV2FrDmbOQUAQfJ1cKZHktkQUDwEqaAKXMMg==",
- "license": "MIT",
- "optional": true
- },
- "node_modules/@types/yauzl": {
- "version": "2.10.3",
- "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz",
- "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/@xmldom/xmldom": {
- "version": "0.8.10",
- "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz",
- "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==",
- "license": "MIT",
- "engines": {
- "node": ">=10.0.0"
- }
- },
- "node_modules/7zip-bin": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-5.2.0.tgz",
- "integrity": "sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A==",
- "license": "MIT"
- },
- "node_modules/abbrev": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
- "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
- "license": "ISC"
- },
- "node_modules/agent-base": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz",
- "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==",
- "license": "MIT",
- "dependencies": {
- "debug": "^4.3.4"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/agentkeepalive": {
- "version": "4.5.0",
- "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz",
- "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==",
- "license": "MIT",
- "dependencies": {
- "humanize-ms": "^1.2.1"
- },
- "engines": {
- "node": ">= 8.0.0"
- }
- },
- "node_modules/aggregate-error": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
- "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
- "license": "MIT",
- "dependencies": {
- "clean-stack": "^2.0.0",
- "indent-string": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/ajv": {
- "version": "6.12.6",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
- "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
- "license": "MIT",
- "dependencies": {
- "fast-deep-equal": "^3.1.1",
- "fast-json-stable-stringify": "^2.0.0",
- "json-schema-traverse": "^0.4.1",
- "uri-js": "^4.2.2"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/epoberezkin"
- }
- },
- "node_modules/ajv-keywords": {
- "version": "3.5.2",
- "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
- "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
- "license": "MIT",
- "peerDependencies": {
- "ajv": "^6.9.1"
- }
- },
- "node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "license": "MIT",
- "dependencies": {
- "color-convert": "^2.0.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/app-builder-bin": {
- "version": "5.0.0-alpha.10",
- "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-5.0.0-alpha.10.tgz",
- "integrity": "sha512-Ev4jj3D7Bo+O0GPD2NMvJl+PGiBAfS7pUGawntBNpCbxtpncfUixqFj9z9Jme7V7s3LBGqsWZZP54fxBX3JKJw==",
- "license": "MIT"
- },
- "node_modules/app-builder-lib": {
- "version": "25.1.7",
- "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-25.1.7.tgz",
- "integrity": "sha512-JxmN+D/Dn7BLQoN+cTFO+zbMHcpI10v/xjyjFO1FKpHbApOG+OQt/xUyVjKWp4FYplIfuHdpxqTXo1PN/Wzm/A==",
- "license": "MIT",
- "dependencies": {
- "@develar/schema-utils": "~2.6.5",
- "@electron/notarize": "2.5.0",
- "@electron/osx-sign": "1.3.1",
- "@electron/rebuild": "3.6.1",
- "@electron/universal": "2.0.1",
- "@malept/flatpak-bundler": "^0.4.0",
- "@types/fs-extra": "9.0.13",
- "async-exit-hook": "^2.0.1",
- "bluebird-lst": "^1.0.9",
- "builder-util": "25.1.7",
- "builder-util-runtime": "9.2.10",
- "chromium-pickle-js": "^0.2.0",
- "config-file-ts": "0.2.8-rc1",
- "debug": "^4.3.4",
- "dotenv": "^16.4.5",
- "dotenv-expand": "^11.0.6",
- "ejs": "^3.1.8",
- "electron-publish": "25.1.7",
- "form-data": "^4.0.0",
- "fs-extra": "^10.1.0",
- "hosted-git-info": "^4.1.0",
- "is-ci": "^3.0.0",
- "isbinaryfile": "^5.0.0",
- "js-yaml": "^4.1.0",
- "json5": "^2.2.3",
- "lazy-val": "^1.0.5",
- "minimatch": "^10.0.0",
- "resedit": "^1.7.0",
- "sanitize-filename": "^1.6.3",
- "semver": "^7.3.8",
- "tar": "^6.1.12",
- "temp-file": "^3.4.0"
- },
- "engines": {
- "node": ">=14.0.0"
- },
- "peerDependencies": {
- "dmg-builder": "25.1.7",
- "electron-builder-squirrel-windows": "25.1.7"
- }
- },
- "node_modules/app-builder-lib/node_modules/fs-extra": {
- "version": "10.1.0",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
- "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
- "license": "MIT",
- "dependencies": {
- "graceful-fs": "^4.2.0",
- "jsonfile": "^6.0.1",
- "universalify": "^2.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/app-builder-lib/node_modules/jsonfile": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
- "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
- "license": "MIT",
- "dependencies": {
- "universalify": "^2.0.0"
- },
- "optionalDependencies": {
- "graceful-fs": "^4.1.6"
- }
- },
- "node_modules/app-builder-lib/node_modules/semver": {
- "version": "7.6.3",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
- "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/app-builder-lib/node_modules/universalify": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
- "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
- "license": "MIT",
- "engines": {
- "node": ">= 10.0.0"
- }
- },
- "node_modules/aproba": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
- "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==",
- "license": "ISC"
- },
- "node_modules/archiver": {
- "version": "5.3.2",
- "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.2.tgz",
- "integrity": "sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "archiver-utils": "^2.1.0",
- "async": "^3.2.4",
- "buffer-crc32": "^0.2.1",
- "readable-stream": "^3.6.0",
- "readdir-glob": "^1.1.2",
- "tar-stream": "^2.2.0",
- "zip-stream": "^4.1.0"
- },
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/archiver-utils": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz",
- "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "glob": "^7.1.4",
- "graceful-fs": "^4.2.0",
- "lazystream": "^1.0.0",
- "lodash.defaults": "^4.2.0",
- "lodash.difference": "^4.5.0",
- "lodash.flatten": "^4.4.0",
- "lodash.isplainobject": "^4.0.6",
- "lodash.union": "^4.6.0",
- "normalize-path": "^3.0.0",
- "readable-stream": "^2.0.0"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/archiver-utils/node_modules/readable-stream": {
- "version": "2.3.8",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
- "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "core-util-is": "~1.0.0",
- "inherits": "~2.0.3",
- "isarray": "~1.0.0",
- "process-nextick-args": "~2.0.0",
- "safe-buffer": "~5.1.1",
- "string_decoder": "~1.1.1",
- "util-deprecate": "~1.0.1"
- }
- },
- "node_modules/archiver-utils/node_modules/safe-buffer": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
- "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
- "license": "MIT",
- "peer": true
- },
- "node_modules/archiver-utils/node_modules/string_decoder": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
- "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "safe-buffer": "~5.1.0"
- }
- },
- "node_modules/are-we-there-yet": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz",
- "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==",
- "deprecated": "This package is no longer supported.",
- "license": "ISC",
- "dependencies": {
- "delegates": "^1.0.0",
- "readable-stream": "^3.6.0"
- },
- "engines": {
- "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
- }
- },
- "node_modules/argparse": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
- "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
- "license": "Python-2.0"
- },
- "node_modules/assert-plus": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
- "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">=0.8"
- }
- },
- "node_modules/astral-regex": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
- "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/async": {
- "version": "3.2.6",
- "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz",
- "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==",
- "license": "MIT"
- },
- "node_modules/async-exit-hook": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz",
- "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==",
- "license": "MIT",
- "engines": {
- "node": ">=0.12.0"
- }
- },
- "node_modules/asynckit": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
- "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
- "license": "MIT"
- },
- "node_modules/at-least-node": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
- "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
- "license": "ISC",
- "engines": {
- "node": ">= 4.0.0"
- }
- },
- "node_modules/balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
- "license": "MIT"
- },
- "node_modules/base64-js": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
- "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT"
- },
- "node_modules/bindings": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
- "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
- "license": "MIT",
- "dependencies": {
- "file-uri-to-path": "1.0.0"
- }
- },
- "node_modules/bl": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
- "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
- "license": "MIT",
- "dependencies": {
- "buffer": "^5.5.0",
- "inherits": "^2.0.4",
- "readable-stream": "^3.4.0"
- }
- },
- "node_modules/bluebird": {
- "version": "3.7.2",
- "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
- "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
- "license": "MIT"
- },
- "node_modules/bluebird-lst": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/bluebird-lst/-/bluebird-lst-1.0.9.tgz",
- "integrity": "sha512-7B1Rtx82hjnSD4PGLAjVWeYH3tHAcVUmChh85a3lltKQm6FresXh9ErQo6oAv6CqxttczC3/kEg8SY5NluPuUw==",
- "license": "MIT",
- "dependencies": {
- "bluebird": "^3.5.5"
- }
- },
- "node_modules/boolean": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz",
- "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==",
- "license": "MIT",
- "optional": true
- },
- "node_modules/brace-expansion": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
- "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0"
- }
- },
- "node_modules/buffer": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
- "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "base64-js": "^1.3.1",
- "ieee754": "^1.1.13"
- }
- },
- "node_modules/buffer-crc32": {
- "version": "0.2.13",
- "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
- "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
- "license": "MIT",
- "engines": {
- "node": "*"
- }
- },
- "node_modules/buffer-from": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
- "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
- "license": "MIT"
- },
- "node_modules/builder-util": {
- "version": "25.1.7",
- "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-25.1.7.tgz",
- "integrity": "sha512-7jPjzBwEGRbwNcep0gGNpLXG9P94VA3CPAZQCzxkFXiV2GMQKlziMbY//rXPI7WKfhsvGgFXjTcXdBEwgXw9ww==",
- "license": "MIT",
- "dependencies": {
- "@types/debug": "^4.1.6",
- "7zip-bin": "~5.2.0",
- "app-builder-bin": "5.0.0-alpha.10",
- "bluebird-lst": "^1.0.9",
- "builder-util-runtime": "9.2.10",
- "chalk": "^4.1.2",
- "cross-spawn": "^7.0.3",
- "debug": "^4.3.4",
- "fs-extra": "^10.1.0",
- "http-proxy-agent": "^7.0.0",
- "https-proxy-agent": "^7.0.0",
- "is-ci": "^3.0.0",
- "js-yaml": "^4.1.0",
- "source-map-support": "^0.5.19",
- "stat-mode": "^1.0.0",
- "temp-file": "^3.4.0"
- }
- },
- "node_modules/builder-util-runtime": {
- "version": "9.2.10",
- "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.10.tgz",
- "integrity": "sha512-6p/gfG1RJSQeIbz8TK5aPNkoztgY1q5TgmGFMAXcY8itsGW6Y2ld1ALsZ5UJn8rog7hKF3zHx5iQbNQ8uLcRlw==",
- "license": "MIT",
- "dependencies": {
- "debug": "^4.3.4",
- "sax": "^1.2.4"
- },
- "engines": {
- "node": ">=12.0.0"
- }
- },
- "node_modules/builder-util/node_modules/fs-extra": {
- "version": "10.1.0",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
- "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
- "license": "MIT",
- "dependencies": {
- "graceful-fs": "^4.2.0",
- "jsonfile": "^6.0.1",
- "universalify": "^2.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/builder-util/node_modules/jsonfile": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
- "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
- "license": "MIT",
- "dependencies": {
- "universalify": "^2.0.0"
- },
- "optionalDependencies": {
- "graceful-fs": "^4.1.6"
- }
- },
- "node_modules/builder-util/node_modules/universalify": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
- "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
- "license": "MIT",
- "engines": {
- "node": ">= 10.0.0"
- }
- },
- "node_modules/cacache": {
- "version": "16.1.3",
- "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz",
- "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==",
- "license": "ISC",
- "dependencies": {
- "@npmcli/fs": "^2.1.0",
- "@npmcli/move-file": "^2.0.0",
- "chownr": "^2.0.0",
- "fs-minipass": "^2.1.0",
- "glob": "^8.0.1",
- "infer-owner": "^1.0.4",
- "lru-cache": "^7.7.1",
- "minipass": "^3.1.6",
- "minipass-collect": "^1.0.2",
- "minipass-flush": "^1.0.5",
- "minipass-pipeline": "^1.2.4",
- "mkdirp": "^1.0.4",
- "p-map": "^4.0.0",
- "promise-inflight": "^1.0.1",
- "rimraf": "^3.0.2",
- "ssri": "^9.0.0",
- "tar": "^6.1.11",
- "unique-filename": "^2.0.0"
- },
- "engines": {
- "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
- }
- },
- "node_modules/cacache/node_modules/glob": {
- "version": "8.1.0",
- "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
- "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
- "deprecated": "Glob versions prior to v9 are no longer supported",
- "license": "ISC",
- "dependencies": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^5.0.1",
- "once": "^1.3.0"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/cacache/node_modules/lru-cache": {
- "version": "7.18.3",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
- "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/cacache/node_modules/minimatch": {
- "version": "5.1.6",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
- "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^2.0.1"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/cacheable-lookup": {
- "version": "5.0.4",
- "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz",
- "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==",
- "license": "MIT",
- "engines": {
- "node": ">=10.6.0"
- }
- },
- "node_modules/cacheable-request": {
- "version": "7.0.4",
- "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz",
- "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==",
- "license": "MIT",
- "dependencies": {
- "clone-response": "^1.0.2",
- "get-stream": "^5.1.0",
- "http-cache-semantics": "^4.0.0",
- "keyv": "^4.0.0",
- "lowercase-keys": "^2.0.0",
- "normalize-url": "^6.0.1",
- "responselike": "^2.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
- }
- },
- "node_modules/chownr": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
- "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
- "license": "ISC",
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/chromium-pickle-js": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz",
- "integrity": "sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==",
- "license": "MIT"
- },
- "node_modules/ci-info": {
- "version": "3.9.0",
- "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
- "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/sibiraj-s"
- }
- ],
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/clean-stack": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
- "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/cli-cursor": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
- "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
- "license": "MIT",
- "dependencies": {
- "restore-cursor": "^3.1.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/cli-spinners": {
- "version": "2.9.2",
- "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz",
- "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/cli-truncate": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz",
- "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "slice-ansi": "^3.0.0",
- "string-width": "^4.2.0"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/cliui": {
- "version": "8.0.1",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
- "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
- "license": "ISC",
- "dependencies": {
- "string-width": "^4.2.0",
- "strip-ansi": "^6.0.1",
- "wrap-ansi": "^7.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/clone": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
- "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==",
- "license": "MIT",
- "engines": {
- "node": ">=0.8"
- }
- },
- "node_modules/clone-response": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz",
- "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==",
- "license": "MIT",
- "dependencies": {
- "mimic-response": "^1.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "license": "MIT",
- "dependencies": {
- "color-name": "~1.1.4"
- },
- "engines": {
- "node": ">=7.0.0"
- }
- },
- "node_modules/color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "license": "MIT"
- },
- "node_modules/color-support": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
- "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
- "license": "ISC",
- "bin": {
- "color-support": "bin.js"
- }
- },
- "node_modules/combined-stream": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
- "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
- "license": "MIT",
- "dependencies": {
- "delayed-stream": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/commander": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz",
- "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==",
- "license": "MIT",
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/compare-version": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz",
- "integrity": "sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/compress-commons": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.2.tgz",
- "integrity": "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "buffer-crc32": "^0.2.13",
- "crc32-stream": "^4.0.2",
- "normalize-path": "^3.0.0",
- "readable-stream": "^3.6.0"
- },
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
- "license": "MIT"
- },
- "node_modules/config-file-ts": {
- "version": "0.2.8-rc1",
- "resolved": "https://registry.npmjs.org/config-file-ts/-/config-file-ts-0.2.8-rc1.tgz",
- "integrity": "sha512-GtNECbVI82bT4RiDIzBSVuTKoSHufnU7Ce7/42bkWZJZFLjmDF2WBpVsvRkhKCfKBnTBb3qZrBwPpFBU/Myvhg==",
- "license": "MIT",
- "dependencies": {
- "glob": "^10.3.12",
- "typescript": "^5.4.3"
- }
- },
- "node_modules/config-file-ts/node_modules/glob": {
- "version": "10.4.5",
- "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
- "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
- "license": "ISC",
- "dependencies": {
- "foreground-child": "^3.1.0",
- "jackspeak": "^3.1.2",
- "minimatch": "^9.0.4",
- "minipass": "^7.1.2",
- "package-json-from-dist": "^1.0.0",
- "path-scurry": "^1.11.1"
- },
- "bin": {
- "glob": "dist/esm/bin.mjs"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/config-file-ts/node_modules/minimatch": {
- "version": "9.0.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
- "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^2.0.1"
- },
- "engines": {
- "node": ">=16 || 14 >=14.17"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/config-file-ts/node_modules/minipass": {
- "version": "7.1.2",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
- "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
- "license": "ISC",
- "engines": {
- "node": ">=16 || 14 >=14.17"
- }
- },
- "node_modules/console-control-strings": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
- "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==",
- "license": "ISC"
- },
- "node_modules/core-util-is": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
- "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==",
- "license": "MIT"
- },
- "node_modules/crc": {
- "version": "3.8.0",
- "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz",
- "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "buffer": "^5.1.0"
- }
- },
- "node_modules/crc-32": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz",
- "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==",
- "license": "Apache-2.0",
- "peer": true,
- "bin": {
- "crc32": "bin/crc32.njs"
- },
- "engines": {
- "node": ">=0.8"
- }
- },
- "node_modules/crc32-stream": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.3.tgz",
- "integrity": "sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "crc-32": "^1.2.0",
- "readable-stream": "^3.4.0"
- },
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/cross-spawn": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
- "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
- "license": "MIT",
- "dependencies": {
- "path-key": "^3.1.0",
- "shebang-command": "^2.0.0",
- "which": "^2.0.1"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/debug": {
- "version": "4.3.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
- "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/decompress-response": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
- "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
- "license": "MIT",
- "dependencies": {
- "mimic-response": "^3.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/decompress-response/node_modules/mimic-response": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
- "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/deep-extend": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
- "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
- "license": "MIT",
- "engines": {
- "node": ">=4.0.0"
- }
- },
- "node_modules/defaults": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz",
- "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==",
- "license": "MIT",
- "dependencies": {
- "clone": "^1.0.2"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/defer-to-connect": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz",
- "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==",
- "license": "MIT",
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/define-data-property": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
- "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "es-define-property": "^1.0.0",
- "es-errors": "^1.3.0",
- "gopd": "^1.0.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/define-properties": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
- "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "define-data-property": "^1.0.1",
- "has-property-descriptors": "^1.0.0",
- "object-keys": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/delayed-stream": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
- "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
- "license": "MIT",
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/delegates": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
- "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==",
- "license": "MIT"
- },
- "node_modules/detect-libc": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
- "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==",
- "license": "Apache-2.0",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/detect-node": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz",
- "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==",
- "license": "MIT",
- "optional": true
- },
- "node_modules/dir-compare": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-4.2.0.tgz",
- "integrity": "sha512-2xMCmOoMrdQIPHdsTawECdNPwlVFB9zGcz3kuhmBO6U3oU+UQjsue0i8ayLKpgBcm+hcXPMVSGUN9d+pvJ6+VQ==",
- "license": "MIT",
- "dependencies": {
- "minimatch": "^3.0.5",
- "p-limit": "^3.1.0 "
- }
- },
- "node_modules/dir-compare/node_modules/brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "node_modules/dir-compare/node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/dmg-builder": {
- "version": "25.1.7",
- "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-25.1.7.tgz",
- "integrity": "sha512-Hac0AfXQrAV62JT99Had6bvUJb/f7vjJTaLOsmA/gAQcrc/cLmNAqCJ0ZZDqwKy2+LKXnxx45TvMXvovKd4iMg==",
- "license": "MIT",
- "dependencies": {
- "app-builder-lib": "25.1.7",
- "builder-util": "25.1.7",
- "builder-util-runtime": "9.2.10",
- "fs-extra": "^10.1.0",
- "iconv-lite": "^0.6.2",
- "js-yaml": "^4.1.0"
- },
- "optionalDependencies": {
- "dmg-license": "^1.0.11"
- }
- },
- "node_modules/dmg-builder/node_modules/fs-extra": {
- "version": "10.1.0",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
- "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
- "license": "MIT",
- "dependencies": {
- "graceful-fs": "^4.2.0",
- "jsonfile": "^6.0.1",
- "universalify": "^2.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/dmg-builder/node_modules/jsonfile": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
- "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
- "license": "MIT",
- "dependencies": {
- "universalify": "^2.0.0"
- },
- "optionalDependencies": {
- "graceful-fs": "^4.1.6"
- }
- },
- "node_modules/dmg-builder/node_modules/universalify": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
- "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
- "license": "MIT",
- "engines": {
- "node": ">= 10.0.0"
- }
- },
- "node_modules/dmg-license": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/dmg-license/-/dmg-license-1.0.11.tgz",
- "integrity": "sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q==",
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "dependencies": {
- "@types/plist": "^3.0.1",
- "@types/verror": "^1.10.3",
- "ajv": "^6.10.0",
- "crc": "^3.8.0",
- "iconv-corefoundation": "^1.1.7",
- "plist": "^3.0.4",
- "smart-buffer": "^4.0.2",
- "verror": "^1.10.0"
- },
- "bin": {
- "dmg-license": "bin/dmg-license.js"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/dotenv": {
- "version": "16.4.5",
- "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz",
- "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==",
- "license": "BSD-2-Clause",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://dotenvx.com"
- }
- },
- "node_modules/dotenv-expand": {
- "version": "11.0.6",
- "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.6.tgz",
- "integrity": "sha512-8NHi73otpWsZGBSZwwknTXS5pqMOrk9+Ssrna8xCaxkzEpU9OTf9R5ArQGVw03//Zmk9MOwLPng9WwndvpAJ5g==",
- "license": "BSD-2-Clause",
- "dependencies": {
- "dotenv": "^16.4.4"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://dotenvx.com"
- }
- },
- "node_modules/eastasianwidth": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
- "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
- "license": "MIT"
- },
- "node_modules/ejs": {
- "version": "3.1.10",
- "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz",
- "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==",
- "license": "Apache-2.0",
- "dependencies": {
- "jake": "^10.8.5"
- },
- "bin": {
- "ejs": "bin/cli.js"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/electron": {
- "version": "32.1.2",
- "resolved": "https://registry.npmjs.org/electron/-/electron-32.1.2.tgz",
- "integrity": "sha512-CXe6doFzhmh1U7daOvUzmF6Cj8hssdYWMeEPRnRO6rB9/bbwMlWctcQ7P8NJXhLQ88/vYUJQrJvlJPh8qM0BRQ==",
- "hasInstallScript": true,
- "license": "MIT",
- "dependencies": {
- "@electron/get": "^2.0.0",
- "@types/node": "^20.9.0",
- "extract-zip": "^2.0.1"
- },
- "bin": {
- "electron": "cli.js"
- },
- "engines": {
- "node": ">= 12.20.55"
- }
- },
- "node_modules/electron-builder": {
- "version": "25.1.7",
- "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-25.1.7.tgz",
- "integrity": "sha512-lsKtX93GSHWnmuteNRvBzgJIjRiiYB0qrJVRjShwBi75Ns+mRdWeOGZiXItqOWj+3g5UyY722kgoq2WlqCB87A==",
- "license": "MIT",
- "dependencies": {
- "app-builder-lib": "25.1.7",
- "builder-util": "25.1.7",
- "builder-util-runtime": "9.2.10",
- "chalk": "^4.1.2",
- "dmg-builder": "25.1.7",
- "fs-extra": "^10.1.0",
- "is-ci": "^3.0.0",
- "lazy-val": "^1.0.5",
- "simple-update-notifier": "2.0.0",
- "yargs": "^17.6.2"
- },
- "bin": {
- "electron-builder": "cli.js",
- "install-app-deps": "install-app-deps.js"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/electron-builder-squirrel-windows": {
- "version": "25.1.7",
- "resolved": "https://registry.npmjs.org/electron-builder-squirrel-windows/-/electron-builder-squirrel-windows-25.1.7.tgz",
- "integrity": "sha512-nJMvw1FNy+6YP8HmjSb0JwMowpdlZpydZGab9KevKO/fIC9wTcr5rkhbLsTfEPOjdAqOTycRoK0mOJCFB/1uig==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "app-builder-lib": "25.1.7",
- "archiver": "^5.3.1",
- "builder-util": "25.1.7",
- "fs-extra": "^10.1.0"
- }
- },
- "node_modules/electron-builder-squirrel-windows/node_modules/fs-extra": {
- "version": "10.1.0",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
- "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "graceful-fs": "^4.2.0",
- "jsonfile": "^6.0.1",
- "universalify": "^2.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/electron-builder-squirrel-windows/node_modules/jsonfile": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
- "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "universalify": "^2.0.0"
- },
- "optionalDependencies": {
- "graceful-fs": "^4.1.6"
- }
- },
- "node_modules/electron-builder-squirrel-windows/node_modules/universalify": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
- "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
- "license": "MIT",
- "peer": true,
- "engines": {
- "node": ">= 10.0.0"
- }
- },
- "node_modules/electron-builder/node_modules/fs-extra": {
- "version": "10.1.0",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
- "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
- "license": "MIT",
- "dependencies": {
- "graceful-fs": "^4.2.0",
- "jsonfile": "^6.0.1",
- "universalify": "^2.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/electron-builder/node_modules/jsonfile": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
- "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
- "license": "MIT",
- "dependencies": {
- "universalify": "^2.0.0"
- },
- "optionalDependencies": {
- "graceful-fs": "^4.1.6"
- }
- },
- "node_modules/electron-builder/node_modules/universalify": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
- "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
- "license": "MIT",
- "engines": {
- "node": ">= 10.0.0"
- }
- },
- "node_modules/electron-publish": {
- "version": "25.1.7",
- "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-25.1.7.tgz",
- "integrity": "sha512-+jbTkR9m39eDBMP4gfbqglDd6UvBC7RLh5Y0MhFSsc6UkGHj9Vj9TWobxevHYMMqmoujL11ZLjfPpMX+Pt6YEg==",
- "license": "MIT",
- "dependencies": {
- "@types/fs-extra": "^9.0.11",
- "builder-util": "25.1.7",
- "builder-util-runtime": "9.2.10",
- "chalk": "^4.1.2",
- "fs-extra": "^10.1.0",
- "lazy-val": "^1.0.5",
- "mime": "^2.5.2"
- }
- },
- "node_modules/electron-publish/node_modules/fs-extra": {
- "version": "10.1.0",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
- "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
- "license": "MIT",
- "dependencies": {
- "graceful-fs": "^4.2.0",
- "jsonfile": "^6.0.1",
- "universalify": "^2.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/electron-publish/node_modules/jsonfile": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
- "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
- "license": "MIT",
- "dependencies": {
- "universalify": "^2.0.0"
- },
- "optionalDependencies": {
- "graceful-fs": "^4.1.6"
- }
- },
- "node_modules/electron-publish/node_modules/universalify": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
- "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
- "license": "MIT",
- "engines": {
- "node": ">= 10.0.0"
- }
- },
- "node_modules/emoji-regex": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "license": "MIT"
- },
- "node_modules/encoding": {
- "version": "0.1.13",
- "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
- "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "iconv-lite": "^0.6.2"
- }
- },
- "node_modules/end-of-stream": {
- "version": "1.4.4",
- "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
- "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
- "license": "MIT",
- "dependencies": {
- "once": "^1.4.0"
- }
- },
- "node_modules/env-paths": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
- "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/err-code": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz",
- "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==",
- "license": "MIT"
- },
- "node_modules/es-define-property": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
- "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "get-intrinsic": "^1.2.4"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-errors": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
- "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es6-error": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz",
- "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==",
- "license": "MIT",
- "optional": true
- },
- "node_modules/escalade": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
- "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/escape-string-regexp": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
- "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/expand-template": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
- "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
- "license": "(MIT OR WTFPL)",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/exponential-backoff": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz",
- "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==",
- "license": "Apache-2.0"
- },
- "node_modules/extract-zip": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
- "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
- "license": "BSD-2-Clause",
- "dependencies": {
- "debug": "^4.1.1",
- "get-stream": "^5.1.0",
- "yauzl": "^2.10.0"
- },
- "bin": {
- "extract-zip": "cli.js"
- },
- "engines": {
- "node": ">= 10.17.0"
- },
- "optionalDependencies": {
- "@types/yauzl": "^2.9.1"
- }
- },
- "node_modules/extsprintf": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz",
- "integrity": "sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==",
- "engines": [
- "node >=0.6.0"
- ],
- "license": "MIT",
- "optional": true
- },
- "node_modules/fast-deep-equal": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
- "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
- "license": "MIT"
- },
- "node_modules/fast-json-stable-stringify": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
- "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
- "license": "MIT"
- },
- "node_modules/fd-slicer": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
- "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
- "license": "MIT",
- "dependencies": {
- "pend": "~1.2.0"
- }
- },
- "node_modules/file-uri-to-path": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
- "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
- "license": "MIT"
- },
- "node_modules/filelist": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz",
- "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==",
- "license": "Apache-2.0",
- "dependencies": {
- "minimatch": "^5.0.1"
- }
- },
- "node_modules/filelist/node_modules/minimatch": {
- "version": "5.1.6",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
- "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^2.0.1"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/foreground-child": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz",
- "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==",
- "license": "ISC",
- "dependencies": {
- "cross-spawn": "^7.0.0",
- "signal-exit": "^4.0.1"
- },
- "engines": {
- "node": ">=14"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/foreground-child/node_modules/signal-exit": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
- "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
- "license": "ISC",
- "engines": {
- "node": ">=14"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/form-data": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
- "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
- "license": "MIT",
- "dependencies": {
- "asynckit": "^0.4.0",
- "combined-stream": "^1.0.8",
- "mime-types": "^2.1.12"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/fs-constants": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
- "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
- "license": "MIT"
- },
- "node_modules/fs-extra": {
- "version": "8.1.0",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
- "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
- "license": "MIT",
- "dependencies": {
- "graceful-fs": "^4.2.0",
- "jsonfile": "^4.0.0",
- "universalify": "^0.1.0"
- },
- "engines": {
- "node": ">=6 <7 || >=8"
- }
- },
- "node_modules/fs-minipass": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
- "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
- "license": "ISC",
- "dependencies": {
- "minipass": "^3.0.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/fs.realpath": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
- "license": "ISC"
- },
- "node_modules/function-bind": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
- "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
- "license": "MIT",
- "optional": true,
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/gauge": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz",
- "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==",
- "deprecated": "This package is no longer supported.",
- "license": "ISC",
- "dependencies": {
- "aproba": "^1.0.3 || ^2.0.0",
- "color-support": "^1.1.3",
- "console-control-strings": "^1.1.0",
- "has-unicode": "^2.0.1",
- "signal-exit": "^3.0.7",
- "string-width": "^4.2.3",
- "strip-ansi": "^6.0.1",
- "wide-align": "^1.1.5"
- },
- "engines": {
- "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
- }
- },
- "node_modules/get-caller-file": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
- "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
- "license": "ISC",
- "engines": {
- "node": "6.* || 8.* || >= 10.*"
- }
- },
- "node_modules/get-intrinsic": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
- "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "es-errors": "^1.3.0",
- "function-bind": "^1.1.2",
- "has-proto": "^1.0.1",
- "has-symbols": "^1.0.3",
- "hasown": "^2.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/get-stream": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
- "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
- "license": "MIT",
- "dependencies": {
- "pump": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/github-from-package": {
- "version": "0.0.0",
- "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
- "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==",
- "license": "MIT"
- },
- "node_modules/glob": {
- "version": "7.2.3",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
- "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
- "deprecated": "Glob versions prior to v9 are no longer supported",
- "license": "ISC",
- "dependencies": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.1.1",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- },
- "engines": {
- "node": "*"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/glob/node_modules/brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "node_modules/glob/node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/global-agent": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz",
- "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==",
- "license": "BSD-3-Clause",
- "optional": true,
- "dependencies": {
- "boolean": "^3.0.1",
- "es6-error": "^4.1.1",
- "matcher": "^3.0.0",
- "roarr": "^2.15.3",
- "semver": "^7.3.2",
- "serialize-error": "^7.0.1"
- },
- "engines": {
- "node": ">=10.0"
- }
- },
- "node_modules/global-agent/node_modules/semver": {
- "version": "7.6.3",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
- "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
- "license": "ISC",
- "optional": true,
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/globalthis": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz",
- "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "define-properties": "^1.2.1",
- "gopd": "^1.0.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/gopd": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
- "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "get-intrinsic": "^1.1.3"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/got": {
- "version": "11.8.6",
- "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz",
- "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==",
- "license": "MIT",
- "dependencies": {
- "@sindresorhus/is": "^4.0.0",
- "@szmarczak/http-timer": "^4.0.5",
- "@types/cacheable-request": "^6.0.1",
- "@types/responselike": "^1.0.0",
- "cacheable-lookup": "^5.0.3",
- "cacheable-request": "^7.0.2",
- "decompress-response": "^6.0.0",
- "http2-wrapper": "^1.0.0-beta.5.2",
- "lowercase-keys": "^2.0.0",
- "p-cancelable": "^2.0.0",
- "responselike": "^2.0.0"
- },
- "engines": {
- "node": ">=10.19.0"
- },
- "funding": {
- "url": "https://github.com/sindresorhus/got?sponsor=1"
- }
- },
- "node_modules/graceful-fs": {
- "version": "4.2.11",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
- "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
- "license": "ISC"
- },
- "node_modules/has-flag": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
- "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/has-property-descriptors": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
- "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "es-define-property": "^1.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-proto": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
- "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-symbols": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
- "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-unicode": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
- "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==",
- "license": "ISC"
- },
- "node_modules/hasown": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
- "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "function-bind": "^1.1.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/hosted-git-info": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
- "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==",
- "license": "ISC",
- "dependencies": {
- "lru-cache": "^6.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/http-cache-semantics": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
- "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==",
- "license": "BSD-2-Clause"
- },
- "node_modules/http-proxy-agent": {
- "version": "7.0.2",
- "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
- "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
- "license": "MIT",
- "dependencies": {
- "agent-base": "^7.1.0",
- "debug": "^4.3.4"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/http2-wrapper": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz",
- "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==",
- "license": "MIT",
- "dependencies": {
- "quick-lru": "^5.1.1",
- "resolve-alpn": "^1.0.0"
- },
- "engines": {
- "node": ">=10.19.0"
- }
- },
- "node_modules/https-proxy-agent": {
- "version": "7.0.5",
- "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz",
- "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==",
- "license": "MIT",
- "dependencies": {
- "agent-base": "^7.0.2",
- "debug": "4"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/humanize-ms": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
- "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==",
- "license": "MIT",
- "dependencies": {
- "ms": "^2.0.0"
- }
- },
- "node_modules/iconv-corefoundation": {
- "version": "1.1.7",
- "resolved": "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz",
- "integrity": "sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==",
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "dependencies": {
- "cli-truncate": "^2.1.0",
- "node-addon-api": "^1.6.3"
- },
- "engines": {
- "node": "^8.11.2 || >=10"
- }
- },
- "node_modules/iconv-lite": {
- "version": "0.6.3",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
- "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
- "license": "MIT",
- "dependencies": {
- "safer-buffer": ">= 2.1.2 < 3.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/ieee754": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
- "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "BSD-3-Clause"
- },
- "node_modules/imurmurhash": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
- "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
- "license": "MIT",
- "engines": {
- "node": ">=0.8.19"
- }
- },
- "node_modules/indent-string": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
- "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/infer-owner": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz",
- "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==",
- "license": "ISC"
- },
- "node_modules/inflight": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
- "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
- "license": "ISC",
- "dependencies": {
- "once": "^1.3.0",
- "wrappy": "1"
- }
- },
- "node_modules/inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
- "license": "ISC"
- },
- "node_modules/ini": {
- "version": "1.3.8",
- "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
- "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
- "license": "ISC"
- },
- "node_modules/ip-address": {
- "version": "9.0.5",
- "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz",
- "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==",
- "license": "MIT",
- "dependencies": {
- "jsbn": "1.1.0",
- "sprintf-js": "^1.1.3"
- },
- "engines": {
- "node": ">= 12"
- }
- },
- "node_modules/is-ci": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz",
- "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==",
- "license": "MIT",
- "dependencies": {
- "ci-info": "^3.2.0"
- },
- "bin": {
- "is-ci": "bin.js"
- }
- },
- "node_modules/is-fullwidth-code-point": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/is-interactive": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz",
- "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/is-lambda": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz",
- "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==",
- "license": "MIT"
- },
- "node_modules/is-unicode-supported": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
- "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/isarray": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
- "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
- "license": "MIT",
- "peer": true
- },
- "node_modules/isbinaryfile": {
- "version": "5.0.2",
- "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.2.tgz",
- "integrity": "sha512-GvcjojwonMjWbTkfMpnVHVqXW/wKMYDfEpY94/8zy8HFMOqb/VL6oeONq9v87q4ttVlaTLnGXnJD4B5B1OTGIg==",
- "license": "MIT",
- "engines": {
- "node": ">= 18.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/gjtorikian/"
- }
- },
- "node_modules/isexe": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
- "license": "ISC"
- },
- "node_modules/jackspeak": {
- "version": "3.4.3",
- "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
- "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
- "license": "BlueOak-1.0.0",
- "dependencies": {
- "@isaacs/cliui": "^8.0.2"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- },
- "optionalDependencies": {
- "@pkgjs/parseargs": "^0.11.0"
- }
- },
- "node_modules/jake": {
- "version": "10.9.2",
- "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz",
- "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==",
- "license": "Apache-2.0",
- "dependencies": {
- "async": "^3.2.3",
- "chalk": "^4.0.2",
- "filelist": "^1.0.4",
- "minimatch": "^3.1.2"
- },
- "bin": {
- "jake": "bin/cli.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/jake/node_modules/brace-expansion": {
- "version": "1.1.11",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "node_modules/jake/node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/js-yaml": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
- "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
- "license": "MIT",
- "dependencies": {
- "argparse": "^2.0.1"
- },
- "bin": {
- "js-yaml": "bin/js-yaml.js"
- }
- },
- "node_modules/jsbn": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
- "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==",
- "license": "MIT"
- },
- "node_modules/json-buffer": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
- "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
- "license": "MIT"
- },
- "node_modules/json-schema-traverse": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
- "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
- "license": "MIT"
- },
- "node_modules/json-stringify-safe": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
- "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==",
- "license": "ISC",
- "optional": true
- },
- "node_modules/json5": {
- "version": "2.2.3",
- "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
- "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
- "license": "MIT",
- "bin": {
- "json5": "lib/cli.js"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/jsonfile": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
- "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
- "license": "MIT",
- "optionalDependencies": {
- "graceful-fs": "^4.1.6"
- }
- },
- "node_modules/keyv": {
- "version": "4.5.4",
- "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
- "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
- "license": "MIT",
- "dependencies": {
- "json-buffer": "3.0.1"
- }
- },
- "node_modules/lazy-val": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz",
- "integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==",
- "license": "MIT"
- },
- "node_modules/lazystream": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz",
- "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "readable-stream": "^2.0.5"
- },
- "engines": {
- "node": ">= 0.6.3"
- }
- },
- "node_modules/lazystream/node_modules/readable-stream": {
- "version": "2.3.8",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
- "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "core-util-is": "~1.0.0",
- "inherits": "~2.0.3",
- "isarray": "~1.0.0",
- "process-nextick-args": "~2.0.0",
- "safe-buffer": "~5.1.1",
- "string_decoder": "~1.1.1",
- "util-deprecate": "~1.0.1"
- }
- },
- "node_modules/lazystream/node_modules/safe-buffer": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
- "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
- "license": "MIT",
- "peer": true
- },
- "node_modules/lazystream/node_modules/string_decoder": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
- "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "safe-buffer": "~5.1.0"
- }
- },
- "node_modules/lodash": {
- "version": "4.17.21",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
- "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
- "license": "MIT"
- },
- "node_modules/lodash.defaults": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
- "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==",
- "license": "MIT",
- "peer": true
- },
- "node_modules/lodash.difference": {
- "version": "4.5.0",
- "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz",
- "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==",
- "license": "MIT",
- "peer": true
- },
- "node_modules/lodash.flatten": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
- "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==",
- "license": "MIT",
- "peer": true
- },
- "node_modules/lodash.isplainobject": {
- "version": "4.0.6",
- "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
- "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
- "license": "MIT",
- "peer": true
- },
- "node_modules/lodash.union": {
- "version": "4.6.0",
- "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz",
- "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==",
- "license": "MIT",
- "peer": true
- },
- "node_modules/log-symbols": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
- "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
- "license": "MIT",
- "dependencies": {
- "chalk": "^4.1.0",
- "is-unicode-supported": "^0.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/lowercase-keys": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
- "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/lru-cache": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
- "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
- "license": "ISC",
- "dependencies": {
- "yallist": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/make-fetch-happen": {
- "version": "10.2.1",
- "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz",
- "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==",
- "license": "ISC",
- "dependencies": {
- "agentkeepalive": "^4.2.1",
- "cacache": "^16.1.0",
- "http-cache-semantics": "^4.1.0",
- "http-proxy-agent": "^5.0.0",
- "https-proxy-agent": "^5.0.0",
- "is-lambda": "^1.0.1",
- "lru-cache": "^7.7.1",
- "minipass": "^3.1.6",
- "minipass-collect": "^1.0.2",
- "minipass-fetch": "^2.0.3",
- "minipass-flush": "^1.0.5",
- "minipass-pipeline": "^1.2.4",
- "negotiator": "^0.6.3",
- "promise-retry": "^2.0.1",
- "socks-proxy-agent": "^7.0.0",
- "ssri": "^9.0.0"
- },
- "engines": {
- "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
- }
- },
- "node_modules/make-fetch-happen/node_modules/agent-base": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
- "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
- "license": "MIT",
- "dependencies": {
- "debug": "4"
- },
- "engines": {
- "node": ">= 6.0.0"
- }
- },
- "node_modules/make-fetch-happen/node_modules/http-proxy-agent": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz",
- "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==",
- "license": "MIT",
- "dependencies": {
- "@tootallnate/once": "2",
- "agent-base": "6",
- "debug": "4"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/make-fetch-happen/node_modules/https-proxy-agent": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
- "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
- "license": "MIT",
- "dependencies": {
- "agent-base": "6",
- "debug": "4"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/make-fetch-happen/node_modules/lru-cache": {
- "version": "7.18.3",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
- "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/matcher": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz",
- "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "escape-string-regexp": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/mime": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
- "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
- "license": "MIT",
- "bin": {
- "mime": "cli.js"
- },
- "engines": {
- "node": ">=4.0.0"
- }
- },
- "node_modules/mime-db": {
- "version": "1.52.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
- "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/mime-types": {
- "version": "2.1.35",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
- "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
- "license": "MIT",
- "dependencies": {
- "mime-db": "1.52.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/mimic-fn": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
- "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/mimic-response": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
- "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==",
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/minimatch": {
- "version": "10.0.1",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz",
- "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==",
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^2.0.1"
- },
- "engines": {
- "node": "20 || >=22"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/minimist": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
- "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/minipass": {
- "version": "3.3.6",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
- "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
- "license": "ISC",
- "dependencies": {
- "yallist": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/minipass-collect": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz",
- "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==",
- "license": "ISC",
- "dependencies": {
- "minipass": "^3.0.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/minipass-fetch": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz",
- "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==",
- "license": "MIT",
- "dependencies": {
- "minipass": "^3.1.6",
- "minipass-sized": "^1.0.3",
- "minizlib": "^2.1.2"
- },
- "engines": {
- "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
- },
- "optionalDependencies": {
- "encoding": "^0.1.13"
- }
- },
- "node_modules/minipass-flush": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz",
- "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==",
- "license": "ISC",
- "dependencies": {
- "minipass": "^3.0.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/minipass-pipeline": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz",
- "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==",
- "license": "ISC",
- "dependencies": {
- "minipass": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/minipass-sized": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz",
- "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==",
- "license": "ISC",
- "dependencies": {
- "minipass": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/minizlib": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
- "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
- "license": "MIT",
- "dependencies": {
- "minipass": "^3.0.0",
- "yallist": "^4.0.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/mkdirp": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
- "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
- "license": "MIT",
- "bin": {
- "mkdirp": "bin/cmd.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/mkdirp-classic": {
- "version": "0.5.3",
- "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
- "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
- "license": "MIT"
- },
- "node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
- "license": "MIT"
- },
- "node_modules/napi-build-utils": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz",
- "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==",
- "license": "MIT"
- },
- "node_modules/negotiator": {
- "version": "0.6.3",
- "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
- "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/node-abi": {
- "version": "3.68.0",
- "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.68.0.tgz",
- "integrity": "sha512-7vbj10trelExNjFSBm5kTvZXXa7pZyKWx9RCKIyqe6I9Ev3IzGpQoqBP3a+cOdxY+pWj6VkP28n/2wWysBHD/A==",
- "license": "MIT",
- "dependencies": {
- "semver": "^7.3.5"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/node-abi/node_modules/semver": {
- "version": "7.6.3",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
- "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/node-addon-api": {
- "version": "1.7.2",
- "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz",
- "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==",
- "license": "MIT",
- "optional": true
- },
- "node_modules/node-api-version": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/node-api-version/-/node-api-version-0.2.0.tgz",
- "integrity": "sha512-fthTTsi8CxaBXMaBAD7ST2uylwvsnYxh2PfaScwpMhos6KlSFajXQPcM4ogNE1q2s3Lbz9GCGqeIHC+C6OZnKg==",
- "license": "MIT",
- "dependencies": {
- "semver": "^7.3.5"
- }
- },
- "node_modules/node-api-version/node_modules/semver": {
- "version": "7.6.3",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
- "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/node-gyp": {
- "version": "9.4.1",
- "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.1.tgz",
- "integrity": "sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ==",
- "license": "MIT",
- "dependencies": {
- "env-paths": "^2.2.0",
- "exponential-backoff": "^3.1.1",
- "glob": "^7.1.4",
- "graceful-fs": "^4.2.6",
- "make-fetch-happen": "^10.0.3",
- "nopt": "^6.0.0",
- "npmlog": "^6.0.0",
- "rimraf": "^3.0.2",
- "semver": "^7.3.5",
- "tar": "^6.1.2",
- "which": "^2.0.2"
- },
- "bin": {
- "node-gyp": "bin/node-gyp.js"
- },
- "engines": {
- "node": "^12.13 || ^14.13 || >=16"
- }
- },
- "node_modules/node-gyp/node_modules/semver": {
- "version": "7.6.3",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
- "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/nopt": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz",
- "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==",
- "license": "ISC",
- "dependencies": {
- "abbrev": "^1.0.0"
- },
- "bin": {
- "nopt": "bin/nopt.js"
- },
- "engines": {
- "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
- }
- },
- "node_modules/normalize-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
- "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
- "license": "MIT",
- "peer": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/normalize-url": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz",
- "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==",
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/npmlog": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz",
- "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==",
- "deprecated": "This package is no longer supported.",
- "license": "ISC",
- "dependencies": {
- "are-we-there-yet": "^3.0.0",
- "console-control-strings": "^1.1.0",
- "gauge": "^4.0.3",
- "set-blocking": "^2.0.0"
- },
- "engines": {
- "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
- }
- },
- "node_modules/object-keys": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
- "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/once": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
- "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
- "license": "ISC",
- "dependencies": {
- "wrappy": "1"
- }
- },
- "node_modules/onetime": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
- "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
- "license": "MIT",
- "dependencies": {
- "mimic-fn": "^2.1.0"
- },
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/ora": {
- "version": "5.4.1",
- "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz",
- "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==",
- "license": "MIT",
- "dependencies": {
- "bl": "^4.1.0",
- "chalk": "^4.1.0",
- "cli-cursor": "^3.1.0",
- "cli-spinners": "^2.5.0",
- "is-interactive": "^1.0.0",
- "is-unicode-supported": "^0.1.0",
- "log-symbols": "^4.1.0",
- "strip-ansi": "^6.0.0",
- "wcwidth": "^1.0.1"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/p-cancelable": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz",
- "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/p-limit": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
- "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
- "license": "MIT",
- "dependencies": {
- "yocto-queue": "^0.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/p-map": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
- "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
- "license": "MIT",
- "dependencies": {
- "aggregate-error": "^3.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/package-json-from-dist": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
- "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
- "license": "BlueOak-1.0.0"
- },
- "node_modules/path-is-absolute": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/path-key": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
- "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/path-scurry": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
- "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
- "license": "BlueOak-1.0.0",
- "dependencies": {
- "lru-cache": "^10.2.0",
- "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
- },
- "engines": {
- "node": ">=16 || 14 >=14.18"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/path-scurry/node_modules/lru-cache": {
- "version": "10.4.3",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
- "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
- "license": "ISC"
- },
- "node_modules/path-scurry/node_modules/minipass": {
- "version": "7.1.2",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
- "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
- "license": "ISC",
- "engines": {
- "node": ">=16 || 14 >=14.17"
- }
- },
- "node_modules/pe-library": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/pe-library/-/pe-library-0.4.1.tgz",
- "integrity": "sha512-eRWB5LBz7PpDu4PUlwT0PhnQfTQJlDDdPa35urV4Osrm0t0AqQFGn+UIkU3klZvwJ8KPO3VbBFsXquA6p6kqZw==",
- "license": "MIT",
- "engines": {
- "node": ">=12",
- "npm": ">=6"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/jet2jet"
- }
- },
- "node_modules/pend": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
- "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==",
- "license": "MIT"
- },
- "node_modules/plist": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz",
- "integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==",
- "license": "MIT",
- "dependencies": {
- "@xmldom/xmldom": "^0.8.8",
- "base64-js": "^1.5.1",
- "xmlbuilder": "^15.1.1"
- },
- "engines": {
- "node": ">=10.4.0"
- }
- },
- "node_modules/prebuild-install": {
- "version": "7.1.2",
- "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.2.tgz",
- "integrity": "sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==",
- "license": "MIT",
- "dependencies": {
- "detect-libc": "^2.0.0",
- "expand-template": "^2.0.3",
- "github-from-package": "0.0.0",
- "minimist": "^1.2.3",
- "mkdirp-classic": "^0.5.3",
- "napi-build-utils": "^1.0.1",
- "node-abi": "^3.3.0",
- "pump": "^3.0.0",
- "rc": "^1.2.7",
- "simple-get": "^4.0.0",
- "tar-fs": "^2.0.0",
- "tunnel-agent": "^0.6.0"
- },
- "bin": {
- "prebuild-install": "bin.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/process-nextick-args": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
- "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
- "license": "MIT",
- "peer": true
- },
- "node_modules/progress": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
- "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
- "license": "MIT",
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/promise-inflight": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
- "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==",
- "license": "ISC"
- },
- "node_modules/promise-retry": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz",
- "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==",
- "license": "MIT",
- "dependencies": {
- "err-code": "^2.0.2",
- "retry": "^0.12.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/pump": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz",
- "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==",
- "license": "MIT",
- "dependencies": {
- "end-of-stream": "^1.1.0",
- "once": "^1.3.1"
- }
- },
- "node_modules/punycode": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
- "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/quick-lru": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz",
- "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==",
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/rc": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
- "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
- "license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
- "dependencies": {
- "deep-extend": "^0.6.0",
- "ini": "~1.3.0",
- "minimist": "^1.2.0",
- "strip-json-comments": "~2.0.1"
- },
- "bin": {
- "rc": "cli.js"
- }
- },
- "node_modules/read-binary-file-arch": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/read-binary-file-arch/-/read-binary-file-arch-1.0.6.tgz",
- "integrity": "sha512-BNg9EN3DD3GsDXX7Aa8O4p92sryjkmzYYgmgTAc6CA4uGLEDzFfxOxugu21akOxpcXHiEgsYkC6nPsQvLLLmEg==",
- "license": "MIT",
- "dependencies": {
- "debug": "^4.3.4"
- },
- "bin": {
- "read-binary-file-arch": "cli.js"
- }
- },
- "node_modules/readable-stream": {
- "version": "3.6.2",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
- "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
- "license": "MIT",
- "dependencies": {
- "inherits": "^2.0.3",
- "string_decoder": "^1.1.1",
- "util-deprecate": "^1.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/readdir-glob": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz",
- "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==",
- "license": "Apache-2.0",
- "peer": true,
- "dependencies": {
- "minimatch": "^5.1.0"
- }
- },
- "node_modules/readdir-glob/node_modules/minimatch": {
- "version": "5.1.6",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
- "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
- "license": "ISC",
- "peer": true,
- "dependencies": {
- "brace-expansion": "^2.0.1"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/require-directory": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
- "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/resedit": {
- "version": "1.7.1",
- "resolved": "https://registry.npmjs.org/resedit/-/resedit-1.7.1.tgz",
- "integrity": "sha512-/FJ6/gKAXbcHtivannhecWsa43kGVFK3aHHv9Jm3x0eFiM31MoGihkAOWbm3UsvjYLRVw0zTkfARy2dI96JL1Q==",
- "license": "MIT",
- "dependencies": {
- "pe-library": "^0.4.1"
- },
- "engines": {
- "node": ">=12",
- "npm": ">=6"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/jet2jet"
- }
- },
- "node_modules/resolve-alpn": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz",
- "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==",
- "license": "MIT"
- },
- "node_modules/responselike": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz",
- "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==",
- "license": "MIT",
- "dependencies": {
- "lowercase-keys": "^2.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/restore-cursor": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
- "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
- "license": "MIT",
- "dependencies": {
- "onetime": "^5.1.0",
- "signal-exit": "^3.0.2"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/retry": {
- "version": "0.12.0",
- "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
- "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==",
- "license": "MIT",
- "engines": {
- "node": ">= 4"
- }
- },
- "node_modules/rimraf": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
- "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
- "deprecated": "Rimraf versions prior to v4 are no longer supported",
- "license": "ISC",
- "dependencies": {
- "glob": "^7.1.3"
- },
- "bin": {
- "rimraf": "bin.js"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/roarr": {
- "version": "2.15.4",
- "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz",
- "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==",
- "license": "BSD-3-Clause",
- "optional": true,
- "dependencies": {
- "boolean": "^3.0.1",
- "detect-node": "^2.0.4",
- "globalthis": "^1.0.1",
- "json-stringify-safe": "^5.0.1",
- "semver-compare": "^1.0.0",
- "sprintf-js": "^1.1.2"
- },
- "engines": {
- "node": ">=8.0"
- }
- },
- "node_modules/safe-buffer": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
- "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT"
- },
- "node_modules/safer-buffer": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
- "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
- "license": "MIT"
- },
- "node_modules/sanitize-filename": {
- "version": "1.6.3",
- "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz",
- "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==",
- "license": "WTFPL OR ISC",
- "dependencies": {
- "truncate-utf8-bytes": "^1.0.0"
- }
- },
- "node_modules/sax": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz",
- "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==",
- "license": "ISC"
- },
- "node_modules/semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- }
- },
- "node_modules/semver-compare": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz",
- "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==",
- "license": "MIT",
- "optional": true
- },
- "node_modules/serialize-error": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz",
- "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "type-fest": "^0.13.1"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/set-blocking": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
- "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
- "license": "ISC"
- },
- "node_modules/shebang-command": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
- "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
- "license": "MIT",
- "dependencies": {
- "shebang-regex": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/shebang-regex": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
- "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/signal-exit": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
- "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
- "license": "ISC"
- },
- "node_modules/simple-concat": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
- "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT"
- },
- "node_modules/simple-get": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
- "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "decompress-response": "^6.0.0",
- "once": "^1.3.1",
- "simple-concat": "^1.0.0"
- }
- },
- "node_modules/simple-update-notifier": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz",
- "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==",
- "license": "MIT",
- "dependencies": {
- "semver": "^7.5.3"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/simple-update-notifier/node_modules/semver": {
- "version": "7.6.3",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
- "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/slice-ansi": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz",
- "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "ansi-styles": "^4.0.0",
- "astral-regex": "^2.0.0",
- "is-fullwidth-code-point": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/smart-buffer": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
- "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
- "license": "MIT",
- "engines": {
- "node": ">= 6.0.0",
- "npm": ">= 3.0.0"
- }
- },
- "node_modules/socks": {
- "version": "2.8.3",
- "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz",
- "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==",
- "license": "MIT",
- "dependencies": {
- "ip-address": "^9.0.5",
- "smart-buffer": "^4.2.0"
- },
- "engines": {
- "node": ">= 10.0.0",
- "npm": ">= 3.0.0"
- }
- },
- "node_modules/socks-proxy-agent": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz",
- "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==",
- "license": "MIT",
- "dependencies": {
- "agent-base": "^6.0.2",
- "debug": "^4.3.3",
- "socks": "^2.6.2"
- },
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/socks-proxy-agent/node_modules/agent-base": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
- "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
- "license": "MIT",
- "dependencies": {
- "debug": "4"
- },
- "engines": {
- "node": ">= 6.0.0"
- }
- },
- "node_modules/source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/source-map-support": {
- "version": "0.5.21",
- "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
- "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
- "license": "MIT",
- "dependencies": {
- "buffer-from": "^1.0.0",
- "source-map": "^0.6.0"
- }
- },
- "node_modules/sprintf-js": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
- "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==",
- "license": "BSD-3-Clause"
- },
- "node_modules/sqlite3": {
- "version": "5.1.7",
- "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.7.tgz",
- "integrity": "sha512-GGIyOiFaG+TUra3JIfkI/zGP8yZYLPQ0pl1bH+ODjiX57sPhrLU5sQJn1y9bDKZUFYkX1crlrPfSYt0BKKdkog==",
- "hasInstallScript": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "bindings": "^1.5.0",
- "node-addon-api": "^7.0.0",
- "prebuild-install": "^7.1.1",
- "tar": "^6.1.11"
- },
- "optionalDependencies": {
- "node-gyp": "8.x"
- },
- "peerDependencies": {
- "node-gyp": "8.x"
- },
- "peerDependenciesMeta": {
- "node-gyp": {
- "optional": true
- }
- }
- },
- "node_modules/sqlite3/node_modules/@npmcli/fs": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz",
- "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "@gar/promisify": "^1.0.1",
- "semver": "^7.3.5"
- }
- },
- "node_modules/sqlite3/node_modules/@npmcli/move-file": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz",
- "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==",
- "deprecated": "This functionality has been moved to @npmcli/fs",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "mkdirp": "^1.0.4",
- "rimraf": "^3.0.2"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/sqlite3/node_modules/@tootallnate/once": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
- "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/sqlite3/node_modules/agent-base": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
- "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "debug": "4"
- },
- "engines": {
- "node": ">= 6.0.0"
- }
- },
- "node_modules/sqlite3/node_modules/cacache": {
- "version": "15.3.0",
- "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz",
- "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "@npmcli/fs": "^1.0.0",
- "@npmcli/move-file": "^1.0.1",
- "chownr": "^2.0.0",
- "fs-minipass": "^2.0.0",
- "glob": "^7.1.4",
- "infer-owner": "^1.0.4",
- "lru-cache": "^6.0.0",
- "minipass": "^3.1.1",
- "minipass-collect": "^1.0.2",
- "minipass-flush": "^1.0.5",
- "minipass-pipeline": "^1.2.2",
- "mkdirp": "^1.0.3",
- "p-map": "^4.0.0",
- "promise-inflight": "^1.0.1",
- "rimraf": "^3.0.2",
- "ssri": "^8.0.1",
- "tar": "^6.0.2",
- "unique-filename": "^1.1.1"
- },
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/sqlite3/node_modules/http-proxy-agent": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz",
- "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@tootallnate/once": "1",
- "agent-base": "6",
- "debug": "4"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/sqlite3/node_modules/https-proxy-agent": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
- "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "agent-base": "6",
- "debug": "4"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/sqlite3/node_modules/make-fetch-happen": {
- "version": "9.1.0",
- "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz",
- "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "agentkeepalive": "^4.1.3",
- "cacache": "^15.2.0",
- "http-cache-semantics": "^4.1.0",
- "http-proxy-agent": "^4.0.1",
- "https-proxy-agent": "^5.0.0",
- "is-lambda": "^1.0.1",
- "lru-cache": "^6.0.0",
- "minipass": "^3.1.3",
- "minipass-collect": "^1.0.2",
- "minipass-fetch": "^1.3.2",
- "minipass-flush": "^1.0.5",
- "minipass-pipeline": "^1.2.4",
- "negotiator": "^0.6.2",
- "promise-retry": "^2.0.1",
- "socks-proxy-agent": "^6.0.0",
- "ssri": "^8.0.0"
- },
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/sqlite3/node_modules/minipass-fetch": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz",
- "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "minipass": "^3.1.0",
- "minipass-sized": "^1.0.3",
- "minizlib": "^2.0.0"
- },
- "engines": {
- "node": ">=8"
- },
- "optionalDependencies": {
- "encoding": "^0.1.12"
- }
- },
- "node_modules/sqlite3/node_modules/node-addon-api": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
- "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
- "license": "MIT"
- },
- "node_modules/sqlite3/node_modules/node-gyp": {
- "version": "8.4.1",
- "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz",
- "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "env-paths": "^2.2.0",
- "glob": "^7.1.4",
- "graceful-fs": "^4.2.6",
- "make-fetch-happen": "^9.1.0",
- "nopt": "^5.0.0",
- "npmlog": "^6.0.0",
- "rimraf": "^3.0.2",
- "semver": "^7.3.5",
- "tar": "^6.1.2",
- "which": "^2.0.2"
- },
- "bin": {
- "node-gyp": "bin/node-gyp.js"
- },
- "engines": {
- "node": ">= 10.12.0"
- }
- },
- "node_modules/sqlite3/node_modules/nopt": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
- "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "abbrev": "1"
- },
- "bin": {
- "nopt": "bin/nopt.js"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/sqlite3/node_modules/semver": {
- "version": "7.6.3",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
- "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
- "license": "ISC",
- "optional": true,
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/sqlite3/node_modules/socks-proxy-agent": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz",
- "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "agent-base": "^6.0.2",
- "debug": "^4.3.3",
- "socks": "^2.6.2"
- },
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/sqlite3/node_modules/ssri": {
- "version": "8.0.1",
- "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz",
- "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "minipass": "^3.1.1"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/sqlite3/node_modules/unique-filename": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz",
- "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "unique-slug": "^2.0.0"
- }
- },
- "node_modules/sqlite3/node_modules/unique-slug": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz",
- "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "imurmurhash": "^0.1.4"
- }
- },
- "node_modules/ssri": {
- "version": "9.0.1",
- "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz",
- "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==",
- "license": "ISC",
- "dependencies": {
- "minipass": "^3.1.1"
- },
- "engines": {
- "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
- }
- },
- "node_modules/stat-mode": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-1.0.0.tgz",
- "integrity": "sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==",
- "license": "MIT",
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/string_decoder": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
- "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
- "license": "MIT",
- "dependencies": {
- "safe-buffer": "~5.2.0"
- }
- },
- "node_modules/string-width": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "license": "MIT",
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/string-width-cjs": {
- "name": "string-width",
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "license": "MIT",
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/strip-ansi-cjs": {
- "name": "strip-ansi",
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/strip-json-comments": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
- "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/sumchecker": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz",
- "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==",
- "license": "Apache-2.0",
- "dependencies": {
- "debug": "^4.1.0"
- },
- "engines": {
- "node": ">= 8.0"
- }
- },
- "node_modules/supports-color": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
- "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
- "license": "MIT",
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/tar": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
- "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
- "license": "ISC",
- "dependencies": {
- "chownr": "^2.0.0",
- "fs-minipass": "^2.0.0",
- "minipass": "^5.0.0",
- "minizlib": "^2.1.1",
- "mkdirp": "^1.0.3",
- "yallist": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/tar-fs": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
- "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==",
- "license": "MIT",
- "dependencies": {
- "chownr": "^1.1.1",
- "mkdirp-classic": "^0.5.2",
- "pump": "^3.0.0",
- "tar-stream": "^2.1.4"
- }
- },
- "node_modules/tar-fs/node_modules/chownr": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
- "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
- "license": "ISC"
- },
- "node_modules/tar-stream": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
- "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
- "license": "MIT",
- "dependencies": {
- "bl": "^4.0.3",
- "end-of-stream": "^1.4.1",
- "fs-constants": "^1.0.0",
- "inherits": "^2.0.3",
- "readable-stream": "^3.1.1"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/tar/node_modules/minipass": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
- "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
- "license": "ISC",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/temp-file": {
- "version": "3.4.0",
- "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.4.0.tgz",
- "integrity": "sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==",
- "license": "MIT",
- "dependencies": {
- "async-exit-hook": "^2.0.1",
- "fs-extra": "^10.0.0"
- }
- },
- "node_modules/temp-file/node_modules/fs-extra": {
- "version": "10.1.0",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
- "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
- "license": "MIT",
- "dependencies": {
- "graceful-fs": "^4.2.0",
- "jsonfile": "^6.0.1",
- "universalify": "^2.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/temp-file/node_modules/jsonfile": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
- "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
- "license": "MIT",
- "dependencies": {
- "universalify": "^2.0.0"
- },
- "optionalDependencies": {
- "graceful-fs": "^4.1.6"
- }
- },
- "node_modules/temp-file/node_modules/universalify": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
- "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
- "license": "MIT",
- "engines": {
- "node": ">= 10.0.0"
- }
- },
- "node_modules/tmp": {
- "version": "0.2.3",
- "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz",
- "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==",
- "license": "MIT",
- "engines": {
- "node": ">=14.14"
- }
- },
- "node_modules/tmp-promise": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz",
- "integrity": "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==",
- "license": "MIT",
- "dependencies": {
- "tmp": "^0.2.0"
- }
- },
- "node_modules/truncate-utf8-bytes": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz",
- "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==",
- "license": "WTFPL",
- "dependencies": {
- "utf8-byte-length": "^1.0.1"
- }
- },
- "node_modules/tunnel-agent": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
- "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
- "license": "Apache-2.0",
- "dependencies": {
- "safe-buffer": "^5.0.1"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/type-fest": {
- "version": "0.13.1",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz",
- "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==",
- "license": "(MIT OR CC0-1.0)",
- "optional": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/typescript": {
- "version": "5.6.2",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz",
- "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==",
- "license": "Apache-2.0",
- "bin": {
- "tsc": "bin/tsc",
- "tsserver": "bin/tsserver"
- },
- "engines": {
- "node": ">=14.17"
- }
- },
- "node_modules/undici-types": {
- "version": "6.19.8",
- "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
- "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
- "license": "MIT"
- },
- "node_modules/unique-filename": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz",
- "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==",
- "license": "ISC",
- "dependencies": {
- "unique-slug": "^3.0.0"
- },
- "engines": {
- "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
- }
- },
- "node_modules/unique-slug": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz",
- "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==",
- "license": "ISC",
- "dependencies": {
- "imurmurhash": "^0.1.4"
- },
- "engines": {
- "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
- }
- },
- "node_modules/universalify": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
- "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
- "license": "MIT",
- "engines": {
- "node": ">= 4.0.0"
- }
- },
- "node_modules/uri-js": {
- "version": "4.4.1",
- "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
- "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
- "license": "BSD-2-Clause",
- "dependencies": {
- "punycode": "^2.1.0"
- }
- },
- "node_modules/utf8-byte-length": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz",
- "integrity": "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==",
- "license": "(WTFPL OR MIT)"
- },
- "node_modules/util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
- "license": "MIT"
- },
- "node_modules/verror": {
- "version": "1.10.1",
- "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz",
- "integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "assert-plus": "^1.0.0",
- "core-util-is": "1.0.2",
- "extsprintf": "^1.2.0"
- },
- "engines": {
- "node": ">=0.6.0"
- }
- },
- "node_modules/wcwidth": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
- "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==",
- "license": "MIT",
- "dependencies": {
- "defaults": "^1.0.3"
- }
- },
- "node_modules/which": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
- "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
- "license": "ISC",
- "dependencies": {
- "isexe": "^2.0.0"
- },
- "bin": {
- "node-which": "bin/node-which"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/wide-align": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
- "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==",
- "license": "ISC",
- "dependencies": {
- "string-width": "^1.0.2 || 2 || 3 || 4"
- }
- },
- "node_modules/wrap-ansi": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
- "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^4.0.0",
- "string-width": "^4.1.0",
- "strip-ansi": "^6.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
- }
- },
- "node_modules/wrap-ansi-cjs": {
- "name": "wrap-ansi",
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
- "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^4.0.0",
- "string-width": "^4.1.0",
- "strip-ansi": "^6.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
- }
- },
- "node_modules/wrappy": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
- "license": "ISC"
- },
- "node_modules/xmlbuilder": {
- "version": "15.1.1",
- "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz",
- "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==",
- "license": "MIT",
- "engines": {
- "node": ">=8.0"
- }
- },
- "node_modules/y18n": {
- "version": "5.0.8",
- "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
- "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
- "license": "ISC",
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/yallist": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
- "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
- "license": "ISC"
- },
- "node_modules/yargs": {
- "version": "17.7.2",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
- "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
- "license": "MIT",
- "dependencies": {
- "cliui": "^8.0.1",
- "escalade": "^3.1.1",
- "get-caller-file": "^2.0.5",
- "require-directory": "^2.1.1",
- "string-width": "^4.2.3",
- "y18n": "^5.0.5",
- "yargs-parser": "^21.1.1"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/yargs-parser": {
- "version": "21.1.1",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
- "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/yauzl": {
- "version": "2.10.0",
- "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
- "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
- "license": "MIT",
- "dependencies": {
- "buffer-crc32": "~0.2.3",
- "fd-slicer": "~1.1.0"
- }
- },
- "node_modules/yocto-queue": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
- "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/zip-stream": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.1.tgz",
- "integrity": "sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "archiver-utils": "^3.0.4",
- "compress-commons": "^4.1.2",
- "readable-stream": "^3.6.0"
- },
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/zip-stream/node_modules/archiver-utils": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-3.0.4.tgz",
- "integrity": "sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "glob": "^7.2.3",
- "graceful-fs": "^4.2.0",
- "lazystream": "^1.0.0",
- "lodash.defaults": "^4.2.0",
- "lodash.difference": "^4.5.0",
- "lodash.flatten": "^4.4.0",
- "lodash.isplainobject": "^4.0.6",
- "lodash.union": "^4.6.0",
- "normalize-path": "^3.0.0",
- "readable-stream": "^3.6.0"
- },
- "engines": {
- "node": ">= 10"
- }
- }
- }
-}
diff --git a/DBVisualiser/package.json b/DBVisualiser/package.json
deleted file mode 100644
index cdfa063..0000000
--- a/DBVisualiser/package.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "name": "dbvisualiser",
- "version": "1.0.0",
- "main": "main.js",
- "scripts": {
- "test": "echo \"Error: no test specified\" && exit 1",
- "start": "electron . --inspect=5858"
- },
- "keywords": [],
- "author": "",
- "license": "ISC",
- "description": "",
- "dependencies": {
- "electron": "^32.1.2",
- "electron-builder": "^25.1.7",
- "sqlite3": "^5.1.7"
- }
-
-}
diff --git a/DBVisualiser/pokemon_forms.db b/DBVisualiser/pokemon_forms.db
deleted file mode 100644
index e69de29..0000000
diff --git a/DBVisualiser/renderer.js b/DBVisualiser/renderer.js
deleted file mode 100644
index b5cd962..0000000
--- a/DBVisualiser/renderer.js
+++ /dev/null
@@ -1,483 +0,0 @@
-const { ipcRenderer } = require('electron');
-
-// Add these variables at the top of the file
-let currentEditingStageIndex, currentEditingPokemonIndex;
-let allPokemon = []; // This will store all Pokémon for the select dropdown
-let currentEvolutionChain = null; // Add this line
-let allPokemonForms = [];
-
-document.addEventListener('DOMContentLoaded', () => {
- loadFormsData();
- setupTabButtons();
- setupSearchButtons();
- setupSaveChangesButton();
-
- const modal = document.getElementById('edit-pokemon-modal');
- const closeBtn = modal.querySelector('.close');
- const form = document.getElementById('edit-pokemon-form');
-
- closeBtn.onclick = () => {
- modal.style.display = 'none';
- };
-
- window.onclick = (event) => {
- if (event.target === modal) {
- modal.style.display = 'none';
- }
- };
-
- form.onsubmit = (e) => {
- e.preventDefault();
- const newPfic = document.getElementById('pokemon-select').value;
- const newMethod = document.getElementById('evolution-method').value;
- updatePokemonInChain(currentEditingStageIndex, currentEditingPokemonIndex, newPfic, newMethod);
- modal.style.display = 'none';
- };
-
- loadAllPokemon();
- setupPokemonFilter();
-});
-
-function setupTabButtons() {
- const tabButtons = document.querySelectorAll('.tab-button');
- tabButtons.forEach(button => {
- button.addEventListener('click', () => {
- const tabName = button.getAttribute('data-tab');
- activateTab(tabName);
- });
- });
-}
-
-function activateTab(tabName) {
- document.querySelectorAll('.tab-button').forEach(btn => btn.classList.remove('active'));
- document.querySelectorAll('.tab-content').forEach(content => content.classList.remove('active'));
-
- document.querySelector(`.tab-button[data-tab="${tabName}"]`).classList.add('active');
- document.getElementById(`${tabName}-tab`).classList.add('active');
-}
-
-function setupSearchButtons() {
- //document.getElementById('forms-search-button').addEventListener('click', searchForms);
- //document.getElementById('evolution-search-button').addEventListener('click', searchEvolution);
-}
-
-function setupSaveChangesButton() {
- //document.getElementById('save-changes').addEventListener('click', saveChanges);
-}
-
-function loadFormsData() {
- ipcRenderer.send('load-all-pokemon');
-}
-
-ipcRenderer.on('all-pokemon-response', (event, response) => {
- if (response.error) {
- console.error('Error loading all Pokémon:', response.error);
- } else {
- allPokemonForms = response.data;
- populateFormsList();
- setupFormsFilter();
- }
-});
-
-function populateFormsList() {
- const listElement = document.getElementById('forms-list-items');
- listElement.innerHTML = '';
- allPokemonForms.forEach(pokemon => {
- const li = document.createElement('li');
- li.textContent = `${pokemon.name} ${pokemon.form_name ? `(${pokemon.form_name})` : ''}`;
- li.addEventListener('click', () => showPokemonDetails(pokemon.PFIC));
- listElement.appendChild(li);
- });
-}
-
-function setupFormsFilter() {
- const filterInput = document.getElementById('forms-filter');
- filterInput.addEventListener('input', () => {
- const filterValue = filterInput.value.toLowerCase();
- const listItems = document.querySelectorAll('#forms-list-items li');
- listItems.forEach(item => {
- const text = item.textContent.toLowerCase();
- item.style.display = text.includes(filterValue) ? '' : 'none';
- });
- });
-}
-
-function showPokemonDetails(pfic) {
- ipcRenderer.send('get-pokemon-details', pfic);
-}
-
-ipcRenderer.on('pokemon-details-response', (event, response) => {
- if (response.error) {
- console.error('Error fetching Pokémon details:', response.error);
- } else {
- displayPokemonDetails(response.data);
- }
-});
-
-function displayPokemonDetails(pokemon) {
- const detailsContent = document.getElementById('details-content');
- const pokemonImage = document.getElementById('pokemon-image');
- const pokemonName = document.getElementById('pokemon-name');
- const pokemonPfic = document.getElementById('pokemon-pfic');
- const pokemonNationalDex = document.getElementById('pokemon-national-dex');
- const pokemonGeneration = document.getElementById('pokemon-generation');
- const storableCheckbox = document.getElementById('storable-checkbox');
- const evolutionChainContent = document.getElementById('details-evolution-chain-content');
-
- pokemonImage.src = `../images-new/${pokemon.PFIC}.png`;
- pokemonImage.onerror = () => { pokemonImage.src = 'placeholder.png'; };
-
- pokemonName.textContent = `${pokemon.name} ${pokemon.form_name ? `(${pokemon.form_name})` : ''}`;
- pokemonPfic.textContent = `PFIC: ${pokemon.PFIC}`;
- pokemonNationalDex.textContent = `National Dex: ${pokemon.national_dex.toString().padStart(4, '0')}`;
- pokemonGeneration.textContent = `Generation: ${pokemon.generation}`;
-
- storableCheckbox.checked = pokemon.storable_in_home;
- storableCheckbox.addEventListener('change', () => updateStorableInHome(pokemon.PFIC, storableCheckbox.checked));
-
- // Load and display evolution chain
- loadEvolutionChain(pokemon.PFIC);
-}
-
-function updateStorableInHome(pfic, storable) {
- ipcRenderer.send('update-storable-in-home', { pfic, storable });
-}
-
-function loadEvolutionChain(pfic) {
- ipcRenderer.send('get-evolution-chain', pfic);
-}
-
-ipcRenderer.on('evolution-chain-response', (event, response) => {
- if (response.error) {
- console.error('Error fetching evolution chain:', response.error);
- } else {
- displayEvolutionChain(response.data);
- }
-});
-
-function displayEvolutionChain(chain) {
- const table = document.getElementById('evolution-table');
- table.innerHTML = '';
-
- const stages = splitIntoStages(chain);
- const maxForms = Math.max(...stages.map(stage => stage.length));
- const rowCount = maxForms % 2 === 0 ? maxForms + 1 : maxForms;
- const middleRow = Math.floor(rowCount / 2)
-
- for (let i = 0; i < rowCount; i++) {
- const row = table.insertRow();
- for (let j = 0; j < stages.length; j++) {
- const cell = row.insertCell();
- }
- }
-
- stages.forEach((stage, stageIndex) => {
- if (stage.length == 1)
- {
- const pokemon = stage[0];
- table.rows[middleRow].cells[stageIndex].appendChild(createPokemonElement(pokemon));
- } else {
- let start = middleRow - Math.floor(stage.length / 2)
-
- stage.forEach((pokemon, index) => {
- let rowIndex = start + index;
-
- // If the number of elements is even, skip the middle row
- if (stage.length % 2 === 0 && rowIndex >= middleRow) {
- rowIndex++;
- }
-
- table.rows[rowIndex].cells[stageIndex].appendChild(createPokemonElement(pokemon));
- });
- }
- });
-}
-
-function createPokemonElement(pokemon) {
- const element = document.createElement('div');
- element.className = 'pokemon-card';
-
- const img = document.createElement('img');
- img.src = `../images-new/${pokemon.pfic}.png`;
- img.alt = pokemon.name;
- img.onerror = () => { img.src = 'placeholder.png'; };
-
- const name = document.createElement('div');
- name.className = 'pokemon-name';
- name.textContent = pokemon.name;
-
- const form = document.createElement('div');
- form.className = 'pokemon-form';
- form.textContent = pokemon.form_name || '';
-
- element.appendChild(img);
- element.appendChild(name);
- element.appendChild(form);
-
- return element;
-}
-
-function createEvolutionArrow() {
- const arrow = document.createElement('div');
- arrow.className = 'evolution-arrow';
- arrow.textContent = '→';
- return arrow;
-}
-
-function createBranchElement(evolutions) {
- const branchElement = document.createElement('div');
- branchElement.className = 'evolution-branch';
- const arrowElement = document.createElement('span');
- arrowElement.className = 'evolution-arrow';
- arrowElement.textContent = '→';
- branchElement.appendChild(arrowElement);
- const methodElement = document.createElement('span');
- methodElement.className = 'evolution-method';
- methodElement.textContent = evolutions[0].method || '';
- branchElement.appendChild(methodElement);
- return branchElement;
-}
-
-function searchForms() {
- const searchTerm = document.getElementById('forms-search').value.toLowerCase();
- const rows = document.querySelectorAll('#forms-table tbody tr');
-
- rows.forEach(row => {
- const text = row.textContent.toLowerCase();
- row.style.display = text.includes(searchTerm) ? '' : 'none';
- });
-}
-
-function searchEvolution() {
- const searchTerm = document.getElementById('evolution-search').value;
- ipcRenderer.send('search-evolution', searchTerm);
-}
-
-ipcRenderer.on('evolution-search-response', (event, response) => {
- if (response.error) {
- console.error('Error searching evolution:', response.error);
- } else if (response.data.length > 0) {
- const pfic = response.data[0].PFIC;
- ipcRenderer.send('get-evolution-chain', pfic);
- } else {
- document.getElementById('evolution-chain').innerHTML = 'No Pokémon found.';
- }
-});
-
-ipcRenderer.on('evolution-chain-response', (event, response) => {
- if (response.error) {
- console.error('Error fetching evolution chain:', response.error);
- } else {
- currentEvolutionChain = response.data; // Add this line
- displayEvolutionChain(currentEvolutionChain);
- }
-});
-
-function createPokemonElement(pokemon, stageIndex, pokemonIndex) {
- const element = document.createElement('div');
- element.className = 'pokemon-card';
-
- const img = document.createElement('img');
- img.src = `../images-new/${pokemon.pfic}.png`;
- img.alt = pokemon.name;
- img.onerror = () => { img.src = 'placeholder.png'; };
-
- const name = document.createElement('div');
- name.className = 'pokemon-name';
- name.textContent = pokemon.name;
-
- const form = document.createElement('div');
- form.className = 'pokemon-form';
- form.textContent = pokemon.form_name || '';
-
- const editButton = document.createElement('button');
- editButton.textContent = 'Edit';
- editButton.className = 'edit-pokemon';
- editButton.addEventListener('click', () => editPokemon(stageIndex, pokemonIndex));
-
- const editButtons = document.createElement('div');
- editButtons.className = 'edit-buttons';
- editButtons.appendChild(editButton);
-
- element.appendChild(img);
- element.appendChild(name);
- element.appendChild(form);
- element.appendChild(editButtons);
-
- return element;
-}
-
-function setupEvolutionControls() {
- document.getElementById('add-stage').addEventListener('click', addStage);
- document.getElementById('save-evolution-changes').addEventListener('click', saveEvolutionChanges);
-}
-
-function editPokemon(stageIndex, pokemonIndex) {
- console.log('Editing Pokemon:', stageIndex, pokemonIndex);
- if (!currentEvolutionChain) {
- console.error('No evolution chain loaded');
- return;
- }
- currentEditingStageIndex = stageIndex;
- currentEditingPokemonIndex = pokemonIndex;
-
- const modal = document.getElementById('edit-pokemon-modal');
- console.log('Modal element:', modal);
- const pokemonSelect = document.getElementById('pokemon-select');
- const evolutionMethod = document.getElementById('evolution-method');
-
- // Set current values
- const currentPokemon = getCurrentPokemon(stageIndex, pokemonIndex);
- console.log('Current Pokemon:', currentPokemon);
- if (currentPokemon) {
- pokemonSelect.value = currentPokemon.pfic;
- evolutionMethod.value = currentPokemon.method || '';
-
- modal.style.display = 'block';
- console.log('Modal display set to block');
- } else {
- console.error('Could not find the current Pokémon');
- }
-}
-
-function removePokemon(stageIndex, pokemonIndex) {
- // Implement remove functionality
- console.log(`Removing Pokémon at stage ${stageIndex}, index ${pokemonIndex}`);
- // Remove the Pokémon from the DOM and update the data structure
-}
-
-function addStage() {
- // Implement add stage functionality
- console.log('Adding new stage');
- // You can open a modal or inline form to add a new stage
-}
-
-function saveEvolutionChanges() {
- console.log('Saving evolution changes');
- ipcRenderer.send('save-evolution-changes', currentEvolutionChain);
-}
-
-function splitIntoStages(chain) {
- const stages = [];
- let currentStage = [chain];
-
- while (currentStage.length > 0) {
- stages.push(currentStage);
- const nextStage = [];
- currentStage.forEach(pokemon => {
- nextStage.push(...pokemon.evolutions);
- });
- currentStage = nextStage;
- }
-
- return stages;
-}
-
-function saveChanges() {
- // Implement the logic to save changes
- // This will involve collecting the data from the forms table
- // and sending it back to the main process to update the database
-}
-
-// Add this function to load all Pokémon
-function loadAllPokemon() {
- ipcRenderer.send('load-all-pokemon');
-}
-
-// Add this event listener
-ipcRenderer.on('all-pokemon-response', (event, response) => {
- if (response.error) {
- console.error('Error loading all Pokémon:', response.error);
- } else {
- allPokemon = response.data;
- populatePokemonSelect();
- populatePokemonList();
- }
-});
-
-// Add this function to populate the Pokémon select dropdown
-function populatePokemonSelect() {
- const select = document.getElementById('pokemon-select');
- select.innerHTML = '';
- allPokemon.forEach(pokemon => {
- const option = document.createElement('option');
- option.value = pokemon.PFIC;
- option.textContent = `${pokemon.PFIC} - ${pokemon.name} ${pokemon.form_name ? `(${pokemon.form_name})` : ''}`;
- select.appendChild(option);
- });
-}
-
-// Add this function to get the current Pokémon being edited
-function getCurrentPokemon(stageIndex, pokemonIndex) {
- if (!currentEvolutionChain) {
- console.error('No evolution chain loaded');
- return null;
- }
- const stages = splitIntoStages(currentEvolutionChain);
- if (stageIndex < 0 || stageIndex >= stages.length || pokemonIndex < 0 || pokemonIndex >= stages[stageIndex].length) {
- console.error('Invalid stage or pokemon index');
- return null;
- }
- return stages[stageIndex][pokemonIndex];
-}
-
-// Add this function to update the Pokémon in the chain
-function updatePokemonInChain(stageIndex, pokemonIndex, newPfic, newMethod) {
- const stages = splitIntoStages(currentEvolutionChain);
- const pokemon = stages[stageIndex][pokemonIndex];
-
- // Update the Pokémon data
- pokemon.pfic = newPfic;
- pokemon.name = allPokemon.find(p => p.PFIC === newPfic).name;
- pokemon.form_name = allPokemon.find(p => p.PFIC === newPfic).form_name;
-
- // Update the evolution method if it's not the first stage
- if (stageIndex > 0) {
- const previousStagePokemon = stages[stageIndex - 1].find(p => p.evolutions.includes(pokemon));
- const evolutionIndex = previousStagePokemon.evolutions.indexOf(pokemon);
- previousStagePokemon.evolutions[evolutionIndex].method = newMethod;
- }
-
- // Redisplay the evolution chain
- displayEvolutionChain(currentEvolutionChain);
-}
-
-// Add this event listener for the save response
-ipcRenderer.on('save-evolution-changes-response', (event, response) => {
- if (response.error) {
- console.error('Error saving evolution changes:', response.error);
- alert('Failed to save changes. Please try again.');
- } else {
- alert('Changes saved successfully!');
- }
-});
-
-// Add this function to populate the Pokémon list
-function populatePokemonList() {
- const listElement = document.getElementById('pokemon-list-items');
- listElement.innerHTML = '';
- allPokemon.forEach(pokemon => {
- const li = document.createElement('li');
- li.textContent = `${pokemon.name} ${pokemon.form_name ? `(${pokemon.form_name})` : ''}`;
- li.addEventListener('click', () => loadEvolutionChain(pokemon.PFIC));
- listElement.appendChild(li);
- });
-}
-
-// Add this function to set up the Pokémon filter
-function setupPokemonFilter() {
- const filterInput = document.getElementById('pokemon-filter');
- filterInput.addEventListener('input', () => {
- const filterValue = filterInput.value.toLowerCase();
- const listItems = document.querySelectorAll('#pokemon-list-items li');
- listItems.forEach(item => {
- const text = item.textContent.toLowerCase();
- item.style.display = text.includes(filterValue) ? '' : 'none';
- });
- });
-}
-
-// Modify the loadEvolutionChain function
-function loadEvolutionChain(pfic) {
- ipcRenderer.send('get-evolution-chain', pfic);
-}
\ No newline at end of file
diff --git a/DBVisualiser/styles.css b/DBVisualiser/styles.css
deleted file mode 100644
index 91d3ccf..0000000
--- a/DBVisualiser/styles.css
+++ /dev/null
@@ -1,338 +0,0 @@
-body {
- font-family: Arial, sans-serif;
- margin: 0;
- padding: 20px;
-}
-
-#tabs {
- margin-bottom: 20px;
-}
-
-.tab-button {
- padding: 10px 20px;
- cursor: pointer;
-}
-
-.tab-button.active {
- background-color: #ddd;
-}
-
-.tab-content {
- display: none;
-}
-
-.tab-content.active {
- display: block;
-}
-
-.search-bar {
- margin-bottom: 20px;
-}
-
-table {
- width: 100%;
- border-collapse: collapse;
-}
-
-th, td {
- border: 1px solid #ddd;
- padding: 8px;
- text-align: left;
-}
-
-th {
- background-color: #f2f2f2;
-}
-
-#evolution-chain {
- display: flex;
- overflow-x: auto;
- padding: 20px;
- align-items: flex-start;
-}
-
-.evolution-stage {
- display: flex;
- flex-direction: column;
- align-items: center;
- margin-right: 40px;
-}
-
-.pokemon-card {
- background-color: #f9f9f9;
- border: 1px solid #ddd;
- border-radius: 10px;
- padding: 10px;
- text-align: center;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: space-between;
- cursor: pointer;
- width: 120px; /* Fixed width */
- height: 100px; /* Fixed height */
-}
-
-.pokemon-card img {
- width: 64px;
- height: 64px;
- object-fit: contain;
-}
-
-.pokemon-name {
- font-weight: bold;
- margin-top: 5px;
-}
-
-.pokemon-form {
- font-size: 0.8em;
- color: #666;
-}
-
-.evolution-branch {
- position: absolute;
- top: 50%;
- left: 100%;
- display: flex;
- flex-direction: column;
- align-items: center;
-}
-
-.evolution-arrow {
- font-size: 24px;
- color: #666;
- margin: 0 10px;
-}
-
-.evolution-method {
- font-size: 0.8em;
- color: #666;
- max-width: 100px;
- text-align: center;
-}
-
-.pokemon-card .edit-buttons {
- display: none;
- position: absolute;
- top: 5px;
- right: 5px;
-}
-
-.pokemon-card:hover .edit-buttons {
- display: block;
-}
-
-.edit-buttons button {
- margin-left: 5px;
- padding: 2px 5px;
- font-size: 0.8em;
-}
-
-#evolution-controls {
- margin-top: 20px;
-}
-
-#evolution-controls button {
- margin-right: 10px;
-}
-
-/* Add these styles at the end of the file */
-.modal {
- display: none;
- position: fixed;
- z-index: 1;
- left: 0;
- top: 0;
- width: 100%;
- height: 100%;
- overflow: auto;
- background-color: rgba(0,0,0,0.4);
-}
-
-.modal-content {
- background-color: #fefefe;
- margin: 15% auto;
- padding: 20px;
- border: 1px solid #888;
- width: 80%;
- max-width: 500px;
-}
-
-.close {
- color: #aaa;
- float: right;
- font-size: 28px;
- font-weight: bold;
- cursor: pointer;
-}
-
-.close:hover,
-.close:focus {
- color: black;
- text-decoration: none;
- cursor: pointer;
-}
-
-#edit-pokemon-form {
- display: flex;
- flex-direction: column;
-}
-
-#edit-pokemon-form label,
-#edit-pokemon-form select,
-#edit-pokemon-form input,
-#edit-pokemon-form button {
- margin-top: 10px;
-}
-
-.evolution-container {
- display: flex;
- height: calc(100vh - 100px); /* Adjust based on your layout */
-}
-
-#pokemon-list {
- width: 250px;
- border-right: 1px solid #ccc;
- overflow-y: auto;
- padding: 10px;
-}
-
-#pokemon-filter {
- width: 100%;
- margin-bottom: 10px;
-}
-
-#pokemon-list-items {
- list-style-type: none;
- padding: 0;
-}
-
-#pokemon-list-items li {
- cursor: pointer;
- padding: 5px;
-}
-
-#pokemon-list-items li:hover {
- background-color: #f0f0f0;
-}
-
-#evolution-chain-container {
- flex-grow: 1;
- padding: 20px;
- overflow-y: auto;
-}
-
-.forms-container {
- display: flex;
- height: calc(100vh - 100px); /* Adjust based on your layout */
-}
-
-#pokemon-forms-list {
- width: 250px;
- border-right: 1px solid #ccc;
- overflow-y: auto;
- padding: 10px;
-}
-
-#forms-filter {
- width: 100%;
- margin-bottom: 10px;
-}
-
-#forms-list-items {
- list-style-type: none;
- padding: 0;
-}
-
-#forms-list-items li {
- cursor: pointer;
- padding: 5px;
-}
-
-#forms-list-items li:hover {
- background-color: #f0f0f0;
-}
-
-#pokemon-details {
- flex-grow: 1;
- padding: 20px;
- overflow-y: auto;
-}
-
-#details-content {
- margin-top: 20px;
-}
-
-#pokemon-basic-info {
- display: flex;
- margin-bottom: 20px;
-}
-
-#pokemon-image {
- width: 200px;
- height: 200px;
- object-fit: contain;
- margin-right: 20px;
-}
-
-#pokemon-info {
- flex-grow: 1;
-}
-
-#pokemon-evolution-chain {
- margin-top: 20px;
-}
-
-#details-evolution-chain-content {
- overflow-x: auto;
- margin-top: 20px;
-}
-
-#evolution-table {
- width: auto;
- border-collapse: collapse;
- border-spacing: 0px;
-}
-
-#evolution-table td {
- vertical-align: middle;
- text-align: center;
- padding: 0%;
- border-color: transparent;
-}
-
-#details-evolution-chain-content .evolution-stage {
- display: inline-flex;
- flex-direction: row;
- justify-content: flex-start;
- align-items: center;
- margin-right: 20px;
-}
-
-#details-evolution-chain-content .pokemon-card {
- text-align: center;
- margin: 0 10px;
- position: relative;
- border: 1px solid #ddd;
- padding: 10px;
- border-radius: 5px;
- display: inline-block;
-}
-
-#details-evolution-chain-content .pokemon-card img {
- width: 64px;
- height: 64px;
- object-fit: contain;
-}
-
-#details-evolution-chain-content .evolution-branch {
- display: inline-flex;
- flex-direction: row;
- align-items: center;
- margin: 0 10px;
-}
-
-#details-evolution-chain-content .evolution-arrow,
-#details-evolution-chain-content .evolution-method {
- margin: 0 5px;
-}
\ No newline at end of file
diff --git a/DataGatherers/DatabaseBuilder.py b/DataGatherers/DatabaseBuilder.py
deleted file mode 100644
index 1f372ee..0000000
--- a/DataGatherers/DatabaseBuilder.py
+++ /dev/null
@@ -1,401 +0,0 @@
-import sqlite3
-import csv
-import re
-
-def create_connection():
- conn = sqlite3.connect('pokemon_database.db')
- conn.text_factory = str
- return conn
-
-def create_tables(conn):
- cursor = conn.cursor()
-
- # Create games table
- cursor.execute('''
- CREATE TABLE IF NOT EXISTS games (
- id INTEGER PRIMARY KEY,
- name TEXT NOT NULL,
- generation INTEGER NOT NULL
- )
- ''')
-
- # Create marks table
- cursor.execute('''
- CREATE TABLE IF NOT EXISTS marks (
- id INTEGER PRIMARY KEY,
- name TEXT NOT NULL,
- icon_path TEXT NOT NULL
- )
- ''')
-
- # Create mark_game_associations table
- cursor.execute('''
- CREATE TABLE IF NOT EXISTS mark_game_associations (
- mark_id INTEGER,
- game_id INTEGER,
- FOREIGN KEY (mark_id) REFERENCES marks (id),
- FOREIGN KEY (game_id) REFERENCES games (id),
- PRIMARY KEY (mark_id, game_id)
- )
- ''')
-
- # Create pokemon table
- cursor.execute('''
- CREATE TABLE IF NOT EXISTS pokemon (
- national_dex_number INTEGER PRIMARY KEY,
- name TEXT NOT NULL,
- introduced_in_gen INTEGER
- )
- ''')
-
- # Create pokemon_forms table
- cursor.execute('''
- CREATE TABLE IF NOT EXISTS pokemon_forms (
- id INTEGER PRIMARY KEY,
- pokemon_id INTEGER NOT NULL,
- form_name TEXT NOT NULL,
- is_default BOOLEAN NOT NULL,
- image_path TEXT NOT NULL,
- FOREIGN KEY (pokemon_id) REFERENCES pokemon (national_dex_number),
- UNIQUE (pokemon_id, form_name)
- )
- ''')
-
- # Create encounter_methods table
- cursor.execute('''
- CREATE TABLE IF NOT EXISTS encounter_methods (
- id INTEGER PRIMARY KEY,
- name TEXT UNIQUE NOT NULL
- )
- ''')
-
- # Create locations table
- cursor.execute('''
- CREATE TABLE IF NOT EXISTS locations (
- id INTEGER PRIMARY KEY,
- name TEXT UNIQUE NOT NULL,
- description TEXT
- )
- ''')
-
- # Create form_encounters table
- cursor.execute('''
- CREATE TABLE IF NOT EXISTS form_encounters (
- id INTEGER PRIMARY KEY,
- form_id INTEGER NOT NULL,
- game_id INTEGER NOT NULL,
- location_id INTEGER NOT NULL,
- encounter_method_id INTEGER NOT NULL,
- FOREIGN KEY (form_id) REFERENCES pokemon_forms (id),
- FOREIGN KEY (game_id) REFERENCES games (id),
- FOREIGN KEY (location_id) REFERENCES locations (id),
- FOREIGN KEY (encounter_method_id) REFERENCES encounter_methods (id),
- UNIQUE (form_id, game_id, location_id, encounter_method_id)
- )
- ''')
-
- # Create alternate_game_names table
- cursor.execute('''
- CREATE TABLE IF NOT EXISTS alternate_game_names (
- id INTEGER PRIMARY KEY,
- game_id INTEGER NOT NULL,
- alternate_name TEXT NOT NULL,
- FOREIGN KEY (game_id) REFERENCES games (id),
- UNIQUE (alternate_name COLLATE NOCASE)
- )
- ''')
-
- conn.commit()
-
-def tidy_location_name(name):
- # Replace '-' with spaces
- name = name.replace('-', ' ')
-
- name = name.replace('#', '')
-
- # Remove 'area' from the end if present
- name = re.sub(r'\sarea$', '', name, flags=re.IGNORECASE)
-
- # Check for cardinal directions at the end
- cardinal_directions = ['north', 'south', 'east', 'west', 'northeast', 'northwest', 'southeast', 'southwest']
- for direction in cardinal_directions:
- if name.lower().endswith(f' {direction}'):
- # Remove the direction from the end and add it in brackets
- name = name[:-len(direction)].strip()
- name += f' ({direction.capitalize()})'
- break
-
- if name.isdigit():
- name = "Route " + name
-
- name = name.replace("Routes", "Route")
-
- # Capitalize the first letter of the first word
- name = name.capitalize()
-
- return name
-
-def generate_location_description(name):
- # Generate a simple description based on the name
- description = f"A location in the Pokémon world known as {name}."
- return description
-
-def load_game_data(conn):
- cursor = conn.cursor()
-
- games = [
- ("Red", 1, ["Red Version"]),
- ("Blue", 1, ["Blue Version"]),
- ("Yellow", 1, ["Yellow Version"]),
- ("Gold", 2, ["Gold Version"]),
- ("Silver", 2, ["Silver Version"]),
- ("Crystal", 2, ["Crystal Version"]),
- ("Ruby", 3, ["Ruby Version"]),
- ("Sapphire", 3, ["Sapphire Version"]),
- ("Emerald", 3, ["Emerald Version"]),
- ("FireRed", 3, ["Fire Red", "Fire-Red"]),
- ("LeafGreen", 3, ["Leaf Green", "Leaf-Green"]),
- ("Diamond", 4, ["Diamond Version"]),
- ("Pearl", 4, ["Pearl Version"]),
- ("Platinum", 4, ["Platinum Version"]),
- ("HeartGold", 4, ["Heart Gold", "Heart-Gold"]),
- ("SoulSilver", 4, ["Soul Silver", "Soul-Silver"]),
- ("Black", 5, ["Black Version"]),
- ("White", 5, ["White Version"]),
- ("Black 2", 5, ["Black Version 2", "Black-2"]),
- ("White 2", 5, ["White Version 2", "White-2"]),
- ("X", 6, ["X Version"]),
- ("Y", 6, ["Y Version"]),
- ("Omega Ruby", 6, ["Omega Ruby Version", "Omega-Ruby"]),
- ("Alpha Sapphire", 6, ["Alpha Sapphire Version", "Alpha-Sapphire"]),
- ("Sun", 7, ["Sun Version"]),
- ("Moon", 7, ["Moon Version"]),
- ("Ultra Sun", 7, ["Ultra Sun Version", "Ultra-Sun"]),
- ("Ultra Moon", 7, ["Ultra Moon Version", "Ultra-Moon"]),
- ("Let's Go Pikachu", 7, ["Let's Go, Pikachu!", "Lets Go Pikachu"]),
- ("Let's Go Eevee", 7, ["Let's Go, Eevee!", "Lets Go Eevee"]),
- ("Sword", 8, ["Sword Version"]),
- ("Shield", 8, ["Shield Version"]),
- ("Expansion Pass", 8, ["Expansion Pass (Sword)", "Expansion Pass (Shield)"]),
- ("Brilliant Diamond", 8, ["Brilliant Diamond Version", "Brilliant-Diamond"]),
- ("Shining Pearl", 8, ["Shining Pearl Version", "Shining-Pearl"]),
- ("Legends Arceus", 8, ["Legends: Arceus", "Legends-Arceus"]),
- ("Scarlet", 9, ["Scarlet Version"]),
- ("Violet", 9, ["Violet Version"]),
- ("The Teal Mask", 9, ["The Teal Mask Version", "The Teal Mask (Scarlet)", "The Teal Mask (Violet)"]),
- ("The Hidden Treasure of Area Zero", 9, ["The Hidden Treasure of Area Zero Version", "The Hidden Treasure of Area Zero (Scarlet)", "The Hidden Treasure of Area Zero (Violet)"]),
-
- ("Pokémon Home", 98, ["Pokémon HOME"]),
- ("Pokémon Go", 99, ["Pokémon GO"]),
- ]
-
- for game in games:
- cursor.execute('''
- INSERT OR IGNORE INTO games (name, generation)
- VALUES (?, ?)
- ''', (game[0], game[1]))
-
- game_id = cursor.lastrowid
-
- # Insert alternate names
- for alt_name in game[2]:
- cursor.execute('''
- INSERT OR IGNORE INTO alternate_game_names (game_id, alternate_name)
- VALUES (?, ?)
- ''', (game_id, alt_name))
-
- conn.commit()
-
-def load_mark_data(conn):
- cursor = conn.cursor()
-
- marks = [
- ("Game Boy", "images/marks/GB_icon_HOME.png", ["Red", "Blue", "Yellow", "Gold", "Silver", "Crystal", "Ruby", "Sapphire", "Emerald", "FireRed", "LeafGreen"]),
- ("Kalos", "images/marks/Blue_pentagon_HOME.png", ["X", "Y", "Omega Ruby", "Alpha Sapphire"]),
- ("Alola", "images/marks/Black_clover_HOME.png", ["Sun", "Moon", "Ultra Sun", "Ultra Moon"]),
- ("Let's Go", "images/marks/Let's_Go_icon_HOME.png", ["Let's Go Pikachu", "Let's Go Eevee"]),
- ("Galar", "images/marks/Galar_symbol_HOME.png", ["Sword", "Shield"]),
- ("Sinnoh", "images/marks/BDSP_icon_HOME.png", ["Brilliant Diamond", "Shining Pearl"]),
- ("Hisui", "images/marks/Arceus_mark_HOME.png", ["Legends Arceus"]),
- ("Paldea", "images/marks/Paldea_icon_HOME.png", ["Scarlet", "Violet"]),
- ]
-
- for mark in marks:
- cursor.execute('''
- INSERT OR IGNORE INTO marks (name, icon_path)
- VALUES (?, ?)
- ''', (mark[0], mark[1]))
-
- mark_id = cursor.lastrowid
-
- for game_name in mark[2]:
- cursor.execute('''
- INSERT OR IGNORE INTO mark_game_associations (mark_id, game_id)
- SELECT ?, id FROM games WHERE name = ?
- ''', (mark_id, game_name))
-
- conn.commit()
-
-def load_pokemon_data(conn):
- cursor = conn.cursor()
-
- with open('pokemon_home_list.csv', 'r', encoding='utf-8') as f:
- reader = csv.reader(f)
- next(reader) # Skip header row if it exists
- for row in reader:
- national_dex_number = int(row[0])
- full_name = row[1]
-
- # Extract the base name and form name
- match = re.match(r'([^(]+)(?:\s*\(([^)]+)\))?', full_name)
- if match:
- base_name = match.group(1).strip()
- form_name = match.group(2).strip() if match.group(2) else "Default"
- else:
- base_name = full_name
- form_name = "Default"
-
- # Insert or update the pokemon entry
- cursor.execute('''
- INSERT OR IGNORE INTO pokemon (national_dex_number, name)
- VALUES (?, ?)
- ''', (national_dex_number, base_name))
-
- # Create the image path
- padded_dex = f"{national_dex_number:04d}"
- if form_name == "Default":
- image_path = f"images/pokemon/{padded_dex}_{base_name}.png"
- else:
- image_path = f"images/pokemon/{padded_dex}_{base_name}_({form_name}).png".replace(" ", "_")
-
- # Insert the form entry
- cursor.execute('''
- INSERT OR IGNORE INTO pokemon_forms (pokemon_id, form_name, is_default, image_path)
- VALUES (?, ?, ?, ?)
- ''', (national_dex_number, form_name, form_name == "Default", image_path))
-
- conn.commit()
-
-def load_encounter_data(conn):
- cursor = conn.cursor()
-
- with open('pokemon_earliest_games.csv', 'r', encoding='utf-8') as f:
- reader = csv.DictReader(f)
- for row in reader:
- national_dex_number = int(row['number'])
- full_name = row['name']
- earliest_game = row['earliest_game']
- obtain_method = row['obtain_method']
- encounter_locations = row['encounter_locations']
- introduced_in_gen = row['introduced_in_gen']
- # Extract the base name and form name
- match = re.match(r'([^(]+)(?:\s*\(([^)]+)\))?', full_name)
- if match:
- base_name = match.group(1).strip()
- form_name = match.group(2).strip() if match.group(2) else "Default"
- if form_name == "None":
- form_name = "Default"
- else:
- base_name = full_name
- form_name = "Default"
-
- # Update the Pokémon entry with introduced_in_gen
- cursor.execute('''
- INSERT OR REPLACE INTO pokemon (national_dex_number, name, introduced_in_gen)
- VALUES (?, ?, ?)
- ''', (national_dex_number, base_name, introduced_in_gen))
-
- cursor.execute('''
- INSERT OR IGNORE INTO pokemon_forms (pokemon_id, form_name, is_default, image_path)
- VALUES (?, ?, ?, ?)
- ''', (national_dex_number, form_name, form_name == "Default", f"images/pokemon/{national_dex_number:04d}_{base_name}.png"))
-
- # Skip encounter data if it's unknown or N/A
- if earliest_game == "Unknown" or obtain_method == "Unknown":
- continue
-
- # Get the form_id
- cursor.execute('''
- SELECT id FROM pokemon_forms
- WHERE pokemon_id = ? AND form_name = ?
- ''', (national_dex_number, form_name))
- form_id = cursor.fetchone()[0]
-
- # Get the game_id (now case-insensitive and including alternate names)
- cursor.execute('''
- SELECT g.id FROM games g
- LEFT JOIN alternate_game_names agn ON g.id = agn.game_id
- WHERE g.name = ? COLLATE NOCASE OR agn.alternate_name = ? COLLATE NOCASE
- ''', (earliest_game, earliest_game))
- result = cursor.fetchone()
- if result:
- game_id = result[0]
- else:
- print(f"Warning: Game '{earliest_game}' not found for {full_name}")
- continue
-
- # Handle gift Pokémon
- if obtain_method.lower() == "gift" and (encounter_locations == "N/A" or not encounter_locations):
- # Insert or get the "Gift" location
- cursor.execute('''
- INSERT OR IGNORE INTO locations (name, description)
- VALUES (?, ?)
- ''', ("Gift", "Pokémon received as a gift"))
- cursor.execute('SELECT id FROM locations WHERE name = ?', ("Gift",))
- location_id = cursor.fetchone()[0]
-
- # Insert or get the "gift" encounter method
- cursor.execute('INSERT OR IGNORE INTO encounter_methods (name) VALUES (?)', ("gift",))
- cursor.execute('SELECT id FROM encounter_methods WHERE name = ?', ("gift",))
- method_id = cursor.fetchone()[0]
-
- # Insert form_encounter for gift Pokémon
- cursor.execute('''
- INSERT OR IGNORE INTO form_encounters
- (form_id, game_id, location_id, encounter_method_id)
- VALUES (?, ?, ?, ?)
- ''', (form_id, game_id, location_id, method_id))
- elif encounter_locations != "N/A" and encounter_locations:
- # Process each encounter location
- for location_info in encounter_locations.split('|'):
- location = location_info.strip()
-
- location = tidy_location_name(location)
-
- # Tidy up the location name and generate a description
- description = tidy_location_name(location)
-
- # Insert or get location_id
- cursor.execute('''
- INSERT OR IGNORE INTO locations (name, description)
- VALUES (?, ?)
- ''', (location, description))
- cursor.execute('SELECT id FROM locations WHERE name = ?', (location,))
- location_id = cursor.fetchone()[0]
-
- # Insert or get encounter_method_id
- cursor.execute('INSERT OR IGNORE INTO encounter_methods (name) VALUES (?)', (obtain_method,))
- cursor.execute('SELECT id FROM encounter_methods WHERE name = ?', (obtain_method,))
- method_id = cursor.fetchone()[0]
-
- # Insert form_encounter
- cursor.execute('''
- INSERT OR IGNORE INTO form_encounters
- (form_id, game_id, location_id, encounter_method_id)
- VALUES (?, ?, ?, ?)
- ''', (form_id, game_id, location_id, method_id))
-
- conn.commit()
-
-def main():
- conn = create_connection()
- create_tables(conn)
- load_game_data(conn)
- load_mark_data(conn)
- load_pokemon_data(conn)
- load_encounter_data(conn)
- conn.close()
- print("All data has been successfully added to the database.")
-
-if __name__ == "__main__":
- main()
\ No newline at end of file
diff --git a/DataGatherers/DefaultForms.json b/DataGatherers/DefaultForms.json
index 75c7354..36898ce 100644
--- a/DataGatherers/DefaultForms.json
+++ b/DataGatherers/DefaultForms.json
@@ -48,5 +48,6 @@
"Unremarkable Form",
"Antique Form",
"Phony Form",
- "Masterpiece Form"
+ "Masterpiece Form",
+ "Chest Form"
]
\ No newline at end of file
diff --git a/DataGatherers/DetermineOriginGame.py b/DataGatherers/DetermineOriginGame.py
index 9ed8033..feab6aa 100644
--- a/DataGatherers/DetermineOriginGame.py
+++ b/DataGatherers/DetermineOriginGame.py
@@ -18,7 +18,6 @@ import sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
-
from DataGatherers.cache_manager import CacheManager
# List of all main series Pokémon games in chronological order, with special games first in each generation
@@ -439,6 +438,10 @@ def parse_form_information(html_content):
headings = soup.find_all('b')
if len(headings) > 0:
for heading in headings:
+ if heading.parent.name == 'sup':
+ continue
+ if "form" not in heading.get_text(strip=True).lower():
+ continue
main_form = heading.get_text(strip=True)
info = {
"main_form": main_form,
@@ -721,7 +724,7 @@ def get_locations_from_bulbapedia(pokemon_name, form, cache: CacheManager, defau
games_string = entries[0].find('a').get('title')
for game in all_games:
if game in games_string:
- record_location_info(game, game_locations, None, "Event")
+ record_location_info(game, game_locations, "Event", "Event")
return game_locations
diff --git a/DataGatherers/ExtractPokemonData.py b/DataGatherers/ExtractPokemonData.py
deleted file mode 100644
index de0f8b4..0000000
--- a/DataGatherers/ExtractPokemonData.py
+++ /dev/null
@@ -1,136 +0,0 @@
-import sqlite3
-import csv
-from typing import List, Dict, Optional
-from bs4 import BeautifulSoup
-import requests
-import re
-from fuzzywuzzy import fuzz
-
-# Import necessary functions from DetermineOriginGame.py
-from DetermineOriginGame import (
- create_pokemon_index,
- get_intro_generation,
- get_locations_from_bulbapedia,
- get_evolution_data_from_bulbapedia,
- split_td_contents,
- parse_form_information,
- get_cached_data,
- all_games,
- pokemon_index,
- cache,
- read_pokemon_list
-)
-
-class Pokemon:
- def __init__(self, number: int, name: str, form: Optional[str] = None):
- self.number = number
- self.name = name
- self.form = form
- self.introduced_in_gen: Optional[int] = None
- self.encounters: Dict[str, List[str]] = {}
- self.evolution_chain: List[Dict] = []
- self.stage: Optional[str] = None
-
-def create_database():
- conn = sqlite3.connect('unprocessed_pokemon_database.db')
- cursor = conn.cursor()
-
- # Create tables
- cursor.execute('''
- CREATE TABLE IF NOT EXISTS pokemon (
- id INTEGER PRIMARY KEY,
- national_dex_number INTEGER,
- name TEXT,
- form TEXT,
- introduced_in_gen INTEGER
- )
- ''')
-
- cursor.execute('''
- CREATE TABLE IF NOT EXISTS encounters (
- id INTEGER PRIMARY KEY,
- pokemon_id INTEGER,
- game TEXT,
- location TEXT,
- FOREIGN KEY (pokemon_id) REFERENCES pokemon (id)
- )
- ''')
-
- cursor.execute('''
- CREATE TABLE IF NOT EXISTS evolution_chain (
- id INTEGER PRIMARY KEY,
- pokemon_id INTEGER,
- stage INTEGER,
- evolves_from TEXT,
- evolution_method TEXT,
- FOREIGN KEY (pokemon_id) REFERENCES pokemon (id)
- )
- ''')
-
- conn.commit()
- return conn
-
-def extract_pokemon_data(pokemon_list: List[Pokemon], conn: sqlite3.Connection):
- cursor = conn.cursor()
-
- for pokemon in pokemon_list:
- print(f"Processing {pokemon.name} ({pokemon.form})")
-
- # Get introduction generation
- pokemon.introduced_in_gen = get_intro_generation(pokemon.name, pokemon.form, cache)
-
- # Get encounter data
- encounter_data = get_locations_from_bulbapedia(pokemon.name, pokemon.form, cache)
- for game, locations in encounter_data.items():
- pokemon.encounters[game] = locations
-
- # Get evolution data
- pokemon.evolution_chain = get_evolution_data_from_bulbapedia(pokemon.name, pokemon.form, cache)
-
- # Insert data into database
- cursor.execute('''
- INSERT INTO pokemon (national_dex_number, name, form, introduced_in_gen)
- VALUES (?, ?, ?, ?)
- ''', (pokemon.number, pokemon.name, pokemon.form, pokemon.introduced_in_gen))
- pokemon_id = cursor.lastrowid
-
- for game, locations in pokemon.encounters.items():
- for location in locations:
- cursor.execute('''
- INSERT INTO encounters (pokemon_id, game, location)
- VALUES (?, ?, ?)
- ''', (pokemon_id, game, location))
-
- if pokemon.evolution_chain:
- for i, stage in enumerate(pokemon.evolution_chain):
- previous_stage = None
- if stage.previous_stage:
- previous_stage = stage.previous_stage.pokemon
- cursor.execute('''
- INSERT INTO evolution_chain (pokemon_id, stage, evolves_from, evolution_method)
- VALUES (?, ?, ?, ?)
- ''', (pokemon_id, i, previous_stage, stage.method))
-
- conn.commit()
-
-def read_and_convert_pokemon_list(filename: str) -> List[Pokemon]:
- pokemon_list = read_pokemon_list(filename, 3000)
- local_list = []
- for entry in pokemon_list:
- number = entry.number
- name = entry.name
- form = entry.form
- local_list.append(Pokemon(number, name, form))
- return local_list
-
-def main():
- get_cached_data()
- conn = create_database()
- pokemon_list = read_and_convert_pokemon_list('pokemon_home_list.csv')
- create_pokemon_index(pokemon_list)
- extract_pokemon_data(pokemon_list, conn)
- conn.close()
- print("Data extraction complete and stored in the database.")
-
-if __name__ == "__main__":
- main()
diff --git a/DataGatherers/Update_evolution_information.py b/DataGatherers/Update_evolution_information.py
index 2bd763a..c8838d7 100644
--- a/DataGatherers/Update_evolution_information.py
+++ b/DataGatherers/Update_evolution_information.py
@@ -3,8 +3,17 @@ from typing import List, Optional
from dataclasses import dataclass
from fuzzywuzzy import fuzz
import re
-from cache_manager import CacheManager
-from DetermineOriginGame import get_evolution_data_from_bulbapedia
+
+import sys
+import os
+import logging
+
+sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+
+from DataGatherers.cache_manager import CacheManager
+from DataGatherers.DetermineOriginGame import get_evolution_data_from_bulbapedia
+
+logger = logging.getLogger('ui_feedback')
@dataclass
class EvolutionInfo:
@@ -91,7 +100,7 @@ def process_evolution_chain(conn, evolution_chain, cache, gender: Optional[str]
for stage in evolution_chain:
from_pfic = get_pokemon_form_by_name(conn, stage.pokemon, stage.form, gender=gender)
if not from_pfic:
- print(f"Warning: Could not find PFIC for {stage.pokemon} {stage.form}")
+ logger.warning(f"Could not find PFIC for {stage.pokemon} {stage.form}")
continue
if stage.next_stage:
@@ -121,8 +130,7 @@ def update_pokemon_baby_status(conn, from_pfic, is_baby_form):
''', (is_baby_form, from_pfic))
conn.commit()
-def update_evolution_chains():
- cache = CacheManager()
+def update_evolution_chains(cache, progress_callback=None):
conn = create_evolution_table()
cursor = conn.cursor()
@@ -130,7 +138,8 @@ def update_evolution_chains():
pokemon_forms = cursor.fetchall()
for name, form in pokemon_forms:
- print(f"Processing {name} {form if form else ''}")
+ if progress_callback:
+ progress_callback(f"Processing {name} {form if form else ''}")
if form and name in form:
form = form.replace(name, "").strip()
@@ -151,4 +160,5 @@ def update_evolution_chains():
conn.close()
if __name__ == "__main__":
- update_evolution_chains()
+ cache = CacheManager()
+ update_evolution_chains(cache)
diff --git a/DataGatherers/pokemondb_scraper.py b/DataGatherers/pokemondb_scraper.py
index 8a0445a..f946f21 100644
--- a/DataGatherers/pokemondb_scraper.py
+++ b/DataGatherers/pokemondb_scraper.py
@@ -4,7 +4,14 @@ from typing import Dict, List, Optional
from dataclasses import dataclass, asdict
import os
import sqlite3
-from cache_manager import CacheManager
+import sys
+import logging
+
+sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+
+from DataGatherers.cache_manager import CacheManager
+
+logger = logging.getLogger('ui_feedback')
@dataclass
class PokemonForm:
@@ -121,7 +128,7 @@ def download_image(url, filename):
with open(filename, 'wb') as f:
f.write(response.content)
-def thingy(cache: CacheManager):
+def retrieve_all_pokemon_forms(cache: CacheManager, progress_callback=None):
db = PokemonDatabase()
pokemon_db_conn = create_pokemon_db()
create_pokemon_storage_db()
@@ -155,7 +162,9 @@ def thingy(cache: CacheManager):
break
pokemon_name = mon.get_text(strip=True)
- print(pokemon_name)
+ logger.info(pokemon_name)
+ if progress_callback:
+ progress_callback(f"Processing {pokemon_name}")
pokemon_url_name = pokemon_name.replace("♀", "-f").replace("♂", "-m").replace("'", "").replace(".", "").replace('é', 'e').replace(':', '')
pokemon_url_name = pokemon_url_name.replace(" ", "-")
@@ -197,7 +206,7 @@ def thingy(cache: CacheManager):
form_name = "None"
if sprite.find('small'):
form_name = sprite.find('small').get_text(strip=True)
- print(sprite_url, form_name)
+ logger.info(f'{sprite_url}, {form_name}')
if form_name != "None":
form += 1
gender = 0
@@ -232,8 +241,8 @@ def thingy(cache: CacheManager):
national_dex_index += 1
- print(f"Total Pokémon forms: {sum(len(forms) for forms in db.pokemon.values())}")
- print(f"Pokémon with multiple forms: {sum(1 for forms in db.pokemon.values() if len(forms) > 1)}")
+ logger.info(f"Total Pokémon forms: {sum(len(forms) for forms in db.pokemon.values())}")
+ logger.info(f"Pokémon with multiple forms: {sum(1 for forms in db.pokemon.values() if len(forms) > 1)}")
if not os.path.exists('images-new'):
os.makedirs('images-new')
@@ -242,14 +251,14 @@ def thingy(cache: CacheManager):
for form in pokemon:
filename = f"images-new/{form.id}.png"
if os.path.exists(filename):
- print(f"Image for {form.id} already exists, skipping download")
+ logger.info(f"Image for {form.id} already exists, skipping download")
else:
download_image(form.sprite_url, filename)
- print(f"Downloaded image for {form.id}")
+ logger.info(f"Downloaded image for {form.id}")
pokemon_db_conn.close()
if __name__ == "__main__":
cache = CacheManager()
- thingy(cache)
+ retrieve_all_pokemon_forms(cache)
cache.close()
\ No newline at end of file
diff --git a/DataGatherers/update_location_information.py b/DataGatherers/update_location_information.py
index efebf70..3b0dd5d 100644
--- a/DataGatherers/update_location_information.py
+++ b/DataGatherers/update_location_information.py
@@ -7,11 +7,15 @@ import json
import sqlite3
from DataGatherers.cache_manager import CacheManager
from DataGatherers.DetermineOriginGame import get_locations_from_bulbapedia
+from event_system import event_system
from bs4 import BeautifulSoup, Tag
import re
import time
import unicodedata
+import logging
+logger = logging.getLogger('ui_feedback')
+
def create_encounters_table():
conn = sqlite3.connect('pokemon_forms.db')
cursor = conn.cursor()
@@ -101,11 +105,11 @@ def extract_bracketed_text(string, timeout=1):
results.append(string[start_index + 1:i])
start_index = -1
else:
- print(f"Warning: Unmatched closing parenthesis at position {i}")
+ logger.warning(f"Warning: Unmatched closing parenthesis at position {i}")
# Handle any remaining unclosed brackets
if stack:
- print(f"Warning: {len(stack)} unmatched opening parentheses")
+ logger.warning(f"Warning: {len(stack)} unmatched opening parentheses")
for unmatched_start in stack:
results.append(string[unmatched_start + 1:])
@@ -230,15 +234,17 @@ def save_encounter(conn, pfic, game, location, days, times, dual_slot, static_en
stars_str = ','.join(sorted(stars)) if stars else None
rods_str = ','.join(sorted(rods)) if rods else None
+ game_id = event_system.call_sync('get_game_id_for_name', game)
+
insert_query = '''
INSERT INTO encounters
- (pfic, game, location, day, time, dual_slot, static_encounter_count, static_encounter, extra_text, stars, rods, fishing, starter)
+ (pfic, game_id, location, day, time, dual_slot, static_encounter_count, static_encounter, extra_text, stars, rods, fishing, starter)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
'''
criteria = {
"pfic": pfic,
- "game": game,
+ "game_id": game_id,
"location": location,
"day": None,
"time": None,
@@ -263,11 +269,11 @@ def save_encounter(conn, pfic, game, location, days, times, dual_slot, static_en
encounter = cursor.fetchone()
if encounter == None or encounter[0] == 0:
- cursor.execute(insert_query, (pfic, game, location, day, None, dual_slot, static_encounter_count,
+ cursor.execute(insert_query, (pfic, game_id, location, day, None, dual_slot, static_encounter_count,
static_encounter, extra_text_str, stars_str, rods_str, fishing, starter))
- print(f"New encounter added for {pfic} in {game} at {location} on {day}")
+ logger.info(f"New encounter added for {pfic} in {game} at {location} on {day}")
else:
- print(f"Identical encounter already exists for {pfic} in {game} at {location} on {day}")
+ logger.info(f"Identical encounter already exists for {pfic} in {game} at {location} on {day}")
elif len(times) > 0:
for time in times:
@@ -280,11 +286,11 @@ def save_encounter(conn, pfic, game, location, days, times, dual_slot, static_en
encounter = cursor.fetchone()
if encounter == None or encounter[0] == 0:
- cursor.execute(insert_query, (pfic, game, location, None, time, dual_slot, static_encounter_count,
+ cursor.execute(insert_query, (pfic, game_id, location, None, time, dual_slot, static_encounter_count,
static_encounter, extra_text_str, stars_str, rods_str, fishing, starter))
- print(f"New encounter added for {pfic} in {game} at {location} at {time}")
+ logger.info(f"New encounter added for {pfic} in {game} at {location} at {time}")
else:
- print(f"Identical encounter already exists for {pfic} in {game} at {location} at {time}")
+ logger.info(f"Identical encounter already exists for {pfic} in {game} at {location} at {time}")
else:
criteria["day"] = None
@@ -296,11 +302,11 @@ def save_encounter(conn, pfic, game, location, days, times, dual_slot, static_en
encounter = cursor.fetchone()
if encounter == None or encounter[0] == 0:
- cursor.execute(insert_query, (pfic, game, location, None, None, dual_slot, static_encounter_count,
+ cursor.execute(insert_query, (pfic, game_id, location, None, None, dual_slot, static_encounter_count,
static_encounter, extra_text_str, stars_str, rods_str, fishing, starter))
- print(f"New encounter added for {pfic} in {game} at {location}")
+ logger.info(f"New encounter added for {pfic} in {game} at {location}")
else:
- print(f"Identical encounter already exists for {pfic} in {game} at {location}")
+ logger.info(f"Identical encounter already exists for {pfic} in {game} at {location}")
conn.commit()
@@ -320,7 +326,7 @@ def compare_forms(a, b):
return False
def process_pokemon_for_location_data(pfic, name, form, national_dex, default_forms, cache, conn):
- print(f"Processing {name} {form if form else ''}")
+ logger.info(f"Processing {name} {form if form else ''}")
if form and name in form:
form = form.replace(name, "").strip()
@@ -348,7 +354,24 @@ def process_pokemon_for_location_data(pfic, name, form, national_dex, default_fo
search_form = form
- encounters_to_ignore = ["trade", "time capsule", "unobtainable", "evolve", "tradeversion", "poké transfer", "friend safari", "unavailable", "pokémon home"]
+ encounters_to_ignore = [
+ "trade",
+ "time capsule",
+ "unobtainable",
+ "evolve",
+ "tradeversion",
+ "poké transfer",
+ "friend safari",
+ "unavailable",
+ "pokémon home",
+ "union circle",
+ "pokémon bank",
+ "pal park",
+ "transfer from dream radar",
+ "global link event",
+ "pokémon channel",
+ "pokémon colosseum bonus disc"
+ ]
encounter_data = get_locations_from_bulbapedia(name, search_form, cache, default_forms)
if encounter_data == None:
@@ -375,17 +398,17 @@ def process_pokemon_for_location_data(pfic, name, form, national_dex, default_fo
continue
if print_encounter:
- print(f"Found in {encounter}:")
+ logger.info(f"Found in {encounter}:")
print_encounter = False
remaining, details = extract_additional_information(location["tag"])
routes, remaining = extract_routes(remaining)
- print(f"Routes: {routes}")
- print(f"Remaining: {remaining.strip()}")
- print(f"Details: {details}")
+ logger.info(f"Routes: {routes}")
+ logger.info(f"Remaining: {remaining.strip()}")
+ logger.info(f"Details: {details}")
if len(details["times"]) > 0:
- print("Stupid Data")
+ logger.info("Stupid Data")
for route in routes:
route_name = f"Route {route}"
@@ -399,9 +422,7 @@ def process_pokemon_for_location_data(pfic, name, form, national_dex, default_fo
save_encounter(conn, pfic, encounter, remaining_location.strip(), details["days"], details["times"], details["dual_slot"], details["static_encounter"], details["static_encounter_count"], details["extra_text"], details["stars"], details["Rods"], details["Fishing"], details["starter"] )
-if __name__ == "__main__":
- cache = CacheManager()
-
+def update_location_information(cache, progress_callback=None):
conn = create_encounters_table()
cursor = conn.cursor()
cursor.execute('''
@@ -418,6 +439,13 @@ if __name__ == "__main__":
default_forms = []
for pfic, name, form, national_dex in pokemon_forms:
+ if progress_callback:
+ progress_callback(f"Processing {name} {form if form else ''}")
process_pokemon_for_location_data(pfic, name, form, national_dex, default_forms, cache, conn)
- conn.close()
+ conn.close()
+
+if __name__ == "__main__":
+ cache = CacheManager()
+ update_location_information(cache)
+
diff --git a/DataGatherers/update_storable_in_home.py b/DataGatherers/update_storable_in_home.py
index 7322a17..f9d547a 100644
--- a/DataGatherers/update_storable_in_home.py
+++ b/DataGatherers/update_storable_in_home.py
@@ -1,8 +1,17 @@
import json
import sqlite3
-from cache_manager import CacheManager
from bs4 import BeautifulSoup, Tag
+import sys
+import os
+import logging
+
+sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+
+from DataGatherers.cache_manager import CacheManager
+
+logger = logging.getLogger('ui_feedback')
+
def create_pokemon_storage_db():
conn = sqlite3.connect('pokemon_forms.db')
cursor = conn.cursor()
@@ -69,7 +78,7 @@ def scrape_all_regions(cache):
url = f"{base_url}{region}pokemon.shtml"
region_pokemon = scrape_serebii_region_pokemon(url, cache)
all_pokemon.extend(region_pokemon)
- print(f"Scraped {len(region_pokemon)} Pokémon from {region.capitalize()} region")
+ logger.info(f"Scraped {len(region_pokemon)} Pokémon from {region.capitalize()} region")
return all_pokemon
@@ -93,11 +102,11 @@ def extract_bracketed_text(string):
results.append(string[start_index + 1:i])
start_index = -1
else:
- print(f"Warning: Unmatched closing parenthesis at position {i}")
+ logger.warning(f"Warning: Unmatched closing parenthesis at position {i}")
# Handle any remaining unclosed brackets
if stack:
- print(f"Warning: {len(stack)} unmatched opening parentheses")
+ logger.warning(f"Warning: {len(stack)} unmatched opening parentheses")
for unmatched_start in stack:
results.append(string[unmatched_start + 1:])
@@ -118,9 +127,7 @@ def compare_forms(a, b):
return False
-if __name__ == "__main__":
- cache = CacheManager()
-
+def update_storable_in_home(cache, progress_callback=None):
conn = create_pokemon_storage_db()
cursor = conn.cursor()
cursor.execute('''
@@ -139,9 +146,12 @@ if __name__ == "__main__":
default_forms = []
for pfic, name, form, national_dex in pokemon_forms:
- print(f"Processing {name} {form if form else ''}")
+
+ if progress_callback:
+ progress_callback(f"Processing {name} {form if form else ''}")
storable_in_home = False
+ default_form = form
if form and name in form:
form = form.replace(name, "").strip()
@@ -150,9 +160,6 @@ if __name__ == "__main__":
if form and ("male" in form.lower() or "female" in form.lower()):
form = None
- if form and form in default_forms:
- form = None
-
if name == "Unown" and (form != "!" and form != "?"):
form = None
@@ -164,23 +171,31 @@ if __name__ == "__main__":
pokemon = get_objects_by_number(all_depositable_pokemon, f"{national_dex:04d}")
for p in pokemon:
+ if form:
+ parts = p['name'].split(" ")
+ if len(parts) > 1 and parts[0] == form:
+ storable_in_home = True
+
+ brackets = extract_bracketed_text(p['name'])
+ if brackets:
+ for bracket in brackets:
+ if name in bracket:
+ bracket = bracket.replace(name, "").strip()
+ if compare_forms(form, bracket):
+ storable_in_home = True
+ break
+ if storable_in_home == False and form and form in default_forms:
+ form = None
+
if form == None and name.lower() in p['name'].lower():
storable_in_home = True
break
- parts = p['name'].split(" ")
- if len(parts) > 1 and parts[0] == form:
- storable_in_home = True
-
- brackets = extract_bracketed_text(p['name'])
- if brackets:
- for bracket in brackets:
- if name in bracket:
- bracket = bracket.replace(name, "").strip()
- if compare_forms(form, bracket):
- storable_in_home = True
- break
-
- print(f"{name} {form if form else ''} is storable in home: {storable_in_home}")
+ logger.info(f"{name} {form if form else ''} is storable in home: {storable_in_home}")
insert_pokemon_storage(conn, pfic, storable_in_home)
+
+if __name__ == "__main__":
+ cache = CacheManager()
+ update_storable_in_home(cache)
+
\ No newline at end of file
diff --git a/Utilities/DBVisualiser.py b/Utilities/DBVisualiser.py
deleted file mode 100644
index 7e07180..0000000
--- a/Utilities/DBVisualiser.py
+++ /dev/null
@@ -1,609 +0,0 @@
-import sys
-import sqlite3
-import json
-import os
-from datetime import datetime
-from PyQt6.QtWidgets import (QApplication, QMainWindow, QListWidget, QLabel,
- QVBoxLayout, QHBoxLayout, QWidget, QPushButton,
- QTableWidget, QTableWidgetItem, QHeaderView,
- QLineEdit, QCheckBox, QFormLayout, QMessageBox,
- QDialog, QComboBox, QFileDialog, QTabWidget)
-from PyQt6.QtGui import QPixmap
-from PyQt6.QtCore import Qt
-
-class PokemonDatabaseApp(QMainWindow):
- def __init__(self):
- super().__init__()
- self.setWindowTitle("Pokémon Database Viewer")
- self.setGeometry(100, 100, 1200, 600)
-
- # Create an in-memory database
- self.conn = sqlite3.connect(':memory:')
- self.cursor = self.conn.cursor()
-
- # Load the database from disk into memory
- self.load_database()
-
- # Apply all existing patches
- self.apply_all_patches()
-
- self.current_pokemon_id = None
- self.current_pokemon_name = None
- self.current_form_id = None
- self.all_pokemon = []
- self.patches = {}
- self.init_ui()
- self.load_locations_list()
-
- def init_ui(self):
- main_layout = QVBoxLayout()
-
- # Create tab widget
- self.tab_widget = QTabWidget()
-
- # Create and add Pokemon tab
- pokemon_tab = self.create_pokemon_tab()
- self.tab_widget.addTab(pokemon_tab, "Pokémon")
-
- # Create and add Locations tab
- locations_tab = self.create_locations_tab()
- self.tab_widget.addTab(locations_tab, "Locations")
-
- main_layout.addWidget(self.tab_widget)
-
- # Add export button
- self.export_button = QPushButton("Export Production Database")
- self.export_button.clicked.connect(self.export_production_database)
- main_layout.addWidget(self.export_button)
-
- container = QWidget()
- container.setLayout(main_layout)
- self.setCentralWidget(container)
-
- self.load_pokemon_list()
-
- def create_pokemon_tab(self):
- pokemon_tab = QWidget()
- tab_layout = QHBoxLayout()
-
- # Pokémon list section
- pokemon_list_layout = QVBoxLayout()
-
- # Search box
- self.search_box = QLineEdit()
- self.search_box.setPlaceholderText("Search Pokémon...")
- self.search_box.textChanged.connect(self.filter_pokemon_list)
- pokemon_list_layout.addWidget(self.search_box)
-
- # Pokémon list
- self.pokemon_list = QListWidget()
- self.pokemon_list.itemClicked.connect(self.load_pokemon_data)
- pokemon_list_layout.addWidget(self.pokemon_list)
-
- tab_layout.addLayout(pokemon_list_layout, 1)
-
- # Pokémon details
- details_layout = QVBoxLayout()
-
- image_and_form_layout = QHBoxLayout()
-
- # Image
- self.image_label = QLabel()
- self.image_label.setFixedSize(200, 200)
- self.image_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
- image_and_form_layout.addWidget(self.image_label)
-
- # Form details
- form_details_layout = QFormLayout()
- self.form_name_edit = QLineEdit()
- self.is_default_checkbox = QCheckBox()
- self.image_path_edit = QLineEdit()
- form_details_layout.addRow("Form Name:", self.form_name_edit)
- form_details_layout.addRow("Default Form:", self.is_default_checkbox)
- form_details_layout.addRow("Image Path:", self.image_path_edit)
-
- # Save button
- self.save_button = QPushButton("Save Form Changes")
- self.save_button.clicked.connect(self.save_form_changes)
- form_details_layout.addRow(self.save_button)
-
- image_and_form_layout.addLayout(form_details_layout)
- details_layout.addLayout(image_and_form_layout)
-
- # Forms list and add new form button
- forms_layout = QHBoxLayout()
- self.forms_list = QListWidget()
- self.forms_list.itemClicked.connect(self.load_form_data)
- forms_layout.addWidget(self.forms_list)
-
- add_form_button = QPushButton("Add New Form")
- add_form_button.clicked.connect(self.add_new_form)
- details_layout.addWidget(add_form_button)
-
- details_layout.addWidget(QLabel("Forms:"))
- details_layout.addLayout(forms_layout)
-
- # Encounters table and add new encounter button
- self.encounters_table = QTableWidget()
- self.encounters_table.setColumnCount(3)
- self.encounters_table.setHorizontalHeaderLabels(['Game', 'Location', 'Method'])
- self.encounters_table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.Stretch)
- details_layout.addWidget(QLabel("Encounters:"))
- details_layout.addWidget(self.encounters_table)
-
- add_encounter_button = QPushButton("Add New Encounter")
- add_encounter_button.clicked.connect(self.add_new_encounter)
- details_layout.addWidget(add_encounter_button)
-
- tab_layout.addLayout(details_layout, 2)
-
- pokemon_tab.setLayout(tab_layout)
- return pokemon_tab
-
- def create_locations_tab(self):
- locations_tab = QWidget()
- tab_layout = QHBoxLayout()
-
- # Locations list
- locations_list_layout = QVBoxLayout()
-
- # Search box for locations
- self.locations_search_box = QLineEdit()
- self.locations_search_box.setPlaceholderText("Search Locations...")
- self.locations_search_box.textChanged.connect(self.filter_locations_list)
- locations_list_layout.addWidget(self.locations_search_box)
-
- # Locations list
- self.locations_list = QListWidget()
- self.locations_list.itemClicked.connect(self.load_location_data)
- locations_list_layout.addWidget(self.locations_list)
-
- # Add new location button
- add_location_button = QPushButton("Add New Location")
- add_location_button.clicked.connect(self.add_new_location)
- locations_list_layout.addWidget(add_location_button)
-
- tab_layout.addLayout(locations_list_layout, 1)
-
- # Location details
- location_details_layout = QFormLayout()
-
- self.location_name_edit = QLineEdit()
- self.location_description_edit = QLineEdit()
-
- location_details_layout.addRow("Name:", self.location_name_edit)
- location_details_layout.addRow("description:", self.location_description_edit)
-
- # Save location changes button
- save_location_button = QPushButton("Save Location Changes")
- save_location_button.clicked.connect(self.save_location_changes)
- location_details_layout.addRow(save_location_button)
-
- tab_layout.addLayout(location_details_layout, 2)
-
- locations_tab.setLayout(tab_layout)
- return locations_tab
-
- def load_database(self):
- disk_conn = sqlite3.connect('pokemon_database.db')
- disk_conn.backup(self.conn)
- disk_conn.close()
-
- def apply_all_patches(self):
- patches_dir = "patches"
- if not os.path.exists(patches_dir):
- return
-
- patch_files = sorted([f for f in os.listdir(patches_dir) if f.endswith('.json')])
- for patch_file in patch_files:
- with open(os.path.join(patches_dir, patch_file), 'r') as f:
- patches = json.load(f)
- self.apply_patches(patches)
-
- def apply_patches(self, patches):
- try:
- for timestamp, patch in patches.items():
- if patch["type"] == "form_update":
- self.cursor.execute("""
- UPDATE pokemon_forms
- SET form_name = ?, is_default = ?, image_path = ?
- WHERE id = ?
- """, (patch["form_name"], patch["is_default"], patch["image_path"], patch["form_id"]))
- elif patch["type"] == "new_form":
- self.cursor.execute("""
- INSERT INTO pokemon_forms (pokemon_id, form_name, is_default, image_path)
- VALUES (?, ?, ?, ?)
- """, (patch["pokemon_id"], patch["form_name"], patch["is_default"], patch["image_path"]))
- elif patch["type"] == "new_encounter":
- self.cursor.execute("""
- INSERT INTO form_encounters (form_id, game_id, location_id, encounter_method_id)
- VALUES (?,
- (SELECT id FROM games WHERE name = ?),
- (SELECT id FROM locations WHERE name = ?),
- (SELECT id FROM encounter_methods WHERE name = ?))
- """, (patch["form_id"], patch["game"], patch["location"], patch["method"]))
- elif patch["type"] == "location_update":
- self.cursor.execute("""
- UPDATE locations
- SET name = ?, description = ?
- WHERE name = ?
- """, (patch["new_name"], patch["description"], patch["old_name"]))
- elif patch["type"] == "new_location":
- self.cursor.execute("""
- INSERT INTO locations (name, description)
- VALUES (?, ?)
- """, (patch["name"], patch["description"]))
-
- self.conn.commit()
- except sqlite3.Error as e:
- print(f"An error occurred while applying patches: {e}")
-
- def load_pokemon_list(self):
- self.cursor.execute("SELECT national_dex_number, name FROM pokemon ORDER BY national_dex_number")
- self.all_pokemon = [f"{row[0]:03d} - {row[1]}" for row in self.cursor.fetchall()]
- self.pokemon_list.addItems(self.all_pokemon)
-
- def filter_pokemon_list(self):
- search_text = self.search_box.text().lower()
- self.pokemon_list.clear()
- for pokemon in self.all_pokemon:
- if search_text in pokemon.lower():
- self.pokemon_list.addItem(pokemon)
-
- def load_pokemon_data(self, item):
- self.current_pokemon_id = int(item.text().split('-')[0])
- self.current_pokemon_name = item.text().split('-')[1]
- # Load forms
- self.forms_list.clear()
- self.cursor.execute("""
- SELECT form_name FROM pokemon_forms
- WHERE pokemon_id = ?
- ORDER BY is_default DESC, form_name
- """, (self.current_pokemon_id,))
- for row in self.cursor.fetchall():
- self.forms_list.addItem(row[0])
-
- # Load default form data
- self.forms_list.setCurrentRow(0)
- self.load_form_data(self.forms_list.item(0))
-
- def load_form_data(self, item):
- if not item:
- return
-
- form_name = item.text()
-
- # Load form data
- self.cursor.execute("""
- SELECT id, form_name, is_default, image_path FROM pokemon_forms
- WHERE pokemon_id = ? AND form_name = ?
- """, (self.current_pokemon_id, form_name))
- form_data = self.cursor.fetchone()
- if form_data:
- self.current_form_id, form_name, is_default, image_path = form_data
-
- # Update form details
- self.form_name_edit.setText(form_name)
- self.is_default_checkbox.setChecked(bool(is_default))
- self.image_path_edit.setText(image_path)
-
- # Load image
- pixmap = QPixmap(image_path)
- self.image_label.setPixmap(pixmap.scaled(200, 200, Qt.AspectRatioMode.KeepAspectRatio))
-
- # Load encounters
- self.encounters_table.setRowCount(0)
- self.cursor.execute("""
- SELECT g.name, l.name, em.name
- FROM form_encounters fe
- JOIN games g ON fe.game_id = g.id
- JOIN locations l ON fe.location_id = l.id
- JOIN encounter_methods em ON fe.encounter_method_id = em.id
- WHERE fe.form_id = ?
- ORDER BY g.name, l.name
- """, (self.current_form_id,))
- for row in self.cursor.fetchall():
- current_row = self.encounters_table.rowCount()
- self.encounters_table.insertRow(current_row)
- for col, value in enumerate(row):
- self.encounters_table.setItem(current_row, col, QTableWidgetItem(str(value)))
-
- def save_form_changes(self):
- if not self.current_form_id:
- return
-
- new_form_name = self.form_name_edit.text()
- new_is_default = self.is_default_checkbox.isChecked()
- new_image_path = self.image_path_edit.text()
-
- # Add changes to patches
- patch = {
- "type": "form_update",
- "form_id": self.current_form_id,
- "form_name": new_form_name,
- "is_default": new_is_default,
- "image_path": new_image_path
- }
- self.add_to_patches(patch)
-
- try:
- self.cursor.execute("""
- UPDATE pokemon_forms
- SET form_name = ?, is_default = ?, image_path = ?
- WHERE id = ?
- """, (new_form_name, new_is_default, new_image_path, self.current_form_id))
- self.conn.commit()
- QMessageBox.information(self, "Success", "Form data updated successfully!")
-
- # Refresh the forms list and current form data
- self.load_pokemon_data(self.pokemon_list.currentItem())
- except sqlite3.Error as e:
- QMessageBox.warning(self, "Error", f"An error occurred: {e}")
-
- def add_new_form(self):
- if not self.current_pokemon_id:
- QMessageBox.warning(self, "Error", "Please select a Pokémon first.")
- return
-
- dialog = QDialog(self)
- dialog.setWindowTitle("Add New Form")
- layout = QFormLayout(dialog)
-
- form_name_edit = QLineEdit()
- layout.addRow("Form Name:", form_name_edit)
-
- buttons = QHBoxLayout()
- save_button = QPushButton("Save")
- save_button.clicked.connect(dialog.accept)
- cancel_button = QPushButton("Cancel")
- cancel_button.clicked.connect(dialog.reject)
- buttons.addWidget(save_button)
- buttons.addWidget(cancel_button)
- layout.addRow(buttons)
-
- if dialog.exec() == QDialog.DialogCode.Accepted:
- form_name = form_name_edit.text()
-
- try:
- self.cursor.execute("""
- INSERT INTO pokemon_forms (pokemon_id, form_name, is_default, image_path)
- VALUES (?, ?, ?, ?)
- """, (self.current_pokemon_id, form_name, False, f"images/pokemon/{self.current_pokemon_id:04d}_{self.current_pokemon_name}_({form_name}).png".replace(" ", "_")))
- self.conn.commit()
- new_form_id = self.cursor.lastrowid
-
- # Add new form to patches
- patch = {
- "type": "new_form",
- "form_id": new_form_id,
- "pokemon_id": self.current_pokemon_id,
- "form_name": form_name,
- "is_default": False,
- "image_path": f"images/pokemon/{self.current_pokemon_id:04d}_{self.current_pokemon_name}_({form_name}).png".replace(" ", "_")
- }
- self.add_to_patches(patch)
-
- QMessageBox.information(self, "Success", "New form added successfully!")
- self.load_pokemon_data(self.pokemon_list.currentItem())
- except sqlite3.Error as e:
- QMessageBox.warning(self, "Error", f"An error occurred: {e}")
-
- def add_new_encounter(self):
- if not self.current_form_id:
- QMessageBox.warning(self, "Error", "Please select a form first.")
- return
-
- dialog = QDialog(self)
- dialog.setWindowTitle("Add New Encounter")
- layout = QFormLayout(dialog)
-
- game_combo = QComboBox()
- self.cursor.execute("SELECT name FROM games ORDER BY name")
- games = [row[0] for row in self.cursor.fetchall()]
- game_combo.addItems(games)
- layout.addRow("Game:", game_combo)
-
- location_combo = QComboBox()
- self.cursor.execute("SELECT name FROM locations ORDER BY name")
- locations = [row[0] for row in self.cursor.fetchall()]
- location_combo.addItems(locations)
- layout.addRow("Location:", location_combo)
-
- method_combo = QComboBox()
- self.cursor.execute("SELECT name FROM encounter_methods ORDER BY name")
- methods = [row[0] for row in self.cursor.fetchall()]
- method_combo.addItems(methods)
- layout.addRow("Method:", method_combo)
-
- buttons = QHBoxLayout()
- save_button = QPushButton("Save")
- save_button.clicked.connect(dialog.accept)
- cancel_button = QPushButton("Cancel")
- cancel_button.clicked.connect(dialog.reject)
- buttons.addWidget(save_button)
- buttons.addWidget(cancel_button)
- layout.addRow(buttons)
-
- if dialog.exec() == QDialog.DialogCode.Accepted:
- game = game_combo.currentText()
- location = location_combo.currentText()
- method = method_combo.currentText()
-
- try:
- self.cursor.execute("""
- INSERT INTO form_encounters (form_id, game_id, location_id, encounter_method_id)
- VALUES (?,
- (SELECT id FROM games WHERE name = ?),
- (SELECT id FROM locations WHERE name = ?),
- (SELECT id FROM encounter_methods WHERE name = ?))
- """, (self.current_form_id, game, location, method))
- self.conn.commit()
- new_encounter_id = self.cursor.lastrowid
-
- # Add new encounter to patches
- patch = {
- "type": "new_encounter",
- "encounter_id": new_encounter_id,
- "form_id": self.current_form_id,
- "game": game,
- "location": location,
- "method": method
- }
- self.add_to_patches(patch)
-
- QMessageBox.information(self, "Success", "New encounter added successfully!")
- self.load_form_data(self.forms_list.currentItem())
- except sqlite3.Error as e:
- QMessageBox.warning(self, "Error", f"An error occurred: {e}")
-
- def add_to_patches(self, patch):
- timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
- self.patches[f"{timestamp}_{len(self.patches)}"] = patch
- self.auto_save_patches()
-
- def auto_save_patches(self):
- patches_dir = "patches"
- if not os.path.exists(patches_dir):
- os.makedirs(patches_dir)
-
- timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
- file_name = f"{patches_dir}/patch_{timestamp}.json"
-
- with open(file_name, 'w') as f:
- json.dump(self.patches, f, indent=2)
-
- print(f"Patches auto-saved to {file_name}")
-
- def closeEvent(self, event):
- reply = QMessageBox.question(self, 'Save Changes',
- "Do you want to save changes to the disk database?",
- QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
- QMessageBox.StandardButton.No)
-
- if reply == QMessageBox.StandardButton.Yes:
- # Save changes to disk
- disk_conn = sqlite3.connect('pokemon_database.db')
- self.conn.backup(disk_conn)
- disk_conn.close()
- QMessageBox.information(self, "Success", "Changes saved to disk database.")
-
- self.conn.close()
- event.accept()
-
- def filter_locations_list(self):
- search_text = self.locations_search_box.text().lower()
- for i in range(self.locations_list.count()):
- item = self.locations_list.item(i)
- if search_text in item.text().lower():
- item.setHidden(False)
- else:
- item.setHidden(True)
-
- def load_location_data(self, item):
- location_name = item.text()
- self.cursor.execute("SELECT name, description FROM locations WHERE name = ?", (location_name,))
- location_data = self.cursor.fetchone()
- if location_data:
- self.location_name_edit.setText(location_data[0])
- self.location_description_edit.setText(location_data[1])
-
- def save_location_changes(self):
- old_name = self.locations_list.currentItem().text()
- new_name = self.location_name_edit.text()
- new_description = self.location_description_edit.text()
-
- try:
- self.cursor.execute("""
- UPDATE locations
- SET name = ?, description = ?
- WHERE name = ?
- """, (new_name, new_description, old_name))
- self.conn.commit()
-
- # Add changes to patches
- patch = {
- "type": "location_update",
- "old_name": old_name,
- "new_name": new_name,
- "description": new_description
- }
- self.add_to_patches(patch)
-
- QMessageBox.information(self, "Success", "Location data updated successfully!")
- self.load_locations_list()
- except sqlite3.Error as e:
- QMessageBox.warning(self, "Error", f"An error occurred: {e}")
-
- def add_new_location(self):
- dialog = QDialog(self)
- dialog.setWindowTitle("Add New Location")
- layout = QFormLayout(dialog)
-
- name_edit = QLineEdit()
- description_edit = QLineEdit()
- layout.addRow("Name:", name_edit)
- layout.addRow("description:", description_edit)
-
- buttons = QHBoxLayout()
- save_button = QPushButton("Save")
- save_button.clicked.connect(dialog.accept)
- cancel_button = QPushButton("Cancel")
- cancel_button.clicked.connect(dialog.reject)
- buttons.addWidget(save_button)
- buttons.addWidget(cancel_button)
- layout.addRow(buttons)
-
- if dialog.exec() == QDialog.DialogCode.Accepted:
- name = name_edit.text()
- description = description_edit.text()
-
- try:
- self.cursor.execute("""
- INSERT INTO locations (name, description)
- VALUES (?, ?)
- """, (name, description))
- self.conn.commit()
-
- # Add new location to patches
- patch = {
- "type": "new_location",
- "name": name,
- "description": description
- }
- self.add_to_patches(patch)
-
- QMessageBox.information(self, "Success", "New location added successfully!")
- self.load_locations_list()
- except sqlite3.Error as e:
- QMessageBox.warning(self, "Error", f"An error occurred: {e}")
-
- def load_locations_list(self):
- self.locations_list.clear()
- self.cursor.execute("SELECT name FROM locations ORDER BY name")
- locations = [row[0] for row in self.cursor.fetchall()]
- self.locations_list.addItems(locations)
-
- def export_production_database(self):
- try:
- # Create a new connection for the production database
- production_db_path = QFileDialog.getSaveFileName(self, "Save Production Database", "", "SQLite Database (*.db)")[0]
- if not production_db_path:
- return # User cancelled the file dialog
-
- production_conn = sqlite3.connect(production_db_path)
-
- # Copy the current in-memory database to the production database
- self.conn.backup(production_conn)
-
- # Close the production database connection
- production_conn.close()
-
- QMessageBox.information(self, "Success", f"Production database exported successfully to {production_db_path}")
- except sqlite3.Error as e:
- QMessageBox.warning(self, "Error", f"An error occurred while exporting the production database: {e}")
-
-if __name__ == '__main__':
- app = QApplication(sys.argv)
- window = PokemonDatabaseApp()
- window.show()
- sys.exit(app.exec())
\ No newline at end of file
diff --git a/Utilities/NewDBVisualiser.py b/Utilities/NewDBVisualiser.py
deleted file mode 100644
index e033216..0000000
--- a/Utilities/NewDBVisualiser.py
+++ /dev/null
@@ -1,296 +0,0 @@
-import sys
-import os
-import sqlite3
-from PyQt5.QtWidgets import (QApplication, QMainWindow, QTableWidget, QTableWidgetItem, QPushButton, QVBoxLayout,
- QHBoxLayout, QWidget, QLineEdit, QLabel, QMessageBox, QTabWidget, QScrollArea, QFrame, QGridLayout)
-from PyQt5.QtCore import Qt
-from PyQt5.QtGui import QPixmap
-
-class PokemonEvolutionWidget(QWidget):
- def __init__(self, conn, pfic):
- super().__init__()
- self.conn = conn
- self.pfic = pfic
- self.layout = QVBoxLayout()
- self.setLayout(self.layout)
- self.stage_width = 200 # Fixed width for each evolution stage
- self.stage_height = 250 # Fixed height for each evolution stage
- self.build_evolution_chain()
-
- def build_evolution_chain(self):
- chain = self.get_full_evolution_chain(self.pfic)
- self.display_evolution_chain(chain)
-
- def get_full_evolution_chain(self, pfic):
- cursor = self.conn.cursor()
- chain = []
- visited = set()
-
- def build_chain(current_pfic):
- if current_pfic in visited:
- return None
- visited.add(current_pfic)
-
- cursor.execute('SELECT name, form_name FROM pokemon_forms WHERE PFIC = ?', (current_pfic,))
- pokemon = cursor.fetchone()
- if not pokemon:
- return None
-
- name, form_name = pokemon
- node = {"pfic": current_pfic, "name": name, "form_name": form_name, "evolutions": []}
-
- cursor.execute('''
- SELECT ec.to_pfic, pf.name, pf.form_name, ec.method
- FROM evolution_chains ec
- JOIN pokemon_forms pf ON ec.to_pfic = pf.PFIC
- WHERE ec.from_pfic = ?
- ''', (current_pfic,))
- evolutions = cursor.fetchall()
-
- for evo_pfic, evo_name, evo_form, method in evolutions:
- evo_node = build_chain(evo_pfic)
- if evo_node:
- node["evolutions"].append({"node": evo_node, "method": method})
-
- return node
-
- chain = build_chain(pfic)
- return chain
-
- def display_evolution_chain(self, chain):
- if not chain:
- return
-
- main_layout = QHBoxLayout()
- self.layout.addLayout(main_layout)
-
- stages = self.split_into_stages(chain)
- for stage_index, stage in enumerate(stages):
- stage_widget = QWidget()
- stage_layout = QGridLayout()
- stage_widget.setLayout(stage_layout)
- stage_widget.setFixedSize(self.stage_width, self.stage_height * len(stage))
-
- for row, pokemon in enumerate(stage):
- pokemon_widget = self.create_pokemon_widget(pokemon["pfic"], pokemon["name"], pokemon["form_name"])
- stage_layout.addWidget(pokemon_widget, row, 0, Qt.AlignCenter)
-
- if stage_index < len(stages) - 1 and pokemon.get("method"):
- arrow_label = QLabel("→")
- arrow_label.setStyleSheet("font-size: 24px;")
- stage_layout.addWidget(arrow_label, row, 1, Qt.AlignCenter)
-
- method_label = QLabel(pokemon["method"])
- method_label.setWordWrap(True)
- method_label.setFixedWidth(80)
- stage_layout.addWidget(method_label, row, 2, Qt.AlignCenter)
-
- main_layout.addWidget(stage_widget)
-
- def split_into_stages(self, chain):
- stages = []
- current_stage = [{"pfic": chain["pfic"], "name": chain["name"], "form_name": chain["form_name"]}]
- stages.append(current_stage)
-
- while current_stage:
- next_stage = []
- for pokemon in current_stage:
- evolutions = self.get_evolutions(pokemon["pfic"])
- for evolution in evolutions:
- next_stage.append({
- "pfic": evolution["to_pfic"],
- "name": evolution["name"],
- "form_name": evolution["form_name"],
- "method": evolution["method"]
- })
- if next_stage:
- stages.append(next_stage)
- current_stage = next_stage
-
- return stages
-
- def get_evolutions(self, pfic):
- cursor = self.conn.cursor()
- cursor.execute('''
- SELECT ec.to_pfic, pf.name, pf.form_name, ec.method
- FROM evolution_chains ec
- JOIN pokemon_forms pf ON ec.to_pfic = pf.PFIC
- WHERE ec.from_pfic = ?
- ''', (pfic,))
- evolutions = cursor.fetchall()
- return [{"to_pfic": to_pfic, "name": name, "form_name": form_name, "method": method} for to_pfic, name, form_name, method in evolutions]
-
- def create_pokemon_widget(self, pfic, name, form_name):
- widget = QWidget()
- layout = QVBoxLayout()
- widget.setLayout(layout)
-
- image_path = f"images-new/{pfic}.png"
- if os.path.exists(image_path):
- pixmap = QPixmap(image_path)
- image_label = QLabel()
- image_label.setPixmap(pixmap.scaled(96, 96, Qt.KeepAspectRatio, Qt.SmoothTransformation))
- layout.addWidget(image_label, alignment=Qt.AlignCenter)
-
- name_label = QLabel(name)
- name_label.setAlignment(Qt.AlignCenter)
- layout.addWidget(name_label)
-
- if form_name:
- form_label = QLabel(form_name)
- form_label.setAlignment(Qt.AlignCenter)
- layout.addWidget(form_label)
-
- return widget
-
-class DatabaseVisualizer(QMainWindow):
- def __init__(self):
- super().__init__()
- self.setWindowTitle("Pokémon Database Visualizer")
- self.setGeometry(100, 100, 1200, 800)
-
- self.conn = sqlite3.connect('pokemon_forms.db')
- self.cursor = self.conn.cursor()
-
- self.central_widget = QWidget()
- self.setCentralWidget(self.central_widget)
-
- self.layout = QVBoxLayout()
- self.central_widget.setLayout(self.layout)
-
- self.tab_widget = QTabWidget()
- self.layout.addWidget(self.tab_widget)
-
- self.forms_tab = QWidget()
- self.evolutions_tab = QWidget()
- self.tab_widget.addTab(self.forms_tab, "Pokémon Forms")
- self.tab_widget.addTab(self.evolutions_tab, "Evolution Chains")
-
- self.setup_forms_tab()
- self.setup_evolutions_tab()
-
- def setup_forms_tab(self):
- layout = QVBoxLayout()
- self.forms_tab.setLayout(layout)
-
- self.search_layout = QHBoxLayout()
- self.search_label = QLabel("Search:")
- self.search_input = QLineEdit()
- self.search_button = QPushButton("Search")
- self.search_button.clicked.connect(self.search_pokemon)
- self.search_layout.addWidget(self.search_label)
- self.search_layout.addWidget(self.search_input)
- self.search_layout.addWidget(self.search_button)
- layout.addLayout(self.search_layout)
-
- self.table = QTableWidget()
- layout.addWidget(self.table)
-
- self.save_button = QPushButton("Save Changes")
- self.save_button.clicked.connect(self.save_changes)
- layout.addWidget(self.save_button)
-
- self.load_forms_data()
-
- def setup_evolutions_tab(self):
- layout = QVBoxLayout()
- self.evolutions_tab.setLayout(layout)
-
- self.evolution_search_layout = QHBoxLayout()
- self.evolution_search_label = QLabel("Search Pokémon:")
- self.evolution_search_input = QLineEdit()
- self.evolution_search_button = QPushButton("Search")
- self.evolution_search_button.clicked.connect(self.search_evolution)
- self.evolution_search_layout.addWidget(self.evolution_search_label)
- self.evolution_search_layout.addWidget(self.evolution_search_input)
- self.evolution_search_layout.addWidget(self.evolution_search_button)
- layout.addLayout(self.evolution_search_layout)
-
- self.evolution_scroll_area = QScrollArea()
- self.evolution_scroll_area.setWidgetResizable(True)
- layout.addWidget(self.evolution_scroll_area)
-
- def load_forms_data(self):
- self.cursor.execute('''
- SELECT pf.PFIC, pf.name, pf.form_name, pf.national_dex, pf.generation, ps.storable_in_home
- FROM pokemon_forms pf
- LEFT JOIN pokemon_storage ps ON pf.PFIC = ps.PFIC
- ''')
- data = self.cursor.fetchall()
-
- self.table.setColumnCount(6)
- self.table.setHorizontalHeaderLabels(["PFIC", "Name", "Form Name", "National Dex", "Generation", "Storable in Home"])
- self.table.setRowCount(len(data))
-
- for row, record in enumerate(data):
- for col, value in enumerate(record):
- item = QTableWidgetItem(str(value))
- if col == 0: # PFIC column
- item.setFlags(item.flags() & ~Qt.ItemIsEditable) # Make PFIC non-editable
- self.table.setItem(row, col, item)
-
- self.table.resizeColumnsToContents()
-
- def search_pokemon(self):
- search_term = self.search_input.text().lower()
- for row in range(self.table.rowCount()):
- match = False
- for col in range(self.table.columnCount()):
- item = self.table.item(row, col)
- if item and search_term in item.text().lower():
- match = True
- break
- self.table.setRowHidden(row, not match)
-
- def save_changes(self):
- try:
- for row in range(self.table.rowCount()):
- pfic = self.table.item(row, 0).text()
- name = self.table.item(row, 1).text()
- form_name = self.table.item(row, 2).text() or None
- national_dex = int(self.table.item(row, 3).text())
- generation = int(self.table.item(row, 4).text())
- storable_in_home = self.table.item(row, 5).text().lower() == 'true'
-
- self.cursor.execute('''
- UPDATE pokemon_forms
- SET name = ?, form_name = ?, national_dex = ?, generation = ?
- WHERE PFIC = ?
- ''', (name, form_name, national_dex, generation, pfic))
-
- self.cursor.execute('''
- INSERT OR REPLACE INTO pokemon_storage (PFIC, storable_in_home)
- VALUES (?, ?)
- ''', (pfic, storable_in_home))
-
- self.conn.commit()
- QMessageBox.information(self, "Success", "Changes saved successfully!")
- except Exception as e:
- QMessageBox.critical(self, "Error", f"An error occurred while saving changes: {str(e)}")
-
- def search_evolution(self):
- search_term = self.evolution_search_input.text().lower()
-
- self.cursor.execute('''
- SELECT DISTINCT name, PFIC
- FROM pokemon_forms
- WHERE LOWER(name) LIKE ?
- ''', (f'%{search_term}%',))
-
- matching_pokemon = self.cursor.fetchall()
-
- if matching_pokemon:
- pokemon_name, pfic = matching_pokemon[0]
- evolution_widget = PokemonEvolutionWidget(self.conn, pfic)
- self.evolution_scroll_area.setWidget(evolution_widget)
- else:
- QMessageBox.information(self, "No Results", "No Pokémon found matching the search term.")
-
- def closeEvent(self, event):
- self.conn.close()
-
-if __name__ == "__main__":
- app = QApplication(sys.argv)
- window = DatabaseVisualizer()
- window.show()
- sys.exit(app.exec_())
\ No newline at end of file
diff --git a/efficiency_plan.txt b/efficiency_plan.txt
new file mode 100644
index 0000000..b71247b
--- /dev/null
+++ b/efficiency_plan.txt
@@ -0,0 +1,1460 @@
+Play Crystal:
+ Catch:
+ - Caterpie: 4 time(s)
+ - Weedle: 3 time(s)
+ - Pidgey: 3 time(s)
+ - Rattata (Female): 2 time(s)
+ - Rattata (Male): 2 time(s)
+ - Spearow: 2 time(s)
+ - Ekans: 2 time(s)
+ - Pikachu (Female): 2 time(s)
+ - Pikachu (Male): 2 time(s)
+ - Sandshrew: 2 time(s)
+ - Nidoran♀: 3 time(s)
+ - Nidoran♂: 3 time(s)
+ - Clefairy: 2 time(s)
+ - Jigglypuff: 2 time(s)
+ - Zubat (Female): 3 time(s)
+ - Zubat (Male): 2 time(s)
+ - Oddish: 6 time(s)
+ - Paras: 2 time(s)
+ - Venonat: 2 time(s)
+ - Diglett: 2 time(s)
+ - Meowth: 2 time(s)
+ - Psyduck: 2 time(s)
+ - Growlithe: 2 time(s)
+ - Poliwag: 5 time(s)
+ - Abra: 5 time(s)
+ - Machop: 3 time(s)
+ - Bellsprout: 3 time(s)
+ - Tentacool: 2 time(s)
+ - Geodude: 3 time(s)
+ - Ponyta: 2 time(s)
+ - Slowpoke: 3 time(s)
+ - Magnemite: 2 time(s)
+ - Farfetch'd: 1 time(s)
+ - Doduo (Female): 2 time(s)
+ - Doduo (Male): 2 time(s)
+ - Seel: 2 time(s)
+ - Grimer: 2 time(s)
+ - Shellder: 2 time(s)
+ - Gastly: 3 time(s)
+ - Onix: 3 time(s)
+ - Drowzee: 3 time(s)
+ - Krabby: 2 time(s)
+ - Voltorb: 2 time(s)
+ - Exeggcute: 2 time(s)
+ - Cubone: 2 time(s)
+ - Lickitung: 1 time(s)
+ - Koffing: 2 time(s)
+ - Rhyhorn (Female): 2 time(s)
+ - Rhyhorn (Male): 2 time(s)
+ - Chansey: 2 time(s)
+ - Tangela: 1 time(s)
+ - Kangaskhan: 1 time(s)
+ - Horsea: 3 time(s)
+ - Goldeen (Female): 2 time(s)
+ - Goldeen (Male): 2 time(s)
+ - Staryu: 2 time(s)
+ - Mr. Mime: 1 time(s)
+ - Scyther (Female): 2 time(s)
+ - Scyther (Male): 2 time(s)
+ - Jynx: 1 time(s)
+ - Electabuzz: 1 time(s)
+ - Magmar: 1 time(s)
+ - Pinsir: 1 time(s)
+ - Tauros: 1 time(s)
+ - Magikarp (Female): 2 time(s)
+ - Magikarp (Male): 2 time(s)
+ - Lapras: 1 time(s)
+ - Ditto: 1 time(s)
+ - Eevee (Female): 6 time(s)
+ - Eevee (Male): 1 time(s)
+ - Porygon: 2 time(s)
+ - Snorlax: 1 time(s)
+ - Dratini: 3 time(s)
+ - Mew: 1 time(s)
+ - Chikorita: 4 time(s)
+ - Cyndaquil: 3 time(s)
+ - Totodile: 3 time(s)
+ - Sentret: 2 time(s)
+ - Hoothoot: 2 time(s)
+ - Ledyba (Female): 2 time(s)
+ - Ledyba (Male): 2 time(s)
+ - Spinarak: 2 time(s)
+ - Chinchou: 2 time(s)
+ - Pichu: -1 time(s)
+ - Cleffa: 0 time(s)
+ - Igglybuff: 0 time(s)
+ - Togepi: 1 time(s)
+ - Natu: 3 time(s)
+ - Marill: 2 time(s)
+ - Sudowoodo (Female): 1 time(s)
+ - Sudowoodo (Male): 1 time(s)
+ - Hoppip: 3 time(s)
+ - Aipom (Female): 1 time(s)
+ - Aipom (Male): 1 time(s)
+ - Sunkern: 2 time(s)
+ - Yanma: 1 time(s)
+ - Wooper (Female): 2 time(s)
+ - Wooper (Male): 2 time(s)
+ - Murkrow (Female): 1 time(s)
+ - Murkrow (Male): 1 time(s)
+ - Misdreavus: 1 time(s)
+ - Unown (A): 1 time(s)
+ - Unown (B): 1 time(s)
+ - Unown (C): 1 time(s)
+ - Unown (D): 1 time(s)
+ - Unown (E): 1 time(s)
+ - Unown (F): 1 time(s)
+ - Unown (G): 1 time(s)
+ - Unown (H): 1 time(s)
+ - Unown (I): 1 time(s)
+ - Unown (J): 1 time(s)
+ - Unown (K): 1 time(s)
+ - Unown (L): 1 time(s)
+ - Unown (M): 1 time(s)
+ - Unown (N): 1 time(s)
+ - Unown (O): 1 time(s)
+ - Unown (P): 1 time(s)
+ - Unown (Q): 1 time(s)
+ - Unown (R): 1 time(s)
+ - Unown (S): 1 time(s)
+ - Unown (T): 1 time(s)
+ - Unown (U): 1 time(s)
+ - Unown (V): 1 time(s)
+ - Unown (W): 1 time(s)
+ - Unown (X): 1 time(s)
+ - Unown (Y): 1 time(s)
+ - Unown (Z): 1 time(s)
+ - Wobbuffet (Female): 1 time(s)
+ - Wobbuffet (Male): 1 time(s)
+ - Pineco: 2 time(s)
+ - Dunsparce: 1 time(s)
+ - Gligar (Female): 1 time(s)
+ - Gligar (Male): 1 time(s)
+ - Snubbull: 2 time(s)
+ - Qwilfish: 1 time(s)
+ - Shuckle: 1 time(s)
+ - Heracross (Female): 1 time(s)
+ - Heracross (Male): 1 time(s)
+ - Sneasel (Female): 1 time(s)
+ - Sneasel (Male): 1 time(s)
+ - Teddiursa: 3 time(s)
+ - Slugma: 2 time(s)
+ - Swinub: 3 time(s)
+ - Corsola: 1 time(s)
+ - Delibird: 1 time(s)
+ - Mantine: 1 time(s)
+ - Skarmory: 1 time(s)
+ - Houndour: 3 time(s)
+ - Phanpy: 3 time(s)
+ - Stantler: 1 time(s)
+ - Smeargle: 1 time(s)
+ - Tyrogue: 1 time(s)
+ - Smoochum: 1 time(s)
+ - Elekid: 1 time(s)
+ - Magby: 1 time(s)
+ - Miltank: 1 time(s)
+ - Raikou: 1 time(s)
+ - Entei: 1 time(s)
+ - Suicune: 1 time(s)
+ - Larvitar: 3 time(s)
+ - Lugia: 1 time(s)
+ - Ho-oh: 1 time(s)
+ - Celebi: 1 time(s)
+ Evolve:
+ - Caterpie into Metapod
+ - Caterpie into Metapod
+ - Caterpie into Metapod
+ - Metapod into Butterfree (Male)
+ - Metapod into Butterfree (Female)
+ - Weedle into Kakuna
+ - Weedle into Kakuna
+ - Kakuna into Beedrill
+ - Pidgey into Pidgeotto
+ - Pidgey into Pidgeotto
+ - Pidgeotto into Pidgeot
+ - Rattata (Female) into Raticate (Female)
+ - Rattata (Male) into Raticate (Male)
+ - Spearow into Fearow
+ - Ekans into Arbok
+ - Pikachu (Female) into Raichu (Female)
+ - Pikachu (Male) into Raichu (Male)
+ - Sandshrew into Sandslash
+ - Nidoran♀ into Nidorina
+ - Nidoran♀ into Nidorina
+ - Nidorina into Nidoqueen
+ - Nidoran♂ into Nidorino
+ - Nidoran♂ into Nidorino
+ - Nidorino into Nidoking
+ - Clefairy into Clefable
+ - Jigglypuff into Wigglytuff
+ - Zubat (Female) into Golbat (Female)
+ - Zubat (Female) into Golbat (Female)
+ - Golbat (Female) into Crobat
+ - Zubat (Male) into Golbat (Male)
+ - Zubat (Male) into Golbat (Male)
+ - Oddish into Gloom (Male)
+ - Oddish into Gloom (Male)
+ - Oddish into Gloom (Female)
+ - Oddish into Gloom (Male)
+ - Oddish into Gloom (Female)
+ - Gloom (Male) into Bellossom
+ - Gloom (Male) into Vileplume (Male)
+ - Gloom (Female) into Vileplume (Female)
+ - Paras into Parasect
+ - Venonat into Venomoth
+ - Diglett into Dugtrio
+ - Meowth into Persian
+ - Psyduck into Golduck
+ - Growlithe into Arcanine
+ - Poliwag into Poliwhirl
+ - Poliwag into Poliwhirl
+ - Poliwag into Poliwhirl
+ - Poliwag into Poliwhirl
+ - Poliwhirl into Politoed (Female)
+ - Poliwhirl into Poliwrath
+ - Poliwhirl into Politoed (Male)
+ - Abra into Kadabra (Female)
+ - Abra into Kadabra (Male)
+ - Abra into Kadabra (Female)
+ - Abra into Kadabra (Male)
+ - Kadabra (Male) into Alakazam (Male)
+ - Kadabra (Female) into Alakazam (Female)
+ - Machop into Machoke
+ - Machop into Machoke
+ - Machoke into Machamp
+ - Bellsprout into Weepinbell
+ - Bellsprout into Weepinbell
+ - Weepinbell into Victreebel
+ - Tentacool into Tentacruel
+ - Geodude into Graveler
+ - Geodude into Graveler
+ - Graveler into Golem
+ - Ponyta into Rapidash
+ - Slowpoke into Slowking
+ - Slowpoke into Slowbro
+ - Magnemite into Magneton
+ - Doduo (Female) into Dodrio (Female)
+ - Doduo (Male) into Dodrio (Male)
+ - Seel into Dewgong
+ - Grimer into Muk
+ - Shellder into Cloyster
+ - Gastly into Haunter
+ - Gastly into Haunter
+ - Haunter into Gengar
+ - Onix into Steelix (Female)
+ - Onix into Steelix (Male)
+ - Drowzee into Hypno (Female)
+ - Drowzee into Hypno (Male)
+ - Krabby into Kingler
+ - Voltorb into Electrode
+ - Exeggcute into Exeggutor
+ - Cubone into Marowak
+ - Koffing into Weezing
+ - Rhyhorn (Female) into Rhydon (Female)
+ - Rhyhorn (Male) into Rhydon (Male)
+ - Chansey into Blissey
+ - Horsea into Seadra
+ - Horsea into Seadra
+ - Seadra into Kingdra
+ - Goldeen (Female) into Seaking (Female)
+ - Goldeen (Male) into Seaking (Male)
+ - Staryu into Starmie
+ - Scyther (Female) into Scizor (Female)
+ - Scyther (Male) into Scizor (Male)
+ - Magikarp (Female) into Gyarados (Female)
+ - Magikarp (Male) into Gyarados (Male)
+ - Eevee (Female) into Vaporeon
+ - Eevee (Female) into Jolteon
+ - Eevee (Female) into Umbreon
+ - Eevee (Female) into Flareon
+ - Eevee (Female) into Espeon
+ - Porygon into Porygon2
+ - Dratini into Dragonair
+ - Dratini into Dragonair
+ - Dragonair into Dragonite
+ - Chikorita into Bayleef
+ - Chikorita into Bayleef
+ - Chikorita into Bayleef
+ - Bayleef into Meganium (Female)
+ - Bayleef into Meganium (Male)
+ - Cyndaquil into Quilava
+ - Cyndaquil into Quilava
+ - Quilava into Typhlosion
+ - Totodile into Croconaw
+ - Totodile into Croconaw
+ - Croconaw into Feraligatr
+ - Sentret into Furret
+ - Hoothoot into Noctowl
+ - Ledyba (Female) into Ledian (Female)
+ - Ledyba (Male) into Ledian (Male)
+ - Spinarak into Ariados
+ - Chinchou into Lanturn
+ - Natu into Xatu (Female)
+ - Natu into Xatu (Male)
+ - Marill into Azumarill
+ - Hoppip into Skiploom
+ - Hoppip into Skiploom
+ - Skiploom into Jumpluff
+ - Sunkern into Sunflora
+ - Wooper (Female) into Quagsire (Female)
+ - Wooper (Male) into Quagsire (Male)
+ - Pineco into Forretress
+ - Snubbull into Granbull
+ - Teddiursa into Ursaring (Female)
+ - Teddiursa into Ursaring (Male)
+ - Slugma into Magcargo
+ - Swinub into Piloswine (Female)
+ - Swinub into Piloswine (Male)
+ - Houndour into Houndoom (Male)
+ - Houndour into Houndoom (Female)
+ - Phanpy into Donphan (Male)
+ - Phanpy into Donphan (Female)
+ - Larvitar into Pupitar
+ - Larvitar into Pupitar
+ - Pupitar into Tyranitar
+ Breed:
+ - Pikachu (Male) to get Pichu
+ - Pikachu (Female) to get Pichu
+ - Clefairy to get Cleffa
+ - Jigglypuff to get Igglybuff
+ - Togetic to get Togepi
+ - Hitmontop to get Tyrogue
+ - Hitmonchan to get Tyrogue
+ - Hitmonlee to get Tyrogue
+ - Jynx to get Smoochum
+ - Electabuzz to get Elekid
+ - Magmar to get Magby
+Play Gold:
+ Catch:
+ - Mankey: 2 time(s)
+ - Articuno: 1 time(s)
+ - Zapdos: 1 time(s)
+ - Moltres: 1 time(s)
+ - Mareep: 3 time(s)
+ - Girafarig (Female): 1 time(s)
+ - Girafarig (Male): 1 time(s)
+ - Remoraid: 3 time(s)
+ Evolve:
+ - Mankey into Primeape
+ - Mareep into Flaaffy
+ - Mareep into Flaaffy
+ - Flaaffy into Ampharos
+ - Remoraid into Octillery (Male)
+ - Remoraid into Octillery (Female)
+Play Silver:
+ Catch:
+ - Vulpix: 2 time(s)
+ Evolve:
+ - Vulpix into Ninetales
+Play Red:
+ Catch:
+ - Bulbasaur: 4 time(s)
+ - Charmander: 3 time(s)
+ - Squirtle: 3 time(s)
+ - Omanyte: 2 time(s)
+ - Kabuto: 2 time(s)
+ - Aerodactyl: 1 time(s)
+ - Mewtwo: 1 time(s)
+ Evolve:
+ - Bulbasaur into Ivysaur
+ - Bulbasaur into Ivysaur
+ - Bulbasaur into Ivysaur
+ - Ivysaur into Venusaur (Male)
+ - Ivysaur into Venusaur (Female)
+ - Charmander into Charmeleon
+ - Charmander into Charmeleon
+ - Charmeleon into Charizard
+ - Squirtle into Wartortle
+ - Squirtle into Wartortle
+ - Wartortle into Blastoise
+ - Omanyte into Omastar
+ - Kabuto into Kabutops
+Play Black 2:
+ Catch:
+ - Eevee (Female): 3 time(s)
+ - Murkrow (Male): 1 time(s)
+ - Sneasel (Female): 1 time(s)
+ - Piloswine (Female): 1 time(s)
+ - Lickitung: 1 time(s)
+ - Aipom (Male): 1 time(s)
+ - Piloswine (Male): 1 time(s)
+ - Tangela: 2 time(s)
+ - Magneton: 1 time(s)
+ - Sneasel (Male): 1 time(s)
+ - Yanma: 1 time(s)
+ - Gligar (Female): 1 time(s)
+ - Aipom (Female): 1 time(s)
+ - Lotad: 4 time(s)
+ - Seedot: 5 time(s)
+ - Taillow: 2 time(s)
+ - Wingull: 2 time(s)
+ - Surskit: 2 time(s)
+ - Shroomish: 2 time(s)
+ - Slakoth: 3 time(s)
+ - Makuhita: 2 time(s)
+ - Azurill: 1 time(s)
+ - Nosepass: 2 time(s)
+ - Aron: 3 time(s)
+ - Meditite (Female): 2 time(s)
+ - Meditite (Male): 2 time(s)
+ - Electrike: 2 time(s)
+ - Plusle: 1 time(s)
+ - Volbeat: 1 time(s)
+ - Illumise: 1 time(s)
+ - Roselia (Female): 2 time(s)
+ - Roselia (Male): 2 time(s)
+ - Gulpin (Female): 2 time(s)
+ - Gulpin (Male): 2 time(s)
+ - Carvanha: 2 time(s)
+ - Wailmer: 2 time(s)
+ - Spoink: 2 time(s)
+ - Trapinch: 3 time(s)
+ - Cacnea: 3 time(s)
+ - Swablu: 2 time(s)
+ - Zangoose: 1 time(s)
+ - Seviper: 1 time(s)
+ - Lunatone: 1 time(s)
+ - Solrock: 1 time(s)
+ - Barboach: 2 time(s)
+ - Corphish: 2 time(s)
+ - Baltoy: 2 time(s)
+ - Lileep: 2 time(s)
+ - Anorith: 2 time(s)
+ - Feebas: 3 time(s)
+ - Castform: 1 time(s)
+ - Kecleon: 1 time(s)
+ - Shuppet: 2 time(s)
+ - Tropius: 1 time(s)
+ - Absol: 1 time(s)
+ - Wynaut: 1 time(s)
+ - Spheal: 3 time(s)
+ - Clamperl: 3 time(s)
+ - Relicanth (Female): 1 time(s)
+ - Relicanth (Male): 1 time(s)
+ - Luvdisc: 1 time(s)
+ - Bagon: 3 time(s)
+ - Beldum: 3 time(s)
+ - Regirock: 1 time(s)
+ - Regice: 1 time(s)
+ - Registeel: 1 time(s)
+ - Latios: 1 time(s)
+ - Turtwig: 3 time(s)
+ - Chimchar: 3 time(s)
+ - Piplup: 3 time(s)
+ - Bidoof (Female): 2 time(s)
+ - Bidoof (Male): 2 time(s)
+ - Budew: -1 time(s)
+ - Cranidos: 2 time(s)
+ - Shieldon: 2 time(s)
+ - Combee (Female): 2 time(s)
+ - Combee (Male): 1 time(s)
+ - Pachirisu (Female): 1 time(s)
+ - Pachirisu (Male): 1 time(s)
+ - Buizel (Female): 2 time(s)
+ - Buizel (Male): 2 time(s)
+ - Drifloon: 2 time(s)
+ - Buneary: 2 time(s)
+ - Stunky: 2 time(s)
+ - Bronzor: 2 time(s)
+ - Bonsly: 1 time(s)
+ - Happiny: 1 time(s)
+ - Chatot: 1 time(s)
+ - Gible (Female): 3 time(s)
+ - Gible (Male): 3 time(s)
+ - Munchlax: 1 time(s)
+ - Riolu: 1 time(s)
+ - Hippopotas (Female): 2 time(s)
+ - Hippopotas (Male): 2 time(s)
+ - Skorupi: 2 time(s)
+ - Croagunk (Female): 2 time(s)
+ - Croagunk (Male): 2 time(s)
+ - Carnivine: 1 time(s)
+ - Finneon (Female): 2 time(s)
+ - Finneon (Male): 2 time(s)
+ - Mantyke: 1 time(s)
+ - Uxie: 1 time(s)
+ - Mesprit: 1 time(s)
+ - Azelf: 1 time(s)
+ - Heatran: 1 time(s)
+ - Regigigas: 1 time(s)
+ - Cresselia: 1 time(s)
+ - Snivy: 3 time(s)
+ - Tepig: 3 time(s)
+ - Oshawott: 3 time(s)
+ - Patrat: 2 time(s)
+ - Lillipup: 3 time(s)
+ - Purrloin: 2 time(s)
+ - Pansage: 2 time(s)
+ - Pansear: 2 time(s)
+ - Panpour: 2 time(s)
+ - Munna: 2 time(s)
+ - Pidove: 4 time(s)
+ - Blitzle: 2 time(s)
+ - Roggenrola: 3 time(s)
+ - Woobat: 2 time(s)
+ - Drilbur: 2 time(s)
+ - Audino: 1 time(s)
+ - Timburr: 3 time(s)
+ - Tympole: 3 time(s)
+ - Throh: 1 time(s)
+ - Sawk: 1 time(s)
+ - Sewaddle: 3 time(s)
+ - Venipede: 3 time(s)
+ - Cottonee: 2 time(s)
+ - Basculin (Blue-Striped Form): 1 time(s)
+ - Basculin (Red-Striped Form): 1 time(s)
+ - Basculin (White-striped Form): 1 time(s)
+ - Sandile: 3 time(s)
+ - Darumaka: 2 time(s)
+ - Darmanitan (Galarian Standard Mode): 1 time(s)
+ - Maractus: 1 time(s)
+ - Dwebble: 2 time(s)
+ - Scraggy: 2 time(s)
+ - Sigilyph: 1 time(s)
+ - Yamask: 2 time(s)
+ - Tirtouga: 2 time(s)
+ - Archen: 2 time(s)
+ - Trubbish: 2 time(s)
+ - Zorua: 2 time(s)
+ - Minccino: 2 time(s)
+ - Gothita: 3 time(s)
+ - Ducklett: 2 time(s)
+ - Vanillite: 3 time(s)
+ - Deerling (Spring Form): 2 time(s)
+ - Emolga: 1 time(s)
+ - Karrablast: 2 time(s)
+ - Foongus: 2 time(s)
+ - Frillish (Female): 2 time(s)
+ - Frillish (Male): 2 time(s)
+ - Alomomola: 1 time(s)
+ - Joltik: 2 time(s)
+ - Ferroseed: 2 time(s)
+ - Klink: 3 time(s)
+ - Tynamo: 3 time(s)
+ - Elgyem: 2 time(s)
+ - Litwick: 3 time(s)
+ - Axew: 3 time(s)
+ - Cubchoo: 2 time(s)
+ - Cryogonal: 1 time(s)
+ - Shelmet: 2 time(s)
+ - Stunfisk: 1 time(s)
+ - Mienfoo: 2 time(s)
+ - Druddigon: 1 time(s)
+ - Golett: 2 time(s)
+ - Pawniard: 2 time(s)
+ - Bouffalant: 1 time(s)
+ - Vullaby: 2 time(s)
+ - Heatmor: 1 time(s)
+ - Durant: 1 time(s)
+ - Deino: 3 time(s)
+ - Larvesta: 2 time(s)
+ - Cobalion: 1 time(s)
+ - Terrakion: 1 time(s)
+ - Virizion: 1 time(s)
+ - Zekrom: 1 time(s)
+ - Kyurem: 1 time(s)
+ - Keldeo (Ordinary Forme): 1 time(s)
+ - Meloetta (Aria Forme): 1 time(s)
+ - Genesect: 1 time(s)
+ Evolve:
+ - Eevee (Female) into Sylveon
+ - Eevee (Female) into Leafeon
+ - Eevee (Female) into Glaceon
+ - Murkrow (Male) into Honchkrow
+ - Sneasel (Female) into Weavile (Female)
+ - Piloswine (Female) into Mamoswine (Female)
+ - Lickitung into Lickilicky
+ - Aipom (Male) into Ambipom (Male)
+ - Piloswine (Male) into Mamoswine (Male)
+ - Tangela into Tangrowth (Female)
+ - Tangela into Tangrowth (Male)
+ - Magneton into Magnezone
+ - Sneasel (Male) into Weavile (Male)
+ - Yanma into Yanmega
+ - Gligar (Female) into Gliscor
+ - Aipom (Female) into Ambipom (Female)
+ - Lotad into Lombre
+ - Lotad into Lombre
+ - Lotad into Lombre
+ - Lombre into Ludicolo (Female)
+ - Lombre into Ludicolo (Male)
+ - Seedot into Nuzleaf (Female)
+ - Seedot into Nuzleaf (Male)
+ - Seedot into Nuzleaf (Female)
+ - Seedot into Nuzleaf (Male)
+ - Nuzleaf (Female) into Shiftry (Female)
+ - Nuzleaf (Male) into Shiftry (Male)
+ - Taillow into Swellow
+ - Wingull into Pelipper
+ - Surskit into Masquerain
+ - Shroomish into Breloom
+ - Slakoth into Vigoroth
+ - Slakoth into Vigoroth
+ - Vigoroth into Slaking
+ - Makuhita into Hariyama
+ - Nosepass into Probopass
+ - Aron into Lairon
+ - Aron into Lairon
+ - Lairon into Aggron
+ - Meditite (Female) into Medicham (Female)
+ - Meditite (Male) into Medicham (Male)
+ - Electrike into Manectric
+ - Roselia (Female) into Roserade (Female)
+ - Roselia (Male) into Roserade (Male)
+ - Gulpin (Female) into Swalot (Female)
+ - Gulpin (Male) into Swalot (Male)
+ - Carvanha into Sharpedo
+ - Wailmer into Wailord
+ - Spoink into Grumpig
+ - Trapinch into Vibrava
+ - Trapinch into Vibrava
+ - Vibrava into Flygon
+ - Cacnea into Cacturne (Male)
+ - Cacnea into Cacturne (Female)
+ - Swablu into Altaria
+ - Barboach into Whiscash
+ - Corphish into Crawdaunt
+ - Baltoy into Claydol
+ - Lileep into Cradily
+ - Anorith into Armaldo
+ - Feebas into Milotic (Male)
+ - Feebas into Milotic (Female)
+ - Shuppet into Banette
+ - Spheal into Sealeo
+ - Spheal into Sealeo
+ - Sealeo into Walrein
+ - Clamperl into Gorebyss
+ - Clamperl into Huntail
+ - Bagon into Shelgon
+ - Bagon into Shelgon
+ - Shelgon into Salamence
+ - Beldum into Metang
+ - Beldum into Metang
+ - Metang into Metagross
+ - Turtwig into Grotle
+ - Turtwig into Grotle
+ - Grotle into Torterra
+ - Chimchar into Monferno
+ - Chimchar into Monferno
+ - Monferno into Infernape
+ - Piplup into Prinplup
+ - Piplup into Prinplup
+ - Prinplup into Empoleon
+ - Bidoof (Female) into Bibarel (Female)
+ - Bidoof (Male) into Bibarel (Male)
+ - Cranidos into Rampardos
+ - Shieldon into Bastiodon
+ - Combee (Female) into Vespiquen
+ - Buizel (Female) into Floatzel (Female)
+ - Buizel (Male) into Floatzel (Male)
+ - Drifloon into Drifblim
+ - Buneary into Lopunny
+ - Stunky into Skuntank
+ - Bronzor into Bronzong
+ - Gible (Female) into Gabite (Female)
+ - Gible (Female) into Gabite (Female)
+ - Gabite (Female) into Garchomp (Female)
+ - Gible (Male) into Gabite (Male)
+ - Gible (Male) into Gabite (Male)
+ - Gabite (Male) into Garchomp (Male)
+ - Hippopotas (Female) into Hippowdon (Female)
+ - Hippopotas (Male) into Hippowdon (Male)
+ - Skorupi into Drapion
+ - Croagunk (Female) into Toxicroak (Female)
+ - Croagunk (Male) into Toxicroak (Male)
+ - Finneon (Female) into Lumineon (Female)
+ - Finneon (Male) into Lumineon (Male)
+ - Snivy into Servine
+ - Snivy into Servine
+ - Servine into Serperior
+ - Tepig into Pignite
+ - Tepig into Pignite
+ - Pignite into Emboar
+ - Oshawott into Dewott
+ - Oshawott into Dewott
+ - Dewott into Samurott
+ - Patrat into Watchog
+ - Lillipup into Herdier
+ - Lillipup into Herdier
+ - Herdier into Stoutland
+ - Purrloin into Liepard
+ - Pansage into Simisage
+ - Pansear into Simisear
+ - Panpour into Simipour
+ - Munna into Musharna
+ - Pidove into Tranquill
+ - Pidove into Tranquill
+ - Pidove into Tranquill
+ - Tranquill into Unfezant (Female)
+ - Tranquill into Unfezant (Male)
+ - Blitzle into Zebstrika
+ - Roggenrola into Boldore
+ - Roggenrola into Boldore
+ - Boldore into Gigalith
+ - Woobat into Swoobat
+ - Drilbur into Excadrill
+ - Timburr into Gurdurr
+ - Timburr into Gurdurr
+ - Gurdurr into Conkeldurr
+ - Tympole into Palpitoad
+ - Tympole into Palpitoad
+ - Palpitoad into Seismitoad
+ - Sewaddle into Swadloon
+ - Sewaddle into Swadloon
+ - Swadloon into Leavanny
+ - Venipede into Whirlipede
+ - Venipede into Whirlipede
+ - Whirlipede into Scolipede
+ - Cottonee into Whimsicott
+ - Sandile into Krokorok
+ - Sandile into Krokorok
+ - Krokorok into Krookodile
+ - Darumaka into Darmanitan (Standard Mode)
+ - Dwebble into Crustle
+ - Scraggy into Scrafty
+ - Yamask into Cofagrigus
+ - Tirtouga into Carracosta
+ - Archen into Archeops
+ - Trubbish into Garbodor
+ - Zorua into Zoroark
+ - Minccino into Cinccino
+ - Gothita into Gothorita
+ - Gothita into Gothorita
+ - Gothorita into Gothitelle
+ - Ducklett into Swanna
+ - Vanillite into Vanillish
+ - Vanillite into Vanillish
+ - Vanillish into Vanilluxe
+ - Deerling (Spring Form) into Sawsbuck (Spring Form)
+ - Karrablast into Escavalier
+ - Foongus into Amoonguss
+ - Frillish (Female) into Jellicent (Female)
+ - Frillish (Male) into Jellicent (Male)
+ - Joltik into Galvantula
+ - Ferroseed into Ferrothorn
+ - Klink into Klang
+ - Klink into Klang
+ - Klang into Klinklang
+ - Tynamo into Eelektrik
+ - Tynamo into Eelektrik
+ - Eelektrik into Eelektross
+ - Elgyem into Beheeyem
+ - Litwick into Lampent
+ - Litwick into Lampent
+ - Lampent into Chandelure
+ - Axew into Fraxure
+ - Axew into Fraxure
+ - Fraxure into Haxorus
+ - Cubchoo into Beartic
+ - Shelmet into Accelgor
+ - Mienfoo into Mienshao
+ - Golett into Golurk
+ - Pawniard into Bisharp
+ - Vullaby into Mandibuzz
+ - Deino into Zweilous
+ - Deino into Zweilous
+ - Zweilous into Hydreigon
+ - Larvesta into Volcarona
+ Breed:
+ - Roselia (Male) to get Budew
+ - Roselia (Female) to get Budew
+ - Lucario to get Riolu
+Play White 2:
+ Catch:
+ - Skitty: 2 time(s)
+ - Minun: 1 time(s)
+ - Numel (Female): 2 time(s)
+ - Numel (Male): 2 time(s)
+ - Latias: 1 time(s)
+ - Glameow: 2 time(s)
+ - Mime Jr.: 1 time(s)
+ - Petilil: 2 time(s)
+ - Solosis: 3 time(s)
+ - Rufflet: 2 time(s)
+ - Reshiram: 1 time(s)
+ Evolve:
+ - Skitty into Delcatty
+ - Numel (Female) into Camerupt (Female)
+ - Numel (Male) into Camerupt (Male)
+ - Glameow into Purugly
+ - Petilil into Lilligant
+ - Solosis into Duosion
+ - Solosis into Duosion
+ - Duosion into Reuniclus
+ - Rufflet into Braviary
+Play Diamond:
+ Catch:
+ - Rhydon (Female): 1 time(s)
+ - Rhydon (Male): 1 time(s)
+ - Poochyena: 2 time(s)
+ - Zigzagoon: 2 time(s)
+ - Wurmple: 7 time(s)
+ - Ralts: 4 time(s)
+ - Nincada: 2 time(s)
+ - Whismur: 3 time(s)
+ - Sableye: 1 time(s)
+ - Mawile: 1 time(s)
+ - Torkoal: 1 time(s)
+ - Spinda: 1 time(s)
+ - Duskull: 3 time(s)
+ - Chimecho: 1 time(s)
+ - Snorunt: 3 time(s)
+ - Starly (Female): 3 time(s)
+ - Starly (Male): 3 time(s)
+ - Kricketot (Female): 2 time(s)
+ - Kricketot (Male): 2 time(s)
+ - Shinx (Female): 3 time(s)
+ - Shinx (Male): 3 time(s)
+ - Burmy (Plant Cloak): 3 time(s)
+ - Cherubi: 2 time(s)
+ - Shellos (East Sea): 1 time(s)
+ - Shellos (West Sea): 2 time(s)
+ - Gastrodon (East Sea): 1 time(s)
+ - Chingling: 1 time(s)
+ - Spiritomb: 1 time(s)
+ - Snover (Female): 2 time(s)
+ - Snover (Male): 2 time(s)
+ - Rotom: 1 time(s)
+ - Dialga: 1 time(s)
+ - Giratina (Altered Forme): 1 time(s)
+ - Phione: 1 time(s)
+ - Darkrai: 1 time(s)
+ - Shaymin (Land Forme): 1 time(s)
+ - Arceus (Normal): 1 time(s)
+ Evolve:
+ - Rhydon (Female) into Rhyperior (Female)
+ - Rhydon (Male) into Rhyperior (Male)
+ - Poochyena into Mightyena
+ - Zigzagoon into Linoone
+ - Wurmple into Silcoon
+ - Wurmple into Silcoon
+ - Wurmple into Silcoon
+ - Wurmple into Cascoon
+ - Wurmple into Cascoon
+ - Wurmple into Cascoon
+ - Silcoon into Beautifly (Male)
+ - Silcoon into Beautifly (Female)
+ - Cascoon into Dustox (Male)
+ - Cascoon into Dustox (Female)
+ - Ralts into Kirlia
+ - Ralts into Kirlia
+ - Ralts into Kirlia
+ - Kirlia into Gardevoir
+ - Kirlia into Gallade
+ - Nincada into Ninjask
+ - Whismur into Loudred
+ - Whismur into Loudred
+ - Loudred into Exploud
+ - Duskull into Dusclops
+ - Duskull into Dusclops
+ - Dusclops into Dusknoir
+ - Snorunt into Froslass
+ - Snorunt into Glalie
+ - Starly (Female) into Staravia (Female)
+ - Starly (Female) into Staravia (Female)
+ - Staravia (Female) into Staraptor (Female)
+ - Starly (Male) into Staravia (Male)
+ - Starly (Male) into Staravia (Male)
+ - Staravia (Male) into Staraptor (Male)
+ - Kricketot (Female) into Kricketune (Female)
+ - Kricketot (Male) into Kricketune (Male)
+ - Shinx (Female) into Luxio (Female)
+ - Shinx (Female) into Luxio (Female)
+ - Luxio (Female) into Luxray (Female)
+ - Shinx (Male) into Luxio (Male)
+ - Shinx (Male) into Luxio (Male)
+ - Luxio (Male) into Luxray (Male)
+ - Burmy (Plant Cloak) into Wormadam (Plant Cloak)
+ - Burmy (Plant Cloak) into Mothim
+ - Cherubi into Cherrim (Overcast Form)
+ - Shellos (West Sea) into Gastrodon (West Sea)
+ - Snover (Female) into Abomasnow (Female)
+ - Snover (Male) into Abomasnow (Male)
+ Breed:
+ - Chimecho to get Chingling
+ - Manaphy to get Phione
+Play Pearl:
+ Catch:
+ - Misdreavus: 1 time(s)
+ - Palkia: 1 time(s)
+ Evolve:
+ - Misdreavus into Mismagius
+Play Platinum:
+ Catch:
+ - Magmar: 1 time(s)
+ - Electabuzz: 1 time(s)
+ - Giratina (Origin Forme): 1 time(s)
+ Evolve:
+ - Magmar into Magmortar
+ - Electabuzz into Electivire
+Play HeartGold:
+ Catch:
+ - Treecko: 3 time(s)
+ - Torchic (Female): 3 time(s)
+ - Torchic (Male): 3 time(s)
+ - Mudkip: 3 time(s)
+ - Kyogre: 1 time(s)
+ - Rayquaza: 1 time(s)
+ Evolve:
+ - Treecko into Grovyle
+ - Treecko into Grovyle
+ - Grovyle into Sceptile
+ - Torchic (Female) into Combusken (Female)
+ - Torchic (Female) into Combusken (Female)
+ - Combusken (Female) into Blaziken (Female)
+ - Torchic (Male) into Combusken (Male)
+ - Torchic (Male) into Combusken (Male)
+ - Combusken (Male) into Blaziken (Male)
+ - Mudkip into Marshtomp
+ - Mudkip into Marshtomp
+ - Marshtomp into Swampert
+Play SoulSilver:
+ Catch:
+ - Groudon: 1 time(s)
+Play Omega Ruby:
+ Catch:
+ - Jirachi: 1 time(s)
+ - Deoxys (Normal Forme): 1 time(s)
+ - Victini: 1 time(s)
+ - Tornadus (Incarnate Forme): 1 time(s)
+ - Landorus (Incarnate Forme): 1 time(s)
+ - Greninja: 1 time(s)
+ - Binacle: 2 time(s)
+ - Skrelp: 2 time(s)
+ - Tyrunt: 2 time(s)
+ - Amaura: 2 time(s)
+ - Klefki: 1 time(s)
+ - Phantump: 2 time(s)
+ - Diancie: 1 time(s)
+ - Hoopa (Hoopa Confined): 1 time(s)
+ - Volcanion: 1 time(s)
+ Evolve:
+ - Binacle into Barbaracle
+ - Skrelp into Dragalge
+ - Tyrunt into Tyrantrum
+ - Amaura into Aurorus
+ - Phantump into Trevenant
+Play Alpha Sapphire:
+ Catch:
+ - Thundurus (Incarnate Forme): 1 time(s)
+ - Clauncher: 2 time(s)
+ Evolve:
+ - Clauncher into Clawitzer
+Play X:
+ Catch:
+ - Rotom (Fan Rotom): 1 time(s)
+ - Rotom (Frost Rotom): 1 time(s)
+ - Rotom (Heat Rotom): 1 time(s)
+ - Rotom (Mow Rotom): 1 time(s)
+ - Rotom (Wash Rotom): 1 time(s)
+ - Chespin: 3 time(s)
+ - Fennekin: 3 time(s)
+ - Froakie: 3 time(s)
+ - Bunnelby: 2 time(s)
+ - Fletchling: 3 time(s)
+ - Scatterbug: 3 time(s)
+ - Vivillon (Fancy Pattern): 1 time(s)
+ - Litleo: 3 time(s)
+ - Flabébé (Blue Flower): 1 time(s)
+ - Flabébé (Orange Flower): 1 time(s)
+ - Flabébé (White Flower): 1 time(s)
+ - Flabébé (Yellow Flower): 1 time(s)
+ - Skiddo: 2 time(s)
+ - Furfrou (Natural Form): 1 time(s)
+ - Honedge: 3 time(s)
+ - Carbink: 1 time(s)
+ - Goomy: 3 time(s)
+ - Pumpkaboo (Average Size): 2 time(s)
+ - Pumpkaboo (Large Size): 1 time(s)
+ - Pumpkaboo (Small Size): 2 time(s)
+ - Pumpkaboo (Super Size): 2 time(s)
+ - Xerneas (Neutral Mode): 1 time(s)
+ - Zygarde (10% Forme): 1 time(s)
+ - Zygarde (50% Forme): 1 time(s)
+ Evolve:
+ - Chespin into Quilladin
+ - Chespin into Quilladin
+ - Quilladin into Chesnaught
+ - Fennekin into Braixen
+ - Fennekin into Braixen
+ - Braixen into Delphox
+ - Froakie into Frogadier
+ - Froakie into Frogadier
+ - Frogadier into Greninja
+ - Bunnelby into Diggersby
+ - Fletchling into Fletchinder
+ - Fletchling into Fletchinder
+ - Fletchinder into Talonflame
+ - Scatterbug into Spewpa
+ - Scatterbug into Spewpa
+ - Spewpa into Vivillon (Meadow Pattern)
+ - Litleo into Pyroar (Male)
+ - Litleo into Pyroar (Female)
+ - Skiddo into Gogoat
+ - Honedge into Doublade
+ - Honedge into Doublade
+ - Doublade into Aegislash (Shield Forme)
+ - Goomy into Sliggoo
+ - Goomy into Sliggoo
+ - Sliggoo into Goodra
+ - Pumpkaboo (Average Size) into Gourgeist (Average Size)
+ - Pumpkaboo (Small Size) into Gourgeist (Small Size)
+ - Pumpkaboo (Super Size) into Gourgeist (Super Size)
+Play Y:
+ Catch:
+ - Yveltal: 1 time(s)
+Play Ultra Sun:
+ Catch:
+ - Rowlet: 3 time(s)
+ - Litten: 3 time(s)
+ - Popplio: 3 time(s)
+ - Pikipek: 3 time(s)
+ - Yungoos: 2 time(s)
+ - Grubbin: 3 time(s)
+ - Crabrawler: 2 time(s)
+ - Oricorio (Baile Style): 1 time(s)
+ - Oricorio (Pa'u Style): 1 time(s)
+ - Oricorio (Pom-Pom Style): 1 time(s)
+ - Oricorio (Sensu Style): 1 time(s)
+ - Cutiefly: 2 time(s)
+ - Rockruff: 2 time(s)
+ - Lycanroc (Midnight Form): 1 time(s)
+ - Wishiwashi (Solo Form): 1 time(s)
+ - Mareanie: 2 time(s)
+ - Mudbray: 2 time(s)
+ - Dewpider: 2 time(s)
+ - Fomantis: 2 time(s)
+ - Morelull: 2 time(s)
+ - Salandit: 2 time(s)
+ - Stufful: 2 time(s)
+ - Bounsweet: 3 time(s)
+ - Comfey: 1 time(s)
+ - Passimian: 1 time(s)
+ - Wimpod: 2 time(s)
+ - Sandygast: 2 time(s)
+ - Pyukumuku: 1 time(s)
+ - Type: Null: 2 time(s)
+ - Minior (Blue Core): 1 time(s)
+ - Minior (Green Core): 1 time(s)
+ - Minior (Indigo Core): 1 time(s)
+ - Minior (Meteor Form): 1 time(s)
+ - Minior (Orange Core): 1 time(s)
+ - Minior (Red Core): 1 time(s)
+ - Minior (Violet Core): 1 time(s)
+ - Minior (Yellow Core): 1 time(s)
+ - Komala: 1 time(s)
+ - Turtonator: 1 time(s)
+ - Togedemaru: 1 time(s)
+ - Mimikyu: 1 time(s)
+ - Bruxish: 1 time(s)
+ - Dhelmise: 1 time(s)
+ - Jangmo-o: 3 time(s)
+ - Tapu Koko: 1 time(s)
+ - Tapu Lele: 1 time(s)
+ - Tapu Bulu: 1 time(s)
+ - Tapu Fini: 1 time(s)
+ - Cosmog: 4 time(s)
+ - Nihilego: 1 time(s)
+ - Buzzwole: 1 time(s)
+ - Xurkitree: 1 time(s)
+ - Kartana: 1 time(s)
+ - Guzzlord: 1 time(s)
+ - Necrozma: 1 time(s)
+ - Magearna: 1 time(s)
+ - Poipole: 2 time(s)
+ - Blacephalon: 1 time(s)
+ - Zeraora: 1 time(s)
+ Evolve:
+ - Rowlet into Dartrix
+ - Rowlet into Dartrix
+ - Dartrix into Decidueye
+ - Litten into Torracat
+ - Litten into Torracat
+ - Torracat into Incineroar
+ - Popplio into Brionne
+ - Popplio into Brionne
+ - Brionne into Primarina
+ - Pikipek into Trumbeak
+ - Pikipek into Trumbeak
+ - Trumbeak into Toucannon
+ - Yungoos into Gumshoos
+ - Grubbin into Charjabug
+ - Grubbin into Charjabug
+ - Charjabug into Vikavolt
+ - Crabrawler into Crabominable
+ - Cutiefly into Ribombee
+ - Rockruff into Lycanroc (Midday Form)
+ - Mareanie into Toxapex
+ - Mudbray into Mudsdale
+ - Dewpider into Araquanid
+ - Fomantis into Lurantis
+ - Morelull into Shiinotic
+ - Salandit into Salazzle
+ - Stufful into Bewear
+ - Bounsweet into Steenee
+ - Bounsweet into Steenee
+ - Steenee into Tsareena
+ - Wimpod into Golisopod
+ - Sandygast into Palossand
+ - Type: Null into Silvally (Type: Normal)
+ - Jangmo-o into Hakamo-o
+ - Jangmo-o into Hakamo-o
+ - Hakamo-o into Kommo-o
+ - Cosmog into Cosmoem
+ - Cosmog into Cosmoem
+ - Cosmog into Cosmoem
+ - Cosmoem into Lunala
+ - Cosmoem into Solgaleo
+ - Poipole into Naganadel
+Play Ultra Moon:
+ Catch:
+ - Oranguru: 1 time(s)
+ - Drampa: 1 time(s)
+ - Pheromosa: 1 time(s)
+ - Celesteela: 1 time(s)
+ - Stakataka: 1 time(s)
+Play Sun:
+ Catch:
+ - Marshadow: 1 time(s)
+Play Sword:
+ Catch:
+ - Sneasel (Female): 1 time(s)
+ - Basculin (Red-Striped Form): 2 time(s)
+ - Grookey: 3 time(s)
+ - Scorbunny: 3 time(s)
+ - Sobble: 3 time(s)
+ - Skwovet: 2 time(s)
+ - Rookidee: 3 time(s)
+ - Blipbug: 3 time(s)
+ - Nickit: 2 time(s)
+ - Gossifleur: 2 time(s)
+ - Wooloo: 2 time(s)
+ - Chewtle: 2 time(s)
+ - Yamper: 2 time(s)
+ - Rolycoly: 3 time(s)
+ - Applin: 3 time(s)
+ - Silicobra: 2 time(s)
+ - Cramorant: 1 time(s)
+ - Arrokuda: 2 time(s)
+ - Toxel: 2 time(s)
+ - Sizzlipede: 2 time(s)
+ - Clobbopus: 2 time(s)
+ - Sinistea: 2 time(s)
+ - Hatenna: 3 time(s)
+ - Impidimp: 3 time(s)
+ - Obstagoon: 1 time(s)
+ - Perrserker: 1 time(s)
+ - Sirfetch'd: 1 time(s)
+ - Mr. Rime: 1 time(s)
+ - Runerigus: 1 time(s)
+ - Milcery: 2 time(s)
+ - Alcremie (Caramel SwirlClover Sweet): 1 time(s)
+ - Alcremie (Caramel SwirlFlower Sweet): 1 time(s)
+ - Alcremie (Caramel SwirlLove Sweet): 1 time(s)
+ - Alcremie (Caramel SwirlRibbon Sweet): 1 time(s)
+ - Alcremie (Caramel SwirlStar Sweet): 1 time(s)
+ - Alcremie (Caramel SwirlStrawberry Sweet): 1 time(s)
+ - Alcremie (Gigantamax): 1 time(s)
+ - Alcremie (Lemon CreamBerry Sweet): 1 time(s)
+ - Alcremie (Lemon CreamClover Sweet): 1 time(s)
+ - Alcremie (Lemon CreamFlower Sweet): 1 time(s)
+ - Alcremie (Lemon CreamLove Sweet): 1 time(s)
+ - Alcremie (Lemon CreamRibbon Sweet): 1 time(s)
+ - Alcremie (Lemon CreamStar Sweet): 1 time(s)
+ - Alcremie (Lemon CreamStrawberry Sweet): 1 time(s)
+ - Alcremie (Matcha CreamBerry Sweet): 1 time(s)
+ - Alcremie (Matcha CreamClover Sweet): 1 time(s)
+ - Alcremie (Matcha CreamFlower Sweet): 1 time(s)
+ - Alcremie (Matcha CreamLove Sweet): 1 time(s)
+ - Alcremie (Matcha CreamRibbon Sweet): 1 time(s)
+ - Alcremie (Matcha CreamStar Sweet): 1 time(s)
+ - Alcremie (Matcha CreamStrawberry Sweet): 1 time(s)
+ - Alcremie (Mint CreamBerry Sweet): 1 time(s)
+ - Alcremie (Mint CreamClover Sweet): 1 time(s)
+ - Alcremie (Mint CreamFlower Sweet): 1 time(s)
+ - Alcremie (Mint CreamLove Sweet): 1 time(s)
+ - Alcremie (Mint CreamRibbon Sweet): 1 time(s)
+ - Alcremie (Mint CreamStar Sweet): 1 time(s)
+ - Alcremie (Mint CreamStrawberry Sweet): 1 time(s)
+ - Alcremie (Rainbow SwirlBerry Sweet): 1 time(s)
+ - Alcremie (Rainbow SwirlClover Sweet): 1 time(s)
+ - Alcremie (Rainbow SwirlFlower Sweet): 1 time(s)
+ - Alcremie (Rainbow SwirlLove Sweet): 1 time(s)
+ - Alcremie (Rainbow SwirlRibbon Sweet): 1 time(s)
+ - Alcremie (Rainbow SwirlStar Sweet): 1 time(s)
+ - Alcremie (Rainbow SwirlStrawberry Sweet): 1 time(s)
+ - Alcremie (Ruby CreamBerry Sweet): 1 time(s)
+ - Alcremie (Ruby CreamClover Sweet): 1 time(s)
+ - Alcremie (Ruby CreamFlower Sweet): 1 time(s)
+ - Alcremie (Ruby CreamLove Sweet): 1 time(s)
+ - Alcremie (Ruby CreamRibbon Sweet): 1 time(s)
+ - Alcremie (Ruby CreamStar Sweet): 1 time(s)
+ - Alcremie (Ruby CreamStrawberry Sweet): 1 time(s)
+ - Alcremie (Ruby SwirlBerry Sweet): 1 time(s)
+ - Alcremie (Ruby SwirlClover Sweet): 1 time(s)
+ - Alcremie (Ruby SwirlFlower Sweet): 1 time(s)
+ - Alcremie (Ruby SwirlLove Sweet): 1 time(s)
+ - Alcremie (Ruby SwirlRibbon Sweet): 1 time(s)
+ - Alcremie (Ruby SwirlStar Sweet): 1 time(s)
+ - Alcremie (Ruby SwirlStrawberry Sweet): 1 time(s)
+ - Alcremie (Salted CreamBerry Sweet): 1 time(s)
+ - Alcremie (Salted CreamClover Sweet): 1 time(s)
+ - Alcremie (Salted CreamFlower Sweet): 1 time(s)
+ - Alcremie (Salted CreamLove Sweet): 1 time(s)
+ - Alcremie (Salted CreamRibbon Sweet): 1 time(s)
+ - Alcremie (Salted CreamStar Sweet): 1 time(s)
+ - Alcremie (Salted CreamStrawberry Sweet): 1 time(s)
+ - Alcremie (Vanilla CreamBerry Sweet): 1 time(s)
+ - Alcremie (Vanilla CreamClover Sweet): 1 time(s)
+ - Alcremie (Vanilla CreamFlower Sweet): 1 time(s)
+ - Alcremie (Vanilla CreamLove Sweet): 1 time(s)
+ - Alcremie (Vanilla CreamRibbon Sweet): 1 time(s)
+ - Alcremie (Vanilla CreamStar Sweet): 1 time(s)
+ - Alcremie (Vanilla CreamStrawberry Sweet): 1 time(s)
+ - Falinks: 1 time(s)
+ - Pincurchin: 1 time(s)
+ - Snom: 2 time(s)
+ - Stonjourner: 1 time(s)
+ - Eiscue (Ice Face): 1 time(s)
+ - Indeedee (Female): 1 time(s)
+ - Indeedee (Male): 1 time(s)
+ - Morpeko (Full Belly Mode): 1 time(s)
+ - Cufant: 2 time(s)
+ - Dracozolt: 1 time(s)
+ - Arctozolt: 1 time(s)
+ - Dracovish: 1 time(s)
+ - Arctovish: 1 time(s)
+ - Duraludon: 1 time(s)
+ - Dreepy: 3 time(s)
+ - Zacian (Hero of Many Battles): 1 time(s)
+ - Eternatus: 1 time(s)
+ - Zarude: 1 time(s)
+ - Zarude (Dada): 1 time(s)
+ Evolve:
+ - Sneasel (Female) into Sneasler
+ - Basculin (Red-Striped Form) into Basculegion (Male)
+ - Basculin (Red-Striped Form) into Basculegion (Female)
+ - Grookey into Thwackey
+ - Grookey into Thwackey
+ - Thwackey into Rillaboom
+ - Scorbunny into Raboot
+ - Scorbunny into Raboot
+ - Raboot into Cinderace
+ - Sobble into Drizzile
+ - Sobble into Drizzile
+ - Drizzile into Inteleon
+ - Skwovet into Greedent
+ - Rookidee into Corvisquire
+ - Rookidee into Corvisquire
+ - Corvisquire into Corviknight
+ - Blipbug into Dottler
+ - Blipbug into Dottler
+ - Dottler into Orbeetle
+ - Nickit into Thievul
+ - Gossifleur into Eldegoss
+ - Wooloo into Dubwool
+ - Chewtle into Drednaw
+ - Yamper into Boltund
+ - Rolycoly into Carkol
+ - Rolycoly into Carkol
+ - Carkol into Coalossal
+ - Applin into Flapple
+ - Applin into Appletun
+ - Silicobra into Sandaconda
+ - Arrokuda into Barraskewda
+ - Toxel into Toxtricity (Amped Form)
+ - Sizzlipede into Centiskorch
+ - Clobbopus into Grapploct
+ - Sinistea into Polteageist
+ - Hatenna into Hattrem
+ - Hatenna into Hattrem
+ - Hattrem into Hatterene
+ - Impidimp into Morgrem
+ - Impidimp into Morgrem
+ - Morgrem into Grimmsnarl
+ - Milcery into Alcremie (Caramel SwirlBerry Sweet)
+ - Snom into Frosmoth
+ - Cufant into Copperajah
+ - Dreepy into Drakloak
+ - Dreepy into Drakloak
+ - Drakloak into Dragapult
+Play Shield:
+ Catch:
+ - Cursola: 1 time(s)
+ - Zamazenta (Hero of Many Battles): 1 time(s)
+Play Expansion Pass:
+ Catch:
+ - Scyther (Male): 1 time(s)
+ - Kubfu: 2 time(s)
+ - Regieleki: 1 time(s)
+ - Regidrago: 1 time(s)
+ - Glastrier: 1 time(s)
+ - Spectrier: 1 time(s)
+ - Calyrex: 1 time(s)
+ Evolve:
+ - Scyther (Male) into Kleavor
+ - Kubfu into Urshifu (Single Strike Style)
+Play Legends Arceus:
+ Catch:
+ - Ursaring (Female): 1 time(s)
+ - Stantler: 1 time(s)
+ - Overqwil: 1 time(s)
+ - Enamorus (Incarnate Forme): 1 time(s)
+ Evolve:
+ - Ursaring (Female) into Ursaluna
+ - Stantler into Wyrdeer
+Play Scarlet:
+ Catch:
+ - Dunsparce: 1 time(s)
+ - Applin: 3 time(s)
+ - Girafarig (Male): 1 time(s)
+ - Bisharp: 1 time(s)
+ - Primeape: 1 time(s)
+ - Sprigatito: 3 time(s)
+ - Fuecoco: 3 time(s)
+ - Quaxly: 3 time(s)
+ - Lechonk: 3 time(s)
+ - Tarountula: 2 time(s)
+ - Nymble: 2 time(s)
+ - Pawmi: 3 time(s)
+ - Tandemaus: 2 time(s)
+ - Maushold (Family of Three): 1 time(s)
+ - Fidough: 2 time(s)
+ - Smoliv: 3 time(s)
+ - Squawkabilly (Blue Plumage): 1 time(s)
+ - Squawkabilly (Green Plumage): 1 time(s)
+ - Squawkabilly (White Plumage): 1 time(s)
+ - Squawkabilly (Yellow Plumage): 1 time(s)
+ - Nacli: 3 time(s)
+ - Charcadet: 3 time(s)
+ - Tadbulb: 2 time(s)
+ - Wattrel: 2 time(s)
+ - Maschiff: 2 time(s)
+ - Shroodle: 2 time(s)
+ - Bramblin: 2 time(s)
+ - Toedscool: 2 time(s)
+ - Klawf: 1 time(s)
+ - Capsakid: 2 time(s)
+ - Rellor: 2 time(s)
+ - Flittle: 2 time(s)
+ - Tinkatink: 3 time(s)
+ - Wiglett: 2 time(s)
+ - Bombirdier: 1 time(s)
+ - Finizen: 2 time(s)
+ - Palafin (Zero Form): 1 time(s)
+ - Varoom: 2 time(s)
+ - Cyclizar: 1 time(s)
+ - Orthworm: 1 time(s)
+ - Glimmet: 2 time(s)
+ - Greavard: 2 time(s)
+ - Flamigo: 1 time(s)
+ - Cetoddle: 2 time(s)
+ - Veluza: 1 time(s)
+ - Dondozo: 1 time(s)
+ - Tatsugiri (Curly Form): 1 time(s)
+ - Tatsugiri (Droopy Form): 1 time(s)
+ - Tatsugiri (Stretchy Form): 1 time(s)
+ - Clodsire: 1 time(s)
+ - Dudunsparce (Three-Segment Form): 1 time(s)
+ - Great Tusk: 1 time(s)
+ - Scream Tail: 1 time(s)
+ - Brute Bonnet: 1 time(s)
+ - Flutter Mane: 1 time(s)
+ - Slither Wing: 1 time(s)
+ - Sandy Shocks: 1 time(s)
+ - Frigibax: 3 time(s)
+ - Gimmighoul (Chest Form): 2 time(s)
+ - Gimmighoul (Roaming Form): 1 time(s)
+ - Wo-Chien: 1 time(s)
+ - Chien-Pao: 1 time(s)
+ - Ting-Lu: 1 time(s)
+ - Chi-Yu: 1 time(s)
+ - Roaring Moon: 1 time(s)
+ - Koraidon: 1 time(s)
+ - Walking Wake: 1 time(s)
+ - Iron Leaves: 1 time(s)
+ Evolve:
+ - Dunsparce into Dudunsparce (Two-Segment Form)
+ - Applin into Dipplin
+ - Dipplin into Hydrapple
+ - Girafarig (Male) into Farigiraf
+ - Bisharp into Kingambit
+ - Primeape into Annihilape
+ - Sprigatito into Floragato
+ - Sprigatito into Floragato
+ - Floragato into Meowscarada
+ - Fuecoco into Crocalor
+ - Fuecoco into Crocalor
+ - Crocalor into Skeledirge
+ - Quaxly into Quaxwell
+ - Quaxly into Quaxwell
+ - Quaxwell into Quaquaval
+ - Lechonk into Oinkologne (Male)
+ - Lechonk into Oinkologne (Female)
+ - Tarountula into Spidops
+ - Nymble into Lokix
+ - Pawmi into Pawmo
+ - Pawmi into Pawmo
+ - Pawmo into Pawmot
+ - Tandemaus into Maushold (Family of Four)
+ - Fidough into Dachsbun
+ - Smoliv into Dolliv
+ - Smoliv into Dolliv
+ - Dolliv into Arboliva
+ - Nacli into Naclstack
+ - Nacli into Naclstack
+ - Naclstack into Garganacl
+ - Charcadet into Ceruledge
+ - Charcadet into Armarouge
+ - Tadbulb into Bellibolt
+ - Wattrel into Kilowattrel
+ - Maschiff into Mabosstiff
+ - Shroodle into Grafaiai
+ - Bramblin into Brambleghast
+ - Toedscool into Toedscruel
+ - Capsakid into Scovillain
+ - Rellor into Rabsca
+ - Flittle into Espathra
+ - Tinkatink into Tinkatuff
+ - Tinkatink into Tinkatuff
+ - Tinkatuff into Tinkaton
+ - Wiglett into Wugtrio
+ - Finizen into Palafin (Hero Form)
+ - Varoom into Revavroom
+ - Glimmet into Glimmora
+ - Greavard into Houndstone
+ - Cetoddle into Cetitan
+ - Frigibax into Arctibax
+ - Frigibax into Arctibax
+ - Arctibax into Baxcalibur
+ - Gimmighoul (Chest Form) into Gholdengo
+Play Violet:
+ Catch:
+ - Iron Treads: 1 time(s)
+ - Iron Bundle: 1 time(s)
+ - Iron Hands: 1 time(s)
+ - Iron Jugulis: 1 time(s)
+ - Iron Moth: 1 time(s)
+ - Iron Thorns: 1 time(s)
+ - Iron Valiant: 1 time(s)
+ - Miraidon: 1 time(s)
+Play The Hidden Treasure of Area Zero:
+ Catch:
+ - Duraludon: 1 time(s)
+ - Poltchageist: 1 time(s)
+ - Sinistcha: 1 time(s)
+ - Okidogi: 1 time(s)
+ - Munkidori: 1 time(s)
+ - Fezandipiti: 1 time(s)
+ - Ogerpon (Teal Mask): 1 time(s)
+ - Gouging Fire: 1 time(s)
+ - Raging Bolt: 1 time(s)
+ - Iron Boulder: 1 time(s)
+ - Iron Crown: 1 time(s)
+ - Terapagos (Normal Form): 1 time(s)
+ - Pecharunt: 1 time(s)
+ Evolve:
+ - Duraludon into Archaludon