package com.yoavst.testing.project import android.graphics.BitmapFactory import android.graphics.Color import android.util.Log import android.widget.Button import android.widget.ImageView import androidx.core.graphics.get import androidx.test.uiautomator.By import androidx.test.uiautomator.UiDevice import androidx.test.uiautomator.UiObject import androidx.test.uiautomator.UiSelector import java.io.File import java.lang.Thread.sleep class GameController( private val device: UiDevice, private val competitor: Competitor = Competitor.of(DATA_FILE.readText()) ) { private var answeredQuestions = 0 private val questionsSeen = mutableSetOf() fun tryPlayRound() { if (!device.hasObject(By.textContains("שניות"))) return val buttonOffset = if (device.hasObject(By.textContains("ספונסר"))) 1 else 0 // get question val questionText = device.findObjects(By.clickable(true).clazz(ImageView::class.java)) .firstOrNull { it.visibleBounds.left == LEFT_OF_ANSWER }?.parent?.text ?: return // get answers val answerButtons = (buttonOffset..(ANSWERS_COUNT - 1 + buttonOffset)).map { UiSelector().clickable(true).className(ImageView::class.java).instance(it) }.map(device::findObject) val answers = answerButtons.map(UiObject::getText) if (answers.any(String::isBlank)) { Log.w(LOG_TAG, "Warning: blank answer") return } // Answer the question val question = Question(questionText, answers) val selectedAnswer = competitor[question] if (selectedAnswer == null || selectedAnswer >= 0) { val (x, y) = ANSWERS_POINTS[selectedAnswer ?: RANDOM_GUESS].first() device.click(x, y) } else return sleep(TIMEOUT_WAIT_FOR_RESULT_FOR_ANSWERING) // check what is the correct answer if possible assert(device.takeScreenshot(BITMAP_FILE)) val bitmap = BitmapFactory.decodeFile(BITMAP_FILE.absolutePath) val correctAnswer = ANSWERS_POINTS.indexOfFirst { it.any { (x, y) -> bitmap[x, y] == CORRECT_ANSWER_COLOR } } .takeIf { it != -1 } if (correctAnswer != null) { competitor[question] = correctAnswer } // report to log Log.i(LOG_TAG, "========= $question ===========") Log.i(LOG_TAG, "${++answeredQuestions}) correct: $correctAnswer, answered: $selectedAnswer") if (selectedAnswer != null && correctAnswer != null && selectedAnswer != correctAnswer) { Log.w(LOG_TAG, "Mismatch: cached answer and correct answer are different") } if (correctAnswer == null) { Log.w(LOG_TAG, "Fail: Could not capture correct answer") } if (question.question in questionsSeen) { Log.w(LOG_TAG, "Repeat: question was seen already") } questionsSeen += question.question Log.i(LOG_TAG, "====================================") } fun tryCloseAd() { val xButton = device.findObject( By.clazz(Button::class.java).clickable(true).hasChild( By.clazz(Button::class.java) ) ) if (xButton != null && xButton.childCount == 1 && xButton.parent.childCount == 2) { xButton.children[0].click() } } fun tryPlayAgain() { device.findObject(By.text("שחק שוב"))?.let { DATA_FILE.writeText(competitor.export()) it.click() } } companion object { private const val TIMEOUT_WAIT_FOR_RESULT_FOR_ANSWERING = 100L private const val LOG_TAG = "Aluf-bot" private const val ANSWERS_COUNT = 4 private const val RANDOM_GUESS = 2 private const val LEFT_OF_ANSWER = 48 private val ANSWERS_POINTS = listOf( listOf(184 to 830), listOf(184 to 1015), listOf(184 to 1200), listOf(184 to 1385) ) private val CORRECT_ANSWER_COLOR = Color.parseColor("#2CB888") private val BITMAP_FILE = File("/sdcard/bot_aluf_hamikraot.png") private val DATA_FILE = File("/sdcard/bot_aluf_hamikraot.json") } }