Skip to content

Added level, nature, ability and language to detection and json output in Pokemon HOME sorter #528

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ language
#include "CommonFramework/VideoPipeline/VideoFeed.h"
#include "CommonFramework/ProgramStats/StatsTracking.h"
#include "CommonTools/OCR/OCR_NumberReader.h"
#include "CommonTools/OCR/OCR_RawOCR.h"
#include "NintendoSwitch/Commands/NintendoSwitch_Commands_PushButtons.h"
#include "Pokemon/Pokemon_Strings.h"
#include "PokemonHome/Inference/PokemonHome_BoxGenderDetector.h"
Expand Down Expand Up @@ -172,6 +173,11 @@ struct Pokemon{
std::string ball_slug = "";
StatsHuntGenderFilter gender = StatsHuntGenderFilter::Genderless;
uint32_t ot_id = 0;
uint32_t level = 0;
std::string origin = "";
std::string language = "";
std::string nature = "";
std::string ability = "";
};

bool operator==(const Pokemon& lhs, const Pokemon& rhs){
Expand All @@ -180,7 +186,12 @@ bool operator==(const Pokemon& lhs, const Pokemon& rhs){
lhs.shiny == rhs.shiny &&
lhs.gmax == rhs.gmax &&
lhs.ball_slug == rhs.ball_slug &&
lhs.gender == rhs.gender;
lhs.gender == rhs.gender &&
lhs.level == rhs.level &&
lhs.origin == rhs.origin &&
lhs.language == rhs.language &&
lhs.nature == rhs.nature &&
lhs.ability == rhs.ability;
}

bool operator<(const std::optional<Pokemon>& lhs, const std::optional<Pokemon>& rhs){
Expand Down Expand Up @@ -242,6 +253,11 @@ std::ostream& operator<<(std::ostream& os, const std::optional<Pokemon>& pokemon
os << "ball_slug:" << pokemon->ball_slug << " ";
os << "gender:" << gender_to_string(pokemon->gender) << " ";
os << "ot_id:" << pokemon->ot_id << " ";
os << "level:" << pokemon->level << " ";
os << "language:" << pokemon->language << " ";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try to keep the same order as other locations>

uint32_t level = 0;
std::string origin = "";
std::string language = "";
std::string nature = "";
std::string ability = "";

os << "origin:" << pokemon->origin << " ";
os << "nature:" << pokemon->nature << " ";
os << "ability:" << pokemon->ability << " ";
os << ")";
}else{
os << "(empty)";
Expand Down Expand Up @@ -384,6 +400,11 @@ void output_boxes_data_json(const std::vector<std::optional<Pokemon>>& boxes_dat
pokemon["ball_slug"] = current_pokemon->ball_slug;
pokemon["gender"] = gender_to_string(current_pokemon->gender);
pokemon["ot_id"] = current_pokemon->ot_id;
pokemon["level"] = current_pokemon->level;
pokemon["language"] = current_pokemon->language;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

uint32_t level = 0;
std::string origin = "";
std::string language = "";
std::string nature = "";
std::string ability = "";

pokemon["origin"] = current_pokemon->origin;
pokemon["nature"] = current_pokemon->nature;
pokemon["ability"] = current_pokemon->ability;
}
pokemon_data.push_back(std::move(pokemon));
}
Expand Down Expand Up @@ -466,6 +487,7 @@ void BoxSorting::program(SingleSwitchProgramEnvironment& env, SwitchControllerCo
ImageFloatBox ot_box(0.492, 0.719, 0.165, 0.049); // OT box
ImageFloatBox nature_box(0.157, 0.783, 0.212, 0.042); // Nature box
ImageFloatBox ability_box(0.158, 0.838, 0.213, 0.042); // Ability box
ImageFloatBox language_box(0.030, 0.175, 0.05, 0.035); // Language box


// vector that will store data for each slot
Expand Down Expand Up @@ -604,6 +626,7 @@ void BoxSorting::program(SingleSwitchProgramEnvironment& env, SwitchControllerCo
box_render.add(COLOR_RED, ot_box);
box_render.add(COLOR_RED, nature_box);
box_render.add(COLOR_RED, ability_box);
box_render.add(COLOR_RED, language_box);

//cycle through each summary of the current box and fill pokemon information
for (size_t row = 0; row < MAX_ROWS; row++){
Expand Down Expand Up @@ -642,12 +665,51 @@ void BoxSorting::program(SingleSwitchProgramEnvironment& env, SwitchControllerCo
}
boxes_data[get_index(box_nb, row, column)]->ot_id = ot_id;

// NOTE edit when adding new struct members (detections go here likely)

// level_box
// ot_box
int level = OCR::read_number_waterfill(env.console, extract_box_reference(screen, level_box), 0xff000000, 0xff7f7f7f);
if (level < 0 || level > 100) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<= 0 ?
And have you tried with eggs ? (I forgot what the program does when there is eggsà

dump_image(env.console, ProgramInfo(), "ReadSummary_Level", screen);
}
boxes_data[get_index(box_nb, row, column)]->level = (uint16_t)level;
env.console.log("Level: " + std::to_string(level), COLOR_GREEN);

// language
std::string language = OCR::ocr_read(Language::English, extract_box_reference(screen, language_box));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Raw OCR isn't perfect and it'd be better to have a dictionnary (a list of words it can find, in this case all languages). That way, OCR will be able to correct minor errors while reading. Also check that all languages slugs are written in latin character (otherwise, the language need to be adapted and can't be english all the time)

if (language.empty()) {
dump_image(env.console, ProgramInfo(), "ReadSummary_Language", screen);
env.console.log("Failed to read language from the box.", COLOR_RED);
} else {
language.erase(language.find_last_not_of(" \n\r\t") + 1);
boxes_data[get_index(box_nb, row, column)]->language = language;
env.console.log("Detected Language: " + language, COLOR_GREEN);
}
// nature_box
std::string nature = OCR::ocr_read(Language::English, extract_box_reference(screen, nature_box));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for the nature, you should be giving the language used by pokemon home as natures from asiatic languages for example won't be readble using an english OCR (also, it'd be better to use a dictionnary)

if (nature.empty()) {
dump_image(env.console, ProgramInfo(), "ReadSummary_Nature", screen);
env.console.log("Failed to read nature from the box.", COLOR_RED);
} else {
nature.erase(nature.find_last_not_of(" \n\r\t") + 1);
boxes_data[get_index(box_nb, row, column)]->nature = nature;
env.console.log("Detected Nature: " + nature, COLOR_GREEN);
}

// ability_box
std::string ability = OCR::ocr_read(Language::English, extract_box_reference(screen, ability_box));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for the ability, you should be giving the language used by pokemon home as abilities from asiatic languages for example won't be readble using an english OCR (also, it'd be better to use a dictionnary)

if (language.empty()) {
dump_image(env.console, ProgramInfo(), "ReadSummary_Ability", screen);
env.console.log("Failed to read ability from the box.", COLOR_RED);
} else {
ability.erase(ability.find_last_not_of(" \n\r\t") + 1);
boxes_data[get_index(box_nb, row, column)]->ability = ability;
env.console.log("Detected Ability: " + ability, COLOR_GREEN);
}
//origin_symbol_box



// NOTE edit when adding new struct members (detections go here likely)
// ot_box

pbf_press_button(context, BUTTON_R, 10, VIDEO_DELAY+15);
context.wait_for_all_requests();
Expand Down