Skip to content

Commit b8efce0

Browse files
committed
Merge branch 'main' into v0.60
2 parents 157e533 + 70438f4 commit b8efce0

File tree

122 files changed

+4653
-2059
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

122 files changed

+4653
-2059
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,7 @@ __pycache__
6464
vcpkg/
6565

6666
CLAUDE.md
67+
68+
build_*/
69+
.cache/*
70+
Packages/*

Common/Qt/Options/KeyBindingWidget.cpp

Lines changed: 0 additions & 60 deletions
This file was deleted.

Common/Qt/Options/TimeDurationWidget.cpp

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ TimeDurationCellWidget<Type>::TimeDurationCellWidget(QWidget& parent, TimeDurati
3939
));
4040

4141
connect(
42-
this, &QLineEdit::textChanged,
43-
this, [this](const QString& text){
44-
std::string error = m_value.set(text.toStdString());
42+
this, &QLineEdit::editingFinished,
43+
this, [this](){
44+
m_value.set(this->text().toStdString());
4545
}
4646
);
4747

@@ -105,43 +105,47 @@ TimeDurationOptionWidget<Type>::TimeDurationOptionWidget(QWidget& parent, TimeDu
105105
"Wireless controllers have larger tick sizes and are imprecise due to wireless communication latency."
106106
));
107107

108-
QLabel* description = nullptr;
108+
m_description = nullptr;
109109
if (value.show_summary()){
110-
description = new QLabel(QString::fromStdString(m_value.time_string()), this);
111-
description->setAlignment(Qt::AlignHCenter);
112-
row1->addWidget(description);
110+
m_description = new QLabel(QString::fromStdString(m_value.time_string()), this);
111+
m_description->setAlignment(Qt::AlignHCenter);
112+
row1->addWidget(m_description);
113113
}
114114

115115
connect(
116116
m_box, &QLineEdit::editingFinished,
117-
this, [this, description](){
117+
this, [this](){
118118
std::string error = m_value.set(m_box->text().toStdString());
119-
if (description == nullptr){
119+
if (m_description == nullptr){
120120
return;
121121
}
122122
if (error.empty()){
123-
description->setText(QString::fromStdString(m_value.time_string()));
123+
m_description->setText(QString::fromStdString(m_value.time_string()));
124124
}else{
125-
description->setText(QString::fromStdString("<font color=\"red\">" + error + "</font>"));
125+
m_description->setText(QString::fromStdString("<font color=\"red\">" + error + "</font>"));
126126
}
127127
}
128128
);
129+
#if 0
129130
connect(
130131
m_box, &QLineEdit::textChanged,
131-
this, [this, description](){
132-
if (description == nullptr){
132+
this, [this, m_description](){
133+
if (m_description == nullptr){
133134
return;
134135
}
135136
std::string text = m_value.time_string(m_box->text().toStdString());
136-
description->setText(QString::fromStdString(text));
137+
m_description->setText(QString::fromStdString(text));
137138
}
138139
);
140+
#endif
139141

140142
value.add_listener(*this);
141143
}
142144
template <typename Type>
143145
void TimeDurationOptionWidget<Type>::update_value(){
144-
m_box->setText(QString::fromStdString(m_value.current_text()));
146+
std::string text = m_value.current_text();
147+
m_box->setText(QString::fromStdString(text));
148+
m_description->setText(QString::fromStdString(m_value.time_string()));
145149
}
146150
template <typename Type>
147151
void TimeDurationOptionWidget<Type>::on_config_value_changed(void* object){

Common/Qt/Options/TimeDurationWidget.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
#include "Common/Cpp/Options/TimeDurationOption.h"
1212
#include "ConfigWidget.h"
1313

14+
class QLabel;
15+
1416
namespace PokemonAutomation{
1517

1618

@@ -42,6 +44,7 @@ class TimeDurationOptionWidget : public QWidget, public ConfigWidget{
4244
private:
4345
TimeDurationOption<Type>& m_value;
4446
QLineEdit* m_box;
47+
QLabel* m_description;
4548
};
4649

4750

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Convert a Pokemon name txt file to a JSON slug list.
4+
Each line of the txt file is converted to a lowercase slug and validated against
5+
the National Pokedex database.
6+
7+
The pokemon name txt file format is one line per pokemon name.
8+
Its content can be downloaded from a site like Serebii.
9+
"""
10+
11+
import argparse
12+
import json
13+
import re
14+
import unicodedata
15+
from pathlib import Path
16+
17+
18+
def normalize_pokemon_name(name: str) -> str:
19+
"""
20+
Convert a Pokemon name to a slug format.
21+
- Converts to lowercase
22+
- Removes accents/diacritics
23+
- Handles special characters
24+
"""
25+
# Remove accents and normalize unicode characters
26+
# NFD = Canonical Decomposition
27+
nfd = unicodedata.normalize('NFD', name)
28+
# Filter out combining characters (accents)
29+
name_no_accents = ''.join(char for char in nfd if unicodedata.category(char) != 'Mn')
30+
31+
# Convert to lowercase
32+
slug = name_no_accents.lower()
33+
34+
# Handle special cases
35+
# Replace apostrophes with '-d' for Farfetch'd and Sirfetch'd
36+
slug = slug.replace("'d", "-d")
37+
38+
# Replace periods and spaces with hyphens for Mr. Mime, Mime Jr., Mr. Rime
39+
slug = slug.replace(". ", "-") # Handle "Mr. " -> "mr-"
40+
slug = slug.replace(" ", "-") # Handle remaining spaces
41+
slug = slug.rstrip(".") # Remove trailing periods (e.g., "mime-jr." -> "mime-jr")
42+
43+
return slug
44+
45+
46+
def main(input_txt: Path, database_json: Path, output_json: Path):
47+
"""
48+
Convert Pokemon names from txt file to JSON slugs.
49+
50+
Args:
51+
input_txt: Path to input text file with Pokemon names (one per line)
52+
database_json: Path to National Pokedex JSON database for validation
53+
output_json: Path to output JSON file
54+
"""
55+
56+
# Load the National Pokedex database
57+
with open(database_json, 'r', encoding='utf-8') as f:
58+
national_pokedex = json.load(f)
59+
60+
# Convert to set for faster lookup
61+
national_pokedex_set = set(national_pokedex)
62+
63+
# Read the input txt file and convert names
64+
pokemon_slugs = []
65+
not_found = []
66+
67+
with open(input_txt, 'r', encoding='utf-8') as f:
68+
for line_num, line in enumerate(f, 1):
69+
line = line.strip()
70+
if not line:
71+
continue
72+
73+
# Pokemon name is the entire line
74+
pokemon_name = line
75+
76+
# Convert to slug
77+
slug = normalize_pokemon_name(pokemon_name)
78+
79+
# Validate against database
80+
if slug in national_pokedex_set:
81+
pokemon_slugs.append(slug)
82+
print(f"✓ {pokemon_name} -> {slug}")
83+
else:
84+
not_found.append((pokemon_name, slug))
85+
print(f"✗ {pokemon_name} -> {slug} (NOT FOUND in database)")
86+
87+
# Report results
88+
print(f"\n{'='*60}")
89+
print(f"Total Pokemon processed: {len(pokemon_slugs) + len(not_found)}")
90+
print(f"Successfully validated: {len(pokemon_slugs)}")
91+
print(f"Not found in database: {len(not_found)}")
92+
93+
if not_found:
94+
print(f"\nPokemon not found in database:")
95+
for name, slug in not_found:
96+
print(f" - {name} ({slug})")
97+
98+
# Write output JSON
99+
with open(output_json, 'w', encoding='utf-8') as f:
100+
json.dump(pokemon_slugs, f, indent=4, ensure_ascii=False)
101+
102+
print(f"\n✓ Output written to: {output_json}")
103+
print(f" Total entries: {len(pokemon_slugs)}")
104+
105+
106+
if __name__ == "__main__":
107+
parser = argparse.ArgumentParser(
108+
description="Convert Pokemon name txt file to JSON slug list.",
109+
formatter_class=argparse.RawDescriptionHelpFormatter,
110+
epilog="""
111+
Example usage:
112+
%(prog)s input.txt Pokedex-National.json output.json
113+
%(prog)s Pokedex-Lumiose.txt Pokedex-National.json Pokedex-Lumiose.json
114+
"""
115+
)
116+
117+
parser.add_argument(
118+
'input_txt',
119+
type=Path,
120+
help='Input text file with Pokemon names (one per line)'
121+
)
122+
123+
parser.add_argument(
124+
'database_json',
125+
type=Path,
126+
help='National Pokedex JSON database file for slug validation'
127+
)
128+
129+
parser.add_argument(
130+
'output_json',
131+
type=Path,
132+
help='Output JSON file to save the slug list'
133+
)
134+
135+
args = parser.parse_args()
136+
137+
main(args.input_txt, args.database_json, args.output_json)

SerialPrograms/Scripts/check_detector_regions.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,26 @@
3232

3333
raw_image = image.copy()
3434

35+
# ==================================================================
36+
# Home summary screen finish loading detector
37+
add_infer_box_to_image(raw_image, 0.388, 0.238, 0.109, 0.062, image)
38+
39+
# ==================================================================
40+
# LZA Hyperspace Timer detection
41+
# add_infer_box_to_image(raw_image, 0.044, 0.111, 0.060, 0.067, image)
42+
43+
44+
# ==================================================================
45+
# LZA Map detector
46+
# add_infer_box_to_image(raw_image, 0.760730, 0.937023, 0.241416, 0.064885, image)
47+
# add_infer_box_to_image(raw_image, 0.005000, 0.150000, 0.025000, 0.110000, image)
48+
# add_infer_box_to_image(raw_image, 0.005000, 0.210000, 0.025000, 0.110000, image)
3549

3650

3751
# ==================================================================
3852
# LZA alert eye detector
39-
add_infer_box_to_image(raw_image, 0.485, 0.088, 0.029, 0.034, image)
40-
add_infer_box_to_image(raw_image, 0.464, 0.142, 0.071, 0.074, image)
53+
# add_infer_box_to_image(raw_image, 0.485, 0.088, 0.029, 0.034, image)
54+
# add_infer_box_to_image(raw_image, 0.464, 0.142, 0.071, 0.074, image)
4155

4256

4357
# ==================================================================

SerialPrograms/Source/CommonFramework/Main.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "Startup/NewVersionCheck.h"
2929
#include "CommonFramework/VideoPipeline/Backends/CameraImplementations.h"
3030
#include "CommonTools/OCR/OCR_RawOCR.h"
31+
#include "ControllerInput/ControllerInput.h"
3132
#include "Windows/MainWindow.h"
3233

3334
#include <iostream>
@@ -164,7 +165,7 @@ int main(int argc, char *argv[]){
164165
int ret = run_program(argc, argv);
165166

166167

167-
// Write program settings back to the json file.
168+
// Write program settings back to the json file.
168169
PERSISTENT_SETTINGS().write();
169170

170171

@@ -176,7 +177,10 @@ int main(int argc, char *argv[]){
176177
Integration::DppClient::Client::instance().disconnect();
177178
#endif
178179

179-
// Force stop the thread pool
180+
// Stop the controllers.
181+
global_input_stop();
182+
183+
// Force stop the thread pool
180184
PokemonAutomation::GlobalThreadPools::realtime_inference().stop();
181185
PokemonAutomation::GlobalThreadPools::normal_inference().stop();
182186

SerialPrograms/Source/CommonTools/VisualDetectors/FrozenImageDetector.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
*
33
* From: https://github.com/PokemonAutomation/
44
*
5-
* Detect if the entire screen is frozen.
5+
* Detect if the entire screen or a part of it is frozen.
66
*/
77

88
#ifndef PokemonAutomation_CommonTools_FrozenImageDetector_H

0 commit comments

Comments
 (0)