package com.quillstudios.pokegoalshelper.ml /** * Categories of ML/CV operation errors for better error handling */ enum class MLErrorType(val description: String) { INITIALIZATION_FAILED("Model initialization failed"), INFERENCE_FAILED("Model inference failed"), PREPROCESSING_FAILED("Image preprocessing failed"), POSTPROCESSING_FAILED("Result postprocessing failed"), MEMORY_ERROR("Memory allocation error"), INVALID_INPUT("Invalid input data"), TIMEOUT_ERROR("Operation timed out"), RESOURCE_ERROR("Resource management error"), CONFIGURATION_ERROR("Configuration error"), UNKNOWN_ERROR("Unknown error occurred") } /** * Result wrapper for ML operations to standardize error handling */ sealed class MLResult { data class Success(val data: T) : MLResult() data class Error(val errorType: MLErrorType, val exception: Throwable, val message: String) : MLResult() /** * Returns the data if successful, or null if error */ fun getOrNull(): T? = when (this) { is Success -> data is Error -> null } /** * Returns the data if successful, or the default value if error */ fun getOrDefault(default: @UnsafeVariance T): T = when (this) { is Success -> data is Error -> default } /** * Execute block if successful */ inline fun onSuccess(block: (T) -> Unit): MLResult { if (this is Success) block(data) return this } /** * Execute block if error */ inline fun onError(block: (MLErrorType, Throwable, String) -> Unit): MLResult { if (this is Error) block(errorType, exception, message) return this } /** * Execute block if specific error type */ inline fun onErrorType(errorType: MLErrorType, block: (Throwable, String) -> Unit): MLResult { if (this is Error && this.errorType == errorType) block(exception, message) return this } /** * Transform the data if successful */ inline fun map(transform: (T) -> R): MLResult = when (this) { is Success -> try { Success(transform(data)) } catch (e: Exception) { Error(MLErrorType.UNKNOWN_ERROR, e, "Transform failed: ${e.message}") } is Error -> this } } /** * Helper functions for creating results */ inline fun mlTry(errorType: MLErrorType, operation: () -> T): MLResult { return try { MLResult.Success(operation()) } catch (e: Exception) { MLResult.Error(errorType, e, "${errorType.description}: ${e.message}") } } inline fun mlTryWithMessage(errorType: MLErrorType, message: String, operation: () -> T): MLResult { return try { MLResult.Success(operation()) } catch (e: Exception) { MLResult.Error(errorType, e, "$message: ${e.message}") } } /** * Create an error result directly */ fun mlError(errorType: MLErrorType, message: String, cause: Throwable? = null): MLResult { val exception = cause ?: RuntimeException(message) return MLResult.Error(errorType, exception, message) } /** * Create an error result from exception */ fun mlErrorFromException(errorType: MLErrorType, exception: Throwable, customMessage: String? = null): MLResult { val message = customMessage ?: "${errorType.description}: ${exception.message}" return MLResult.Error(errorType, exception, message) }