Enhance findPinCodeNodes logic in ScreenXmlParser with regex support and size tolerance improvements
Refactored the PIN pad detection method to support flexible text matching using regex (e.g., "1", "key 1"). Updated node grouping logic to allow size tolerance for identifying clickable nodes, enabling fallback handling when exact matches fail. Improved debugging output for easier issue diagnosis.
This commit is contained in:
parent
712b73316c
commit
cefad834c7
@ -398,12 +398,14 @@ QString ScreenXmlParser::parseProfilePhone() {
|
||||
|
||||
QList<Node> ScreenXmlParser::findPinCodeNodes(const QString &pinCode) {
|
||||
// Способ 1: ищем кликабельные ноды с текстом-цифрой (0-9)
|
||||
// Поддерживаем форматы: "1", "key 1", и т.п.
|
||||
QMap<QString, Node> digitMap;
|
||||
static const QRegularExpression digitRx(R"(^(?:key\s+)?(\d)$)", QRegularExpression::CaseInsensitiveOption);
|
||||
for (const Node &node : m_nodes) {
|
||||
if (!node.clickable || node.width() <= 0 || node.height() <= 0) continue;
|
||||
const QString t = node.text.trimmed();
|
||||
if (t.size() == 1 && t.at(0).isDigit()) {
|
||||
digitMap[t] = node;
|
||||
if (const auto match = digitRx.match(t); match.hasMatch()) {
|
||||
digitMap[match.captured(1)] = node;
|
||||
}
|
||||
}
|
||||
|
||||
@ -421,42 +423,62 @@ QList<Node> ScreenXmlParser::findPinCodeNodes(const QString &pinCode) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Способ 2 (fallback): группируем clickable-ноды одинакового размера,
|
||||
// Способ 2 (fallback): группируем clickable-ноды похожего размера,
|
||||
// ищем сетку 4x3 по паттерну (не привязываясь к координатам экрана)
|
||||
QMap<QPair<int,int>, QList<Node>> sizeGroups;
|
||||
constexpr int SIZE_TOLERANCE = 10; // допуск в пикселях
|
||||
|
||||
// Собираем все clickable ноды с положительным размером
|
||||
QList<Node> allClickable;
|
||||
for (const Node &node : m_nodes) {
|
||||
if (!node.clickable || node.width() <= 0 || node.height() <= 0) continue;
|
||||
if (node.width() == node.height()) { // кнопки пин-пада квадратные
|
||||
sizeGroups[{node.width(), node.height()}].append(node);
|
||||
allClickable.append(node);
|
||||
}
|
||||
|
||||
// Группируем с допуском: для каждой ноды проверяем, подходит ли она к существующей группе
|
||||
auto fuzzyGroup = [&](bool squareOnly) -> QList<Node> {
|
||||
QList<QList<Node>> groups;
|
||||
QList<QPair<int,int>> groupSizes; // эталонный размер каждой группы
|
||||
|
||||
for (const Node &node : allClickable) {
|
||||
if (squareOnly && std::abs(node.width() - node.height()) > SIZE_TOLERANCE)
|
||||
continue;
|
||||
bool placed = false;
|
||||
for (int g = 0; g < groups.size(); ++g) {
|
||||
if (std::abs(node.width() - groupSizes[g].first) <= SIZE_TOLERANCE &&
|
||||
std::abs(node.height() - groupSizes[g].second) <= SIZE_TOLERANCE) {
|
||||
groups[g].append(node);
|
||||
placed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!placed) {
|
||||
groups.append({node});
|
||||
groupSizes.append({node.width(), node.height()});
|
||||
}
|
||||
}
|
||||
|
||||
// Ищем группу из >= 12 одинаковых кнопок (пин-пад: 3x4 = 12)
|
||||
QList<Node> candidates;
|
||||
for (auto it = sizeGroups.begin(); it != sizeGroups.end(); ++it) {
|
||||
if (it.value().size() >= 12 &&
|
||||
(candidates.isEmpty() || it.value().size() < candidates.size())) {
|
||||
candidates = it.value();
|
||||
}
|
||||
QList<Node> best;
|
||||
for (const auto &grp : groups) {
|
||||
if (grp.size() >= 12 && (best.size() < 12 || grp.size() < best.size()))
|
||||
best = grp;
|
||||
}
|
||||
return best;
|
||||
};
|
||||
|
||||
// Сначала квадратные, потом любые
|
||||
QList<Node> candidates = fuzzyGroup(true);
|
||||
if (candidates.size() < 12)
|
||||
candidates = fuzzyGroup(false);
|
||||
|
||||
if (candidates.size() < 12) {
|
||||
// Попробуем без ограничения на квадрат, но с >= 12
|
||||
sizeGroups.clear();
|
||||
for (const Node &node : m_nodes) {
|
||||
if (!node.clickable || node.width() <= 0 || node.height() <= 0) continue;
|
||||
sizeGroups[{node.width(), node.height()}].append(node);
|
||||
// Дебаг: выводим все clickable ноды и их размеры
|
||||
qWarning() << "[findPinCodeNodes] grid not found. Total clickable nodes:" << allClickable.size();
|
||||
for (const Node &n : allClickable) {
|
||||
qDebug() << " clickable:" << n.width() << "x" << n.height()
|
||||
<< "pos:" << n.x() << "," << n.y()
|
||||
<< "class:" << n.className
|
||||
<< "text:" << n.text.left(30);
|
||||
}
|
||||
for (auto it = sizeGroups.begin(); it != sizeGroups.end(); ++it) {
|
||||
if (it.value().size() >= 12 &&
|
||||
(candidates.size() < 12 || it.value().size() < candidates.size())) {
|
||||
candidates = it.value();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (candidates.size() < 12) {
|
||||
qWarning() << "[findPinCodeNodes] grid not found: no group of 12+ same-sized clickable nodes";
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user