fix(agent): search horizontally for exact purchase size (#230)
This commit is contained in:
+38
-16
@@ -823,18 +823,22 @@ class PurchaseRehearsalExecutor(
|
||||
currentSignature = inspected.signature
|
||||
}
|
||||
}
|
||||
if (dimension == "color") {
|
||||
locateExactColorHorizontally(input, target)?.let { return it }
|
||||
if (dimension == "color" || dimension == "size") {
|
||||
locateExactDimensionHorizontally(input, dimension, target)?.let { return it }
|
||||
}
|
||||
return SpecLookup(failure = failure(SPEC_TARGET_NOT_VISIBLE, "有界搜索后未找到精确规格"))
|
||||
}
|
||||
|
||||
/**
|
||||
* Compatibility fallback for horizontally paged PDD color rows. The
|
||||
* Compatibility fallback for horizontally paged PDD color or size rows. The
|
||||
* established visible/vertical lookup above remains the primary path, so
|
||||
* already successful purchases never enter this branch.
|
||||
*/
|
||||
private fun locateExactColorHorizontally(input: PurchaseExecutionInput, target: String): SpecLookup? {
|
||||
private fun locateExactDimensionHorizontally(
|
||||
input: PurchaseExecutionInput,
|
||||
dimension: String,
|
||||
target: String,
|
||||
): SpecLookup? {
|
||||
val swipeLimit = DEFAULT_COLLECTOR.limits.getValue("specHorizontalSwipes")
|
||||
val stableReadLimit = DEFAULT_COLLECTOR.limits.getValue("stableEdgeReads")
|
||||
data class ColorInspection(
|
||||
@@ -857,7 +861,7 @@ class PurchaseRehearsalExecutor(
|
||||
"",
|
||||
)
|
||||
}
|
||||
val values = screen.dimensions.filter { it.key == "color" }.flatMap { it.values }
|
||||
val values = screen.dimensions.filter { it.key == dimension }.flatMap { it.values }
|
||||
val exact = values.filter { it.text == target }
|
||||
val lookup = when {
|
||||
exact.size > 1 -> SpecLookup(failure = failure(SPEC_TARGET_AMBIGUOUS, "精确规格匹配到多个控件"))
|
||||
@@ -865,7 +869,7 @@ class PurchaseRehearsalExecutor(
|
||||
exact.size == 1 -> SpecLookup(failure = failure(SPEC_SAFE_TARGET_MISSING, "精确规格当前不可安全点击"))
|
||||
else -> null
|
||||
}
|
||||
val rows = specColorRows(values)
|
||||
val rows = specValueRows(values)
|
||||
val signature = rows.flatten().joinToString("|") { value ->
|
||||
val bounds = value.node.bounds
|
||||
"${value.text}:${bounds.left},${bounds.top},${bounds.right},${bounds.bottom}:${value.available}"
|
||||
@@ -878,7 +882,7 @@ class PurchaseRehearsalExecutor(
|
||||
var verticalRecoverySwipes = 0
|
||||
var previousVerticalSignature: String? = null
|
||||
var verticalStableReads = 0
|
||||
while (inspected.rows.none { it.size > 1 } && verticalRecoverySwipes < swipeLimit) {
|
||||
while (horizontalSpecRow(inspected.screen, inspected.rows) == null && verticalRecoverySwipes < swipeLimit) {
|
||||
val container = inspected.screen.specPanelContainer ?: break
|
||||
if (!driver.swipePurchaseIn(container, SwipeDirection.DOWN, 350)) break
|
||||
verticalRecoverySwipes++
|
||||
@@ -890,21 +894,21 @@ class PurchaseRehearsalExecutor(
|
||||
if (verticalStableReads >= stableReadLimit) break
|
||||
}
|
||||
|
||||
val initialRow = inspected.rows.firstOrNull { it.size > 1 }
|
||||
val initialRow = horizontalSpecRow(inspected.screen, inspected.rows)
|
||||
?: return SpecLookup(failure = failure(
|
||||
SPEC_TARGET_NOT_VISIBLE,
|
||||
"有界搜索后未找到精确规格 [dimension=color;horizontalSwipes=0;verticalRecoverySwipes=$verticalRecoverySwipes;visibleCandidates=${inspected.rows.flatten().size};reason=noHorizontalRow]",
|
||||
"有界搜索后未找到精确规格 [dimension=$dimension;horizontalSwipes=0;verticalRecoverySwipes=$verticalRecoverySwipes;visibleCandidates=${inspected.rows.flatten().size};reason=noHorizontalRow]",
|
||||
))
|
||||
|
||||
var horizontalSwipes = 0
|
||||
var previousSignature: String? = null
|
||||
var stableReads = 0
|
||||
while (horizontalSwipes < swipeLimit) {
|
||||
val anchor = inspected.rows.firstOrNull { it.size > 1 }?.firstOrNull()?.node ?: initialRow.first().node
|
||||
val anchor = horizontalSpecRow(inspected.screen, inspected.rows)?.firstOrNull()?.node ?: initialRow.first().node
|
||||
if (!driver.swipeSpecRow(anchor, SwipeDirection.RIGHT)) {
|
||||
return SpecLookup(failure = failure(
|
||||
SPEC_TARGET_NOT_VISIBLE,
|
||||
"有界搜索后未找到精确规格 [dimension=color;horizontalSwipes=$horizontalSwipes;verticalRecoverySwipes=$verticalRecoverySwipes;visibleCandidates=${inspected.rows.flatten().size};reason=restoreSwipeFailed]",
|
||||
"有界搜索后未找到精确规格 [dimension=$dimension;horizontalSwipes=$horizontalSwipes;verticalRecoverySwipes=$verticalRecoverySwipes;visibleCandidates=${inspected.rows.flatten().size};reason=restoreSwipeFailed]",
|
||||
))
|
||||
}
|
||||
horizontalSwipes++
|
||||
@@ -919,15 +923,15 @@ class PurchaseRehearsalExecutor(
|
||||
previousSignature = null
|
||||
stableReads = 0
|
||||
while (horizontalSwipes < swipeLimit * 2) {
|
||||
val anchor = inspected.rows.firstOrNull { it.size > 1 }?.firstOrNull()?.node
|
||||
val anchor = horizontalSpecRow(inspected.screen, inspected.rows)?.firstOrNull()?.node
|
||||
?: return SpecLookup(failure = failure(
|
||||
SPEC_TARGET_NOT_VISIBLE,
|
||||
"有界搜索后未找到精确规格 [dimension=color;horizontalSwipes=$horizontalSwipes;verticalRecoverySwipes=$verticalRecoverySwipes;visibleCandidates=${inspected.rows.flatten().size};reason=rowLost]",
|
||||
"有界搜索后未找到精确规格 [dimension=$dimension;horizontalSwipes=$horizontalSwipes;verticalRecoverySwipes=$verticalRecoverySwipes;visibleCandidates=${inspected.rows.flatten().size};reason=rowLost]",
|
||||
))
|
||||
if (!driver.swipeSpecRow(anchor, SwipeDirection.LEFT)) {
|
||||
return SpecLookup(failure = failure(
|
||||
SPEC_TARGET_NOT_VISIBLE,
|
||||
"有界搜索后未找到精确规格 [dimension=color;horizontalSwipes=$horizontalSwipes;verticalRecoverySwipes=$verticalRecoverySwipes;visibleCandidates=${inspected.rows.flatten().size};reason=searchSwipeFailed]",
|
||||
"有界搜索后未找到精确规格 [dimension=$dimension;horizontalSwipes=$horizontalSwipes;verticalRecoverySwipes=$verticalRecoverySwipes;visibleCandidates=${inspected.rows.flatten().size};reason=searchSwipeFailed]",
|
||||
))
|
||||
}
|
||||
horizontalSwipes++
|
||||
@@ -940,11 +944,29 @@ class PurchaseRehearsalExecutor(
|
||||
}
|
||||
return SpecLookup(failure = failure(
|
||||
SPEC_TARGET_NOT_VISIBLE,
|
||||
"有界搜索后未找到精确规格 [dimension=color;horizontalSwipes=$horizontalSwipes;verticalRecoverySwipes=$verticalRecoverySwipes;visibleCandidates=${inspected.rows.flatten().size};reason=edgeReached]",
|
||||
"有界搜索后未找到精确规格 [dimension=$dimension;horizontalSwipes=$horizontalSwipes;verticalRecoverySwipes=$verticalRecoverySwipes;visibleCandidates=${inspected.rows.flatten().size};reason=edgeReached]",
|
||||
))
|
||||
}
|
||||
|
||||
private fun specColorRows(values: List<VisibleSpecValue>): List<List<VisibleSpecValue>> {
|
||||
private fun horizontalSpecRow(
|
||||
screen: ParsedPddScreen,
|
||||
rows: List<List<VisibleSpecValue>>,
|
||||
): List<VisibleSpecValue>? = rows.firstOrNull { row ->
|
||||
row.size > 1 || row.any { value -> hasDedicatedHorizontalAncestor(screen, value.node) }
|
||||
}
|
||||
|
||||
private fun hasDedicatedHorizontalAncestor(screen: ParsedPddScreen, source: SnapshotNode): Boolean {
|
||||
val byPath = screen.sourceNodes.associateBy(SnapshotNode::path)
|
||||
var current: SnapshotNode? = source
|
||||
while (current != null) {
|
||||
if (current.path == screen.specPanelContainer?.path) return false
|
||||
if (current.scrollable && current.bounds.width > current.bounds.height) return true
|
||||
current = current.parentPath?.let(byPath::get)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun specValueRows(values: List<VisibleSpecValue>): List<List<VisibleSpecValue>> {
|
||||
val sorted = values.sortedWith(compareBy({ it.node.bounds.centerY }, { it.node.bounds.left }))
|
||||
val rows = mutableListOf<MutableList<VisibleSpecValue>>()
|
||||
val centers = mutableListOf<Int>()
|
||||
|
||||
Reference in New Issue
Block a user