@ -16,6 +16,8 @@ import android.media.projection.MediaProjectionManager
import android.os.*
import android.util.DisplayMetrics
import android.util.Log
import com.quillstudios.pokegoalshelper.utils.PGHLog
import com.quillstudios.pokegoalshelper.ml.MLErrorType
import android.view.WindowManager
import android.view.View
import android.view.Gravity
@ -148,11 +150,13 @@ class ScreenCaptureService : Service() {
mlInferenceEngine = YOLOInferenceEngine ( this )
Thread {
runBlocking {
if ( ! mlInferenceEngine !! . initialize ( ) ) {
Log . e ( TAG , " ❌ Failed to initialize ML inference engine " )
} else {
Log . i ( TAG , " ✅ ML inference engine initialized for screen capture " )
}
mlInferenceEngine !! . initialize ( )
. onSuccess {
PGHLog . i ( TAG , " ✅ ML inference engine initialized for screen capture " )
}
. onError { errorType , exception , message ->
PGHLog . e ( TAG , " ❌ Failed to initialize ML inference engine: $message ( ${errorType.name} ) " , exception )
}
}
} . start ( )
@ -169,7 +173,7 @@ class ScreenCaptureService : Service() {
onClose = { stopSelf ( ) }
)
Log . d ( TAG , " ✅ MVC architecture initialized " )
PGH Log. d ( TAG , " ✅ MVC architecture initialized " )
}
override fun onBind ( intent : Intent ? ) : IBinder = binder
@ -238,7 +242,7 @@ class ScreenCaptureService : Service() {
}
private fun startScreenCapture ( resultData : Intent ) {
Log . d ( TAG , " Starting screen capture " )
PGH Log. d ( TAG , " Starting screen capture " )
try {
val notification = NotificationCompat . Builder ( this , CHANNEL_ID )
@ -260,28 +264,28 @@ class ScreenCaptureService : Service() {
)
. build ( )
Log . d ( TAG , " Starting foreground service " )
PGH Log. d ( TAG , " Starting foreground service " )
startForeground ( NOTIFICATION_ID , notification )
// Use the screen capture manager to start capture
if ( ! screenCaptureManager . startCapture ( resultData ) ) {
Log . e ( TAG , " Failed to start screen capture via manager " )
PGH Log. e ( TAG , " Failed to start screen capture via manager " )
stopSelf ( )
return
}
Log . d ( TAG , " Screen capture setup complete " )
PGH Log. d ( TAG , " Screen capture setup complete " )
// Show floating overlay
enhancedFloatingFAB ?. show ( )
} catch ( e : Exception ) {
Log . e ( TAG , " Error starting screen capture " , e )
PGH Log. e ( TAG , " Error starting screen capture " , e )
stopSelf ( )
}
}
private fun stopScreenCapture ( ) {
Log . d ( TAG , " Stopping screen capture " )
PGH Log. d ( TAG , " Stopping screen capture " )
handler . removeCallbacks ( captureRunnable )
hideDetectionOverlay ( )
@ -311,7 +315,7 @@ class ScreenCaptureService : Service() {
// Don't close the image yet - it will be closed in triggerManualDetection
}
} catch ( e : Exception ) {
Log . e ( TAG , " Error handling captured image " , e )
PGH Log. e ( TAG , " Error handling captured image " , e )
}
}
@ -320,7 +324,7 @@ class ScreenCaptureService : Service() {
private fun captureScreen ( ) {
// Trigger image capture by reading from the ImageReader
// The onImageAvailableListener will handle the actual processing
Log . d ( TAG , " Triggering screen capture... " )
PGH Log. d ( TAG , " Triggering screen capture... " )
}
private fun processImage ( image : Image ) {
@ -331,7 +335,7 @@ class ScreenCaptureService : Service() {
// Get screen dimensions from the manager
val screenDimensions = screenCaptureManager . getScreenDimensions ( )
if ( screenDimensions == null ) {
Log . e ( TAG , " Screen dimensions not available from manager " )
PGH Log. e ( TAG , " Screen dimensions not available from manager " )
return
}
val ( screenWidth , screenHeight ) = screenDimensions
@ -342,8 +346,8 @@ class ScreenCaptureService : Service() {
val rowStride = planes [ 0 ] . rowStride
val rowPadding = rowStride - pixelStride * screenWidth
Log . d ( TAG , " 🖼️ CAPTURE DEBUG: pixelStride= $pixelStride , rowStride= $rowStride , rowPadding= $rowPadding " )
Log . d ( TAG , " 🖼️ CAPTURE DEBUG: screenSize= ${screenWidth} x ${screenHeight} , expected bitmap= ${screenWidth + rowPadding / pixelStride} x ${screenHeight} " )
PGH Log. d ( TAG , " 🖼️ CAPTURE DEBUG: pixelStride= $pixelStride , rowStride= $rowStride , rowPadding= $rowPadding " )
PGH Log. d ( TAG , " 🖼️ CAPTURE DEBUG: screenSize= ${screenWidth} x ${screenHeight} , expected bitmap= ${screenWidth + rowPadding / pixelStride} x ${screenHeight} " )
// Create bitmap from image
bitmap = Bitmap . createBitmap (
@ -353,26 +357,26 @@ class ScreenCaptureService : Service() {
)
bitmap . copyPixelsFromBuffer ( buffer )
Log . d ( TAG , " 🖼️ CAPTURE DEBUG: created bitmap= ${bitmap.width} x ${bitmap.height} " )
PGH Log. d ( TAG , " 🖼️ CAPTURE DEBUG: created bitmap= ${bitmap.width} x ${bitmap.height} " )
// Convert to cropped bitmap if needed
croppedBitmap = if ( rowPadding == 0 ) {
Log . d ( TAG , " 🖼️ CAPTURE DEBUG: No padding, using original bitmap " )
PGH Log. d ( TAG , " 🖼️ CAPTURE DEBUG: No padding, using original bitmap " )
bitmap
} else {
Log . d ( TAG , " 🖼️ CAPTURE DEBUG: Cropping bitmap from ${bitmap.width} x ${bitmap.height} to ${screenWidth} x ${screenHeight} " )
PGH Log. d ( TAG , " 🖼️ CAPTURE DEBUG: Cropping bitmap from ${bitmap.width} x ${bitmap.height} to ${screenWidth} x ${screenHeight} " )
Bitmap . createBitmap ( bitmap , 0 , 0 , screenWidth , screenHeight )
}
Log . d ( TAG , " 🖼️ CAPTURE DEBUG: final bitmap= ${croppedBitmap.width} x ${croppedBitmap.height} " )
PGH Log. d ( TAG , " 🖼️ CAPTURE DEBUG: final bitmap= ${croppedBitmap.width} x ${croppedBitmap.height} " )
// Convert to OpenCV Mat for analysis - with proper resource management
Mat ( ) . use { mat ->
Utils . bitmapToMat ( croppedBitmap , mat )
// DEBUG: Check color conversion
Log . d ( TAG , " 🎨 COLOR DEBUG: Mat type= ${mat.type()} , channels= ${mat.channels()} " )
Log . d ( TAG , " 🎨 COLOR DEBUG: OpenCV expects BGR, Android Bitmap is ARGB " )
PGH Log. d ( TAG , " 🎨 COLOR DEBUG: Mat type= ${mat.type()} , channels= ${mat.channels()} " )
PGH Log. d ( TAG , " 🎨 COLOR DEBUG: OpenCV expects BGR, Android Bitmap is ARGB " )
// Sample a center pixel to check color values
if ( mat . rows ( ) > 0 && mat . cols ( ) > 0 ) {
@ -383,8 +387,8 @@ class ScreenCaptureService : Service() {
val b = pixel [ 0 ] . toInt ( )
val g = pixel [ 1 ] . toInt ( )
val r = pixel [ 2 ] . toInt ( )
Log . d ( TAG , " 🎨 COLOR DEBUG: Center pixel ( ${centerX} , ${centerY} ) BGR=( $b , $g , $r ) -> RGB=( ${r} , ${g} , ${b} ) " )
Log . d ( TAG , " 🎨 COLOR DEBUG: Center pixel hex = # ${String.format("%02x%02x%02x", r, g, b)} " )
PGH Log. d ( TAG , " 🎨 COLOR DEBUG: Center pixel ( ${centerX} , ${centerY} ) BGR=( $b , $g , $r ) -> RGB=( ${r} , ${g} , ${b} ) " )
PGH Log. d ( TAG , " 🎨 COLOR DEBUG: Center pixel hex = # ${String.format("%02x%02x%02x", r, g, b)} " )
}
}
@ -393,7 +397,7 @@ class ScreenCaptureService : Service() {
}
} catch ( e : Exception ) {
Log . e ( TAG , " Error processing image " , e )
PGH Log. e ( TAG , " Error processing image " , e )
} finally {
// Always clean up bitmaps in finally block to prevent leaks
if ( croppedBitmap != null && croppedBitmap != bitmap ) {
@ -404,24 +408,24 @@ class ScreenCaptureService : Service() {
}
private fun analyzePokemonScreen ( mat : Mat ) {
Log . i ( TAG , " 📱 ANALYZING SCREEN: ${mat.cols()} x ${mat.rows()} " )
PGH Log. i ( TAG , " 📱 ANALYZING SCREEN: ${mat.cols()} x ${mat.rows()} " )
// Check if analysis has been stuck for too long (30 seconds max)
val currentTime = System . currentTimeMillis ( )
if ( isAnalyzing && ( currentTime - analysisStartTime ) > 30000 ) {
Log . w ( TAG , " ⚠️ Analysis stuck for >30s, resetting flag " )
PGH Log. w ( TAG , " ⚠️ Analysis stuck for >30s, resetting flag " )
isAnalyzing = false
}
// Skip if already analyzing
if ( isAnalyzing ) {
Log . d ( TAG , " ⏭️ Skipping analysis - previous cycle still in progress " )
PGH Log. d ( TAG , " ⏭️ Skipping analysis - previous cycle still in progress " )
return
}
isAnalyzing = true
analysisStartTime = currentTime
Log . d ( TAG , " 🔄 Starting new analysis cycle " )
PGH Log. d ( TAG , " 🔄 Starting new analysis cycle " )
try {
// Run ML inference first
@ -429,25 +433,35 @@ class ScreenCaptureService : Service() {
Utils . matToBitmap ( mat , bitmap )
val detections : List < MLDetection > = runBlocking {
mlInferenceEngine ?. detect ( bitmap ) ?: emptyList ( )
mlInferenceEngine ?. detect ( bitmap )
?. onErrorType ( MLErrorType . MEMORY_ERROR ) { exception , message ->
PGHLog . w ( TAG , " ⚠️ Memory error during detection, may retry with smaller image: $message " )
}
?. onErrorType ( MLErrorType . TIMEOUT_ERROR ) { exception , message ->
PGHLog . w ( TAG , " ⚠️ Detection timed out, analysis may be too complex: $message " )
}
?. onErrorType ( MLErrorType . INVALID_INPUT ) { exception , message ->
PGHLog . e ( TAG , " ❌ Invalid input to ML engine: $message " )
}
?. getOrDefault ( emptyList ( ) ) ?: emptyList ( )
}
if ( detections . isEmpty ( ) ) {
Log . i ( TAG , " 🔍 No Pokemon UI elements detected by ONNX YOLO " )
PGH Log. i ( TAG , " 🔍 No Pokemon UI elements detected by ONNX YOLO " )
isAnalyzing = false
return
}
Log . i ( TAG , " 🎯 ONNX YOLO detected ${detections.size} UI elements " )
PGH Log. i ( TAG , " 🎯 ONNX YOLO detected ${detections.size} UI elements " )
// Log ALL detections for debugging
detections . forEachIndexed { index , detection ->
Log . i ( TAG , " $index : ${detection.className} ( ${String.format("%.3f", detection.confidence)} ) at [ ${detection.boundingBox.left} , ${detection.boundingBox.top} , ${detection.boundingBox.width} , ${detection.boundingBox.height} ] " )
PGH Log. i ( TAG , " $index : ${detection.className} ( ${String.format("%.3f", detection.confidence)} ) at [ ${detection.boundingBox.left} , ${detection.boundingBox.top} , ${detection.boundingBox.width} , ${detection.boundingBox.height} ] " )
}
// Show breakdown by type
val detectionCounts = detections . groupBy { it . className } . mapValues { it . value . size }
Log . i ( TAG , " 🔍 Detection counts by type: $detectionCounts " )
PGH Log. i ( TAG , " 🔍 Detection counts by type: $detectionCounts " )
// Check for commonly missing elements
val expectedElements = listOf ( " pokemon_level " , " attack_value " , " sp_def_value " , " shiny_icon " ,
@ -456,18 +470,18 @@ class ScreenCaptureService : Service() {
detections . none { detection -> detection . className . startsWith ( expected . split ( " _ " ) . take ( 2 ) . joinToString ( " _ " ) ) }
}
if ( missingElements . isNotEmpty ( ) ) {
Log . w ( TAG , " ⚠️ Missing expected elements: $missingElements " )
PGH Log. w ( TAG , " ⚠️ Missing expected elements: $missingElements " )
}
// Show detection overlay IMMEDIATELY (no OCR blocking)
showYOLODetectionOverlay ( detections )
Log . i ( TAG , " 📺 Overlay displayed with ${detections.size} detections " )
PGH Log. i ( TAG , " 📺 Overlay displayed with ${detections.size} detections " )
// Extract Pokemon info using YOLO detections in background
extractPokemonInfoFromYOLOAsync ( mat , detections )
} catch ( e : Exception ) {
Log . e ( TAG , " Error analyzing Pokemon screen " , e )
PGH Log. e ( TAG , " Error analyzing Pokemon screen " , e )
isAnalyzing = false
}
}
@ -486,18 +500,18 @@ class ScreenCaptureService : Service() {
handler . post {
try {
if ( pokemonInfo != null ) {
Log . i ( TAG , " 🔥 POKEMON DATA EXTRACTED SUCCESSFULLY! " )
PGH Log. i ( TAG , " 🔥 POKEMON DATA EXTRACTED SUCCESSFULLY! " )
logPokemonInfo ( pokemonInfo )
// TODO: Send to your API
// sendToAPI(pokemonInfo)
} else {
Log . i ( TAG , " ❌ Could not extract complete Pokemon info " )
PGH Log. i ( TAG , " ❌ Could not extract complete Pokemon info " )
}
} finally {
// Analysis cycle complete, allow next one
isAnalyzing = false
val duration = System . currentTimeMillis ( ) - analysisStartTime
Log . d ( TAG , " ✅ Analysis cycle complete after ${duration} ms - ready for next " )
PGH Log. d ( TAG , " ✅ Analysis cycle complete after ${duration} ms - ready for next " )
}
}
@ -505,13 +519,13 @@ class ScreenCaptureService : Service() {
matCopy . release ( )
} catch ( e : Exception ) {
Log . e ( TAG , " Error in async Pokemon extraction " , e )
PGH Log. e ( TAG , " Error in async Pokemon extraction " , e )
matCopy . release ( )
// Clear flag on error too
handler . post {
isAnalyzing = false
Log . d ( TAG , " ❌ Analysis cycle failed - ready for next " )
PGH Log. d ( TAG , " ❌ Analysis cycle failed - ready for next " )
}
}
}
@ -519,7 +533,7 @@ class ScreenCaptureService : Service() {
private fun extractPokemonInfoFromYOLO ( mat : Mat , detections : List < MLDetection > ) : PokemonInfo ? {
try {
Log . i ( TAG , " 🎯 Extracting Pokemon info from ${detections.size} YOLO detections " )
PGH Log. i ( TAG , " 🎯 Extracting Pokemon info from ${detections.size} YOLO detections " )
// Group detections by type
val detectionMap = detections . groupBy { it . className }
@ -542,7 +556,7 @@ class ScreenCaptureService : Service() {
// Wait for all OCR tasks to complete (max 10 seconds total)
val completed = latch . await ( 10 , TimeUnit . SECONDS )
if ( ! completed ) {
Log . w ( TAG , " ⏱️ Some OCR tasks timed out after 10 seconds " )
PGH Log. w ( TAG , " ⏱️ Some OCR tasks timed out after 10 seconds " )
}
// Extract results
@ -579,20 +593,20 @@ class ScreenCaptureService : Service() {
// Detect tera type
val teraType = detectTeraTypeFromDetections ( detectionMap )
Log . i ( TAG , " 📊 YOLO extraction summary: " )
Log . i ( TAG , " Nickname: ' ${nickname ?: "null"} ' " )
Log . i ( TAG , " Level: ${level ?: "null"} " )
Log . i ( TAG , " Species: ' ${species ?: "null"} ' " )
Log . i ( TAG , " Nature: ' ${nature ?: "null"} ' " )
Log . i ( TAG , " Ability: ' ${ability ?: "null"} ' " )
Log . i ( TAG , " Gender: ' ${gender ?: "null"} ' " )
Log . i ( TAG , " Pokeball: ' ${pokeballType ?: "null"} ' " )
Log . i ( TAG , " Types: ${types} " )
Log . i ( TAG , " Tera: ' ${teraType ?: "null"} ' " )
Log . i ( TAG , " Shiny: $isShiny " )
PGH Log. i ( TAG , " 📊 YOLO extraction summary: " )
PGH Log. i ( TAG , " Nickname: ' ${nickname ?: "null"} ' " )
PGH Log. i ( TAG , " Level: ${level ?: "null"} " )
PGH Log. i ( TAG , " Species: ' ${species ?: "null"} ' " )
PGH Log. i ( TAG , " Nature: ' ${nature ?: "null"} ' " )
PGH Log. i ( TAG , " Ability: ' ${ability ?: "null"} ' " )
PGH Log. i ( TAG , " Gender: ' ${gender ?: "null"} ' " )
PGH Log. i ( TAG , " Pokeball: ' ${pokeballType ?: "null"} ' " )
PGH Log. i ( TAG , " Types: ${types} " )
PGH Log. i ( TAG , " Tera: ' ${teraType ?: "null"} ' " )
PGH Log. i ( TAG , " Shiny: $isShiny " )
if ( nickname . isNullOrBlank ( ) && species . isNullOrBlank ( ) && level == null ) {
Log . w ( TAG , " ⚠️ No essential Pokemon data found with YOLO detection " )
PGH Log. w ( TAG , " ⚠️ No essential Pokemon data found with YOLO detection " )
return null
}
@ -621,7 +635,7 @@ class ScreenCaptureService : Service() {
)
} catch ( e : Exception ) {
Log . e ( TAG , " Error extracting Pokemon info from YOLO detections " , e )
PGH Log. e ( TAG , " Error extracting Pokemon info from YOLO detections " , e )
return null
}
}
@ -634,7 +648,7 @@ class ScreenCaptureService : Service() {
results [ key ] = text
}
} catch ( e : Exception ) {
Log . e ( TAG , " Error in OCR task for $key " , e )
PGH Log. e ( TAG , " Error in OCR task for $key " , e )
synchronized ( results ) {
results [ key ] = null
}
@ -653,7 +667,7 @@ class ScreenCaptureService : Service() {
results [ key ] = level
}
} catch ( e : Exception ) {
Log . e ( TAG , " Error in level OCR task " , e )
PGH Log. e ( TAG , " Error in level OCR task " , e )
synchronized ( results ) {
results [ key ] = null
}
@ -689,9 +703,9 @@ class ScreenCaptureService : Service() {
val safeBbox = Rect ( clippedX , clippedY , clippedWidth , clippedHeight )
// Debug logging for bounding box transformations
Log . d ( TAG , " 📏 Expanded bbox for ${detection.className} : [ ${bbox.left} , ${bbox.top} , ${bbox.width} , ${bbox.height} ] → [ ${expandedBbox.x} , ${expandedBbox.y} , ${expandedBbox.width} , ${expandedBbox.height} ] " )
PGH Log. d ( TAG , " 📏 Expanded bbox for ${detection.className} : [ ${bbox.left} , ${bbox.top} , ${bbox.width} , ${bbox.height} ] → [ ${expandedBbox.x} , ${expandedBbox.y} , ${expandedBbox.width} , ${expandedBbox.height} ] " )
if ( safeBbox . x != expandedBbox . x || safeBbox . y != expandedBbox . y || safeBbox . width != expandedBbox . width || safeBbox . height != expandedBbox . height ) {
Log . w ( TAG , " ⚠️ Clipped bbox for ${detection.className} : expanded=[ ${expandedBbox.x} , ${expandedBbox.y} , ${expandedBbox.width} , ${expandedBbox.height} ] → safe=[ ${safeBbox.x} , ${safeBbox.y} , ${safeBbox.width} , ${safeBbox.height} ] (image: ${mat.cols()} x ${mat.rows()} ) " )
PGH Log. w ( TAG , " ⚠️ Clipped bbox for ${detection.className} : expanded=[ ${expandedBbox.x} , ${expandedBbox.y} , ${expandedBbox.width} , ${expandedBbox.height} ] → safe=[ ${safeBbox.x} , ${safeBbox.y} , ${safeBbox.width} , ${safeBbox.height} ] (image: ${mat.cols()} x ${mat.rows()} ) " )
}
// Extract region of interest using safe bounding box
@ -717,14 +731,14 @@ class ScreenCaptureService : Service() {
processedRoi . release ( )
if ( extractedText != null ) {
Log . i ( TAG , " ✅ YOLO SUCCESS: ${detection.className} = ' $extractedText ' (conf: ${String.format("%.2f", detection.confidence)} ) " )
PGH Log. i ( TAG , " ✅ YOLO SUCCESS: ${detection.className} = ' $extractedText ' (conf: ${String.format("%.2f", detection.confidence)} ) " )
} else {
Log . w ( TAG , " ❌ YOLO FAILED: ${detection.className} - no text found (conf: ${String.format("%.2f", detection.confidence)} ) " )
PGH Log. w ( TAG , " ❌ YOLO FAILED: ${detection.className} - no text found (conf: ${String.format("%.2f", detection.confidence)} ) " )
}
return extractedText
} catch ( e : Exception ) {
Log . e ( TAG , " Error extracting text from YOLO detection ${detection.className} " , e )
PGH Log. e ( TAG , " Error extracting text from YOLO detection ${detection.className} " , e )
return null
}
}
@ -874,10 +888,10 @@ class ScreenCaptureService : Service() {
private fun showYOLODetectionOverlay ( detections : List < MLDetection > ) {
try {
Log . i ( TAG , " 🎨 Creating YOLO detection overlay for ${detections.size} detections " )
PGH Log. i ( TAG , " 🎨 Creating YOLO detection overlay for ${detections.size} detections " )
if ( detectionOverlay == null ) {
Log . i ( TAG , " 🆕 Creating new DetectionOverlay instance " )
PGH Log. i ( TAG , " 🆕 Creating new DetectionOverlay instance " )
detectionOverlay = DetectionOverlay ( this )
}
@ -893,12 +907,12 @@ class ScreenCaptureService : Service() {
)
} . toMap ( )
Log . i ( TAG , " 📺 Showing YOLO overlay with ${regions.size} regions... " )
PGH Log. i ( TAG , " 📺 Showing YOLO overlay with ${regions.size} regions... " )
detectionOverlay ?. showOverlay ( regions )
Log . i ( TAG , " ✅ YOLO overlay show command sent " )
PGH Log. i ( TAG , " ✅ YOLO overlay show command sent " )
} catch ( e : Exception ) {
Log . e ( TAG , " ❌ Error showing YOLO detection overlay " , e )
PGH Log. e ( TAG , " ❌ Error showing YOLO detection overlay " , e )
}
}
@ -908,7 +922,7 @@ class ScreenCaptureService : Service() {
private fun performOCR ( bitmap : Bitmap , purpose : String ) : String ? {
try {
Log . d ( TAG , " 🔍 Starting OCR for $purpose - bitmap: ${bitmap.width} x ${bitmap.height} " )
PGH Log. d ( TAG , " 🔍 Starting OCR for $purpose - bitmap: ${bitmap.width} x ${bitmap.height} " )
// Create InputImage for ML Kit
val image = InputImage . fromBitmap ( bitmap , 0 )
@ -922,18 +936,18 @@ class ScreenCaptureService : Service() {
recognizer . process ( image )
. addOnSuccessListener { visionText ->
result = visionText . text . trim ( )
Log . d ( TAG , " 🔍 Raw OCR result for $purpose : ' ${visionText.text} ' (blocks: ${visionText.textBlocks.size} ) " )
PGH Log. d ( TAG , " 🔍 Raw OCR result for $purpose : ' ${visionText.text} ' (blocks: ${visionText.textBlocks.size} ) " )
if ( result . isNullOrBlank ( ) ) {
Log . w ( TAG , " ⚠️ OCR for $purpose : NO TEXT DETECTED - ML Kit found ${visionText.textBlocks.size} text blocks but text is empty " )
PGH Log. w ( TAG , " ⚠️ OCR for $purpose : NO TEXT DETECTED - ML Kit found ${visionText.textBlocks.size} text blocks but text is empty " )
} else {
Log . i ( TAG , " ✅ OCR SUCCESS for $purpose : ' ${result} ' ( ${result!!.length} chars) " )
PGH Log. i ( TAG , " ✅ OCR SUCCESS for $purpose : ' ${result} ' ( ${result!!.length} chars) " )
}
latch . countDown ( )
}
. addOnFailureListener { e ->
ocrError = e
Log . e ( TAG , " ❌ OCR failed for $purpose : ${e.message} " , e )
PGH Log. e ( TAG , " ❌ OCR failed for $purpose : ${e.message} " , e )
latch . countDown ( )
}
@ -941,22 +955,22 @@ class ScreenCaptureService : Service() {
val completed = latch . await ( 5 , TimeUnit . SECONDS )
if ( ! completed ) {
Log . e ( TAG , " ⏱️ OCR timeout for $purpose after 5 seconds " )
PGH Log. e ( TAG , " ⏱️ OCR timeout for $purpose after 5 seconds " )
return null
}
if ( ocrError != null ) {
Log . e ( TAG , " ❌ OCR error for $purpose : ${ocrError!!.message} " )
PGH Log. e ( TAG , " ❌ OCR error for $purpose : ${ocrError!!.message} " )
return null
}
// Clean and process the result
val cleanedResult = cleanOCRResult ( result , purpose )
Log . d ( TAG , " 🧙 Cleaned result for $purpose : ' ${cleanedResult} ' " )
PGH Log. d ( TAG , " 🧙 Cleaned result for $purpose : ' ${cleanedResult} ' " )
return cleanedResult
} catch ( e : Exception ) {
Log . e ( TAG , " ❌ Error in OCR for $purpose " , e )
PGH Log. e ( TAG , " ❌ Error in OCR for $purpose " , e )
return null
}
}
@ -1014,7 +1028,7 @@ class ScreenCaptureService : Service() {
val resized = Mat ( )
Imgproc . resize ( roi , resized , Size ( roi . width ( ) * scale , roi . height ( ) * scale ) )
Log . d ( TAG , " 🔍 Upscaled OCR region from ${roi.width()} x ${roi.height()} to ${resized.width()} x ${resized.height()} " )
PGH Log. d ( TAG , " 🔍 Upscaled OCR region from ${roi.width()} x ${roi.height()} to ${resized.width()} x ${resized.height()} " )
resized
} else {
val copy = Mat ( )
@ -1057,7 +1071,7 @@ class ScreenCaptureService : Service() {
return result
} catch ( e : Exception ) {
Log . e ( TAG , " Error preprocessing image, using original " , e )
PGH Log. e ( TAG , " Error preprocessing image, using original " , e )
// Return copy of original if preprocessing fails
val result = Mat ( )
roi . copyTo ( result )
@ -1082,32 +1096,32 @@ class ScreenCaptureService : Service() {
}
private fun logPokemonInfo ( pokemonInfo : PokemonInfo ) {
Log . i ( TAG , " ====== POKEMON INFO EXTRACTED ====== " )
Log . i ( TAG , " 🎾 Pokeball: ${pokemonInfo.pokeballType} " )
Log . i ( TAG , " 📛 Nickname: ${pokemonInfo.nickname} " )
Log . i ( TAG , " ⚤ Gender: ${pokemonInfo.gender} " )
Log . i ( TAG , " 📊 Level: ${pokemonInfo.level} " )
Log . i ( TAG , " 🌍 Language: ${pokemonInfo.language} " )
Log . i ( TAG , " 🎮 Game Source: ${pokemonInfo.gameSource} " )
Log . i ( TAG , " ⭐ Favorited: ${pokemonInfo.isFavorited} " )
Log . i ( TAG , " 🔢 Dex #: ${pokemonInfo.nationalDexNumber} " )
Log . i ( TAG , " 🐾 Species: ${pokemonInfo.species} " )
Log . i ( TAG , " 🏷️ Type 1: ${pokemonInfo.primaryType} " )
Log . i ( TAG , " 🏷️ Type 2: ${pokemonInfo.secondaryType} " )
Log . i ( TAG , " 🏆 Stamps: ${pokemonInfo.stamps} " )
Log . i ( TAG , " 🏷️ Labels: ${pokemonInfo.labels} " )
Log . i ( TAG , " ✅ Marks: ${pokemonInfo.marks} " )
PGH Log. i ( TAG , " ====== POKEMON INFO EXTRACTED ====== " )
PGH Log. i ( TAG , " 🎾 Pokeball: ${pokemonInfo.pokeballType} " )
PGH Log. i ( TAG , " 📛 Nickname: ${pokemonInfo.nickname} " )
PGH Log. i ( TAG , " ⚤ Gender: ${pokemonInfo.gender} " )
PGH Log. i ( TAG , " 📊 Level: ${pokemonInfo.level} " )
PGH Log. i ( TAG , " 🌍 Language: ${pokemonInfo.language} " )
PGH Log. i ( TAG , " 🎮 Game Source: ${pokemonInfo.gameSource} " )
PGH Log. i ( TAG , " ⭐ Favorited: ${pokemonInfo.isFavorited} " )
PGH Log. i ( TAG , " 🔢 Dex #: ${pokemonInfo.nationalDexNumber} " )
PGH Log. i ( TAG , " 🐾 Species: ${pokemonInfo.species} " )
PGH Log. i ( TAG , " 🏷️ Type 1: ${pokemonInfo.primaryType} " )
PGH Log. i ( TAG , " 🏷️ Type 2: ${pokemonInfo.secondaryType} " )
PGH Log. i ( TAG , " 🏆 Stamps: ${pokemonInfo.stamps} " )
PGH Log. i ( TAG , " 🏷️ Labels: ${pokemonInfo.labels} " )
PGH Log. i ( TAG , " ✅ Marks: ${pokemonInfo.marks} " )
if ( pokemonInfo . stats != null ) {
Log . i ( TAG , " 📈 Stats: HP: ${pokemonInfo.stats.hp} ATK: ${pokemonInfo.stats.attack} DEF: ${pokemonInfo.stats.defense} " )
Log . i ( TAG , " SP.ATK: ${pokemonInfo.stats.spAttack} SP.DEF: ${pokemonInfo.stats.spDefense} SPD: ${pokemonInfo.stats.speed} " )
PGH Log. i ( TAG , " 📈 Stats: HP: ${pokemonInfo.stats.hp} ATK: ${pokemonInfo.stats.attack} DEF: ${pokemonInfo.stats.defense} " )
PGH Log. i ( TAG , " SP.ATK: ${pokemonInfo.stats.spAttack} SP.DEF: ${pokemonInfo.stats.spDefense} SPD: ${pokemonInfo.stats.speed} " )
}
Log . i ( TAG , " ⚔️ Moves: ${pokemonInfo.moves} " )
Log . i ( TAG , " 💪 Ability: ${pokemonInfo.ability} " )
Log . i ( TAG , " 🎭 Nature: ${pokemonInfo.nature} " )
Log . i ( TAG , " 👤 OT: ${pokemonInfo.originalTrainerName} " )
Log . i ( TAG , " 🔢 ID: ${pokemonInfo.originalTrainerId} " )
Log . i ( TAG , " 🎯 Confidence: ${String.format("%.2f", pokemonInfo.extractionConfidence)} " )
Log . i ( TAG , " ==================================== " )
PGH Log. i ( TAG , " ⚔️ Moves: ${pokemonInfo.moves} " )
PGH Log. i ( TAG , " 💪 Ability: ${pokemonInfo.ability} " )
PGH Log. i ( TAG , " 🎭 Nature: ${pokemonInfo.nature} " )
PGH Log. i ( TAG , " 👤 OT: ${pokemonInfo.originalTrainerName} " )
PGH Log. i ( TAG , " 🔢 ID: ${pokemonInfo.originalTrainerId} " )
PGH Log. i ( TAG , " 🎯 Confidence: ${String.format("%.2f", pokemonInfo.extractionConfidence)} " )
PGH Log. i ( TAG , " ==================================== " )
}
private fun convertImageToMat ( image : Image ) : Mat ? {
@ -1119,7 +1133,7 @@ class ScreenCaptureService : Service() {
// Get screen dimensions from the manager
val screenDimensions = screenCaptureManager . getScreenDimensions ( )
if ( screenDimensions == null ) {
Log . e ( TAG , " Screen dimensions not available from manager " )
PGH Log. e ( TAG , " Screen dimensions not available from manager " )
return null
}
val ( screenWidth , screenHeight ) = screenDimensions
@ -1162,7 +1176,7 @@ class ScreenCaptureService : Service() {
bgrMat
} catch ( e : Exception ) {
Log . e ( TAG , " ❌ Error converting image to Mat " , e )
PGH Log. e ( TAG , " ❌ Error converting image to Mat " , e )
// Clean up on error
mat ?. release ( )
if ( croppedBitmap != null && croppedBitmap != bitmap ) {
@ -1174,7 +1188,7 @@ class ScreenCaptureService : Service() {
}
private fun triggerManualDetection ( ) {
Log . d ( TAG , " 🔍 Manual detection triggered via MVC! " )
PGH Log. d ( TAG , " 🔍 Manual detection triggered via MVC! " )
latestImage ?. let { image ->
try {
@ -1187,7 +1201,7 @@ class ScreenCaptureService : Service() {
Utils . matToBitmap ( mat , bitmap )
val detections : List < MLDetection > = runBlocking {
mlInferenceEngine ?. detect ( bitmap ) ?: emptyList ( )
mlInferenceEngine ?. detect ( bitmap ) ?. getOrDefault ( emptyList ( ) ) ?: emptyList ( )
}
// Show detection overlay with results
@ -1200,7 +1214,7 @@ class ScreenCaptureService : Service() {
mat . release ( )
} else {
Log . e ( TAG , " ❌ Failed to convert image to Mat " )
PGH Log. e ( TAG , " ❌ Failed to convert image to Mat " )
}
// Close the image after processing to free the buffer
@ -1208,10 +1222,10 @@ class ScreenCaptureService : Service() {
latestImage = null
} catch ( e : Exception ) {
Log . e ( TAG , " ❌ Error in manual detection " , e )
PGH Log. e ( TAG , " ❌ Error in manual detection " , e )
}
} ?: run {
Log . w ( TAG , " ⚠️ No image available for detection " )
PGH Log. w ( TAG , " ⚠️ No image available for detection " )
}
}
@ -1233,11 +1247,11 @@ class ScreenCaptureService : Service() {
ocrExecutor . shutdown ( )
try {
if ( ! ocrExecutor . awaitTermination ( 5 , TimeUnit . SECONDS ) ) {
Log . w ( TAG , " OCR executor did not terminate gracefully, forcing shutdown " )
PGH Log. w ( TAG , " OCR executor did not terminate gracefully, forcing shutdown " )
ocrExecutor . shutdownNow ( )
}
} catch ( e : InterruptedException ) {
Log . w ( TAG , " Interrupted while waiting for OCR executor termination " )
PGH Log. w ( TAG , " Interrupted while waiting for OCR executor termination " )
ocrExecutor . shutdownNow ( )
Thread . currentThread ( ) . interrupt ( )
}