From 0c0a1f1765331721c046f44da8b9f5bf84a89efd Mon Sep 17 00:00:00 2001 From: Martin Georgiev <3349414+Thinkorswim@users.noreply.github.com> Date: Tue, 21 Oct 2025 17:16:49 +0300 Subject: [PATCH 01/12] Add a separate quality assessment library --- build.gradle.kts | 4 + gradle/libs.versions.toml | 12 + settings.gradle.kts | 4 +- simq/.gitignore | 1 + simq/build.gradle.kts | 52 ++++ simq/consumer-rules.pro | 0 simq/proguard-rules.pro | 21 ++ simq/src/main/AndroidManifest.xml | 4 + .../com/simprints/simq/QualityParameters.kt | 26 ++ .../java/com/simprints/simq/QualityWeights.kt | 17 ++ simq/src/main/java/com/simprints/simq/SimQ.kt | 122 ++++++++ .../simq/analysis/AlignmentAnalysis.kt | 37 +++ .../simprints/simq/analysis/BlurAnalysis.kt | 61 ++++ .../simq/analysis/BrightnessAnalysis.kt | 55 ++++ .../simq/analysis/ContrastAnalysis.kt | 54 ++++ .../com/simprints/simq/utils/OpenCVLoader.kt | 21 ++ .../com/simprints/simq/utils/QualityUtils.kt | 100 ++++++ .../simprints/simq/AlignmentAnalysisTest.kt | 104 +++++++ .../com/simprints/simq/QualityUtilsTest.kt | 222 ++++++++++++++ .../com/simprints/simq/QualityWeightsTest.kt | 82 +++++ .../test/java/com/simprints/simq/SimQTest.kt | 284 ++++++++++++++++++ .../com/simprints/simq/shadows/ShadowCore.kt | 23 ++ .../simprints/simq/shadows/ShadowCvType.kt | 21 ++ .../simprints/simq/shadows/ShadowImgproc.kt | 25 ++ .../com/simprints/simq/shadows/ShadowMat.kt | 33 ++ .../simq/shadows/ShadowMatOfDouble.kt | 25 ++ .../simq/shadows/ShadowOpenCVLoader.kt | 23 ++ .../simq/shadows/ShadowOpenCVUtils.kt | 23 ++ .../detection/MlKitFaceDetectionProcessor.kt | 95 +++--- 29 files changed, 1505 insertions(+), 46 deletions(-) create mode 100644 simq/.gitignore create mode 100644 simq/build.gradle.kts create mode 100644 simq/consumer-rules.pro create mode 100644 simq/proguard-rules.pro create mode 100644 simq/src/main/AndroidManifest.xml create mode 100644 simq/src/main/java/com/simprints/simq/QualityParameters.kt create mode 100644 simq/src/main/java/com/simprints/simq/QualityWeights.kt create mode 100644 simq/src/main/java/com/simprints/simq/SimQ.kt create mode 100644 simq/src/main/java/com/simprints/simq/analysis/AlignmentAnalysis.kt create mode 100644 simq/src/main/java/com/simprints/simq/analysis/BlurAnalysis.kt create mode 100644 simq/src/main/java/com/simprints/simq/analysis/BrightnessAnalysis.kt create mode 100644 simq/src/main/java/com/simprints/simq/analysis/ContrastAnalysis.kt create mode 100644 simq/src/main/java/com/simprints/simq/utils/OpenCVLoader.kt create mode 100644 simq/src/main/java/com/simprints/simq/utils/QualityUtils.kt create mode 100644 simq/src/test/java/com/simprints/simq/AlignmentAnalysisTest.kt create mode 100644 simq/src/test/java/com/simprints/simq/QualityUtilsTest.kt create mode 100644 simq/src/test/java/com/simprints/simq/QualityWeightsTest.kt create mode 100644 simq/src/test/java/com/simprints/simq/SimQTest.kt create mode 100644 simq/src/test/java/com/simprints/simq/shadows/ShadowCore.kt create mode 100644 simq/src/test/java/com/simprints/simq/shadows/ShadowCvType.kt create mode 100644 simq/src/test/java/com/simprints/simq/shadows/ShadowImgproc.kt create mode 100644 simq/src/test/java/com/simprints/simq/shadows/ShadowMat.kt create mode 100644 simq/src/test/java/com/simprints/simq/shadows/ShadowMatOfDouble.kt create mode 100644 simq/src/test/java/com/simprints/simq/shadows/ShadowOpenCVLoader.kt create mode 100644 simq/src/test/java/com/simprints/simq/shadows/ShadowOpenCVUtils.kt diff --git a/build.gradle.kts b/build.gradle.kts index 08d3e95..4dda8ee 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,6 +8,9 @@ val projectGroupId = "com.simprints.biometrics" val projectArtifactId = "simface" val projectVersion = "2025.3.1" +group = projectGroupId +version = projectVersion + android { namespace = "$projectGroupId.$projectArtifactId" @@ -35,6 +38,7 @@ android { } dependencies { + implementation(project(":simq")) // Tensorflow versions that works with Edgeface api(libs.tensorflow.lite.support) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 893e34d..4f65774 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,6 +8,12 @@ tensorflowLiteMetadata = "0.5.0" tensorflowLiteSupport = "0.5.0" faceDetection = "16.1.7" ejmlSimple = "0.44.0" +coreKtx = "1.17.0" +junit = "4.13.2" +appcompat = "1.6.1" +material = "1.10.0" +opencv = "4.10.0" +roboelectric = "4.11.1" [libraries] androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } @@ -18,6 +24,12 @@ tensorflow-lite-metadata = { module = "org.tensorflow:tensorflow-lite-metadata", tensorflow-lite-support = { module = "org.tensorflow:tensorflow-lite-support", version.ref = "tensorflowLiteSupport" } face-detection = { module = "com.google.mlkit:face-detection", version.ref = "faceDetection" } ejml-simple = { module = "org.ejml:ejml-simple", version.ref = "ejmlSimple" } +androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } +junit = { group = "junit", name = "junit", version.ref = "junit" } +androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" } +material = { group = "com.google.android.material", name = "material", version.ref = "material" } +opencv = { module = "org.opencv:opencv", version.ref = "opencv" } +roboelectric = {module = "org.robolectric:robolectric", version.ref = "roboelectric" } [plugins] jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } diff --git a/settings.gradle.kts b/settings.gradle.kts index 48f3186..e953f8c 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -20,5 +20,5 @@ dependencyResolutionManagement { } } -rootProject.name = "Biometrics-SimFace" -include(":Biometrics-SimFace") +rootProject.name = "simface" +include(":simq") diff --git a/simq/.gitignore b/simq/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/simq/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/simq/build.gradle.kts b/simq/build.gradle.kts new file mode 100644 index 0000000..3809e93 --- /dev/null +++ b/simq/build.gradle.kts @@ -0,0 +1,52 @@ +plugins { + alias(libs.plugins.android.library) + alias(libs.plugins.jetbrains.kotlin.android) +} + +android { + namespace = "com.simprints.simq" + compileSdk = 36 + + defaultConfig { + minSdk = 24 + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles("consumer-rules.pro") + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + kotlinOptions { + jvmTarget = "11" + } + + testOptions { + unitTests { + isIncludeAndroidResources = true + } + } +} + +dependencies { + + implementation(libs.androidx.core.ktx) + implementation(libs.androidx.appcompat) + implementation(libs.material) + api(libs.opencv) + + testImplementation(libs.junit) + testImplementation(libs.roboelectric) + androidTestImplementation(libs.androidx.junit) + androidTestImplementation(libs.androidx.espresso.core) +} diff --git a/simq/consumer-rules.pro b/simq/consumer-rules.pro new file mode 100644 index 0000000..e69de29 diff --git a/simq/proguard-rules.pro b/simq/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/simq/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/simq/src/main/AndroidManifest.xml b/simq/src/main/AndroidManifest.xml new file mode 100644 index 0000000..8bdb7e1 --- /dev/null +++ b/simq/src/main/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + + diff --git a/simq/src/main/java/com/simprints/simq/QualityParameters.kt b/simq/src/main/java/com/simprints/simq/QualityParameters.kt new file mode 100644 index 0000000..0942dbb --- /dev/null +++ b/simq/src/main/java/com/simprints/simq/QualityParameters.kt @@ -0,0 +1,26 @@ +package com.simprints.simq + +data class QualityParameters( + // Alignment thresholds + val maxAlignmentAngle: Double = 20.0, + val maxIndividualAngle: Double = 25.0, + + // Blur thresholds (Laplacian variance) + val minBlur: Double = 50_000.0, + val maxBlur: Double = 100_000.0, + + // Brightness thresholds (0-255) + val minBrightness: Double = 30.0, + val optimalBrightnessLow: Double = 80.0, + val optimalBrightnessHigh: Double = 150.0, + val maxBrightness: Double = 190.0, + val brightnessSteepness: Double = 0.3, + + // Contrast thresholds (std dev) + val minContrast: Double = 30.0, + val maxContrast: Double = 47.0 +) { + companion object { + val DEFAULT = QualityParameters() + } +} diff --git a/simq/src/main/java/com/simprints/simq/QualityWeights.kt b/simq/src/main/java/com/simprints/simq/QualityWeights.kt new file mode 100644 index 0000000..23ead10 --- /dev/null +++ b/simq/src/main/java/com/simprints/simq/QualityWeights.kt @@ -0,0 +1,17 @@ +package com.simprints.simq + +/** + * Default quality weights for face assessment. + * These control how much each metric contributes to the final score. + */ +data class QualityWeights( + val alignment: Double = 0.3, + val blur: Double = 0.3, + val brightness: Double = 0.3, + val contrast: Double = 0.1, + val eyeOpenness: Double = 0.0 +) { + companion object { + val DEFAULT = QualityWeights() + } +} diff --git a/simq/src/main/java/com/simprints/simq/SimQ.kt b/simq/src/main/java/com/simprints/simq/SimQ.kt new file mode 100644 index 0000000..9ff5865 --- /dev/null +++ b/simq/src/main/java/com/simprints/simq/SimQ.kt @@ -0,0 +1,122 @@ +package com.simprints.simq + +import android.graphics.Bitmap +import com.simprints.simq.analysis.AlignmentAnalysis +import com.simprints.simq.analysis.BlurAnalysis +import com.simprints.simq.analysis.BrightnessAnalysis +import com.simprints.simq.analysis.ContrastAnalysis +import com.simprints.simq.utils.OpenCVLoader +import com.simprints.simq.utils.QualityUtils + +object SimQ { + + init { + OpenCVLoader.init() + } + + /** + * Calculates face quality score (0.0 - 1.0). + * + * @param bitmap The cropped face bitmap + * @param imageWidth Width of the original full image (not used in current implementation) + * @param imageHeight Height of the original full image (not used in current implementation) + * @param boundingBox Bounding box of the face in the original image (not used in current implementation) + * @param pitch Face pitch angle in degrees (head nod, default: 0.0) + * @param yaw Face yaw angle in degrees (head rotation, default: 0.0) + * @param roll Face roll angle in degrees (head tilt, default: 0.0) + * @param leftEyeOpenness Left eye openness probability (0.0-1.0, optional) + * @param rightEyeOpenness Right eye openness probability (0.0-1.0, optional) + * @param centerCrop Fraction of the bitmap to use for quality assessment (default: 0.5) + * @param horizontalDisplacement Horizontal displacement for center crop (default: 0.0) + * @param verticalDisplacement Vertical displacement for center crop (default: 0.0) + * @param weights Custom weights for quality metrics (optional) + * @param parameters Custom quality parameters (optional) + * @return Quality score between 0.0 and 1.0, or 0.0 if calculation fails + */ + @JvmStatic + fun calculateFaceQuality( + bitmap: Bitmap, + pitch: Double = 0.0, + yaw: Double = 0.0, + roll: Double = 0.0, + leftEyeOpenness: Double? = null, + rightEyeOpenness: Double? = null, + centerCrop: Float = 0.5f, + horizontalDisplacement: Float = 0.0f, + verticalDisplacement: Float = 0.0f, + weights: QualityWeights = QualityWeights.DEFAULT, + parameters: QualityParameters = QualityParameters.DEFAULT + ): Float { + return try { + // Resize bitmap to target area (256x256 = 65536) + val resizedBitmap = QualityUtils.resizeBitmap(bitmap, 65536.0) + + // Crop the bitmap + val croppedBitmap = QualityUtils.centerCropBitmap( + resizedBitmap, + centerCrop, + horizontalDisplacement, + verticalDisplacement + ) + + var totalScore = 0.0 + var totalWeight = 0.0 + + val alignmentScore = AlignmentAnalysis.calculateScore( + pitch, yaw, roll, + parameters.maxAlignmentAngle, + parameters.maxIndividualAngle + ) + totalScore += weights.alignment * alignmentScore + totalWeight += weights.alignment + + val blurScore = BlurAnalysis.calculateScore( + croppedBitmap, + parameters.minBlur, + parameters.maxBlur + ) + totalScore += weights.blur * blurScore + totalWeight += weights.blur + + val brightnessScore = BrightnessAnalysis.calculateScore( + croppedBitmap, + parameters.minBrightness, + parameters.optimalBrightnessLow, + parameters.optimalBrightnessHigh, + parameters.maxBrightness, + parameters.brightnessSteepness + ) + totalScore += weights.brightness * brightnessScore + totalWeight += weights.brightness + + val contrastScore = ContrastAnalysis.calculateScore( + croppedBitmap, + parameters.minContrast, + parameters.maxContrast + ) + totalScore += weights.contrast * contrastScore + totalWeight += weights.contrast + + if (leftEyeOpenness != null && rightEyeOpenness != null) { + val eyeScore = (leftEyeOpenness + rightEyeOpenness) / 2.0 + totalScore += weights.eyeOpenness * eyeScore + totalWeight += weights.eyeOpenness + } + + // Clean up + if (croppedBitmap != bitmap && croppedBitmap != resizedBitmap) { + croppedBitmap.recycle() + } + if (resizedBitmap != bitmap) { + resizedBitmap.recycle() + } + + // Normalize and clamp to 0-1 range + val finalScore = if (totalWeight > 0) totalScore / totalWeight else 0.0 + finalScore.coerceIn(0.0, 1.0).toFloat() + + } catch (e: Exception) { + 0.0f + } + } +} diff --git a/simq/src/main/java/com/simprints/simq/analysis/AlignmentAnalysis.kt b/simq/src/main/java/com/simprints/simq/analysis/AlignmentAnalysis.kt new file mode 100644 index 0000000..74c4947 --- /dev/null +++ b/simq/src/main/java/com/simprints/simq/analysis/AlignmentAnalysis.kt @@ -0,0 +1,37 @@ +package com.simprints.simq.analysis + +import kotlin.math.absoluteValue + +object AlignmentAnalysis { + + /** + * Calculates alignment score based on pitch, yaw, and roll angles. + * + * @param pitch Face pitch angle in degrees (head nod) + * @param yaw Face yaw angle in degrees (head rotation) + * @param roll Face roll angle in degrees (head tilt) + * @param maxAngle Maximum acceptable angle for quality scoring + * @param maxIndividualAngle Absolute maximum angle before rejection + * @return Alignment score between 0.0 and 1.0 + */ + fun calculateScore( + pitch: Double, + yaw: Double, + roll: Double, + maxAngle: Double, + maxIndividualAngle: Double + ): Double { + // Reject if any angle is too extreme + if (pitch.absoluteValue > maxIndividualAngle || + yaw.absoluteValue > maxIndividualAngle || + roll.absoluteValue > maxIndividualAngle) { + return 0.0 + } + + val pitchScore = maxOf(0.0, 1.0 - (pitch.absoluteValue / maxAngle)) + val yawScore = maxOf(0.0, 1.0 - (yaw.absoluteValue / maxAngle)) + val rollScore = maxOf(0.0, 1.0 - (roll.absoluteValue / maxAngle)) + + return (pitchScore + yawScore + rollScore) / 3.0 + } +} diff --git a/simq/src/main/java/com/simprints/simq/analysis/BlurAnalysis.kt b/simq/src/main/java/com/simprints/simq/analysis/BlurAnalysis.kt new file mode 100644 index 0000000..4c2637a --- /dev/null +++ b/simq/src/main/java/com/simprints/simq/analysis/BlurAnalysis.kt @@ -0,0 +1,61 @@ +package com.simprints.simq.analysis + +import android.graphics.Bitmap +import com.simprints.simq.utils.QualityUtils +import org.opencv.android.Utils +import org.opencv.core.Core +import org.opencv.core.CvType +import org.opencv.core.Mat +import org.opencv.core.MatOfDouble +import org.opencv.imgproc.Imgproc +import kotlin.math.pow + +object BlurAnalysis { + + /** + * Calculates blur score using Laplacian variance. + * + * @param bitmap The face image to analyze + * @param minBlur Minimum acceptable blur threshold + * @param maxBlur Maximum blur threshold for optimal score + * @return Blur score between 0.0 and 1.0 + */ + fun calculateScore(bitmap: Bitmap, minBlur: Double, maxBlur: Double): Double { + return try { + val laplacianVariance = calculateLaplacianVariance(bitmap) + QualityUtils.rampScore(laplacianVariance, minBlur, maxBlur) + } catch (e: Exception) { + 1.0 // Default to good score if OpenCV not available + } + } + + /** + * Calculates Laplacian blur variance using OpenCV. + * + * @param bitmap The face image to analyze + * @param ksize Kernel size for Laplacian operator (default: 5) + * @return Laplacian variance value + */ + private fun calculateLaplacianVariance(bitmap: Bitmap, ksize: Int = 5): Double { + val mat = Mat() + val gray = Mat() + Utils.bitmapToMat(bitmap, mat) + Imgproc.cvtColor(mat, gray, Imgproc.COLOR_BGR2GRAY) + + val laplacian = Mat() + Imgproc.Laplacian(gray, laplacian, CvType.CV_64F, ksize) + + val mean = MatOfDouble() + val stddev = MatOfDouble() + Core.meanStdDev(laplacian, mean, stddev) + val laplacianVariance = stddev.toArray()[0].pow(2.0) + + mat.release() + gray.release() + laplacian.release() + mean.release() + stddev.release() + + return laplacianVariance + } +} diff --git a/simq/src/main/java/com/simprints/simq/analysis/BrightnessAnalysis.kt b/simq/src/main/java/com/simprints/simq/analysis/BrightnessAnalysis.kt new file mode 100644 index 0000000..6630661 --- /dev/null +++ b/simq/src/main/java/com/simprints/simq/analysis/BrightnessAnalysis.kt @@ -0,0 +1,55 @@ +package com.simprints.simq.analysis + +import android.graphics.Bitmap +import com.simprints.simq.utils.QualityUtils +import org.opencv.android.Utils +import org.opencv.core.Core +import org.opencv.core.Mat +import org.opencv.imgproc.Imgproc + +object BrightnessAnalysis { + + /** + * Calculates brightness score using plateau function. + * + * @param bitmap The face image to analyze + * @param edgeLow Lower edge threshold (minimum acceptable brightness) + * @param centerLow Lower center threshold (start of optimal range) + * @param centerHigh Upper center threshold (end of optimal range) + * @param edgeHigh Upper edge threshold (maximum acceptable brightness) + * @param steepness Steepness of the sigmoid falloff + * @return Brightness score between 0.0 and 1.0 + */ + fun calculateScore( + bitmap: Bitmap, + edgeLow: Double, + centerLow: Double, + centerHigh: Double, + edgeHigh: Double, + steepness: Double + ): Double { + return try { + val brightness = analyzeBrightness(bitmap) + QualityUtils.plateauScore(brightness, centerLow, centerHigh, edgeLow, edgeHigh, steepness) + } catch (e: Exception) { + 1.0 + } + } + + /** + * Analyzes brightness of bitmap using OpenCV. + * + * @param bitmap The face image to analyze + * @return Mean brightness value (0-255) + */ + private fun analyzeBrightness(bitmap: Bitmap): Double { + val mat = Mat() + val gray = Mat() + Utils.bitmapToMat(bitmap, mat) + Imgproc.cvtColor(mat, gray, Imgproc.COLOR_BGR2GRAY) + val brightness = Core.mean(gray).`val`[0] + mat.release() + gray.release() + return brightness + } +} diff --git a/simq/src/main/java/com/simprints/simq/analysis/ContrastAnalysis.kt b/simq/src/main/java/com/simprints/simq/analysis/ContrastAnalysis.kt new file mode 100644 index 0000000..239517a --- /dev/null +++ b/simq/src/main/java/com/simprints/simq/analysis/ContrastAnalysis.kt @@ -0,0 +1,54 @@ +package com.simprints.simq.analysis + +import android.graphics.Bitmap +import com.simprints.simq.utils.QualityUtils +import org.opencv.android.Utils +import org.opencv.core.Core +import org.opencv.core.Mat +import org.opencv.core.MatOfDouble +import org.opencv.imgproc.Imgproc + +object ContrastAnalysis { + + /** + * Calculates contrast score using standard deviation. + * + * @param bitmap The face image to analyze + * @param minContrast Minimum acceptable contrast threshold + * @param maxContrast Maximum contrast threshold for optimal score + * @return Contrast score between 0.0 and 1.0 + */ + fun calculateScore(bitmap: Bitmap, minContrast: Double, maxContrast: Double): Double { + return try { + val contrast = analyzeContrast(bitmap) + QualityUtils.rampScore(contrast, minContrast, maxContrast) + } catch (e: Exception) { + 1.0 // Default to good score if OpenCV not available + } + } + + /** + * Analyzes contrast of bitmap using OpenCV (standard deviation). + * + * @param bitmap The face image to analyze + * @return Standard deviation value representing contrast + */ + private fun analyzeContrast(bitmap: Bitmap): Double { + val mat = Mat() + val gray = Mat() + Utils.bitmapToMat(bitmap, mat) + Imgproc.cvtColor(mat, gray, Imgproc.COLOR_BGR2GRAY) + + val mean = MatOfDouble() + val stddev = MatOfDouble() + Core.meanStdDev(gray, mean, stddev) + val stdDevValue = stddev.toArray()[0] + + mat.release() + gray.release() + mean.release() + stddev.release() + + return stdDevValue + } +} diff --git a/simq/src/main/java/com/simprints/simq/utils/OpenCVLoader.kt b/simq/src/main/java/com/simprints/simq/utils/OpenCVLoader.kt new file mode 100644 index 0000000..b623a1f --- /dev/null +++ b/simq/src/main/java/com/simprints/simq/utils/OpenCVLoader.kt @@ -0,0 +1,21 @@ +package com.simprints.simq.utils + +import android.util.Log +import org.opencv.android.OpenCVLoader as AndroidOpenCVLoader + +/** + * Singleton object to handle OpenCV library loading. + * Ensures the native library is loaded only once during the application lifecycle. + */ +object OpenCVLoader { + + private const val TAG = "OpenCV" + + fun init() { + if (!AndroidOpenCVLoader.initLocal()) { + Log.e(TAG, "OpenCV not loaded!") + } else { + Log.d(TAG, "OpenCV loaded successfully!") + } + } +} diff --git a/simq/src/main/java/com/simprints/simq/utils/QualityUtils.kt b/simq/src/main/java/com/simprints/simq/utils/QualityUtils.kt new file mode 100644 index 0000000..7a3f3f9 --- /dev/null +++ b/simq/src/main/java/com/simprints/simq/utils/QualityUtils.kt @@ -0,0 +1,100 @@ +package com.simprints.simq.utils + +import android.graphics.Bitmap +import kotlin.math.exp +import kotlin.math.roundToInt +import kotlin.math.sqrt + +object QualityUtils { + + /** + * Ramp scoring function: linear interpolation between min and max. + * + * @param x The input value to score + * @param min Minimum threshold (scores 0.0 below this) + * @param max Maximum threshold (scores 1.0 above this) + * @return Score between 0.0 and 1.0 + */ + fun rampScore(x: Double, min: Double, max: Double): Double { + return when { + x < min -> 0.0 + x > max -> 1.0 + else -> (x - min) / (max - min) + } + } + + /** + * Plateau scoring function: optimal range with smooth sigmoid falloff. + * + * @param x The input value to score + * @param centerLow Lower bound of optimal range + * @param centerHigh Upper bound of optimal range + * @param edgeLow Lower edge threshold + * @param edgeHigh Upper edge threshold + * @param steepness Steepness of sigmoid falloff + * @return Score between 0.0 and 1.0 + */ + fun plateauScore( + x: Double, + centerLow: Double, + centerHigh: Double, + edgeLow: Double, + edgeHigh: Double, + steepness: Double + ): Double { + return when { + x in centerLow..centerHigh -> 1.0 + x < centerLow -> 1.0 / (1.0 + exp(-steepness * (x - edgeLow))) + else -> 1.0 / (1.0 + exp(steepness * (x - edgeHigh))) + }.coerceIn(0.0, 1.0) + } + + /** + * Crops bitmap to center region with optional displacement. + * + * @param bitmap The bitmap to crop + * @param centerCrop Fraction of the bitmap to use (0.0-1.0) + * @param horizontalDisplacement Horizontal displacement factor (-1.0 to 1.0) + * @param verticalDisplacement Vertical displacement factor (-1.0 to 1.0) + * @return Cropped bitmap + */ + fun centerCropBitmap( + bitmap: Bitmap, + centerCrop: Float, + horizontalDisplacement: Float, + verticalDisplacement: Float + ): Bitmap { + val width = bitmap.width + val height = bitmap.height + + val hAbsDisplacement = (width * horizontalDisplacement).toInt() + val vAbsDisplacement = (height * verticalDisplacement).toInt() + + val cropWidth = (width * centerCrop).toInt() + val cropHeight = (height * centerCrop).toInt() + val startX = hAbsDisplacement + (width - cropWidth) / 2 + val startY = vAbsDisplacement + (height - cropHeight) / 2 + + return Bitmap.createBitmap(bitmap, startX, startY, cropWidth, cropHeight) + } + + /** + * Resizes bitmap to a target area while maintaining aspect ratio. + * + * @param bitmap The bitmap to resize + * @param targetArea Target area in pixels (default: 65536 = 256x256) + * @return Resized bitmap + */ + fun resizeBitmap(bitmap: Bitmap, targetArea: Double = 65536.0): Bitmap { + val aspectRatio = bitmap.width.toFloat() / bitmap.height.toFloat() + val newHeight = sqrt(targetArea / aspectRatio) + val newWidth = aspectRatio * newHeight + + return Bitmap.createScaledBitmap( + bitmap, + newWidth.roundToInt(), + newHeight.roundToInt(), + true + ) + } +} diff --git a/simq/src/test/java/com/simprints/simq/AlignmentAnalysisTest.kt b/simq/src/test/java/com/simprints/simq/AlignmentAnalysisTest.kt new file mode 100644 index 0000000..e002a39 --- /dev/null +++ b/simq/src/test/java/com/simprints/simq/AlignmentAnalysisTest.kt @@ -0,0 +1,104 @@ +package com.simprints.simq + +import com.simprints.simq.analysis.AlignmentAnalysis +import org.junit.Assert +import org.junit.Test + +class AlignmentAnalysisTest { + + private val maxAngle = 20.0 + private val maxIndividualAngle = 25.0 + + @Test + fun `perfect alignment returns score of 1_0`() { + val score = AlignmentAnalysis.calculateScore( + pitch = 0.0, + yaw = 0.0, + roll = 0.0, + maxAngle = maxAngle, + maxIndividualAngle = maxIndividualAngle + ) + Assert.assertEquals(1.0, score, 0.001) + } + + @Test + fun `angle at half max threshold returns score of 0_5`() { + val halfAngle = maxAngle / 2 + val score = AlignmentAnalysis.calculateScore( + pitch = halfAngle, + yaw = halfAngle, + roll = halfAngle, + maxAngle = maxAngle, + maxIndividualAngle = maxIndividualAngle + ) + Assert.assertEquals(0.5, score, 0.001) + } + + @Test + fun `negative angles are treated as absolute values`() { + val score1 = AlignmentAnalysis.calculateScore( + pitch = -10.0, + yaw = -10.0, + roll = -10.0, + maxAngle = maxAngle, + maxIndividualAngle = maxIndividualAngle + ) + + val score2 = AlignmentAnalysis.calculateScore( + pitch = 10.0, + yaw = 10.0, + roll = 10.0, + maxAngle = maxAngle, + maxIndividualAngle = maxIndividualAngle + ) + + Assert.assertEquals(score1, score2, 0.001) + } + + @Test + fun `any single angle exceeding maxIndividualAngle rejects entire score`() { + // Test pitch rejection + val pitchScore = AlignmentAnalysis.calculateScore( + pitch = 26.0, + yaw = 0.0, + roll = 0.0, + maxAngle = maxAngle, + maxIndividualAngle = maxIndividualAngle + ) + Assert.assertEquals(0.0, pitchScore, 0.001) + + // Test yaw rejection + val yawScore = AlignmentAnalysis.calculateScore( + pitch = 0.0, + yaw = 26.0, + roll = 0.0, + maxAngle = maxAngle, + maxIndividualAngle = maxIndividualAngle + ) + Assert.assertEquals(0.0, yawScore, 0.001) + + // Test roll rejection + val rollScore = AlignmentAnalysis.calculateScore( + pitch = 0.0, + yaw = 0.0, + roll = 26.0, + maxAngle = maxAngle, + maxIndividualAngle = maxIndividualAngle + ) + Assert.assertEquals(0.0, rollScore, 0.001) + } + + @Test + fun `mixed angles calculate average score correctly`() { + // Perfect pitch, half-max yaw, max roll + val score = AlignmentAnalysis.calculateScore( + pitch = 0.0, // Score: 1.0 + yaw = 10.0, // Score: 0.5 (10/20) + roll = 20.0, // Score: 0.0 (20/20) + maxAngle = maxAngle, + maxIndividualAngle = maxIndividualAngle + ) + // Average: (1.0 + 0.5 + 0.0) / 3 = 0.5 + Assert.assertEquals(0.5, score, 0.001) + } +} diff --git a/simq/src/test/java/com/simprints/simq/QualityUtilsTest.kt b/simq/src/test/java/com/simprints/simq/QualityUtilsTest.kt new file mode 100644 index 0000000..37973d7 --- /dev/null +++ b/simq/src/test/java/com/simprints/simq/QualityUtilsTest.kt @@ -0,0 +1,222 @@ +package com.simprints.simq + +import android.graphics.Bitmap +import com.simprints.simq.utils.QualityUtils +import org.junit.Assert +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner + +@RunWith(RobolectricTestRunner::class) +class QualityUtilsTest { + + @Test + fun `rampScore returns 0 when below minimum`() { + val score = QualityUtils.rampScore(x = 10.0, min = 20.0, max = 100.0) + Assert.assertEquals(0.0, score, 0.001) + } + + @Test + fun `rampScore returns 1 when above maximum`() { + val score = QualityUtils.rampScore(x = 150.0, min = 20.0, max = 100.0) + Assert.assertEquals(1.0, score, 0.001) + } + + @Test + fun `rampScore returns 0_5 at midpoint`() { + val score = QualityUtils.rampScore(x = 60.0, min = 20.0, max = 100.0) + Assert.assertEquals(0.5, score, 0.001) + } + + @Test + fun `rampScore interpolates linearly`() { + val score = QualityUtils.rampScore(x = 30.0, min = 20.0, max = 120.0) + // (30 - 20) / (120 - 20) = 10/100 = 0.1 + Assert.assertEquals(0.1, score, 0.001) + } + + @Test + fun `plateauScore returns 1 in optimal range`() { + val score1 = QualityUtils.plateauScore( + x = 100.0, + centerLow = 80.0, + centerHigh = 150.0, + edgeLow = 30.0, + edgeHigh = 190.0, + steepness = 0.3 + ) + Assert.assertEquals(1.0, score1, 0.001) + + val score2 = QualityUtils.plateauScore( + x = 80.0, + centerLow = 80.0, + centerHigh = 150.0, + edgeLow = 30.0, + edgeHigh = 190.0, + steepness = 0.3 + ) + Assert.assertEquals(1.0, score2, 0.001) + + val score3 = QualityUtils.plateauScore( + x = 150.0, + centerLow = 80.0, + centerHigh = 150.0, + edgeLow = 30.0, + edgeHigh = 190.0, + steepness = 0.3 + ) + Assert.assertEquals(1.0, score3, 0.001) + } + + @Test + fun `plateauScore decreases outside optimal range`() { + // Below center + val scoreLow = QualityUtils.plateauScore( + x = 50.0, + centerLow = 80.0, + centerHigh = 150.0, + edgeLow = 30.0, + edgeHigh = 190.0, + steepness = 0.3 + ) + Assert.assertTrue(scoreLow < 1.0) + Assert.assertTrue(scoreLow > 0.0) + + // Above center + val scoreHigh = QualityUtils.plateauScore( + x = 170.0, + centerLow = 80.0, + centerHigh = 150.0, + edgeLow = 30.0, + edgeHigh = 190.0, + steepness = 0.3 + ) + Assert.assertTrue(scoreHigh < 1.0) + Assert.assertTrue(scoreHigh > 0.0) + } + + @Test + fun `plateauScore is clamped between 0 and 1`() { + val scoreVeryLow = QualityUtils.plateauScore( + x = 0.0, + centerLow = 80.0, + centerHigh = 150.0, + edgeLow = 30.0, + edgeHigh = 190.0, + steepness = 0.3 + ) + Assert.assertTrue(scoreVeryLow >= 0.0 && scoreVeryLow <= 1.0) + + val scoreVeryHigh = QualityUtils.plateauScore( + x = 300.0, + centerLow = 80.0, + centerHigh = 150.0, + edgeLow = 30.0, + edgeHigh = 190.0, + steepness = 0.3 + ) + Assert.assertTrue(scoreVeryHigh >= 0.0 && scoreVeryHigh <= 1.0) + } + + @Test + fun `plateauScore is symmetric around optimal range`() { + val scoreLow = QualityUtils.plateauScore( + x = 50.0, + centerLow = 80.0, + centerHigh = 150.0, + edgeLow = 30.0, + edgeHigh = 190.0, + steepness = 0.3 + ) + + val scoreHigh = QualityUtils.plateauScore( + x = 180.0, + centerLow = 80.0, + centerHigh = 150.0, + edgeLow = 30.0, + edgeHigh = 190.0, + steepness = 0.3 + ) + + // Should be approximately equal due to symmetry + Assert.assertEquals(scoreLow, scoreHigh, 0.1) + } + + @Test + fun `centerCropBitmap with no displacement crops center`() { + val bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888) + val cropped = QualityUtils.centerCropBitmap( + bitmap = bitmap, + centerCrop = 0.5f, + horizontalDisplacement = 0.0f, + verticalDisplacement = 0.0f + ) + + Assert.assertEquals(50, cropped.width) + Assert.assertEquals(50, cropped.height) + } + + @Test + fun `centerCropBitmap with full crop returns same size`() { + val bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888) + val cropped = QualityUtils.centerCropBitmap( + bitmap = bitmap, + centerCrop = 1.0f, + horizontalDisplacement = 0.0f, + verticalDisplacement = 0.0f + ) + + Assert.assertEquals(100, cropped.width) + Assert.assertEquals(100, cropped.height) + } + + @Test + fun `resizeBitmap maintains aspect ratio for square bitmap`() { + val bitmap = Bitmap.createBitmap(512, 512, Bitmap.Config.ARGB_8888) + val resized = QualityUtils.resizeBitmap(bitmap, targetArea = 65536.0) + + Assert.assertEquals(256, resized.width) + Assert.assertEquals(256, resized.height) + } + + @Test + fun `resizeBitmap maintains aspect ratio for rectangular bitmap`() { + val bitmap = Bitmap.createBitmap(800, 400, Bitmap.Config.ARGB_8888) + val resized = QualityUtils.resizeBitmap(bitmap, targetArea = 65536.0) + + val aspectRatio = resized.width.toDouble() / resized.height.toDouble() + Assert.assertEquals(2.0, aspectRatio, 0.01) + + val area = resized.width * resized.height + Assert.assertEquals(65536.0, area.toDouble(), 1000.0) + } + + @Test + fun `resizeBitmap scales down large bitmap`() { + val bitmap = Bitmap.createBitmap(1024, 1024, Bitmap.Config.ARGB_8888) + val resized = QualityUtils.resizeBitmap(bitmap, targetArea = 65536.0) + + Assert.assertTrue(resized.width < bitmap.width) + Assert.assertTrue(resized.height < bitmap.height) + } + + @Test + fun `resizeBitmap scales up small bitmap`() { + val bitmap = Bitmap.createBitmap(64, 64, Bitmap.Config.ARGB_8888) + val resized = QualityUtils.resizeBitmap(bitmap, targetArea = 65536.0) + + Assert.assertTrue(resized.width > bitmap.width) + Assert.assertTrue(resized.height > bitmap.height) + } + + @Test + fun `resizeBitmap handles different target areas`() { + val bitmap = Bitmap.createBitmap(512, 512, Bitmap.Config.ARGB_8888) + + val smallResize = QualityUtils.resizeBitmap(bitmap, targetArea = 16384.0) + val largeResize = QualityUtils.resizeBitmap(bitmap, targetArea = 262144.0) + + Assert.assertTrue(smallResize.width < largeResize.width) + Assert.assertTrue(smallResize.height < largeResize.height) + } +} diff --git a/simq/src/test/java/com/simprints/simq/QualityWeightsTest.kt b/simq/src/test/java/com/simprints/simq/QualityWeightsTest.kt new file mode 100644 index 0000000..2222903 --- /dev/null +++ b/simq/src/test/java/com/simprints/simq/QualityWeightsTest.kt @@ -0,0 +1,82 @@ +package com.simprints.simq + +import android.graphics.Bitmap +import com.simprints.simq.shadows.ShadowCore +import com.simprints.simq.shadows.ShadowCvType +import com.simprints.simq.shadows.ShadowImgproc +import com.simprints.simq.shadows.ShadowMat +import com.simprints.simq.shadows.ShadowMatOfDouble +import com.simprints.simq.shadows.ShadowOpenCVLoader +import com.simprints.simq.shadows.ShadowOpenCVUtils +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNotEquals +import org.junit.Assert.assertTrue +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config + +@RunWith(RobolectricTestRunner::class) +@Config(shadows = [ + ShadowOpenCVLoader::class, + ShadowOpenCVUtils::class, + ShadowMat::class, + ShadowMatOfDouble::class, + ShadowImgproc::class, + ShadowCore::class, + ShadowCvType::class +]) + +class QualityWeightsTest { + + private fun createTestBitmap(width: Int = 256, height: Int = 256): Bitmap { + return Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888) + } + + @Test + fun `default weights sum to 1_0`() { + val weights = QualityWeights.DEFAULT + val sum = weights.alignment + weights.blur + weights.brightness + + weights.contrast + weights.eyeOpenness + assertEquals(1.0, sum, 0.001) + } + + @Test + fun `custom weights can be created`() { + val customWeights = QualityWeights( + alignment = 0.25, + blur = 0.25, + brightness = 0.25, + contrast = 0.15, + eyeOpenness = 0.10 + ) + + assertEquals(0.25, customWeights.alignment, 0.001) + assertEquals(0.25, customWeights.blur, 0.001) + assertEquals(0.25, customWeights.brightness, 0.001) + assertEquals(0.15, customWeights.contrast, 0.001) + assertEquals(0.10, customWeights.eyeOpenness, 0.001) + } + + @Test + fun `calculateFaceQuality with all weights maximizing one metric`() { + val bitmap = createTestBitmap() + + // Only alignment weight + val alignmentOnly = SimQ.calculateFaceQuality( + bitmap = bitmap, + pitch = 0.0, + yaw = 0.0, + roll = 0.0, + weights = QualityWeights( + alignment = 1.0, + blur = 0.0, + brightness = 0.0, + contrast = 0.0, + eyeOpenness = 0.0 + ) + ) + + assertEquals(alignmentOnly, 1f) + } +} diff --git a/simq/src/test/java/com/simprints/simq/SimQTest.kt b/simq/src/test/java/com/simprints/simq/SimQTest.kt new file mode 100644 index 0000000..da25fd5 --- /dev/null +++ b/simq/src/test/java/com/simprints/simq/SimQTest.kt @@ -0,0 +1,284 @@ +package com.simprints.simq + +import android.graphics.Bitmap +import com.simprints.simq.shadows.ShadowCore +import com.simprints.simq.shadows.ShadowCvType +import com.simprints.simq.shadows.ShadowImgproc +import com.simprints.simq.shadows.ShadowMat +import com.simprints.simq.shadows.ShadowMatOfDouble +import com.simprints.simq.shadows.ShadowOpenCVLoader +import com.simprints.simq.shadows.ShadowOpenCVUtils +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config +import org.opencv.android.OpenCVLoader as AndroidOpenCVLoader + +@RunWith(RobolectricTestRunner::class) +@Config(shadows = [ + ShadowOpenCVLoader::class, + ShadowOpenCVUtils::class, + ShadowMat::class, + ShadowMatOfDouble::class, + ShadowImgproc::class, + ShadowCore::class, + ShadowCvType::class +]) + +class SimQTest { + + private fun createTestBitmap(width: Int = 256, height: Int = 256): Bitmap { + return Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888) + } + + @Test + fun `calculateFaceQuality returns value between 0 and 1`() { + val bitmap = createTestBitmap() + val quality = SimQ.calculateFaceQuality(bitmap) + + assertTrue(quality >= 0.0f) + assertTrue(quality <= 1.0f) + } + + @Test + fun `calculateFaceQuality with perfect alignment returns higher score`() { + val bitmap = createTestBitmap() + + val perfectScore = SimQ.calculateFaceQuality( + bitmap = bitmap, + pitch = 0.0, + yaw = 0.0, + roll = 0.0 + ) + + val poorAlignmentScore = SimQ.calculateFaceQuality( + bitmap = bitmap, + pitch = 20.0, + yaw = 20.0, + roll = 20.0 + ) + + assertTrue(perfectScore >= poorAlignmentScore) + } + + @Test + fun `calculateFaceQuality with extreme angles returns low score`() { + val bitmap = createTestBitmap() + + val quality = SimQ.calculateFaceQuality( + bitmap = bitmap, + pitch = 30.0, // Exceeds maxIndividualAngle + yaw = 0.0, + roll = 0.0 + ) + + assertTrue(quality < 0.5f) + } + + @Test + fun `calculateFaceQuality with eye openness includes it in calculation`() { + val bitmap = createTestBitmap() + + // Test with eyes open + val openEyesScore = SimQ.calculateFaceQuality( + bitmap = bitmap, + leftEyeOpenness = 1.0, + rightEyeOpenness = 1.0, + weights = QualityWeights( + alignment = 0.3, + blur = 0.2, + brightness = 0.2, + contrast = 0.1, + eyeOpenness = 0.2 + ) + ) + + // Test with eyes closed + val closedEyesScore = SimQ.calculateFaceQuality( + bitmap = bitmap, + leftEyeOpenness = 0.0, + rightEyeOpenness = 0.0, + weights = QualityWeights( + alignment = 0.3, + blur = 0.2, + brightness = 0.2, + contrast = 0.1, + eyeOpenness = 0.2 + ) + ) + + // Open eyes should score higher when eye weight is significant + assertTrue(openEyesScore >= closedEyesScore) + } + + @Test + fun `calculateFaceQuality without eye openness ignores eye weight`() { + val bitmap = createTestBitmap() + + val qualityNoEyes = SimQ.calculateFaceQuality( + bitmap = bitmap, + leftEyeOpenness = null, + rightEyeOpenness = null, + weights = QualityWeights(eyeOpenness = 0.2) + ) + + // Should still return valid score + assertTrue(qualityNoEyes >= 0.0f) + assertTrue(qualityNoEyes <= 1.0f) + } + + @Test + fun `calculateFaceQuality with only left eye openness provided`() { + val bitmap = createTestBitmap() + + // Only one eye value - should not use eye openness + val quality = SimQ.calculateFaceQuality( + bitmap = bitmap, + leftEyeOpenness = 1.0, + rightEyeOpenness = null, + weights = QualityWeights(eyeOpenness = 0.2) + ) + + assertTrue(quality >= 0.0f && quality <= 1.0f) + } + + @Test + fun `calculateFaceQuality with custom weights affects result`() { + val bitmap = createTestBitmap() + + // Weight alignment heavily + val alignmentWeighted = SimQ.calculateFaceQuality( + bitmap = bitmap, + pitch = 20.0, + yaw = 20.0, + roll = 20.0, + weights = QualityWeights( + alignment = 0.9, + blur = 0.025, + brightness = 0.025, + contrast = 0.025, + eyeOpenness = 0.025 + ) + ) + + // Weight other factors + val otherWeighted = SimQ.calculateFaceQuality( + bitmap = bitmap, + pitch = 20.0, + yaw = 20.0, + roll = 20.0, + weights = QualityWeights( + alignment = 0.025, + blur = 0.325, + brightness = 0.325, + contrast = 0.325, + eyeOpenness = 0.0 + ) + ) + + // With poor alignment, heavily weighting alignment should give lower score + assertTrue(alignmentWeighted < otherWeighted) + } + + @Test + fun `calculateFaceQuality with custom parameters affects thresholds`() { + val bitmap = createTestBitmap() + + // Strict parameters + val strictQuality = SimQ.calculateFaceQuality( + bitmap = bitmap, + pitch = 15.0, + yaw = 15.0, + roll = 15.0, + parameters = QualityParameters( + maxAlignmentAngle = 10.0, + maxIndividualAngle = 20.0 + ) + ) + + // Lenient parameters + val lenientQuality = SimQ.calculateFaceQuality( + bitmap = bitmap, + pitch = 15.0, + yaw = 15.0, + roll = 15.0, + parameters = QualityParameters( + maxAlignmentAngle = 30.0, + maxIndividualAngle = 40.0 + ) + ) + + // Same angles should score better with lenient parameters + assertTrue(lenientQuality >= strictQuality) + } + + + @Test + fun `calculateFaceQuality handles different bitmap sizes`() { + val smallBitmap = createTestBitmap(64, 64) + val mediumBitmap = createTestBitmap(256, 256) + val largeBitmap = createTestBitmap(1024, 1024) + + val smallQuality = SimQ.calculateFaceQuality(smallBitmap) + val mediumQuality = SimQ.calculateFaceQuality(mediumBitmap) + val largeQuality = SimQ.calculateFaceQuality(largeBitmap) + + // All should return valid scores + assertTrue(smallQuality >= 0.0f && smallQuality <= 1.0f) + assertTrue(mediumQuality >= 0.0f && mediumQuality <= 1.0f) + assertTrue(largeQuality >= 0.0f && largeQuality <= 1.0f) + } + + @Test + fun `calculateFaceQuality with default parameters returns reasonable score`() { + val bitmap = createTestBitmap() + + val quality = SimQ.calculateFaceQuality(bitmap) + + assertTrue(quality >= 0.0f) + assertTrue(quality <= 1.0f) + } + + @Test + fun `calculateFaceQuality is consistent with same inputs`() { + val bitmap = createTestBitmap() + + val quality1 = SimQ.calculateFaceQuality( + bitmap = bitmap, + pitch = 10.0, + yaw = 5.0, + roll = -3.0 + ) + + val quality2 = SimQ.calculateFaceQuality( + bitmap = bitmap, + pitch = 10.0, + yaw = 5.0, + roll = -3.0 + ) + + assertEquals(quality1, quality2, 0.001f) + } + + + + @Test + fun `calculateFaceQuality with zero weights returns zero or handled gracefully`() { + val bitmap = createTestBitmap() + + val quality = SimQ.calculateFaceQuality( + bitmap = bitmap, + weights = QualityWeights( + alignment = 0.0, + blur = 0.0, + brightness = 0.0, + contrast = 0.0, + eyeOpenness = 0.0 + ) + ) + + assertTrue(quality >= 0.0f && quality <= 1.0f) + } +} diff --git a/simq/src/test/java/com/simprints/simq/shadows/ShadowCore.kt b/simq/src/test/java/com/simprints/simq/shadows/ShadowCore.kt new file mode 100644 index 0000000..8103f2b --- /dev/null +++ b/simq/src/test/java/com/simprints/simq/shadows/ShadowCore.kt @@ -0,0 +1,23 @@ +package com.simprints.simq.shadows + +import org.robolectric.annotation.Implementation +import org.robolectric.annotation.Implements + +@Implements(org.opencv.core.Core::class) +class ShadowCore { + + companion object { + @JvmStatic + @Implementation + fun meanStdDev(src: Any, mean: Any, stddev: Any) { + // The MatOfDouble shadows will handle returning default values + } + + @JvmStatic + @Implementation + fun mean(src: Any): Any { + // Return a mock scalar + return Any() + } + } +} diff --git a/simq/src/test/java/com/simprints/simq/shadows/ShadowCvType.kt b/simq/src/test/java/com/simprints/simq/shadows/ShadowCvType.kt new file mode 100644 index 0000000..37be13d --- /dev/null +++ b/simq/src/test/java/com/simprints/simq/shadows/ShadowCvType.kt @@ -0,0 +1,21 @@ +package com.simprints.simq.shadows + +import org.robolectric.annotation.Implementation +import org.robolectric.annotation.Implements + +@Implements(org.opencv.core.CvType::class) +class ShadowCvType { + + companion object { + const val CV_8U = 0 + const val CV_8S = 1 + const val CV_16U = 2 + const val CV_16S = 3 + const val CV_32S = 4 + const val CV_32F = 5 + const val CV_64F = 6 + const val CV_8UC1 = 0 + const val CV_8UC3 = 16 + const val CV_8UC4 = 24 + } +} diff --git a/simq/src/test/java/com/simprints/simq/shadows/ShadowImgproc.kt b/simq/src/test/java/com/simprints/simq/shadows/ShadowImgproc.kt new file mode 100644 index 0000000..ecbda81 --- /dev/null +++ b/simq/src/test/java/com/simprints/simq/shadows/ShadowImgproc.kt @@ -0,0 +1,25 @@ +package com.simprints.simq.shadows + +import org.robolectric.annotation.Implementation +import org.robolectric.annotation.Implements + +@Implements(org.opencv.imgproc.Imgproc::class) +class ShadowImgproc { + + companion object { + const val COLOR_BGR2GRAY = 6 + const val COLOR_RGB2GRAY = 7 + + @JvmStatic + @Implementation + fun cvtColor(src: Any, dst: Any, code: Int) { + // Mock implementation + } + + @JvmStatic + @Implementation + fun Laplacian(src: Any, dst: Any, ddepth: Int, ksize: Int = 1, scale: Double = 1.0, delta: Double = 0.0) { + // Mock implementation + } + } +} diff --git a/simq/src/test/java/com/simprints/simq/shadows/ShadowMat.kt b/simq/src/test/java/com/simprints/simq/shadows/ShadowMat.kt new file mode 100644 index 0000000..93dbb05 --- /dev/null +++ b/simq/src/test/java/com/simprints/simq/shadows/ShadowMat.kt @@ -0,0 +1,33 @@ +package com.simprints.simq.shadows + +import org.robolectric.annotation.Implementation +import org.robolectric.annotation.Implements + +@Implements(org.opencv.core.Mat::class) +class ShadowMat { + + @Implementation + fun __constructor__() { + // Mock constructor + } + + @Implementation + fun __constructor__(rows: Int, cols: Int, type: Int) { + // Mock constructor + } + + @Implementation + fun release() { + // Mock implementation - does nothing + } + + @Implementation + fun rows(): Int { + return 0 + } + + @Implementation + fun cols(): Int { + return 0 + } +} diff --git a/simq/src/test/java/com/simprints/simq/shadows/ShadowMatOfDouble.kt b/simq/src/test/java/com/simprints/simq/shadows/ShadowMatOfDouble.kt new file mode 100644 index 0000000..651fe73 --- /dev/null +++ b/simq/src/test/java/com/simprints/simq/shadows/ShadowMatOfDouble.kt @@ -0,0 +1,25 @@ +package com.simprints.simq.shadows + +import org.robolectric.annotation.Implementation +import org.robolectric.annotation.Implements + +@Implements(org.opencv.core.MatOfDouble::class) +class ShadowMatOfDouble { + + private var values: DoubleArray = doubleArrayOf(50.0) // Default standard deviation for mock + + @Implementation + fun __constructor__() { + // Mock constructor + } + + @Implementation + fun toArray(): DoubleArray { + return values + } + + @Implementation + fun release() { + // Mock implementation - does nothing + } +} diff --git a/simq/src/test/java/com/simprints/simq/shadows/ShadowOpenCVLoader.kt b/simq/src/test/java/com/simprints/simq/shadows/ShadowOpenCVLoader.kt new file mode 100644 index 0000000..7f3275c --- /dev/null +++ b/simq/src/test/java/com/simprints/simq/shadows/ShadowOpenCVLoader.kt @@ -0,0 +1,23 @@ +package com.simprints.simq.shadows + +import org.robolectric.annotation.Implementation +import org.robolectric.annotation.Implements + +@Implements(org.opencv.android.OpenCVLoader::class) +class ShadowOpenCVLoader { + + companion object { + @JvmStatic + @Implementation + fun initLocal(): Boolean { + // Return true to simulate successful OpenCV initialization + return true + } + + @JvmStatic + @Implementation + fun initDebug(): Boolean { + return true + } + } +} diff --git a/simq/src/test/java/com/simprints/simq/shadows/ShadowOpenCVUtils.kt b/simq/src/test/java/com/simprints/simq/shadows/ShadowOpenCVUtils.kt new file mode 100644 index 0000000..2d88c04 --- /dev/null +++ b/simq/src/test/java/com/simprints/simq/shadows/ShadowOpenCVUtils.kt @@ -0,0 +1,23 @@ +package com.simprints.simq.shadows + +import android.graphics.Bitmap +import org.robolectric.annotation.Implementation +import org.robolectric.annotation.Implements + +@Implements(org.opencv.android.Utils::class) +class ShadowOpenCVUtils { + + companion object { + @JvmStatic + @Implementation + fun bitmapToMat(bitmap: Bitmap, mat: Any) { + // Mock implementation + } + + @JvmStatic + @Implementation + fun matToBitmap(mat: Any, bitmap: Bitmap) { + // Mock implementation + } + } +} diff --git a/src/main/java/com/simprints/biometrics/simface/detection/MlKitFaceDetectionProcessor.kt b/src/main/java/com/simprints/biometrics/simface/detection/MlKitFaceDetectionProcessor.kt index 99fc493..e941283 100644 --- a/src/main/java/com/simprints/biometrics/simface/detection/MlKitFaceDetectionProcessor.kt +++ b/src/main/java/com/simprints/biometrics/simface/detection/MlKitFaceDetectionProcessor.kt @@ -10,10 +10,12 @@ import com.simprints.biometrics.simface.Utils.clampToBounds import com.simprints.biometrics.simface.data.FaceDetection import com.simprints.biometrics.simface.data.FacialLandmarks import com.simprints.biometrics.simface.data.Point2D +import com.simprints.simq.QualityParameters +import com.simprints.simq.QualityWeights +import com.simprints.simq.SimQ import kotlin.coroutines.resume import kotlin.coroutines.resumeWithException import kotlin.coroutines.suspendCoroutine -import kotlin.math.absoluteValue internal class MlKitFaceDetectionProcessor( private val faceDetector: FaceDetector, @@ -41,7 +43,7 @@ internal class MlKitFaceDetectionProcessor( yaw = face.headEulerAngleY, roll = face.headEulerAngleZ, landmarks = buildLandmarks(face), - quality = calculateFaceQuality(face, image.width, image.height), + quality = calculateFaceQuality(face, image), ) faceDetections.add(faceDetection) } @@ -71,7 +73,7 @@ internal class MlKitFaceDetectionProcessor( ), yaw = face.headEulerAngleY, roll = face.headEulerAngleZ, - quality = calculateFaceQuality(face, image.width, image.height), + quality = calculateFaceQuality(face, image), landmarks = buildLandmarks(face), ) faceDetections.add(faceDetection) @@ -85,54 +87,59 @@ internal class MlKitFaceDetectionProcessor( private fun calculateFaceQuality( face: Face, - imageWidth: Int, - imageHeight: Int, + image: Bitmap, ): Float { return try { - var score = 0.0 - - // These should add to 1.0 - val faceRotationWeight = 0.3 - val faceTiltWeight = 0.05 - val faceNodWeight = 0.05 - val faceSizeWeight = 0.3 - val eyeOpennessWeight = 0.3 - - // Face Rotation Score - score += faceRotationWeight * (1.0 - (face.headEulerAngleY.absoluteValue / 90.0)) - - // Face Tilt Score - score += faceTiltWeight * (1.0 - (face.headEulerAngleZ.absoluteValue / 90.0)) - - // Face Nod Score - score += faceNodWeight * (1.0 - (face.headEulerAngleX.absoluteValue / 90.0)) - - // Face Size Relative to Image Size - val faceArea = face.boundingBox.width() * face.boundingBox.height() - val imageArea = imageWidth * imageHeight - score += faceSizeWeight * (faceArea.toDouble() / imageArea) - - // Eye Openness Score - score += eyeOpennessWeight * calculateEyeOpennessScore(face) - - // TODO: Blur Detection - // TODO: Brightness and Contrast Score - - // Just in case limit to 0-1 range - return score.coerceIn(0.0, 1.0).toFloat() + val boundingBox = face.boundingBox.clampToBounds(image.width, image.height) + val faceBitmap = Bitmap.createBitmap( + image, + boundingBox.left, + boundingBox.top, + boundingBox.width(), + boundingBox.height() + ) + + val parameters = QualityParameters( + maxAlignmentAngle = 20.0, + maxIndividualAngle = 25.0, + minBlur = 50.0, + maxBlur = 100.0, + minBrightness = 30.0, + optimalBrightnessLow = 80.0, + optimalBrightnessHigh = 150.0, + maxBrightness = 190.0, + brightnessSteepness = 0.3, + minContrast = 30.0, + maxContrast = 47.0 + ) + + val weights = QualityWeights( + alignment = 0.28, + blur = 0.3, + brightness = 0.1, + contrast = 0.3, + eyeOpenness = 0.02 + ) + + val qualityScore = SimQ.calculateFaceQuality( + bitmap = faceBitmap, + pitch = face.headEulerAngleX.toDouble(), + yaw = face.headEulerAngleY.toDouble(), + roll = face.headEulerAngleZ.toDouble(), + leftEyeOpenness = face.leftEyeOpenProbability?.toDouble(), + rightEyeOpenness = face.rightEyeOpenProbability?.toDouble(), + weights = weights, + parameters = parameters + ) + + faceBitmap.recycle() + + qualityScore } catch (e: Exception) { - println("Error calculating face quality: ${e.message}") 0.0f } } - private fun calculateEyeOpennessScore(face: Face): Double { - val leftEyeScore = face.leftEyeOpenProbability ?: return 0.0 - val rightEyeScore = face.rightEyeOpenProbability ?: return 0.0 - - return (leftEyeScore + rightEyeScore) / 2.0 - } - private fun buildLandmarks(face: Face): FacialLandmarks? { val leftEye = face.getLandmark(FaceLandmark.LEFT_EYE)?.position ?: face.getContour(FaceContour.LEFT_EYE)?.points?.getOrNull(4) From f199f8c7e94d9f7d5d6b9336d5cc2b1dca2adeff Mon Sep 17 00:00:00 2001 From: Martin Georgiev <3349414+Thinkorswim@users.noreply.github.com> Date: Tue, 21 Oct 2025 17:19:10 +0300 Subject: [PATCH 02/12] Bump SimFace version number --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 4dda8ee..7925177 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,7 +6,7 @@ plugins { val projectGroupId = "com.simprints.biometrics" val projectArtifactId = "simface" -val projectVersion = "2025.3.1" +val projectVersion = "2025.3.2" group = projectGroupId version = projectVersion From d62ca1fe0b910172b340a0ab71941c1227ca662f Mon Sep 17 00:00:00 2001 From: Martin Georgiev <3349414+Thinkorswim@users.noreply.github.com> Date: Tue, 21 Oct 2025 17:27:49 +0300 Subject: [PATCH 03/12] Fix robolectric name --- gradle/libs.versions.toml | 4 ++-- simq/build.gradle.kts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4f65774..15d2db0 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,7 +13,7 @@ junit = "4.13.2" appcompat = "1.6.1" material = "1.10.0" opencv = "4.10.0" -roboelectric = "4.11.1" +robolectric = "4.11.1" [libraries] androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } @@ -29,7 +29,7 @@ junit = { group = "junit", name = "junit", version.ref = "junit" } androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" } material = { group = "com.google.android.material", name = "material", version.ref = "material" } opencv = { module = "org.opencv:opencv", version.ref = "opencv" } -roboelectric = {module = "org.robolectric:robolectric", version.ref = "roboelectric" } +robolectric = {module = "org.robolectric:robolectric", version.ref = "robolectric" } [plugins] jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } diff --git a/simq/build.gradle.kts b/simq/build.gradle.kts index 3809e93..ba43607 100644 --- a/simq/build.gradle.kts +++ b/simq/build.gradle.kts @@ -46,7 +46,7 @@ dependencies { api(libs.opencv) testImplementation(libs.junit) - testImplementation(libs.roboelectric) + testImplementation(libs.robolectric) androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.espresso.core) } From 8b0ad9538abd1a52f31a7ec6aa5b34662ba51066 Mon Sep 17 00:00:00 2001 From: Martin Georgiev <3349414+Thinkorswim@users.noreply.github.com> Date: Tue, 21 Oct 2025 17:30:22 +0300 Subject: [PATCH 04/12] Fix minSdk mismatch --- simq/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simq/build.gradle.kts b/simq/build.gradle.kts index ba43607..5b7e104 100644 --- a/simq/build.gradle.kts +++ b/simq/build.gradle.kts @@ -8,7 +8,7 @@ android { compileSdk = 36 defaultConfig { - minSdk = 24 + minSdk = 23 testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles("consumer-rules.pro") From 61c58c7c92b7bec56e4491d0f0f0c7d9e8c475c5 Mon Sep 17 00:00:00 2001 From: Martin Georgiev <3349414+Thinkorswim@users.noreply.github.com> Date: Tue, 21 Oct 2025 17:42:15 +0300 Subject: [PATCH 05/12] Update FaceDetectionProcessorTest.kt --- .../simface/detection/FaceDetectionProcessorTest.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/androidTest/java/com/simprints/biometrics/simface/detection/FaceDetectionProcessorTest.kt b/src/androidTest/java/com/simprints/biometrics/simface/detection/FaceDetectionProcessorTest.kt index da0f188..5f8fc5b 100644 --- a/src/androidTest/java/com/simprints/biometrics/simface/detection/FaceDetectionProcessorTest.kt +++ b/src/androidTest/java/com/simprints/biometrics/simface/detection/FaceDetectionProcessorTest.kt @@ -11,7 +11,6 @@ import com.simprints.biometrics.simface.data.FaceDetection import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.test.runTest import org.junit.After -import org.junit.Assert import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test @@ -65,7 +64,7 @@ class FaceDetectionProcessorTest { val faces = resultDeferred.await() assertTrue(faces.isNotEmpty()) val face = faces[0] - assertTrue(face.quality < 0.5) + assertTrue(face.quality < 0.6) } @Test @@ -115,7 +114,7 @@ class FaceDetectionProcessorTest { assertTrue(faces.isNotEmpty()) val face = faces[0] - assertTrue(face.quality < 0.5) + assertTrue(face.quality < 0.6) } @Test From efa7429d190cf90d8aebfa8306b5123cf68314c9 Mon Sep 17 00:00:00 2001 From: Martin Georgiev <3349414+Thinkorswim@users.noreply.github.com> Date: Thu, 23 Oct 2025 16:43:11 +0300 Subject: [PATCH 06/12] Update initialization, tests, helper functioons --- build.gradle.kts | 1 + gradle/libs.versions.toml | 6 +- settings.gradle.kts | 3 +- simq/build.gradle.kts | 10 +- .../simprints/simq/AlignmentAnalysisTest.kt | 111 +++++++ .../java/com/simprints/simq/BitmapExtTest.kt | 90 ++++++ .../com/simprints/simq/QualityWeightsTest.kt | 77 +++++ .../simprints/simq/ScoringFunctionsTest.kt | 153 ++++++++++ .../java/com/simprints/simq/SimQTest.kt | 266 ++++++++++++++++ .../com/simprints/simq/QualityParameters.kt | 5 +- .../java/com/simprints/simq/QualityWeights.kt | 2 +- simq/src/main/java/com/simprints/simq/SimQ.kt | 131 ++++---- .../simq/analysis/AlignmentAnalysis.kt | 12 +- .../simprints/simq/analysis/BlurAnalysis.kt | 38 +-- .../simq/analysis/BrightnessAnalysis.kt | 23 +- .../simq/analysis/ContrastAnalysis.kt | 31 +- .../com/simprints/simq/utils/BitmapExt.kt | 43 +++ .../com/simprints/simq/utils/OpenCVLoader.kt | 3 +- .../com/simprints/simq/utils/QualityUtils.kt | 100 ------ .../simprints/simq/utils/ScoringFunctions.kt | 47 +++ .../simprints/simq/AlignmentAnalysisTest.kt | 104 ------- .../com/simprints/simq/QualityUtilsTest.kt | 222 -------------- .../com/simprints/simq/QualityWeightsTest.kt | 82 ----- .../test/java/com/simprints/simq/SimQTest.kt | 284 ------------------ .../com/simprints/simq/shadows/ShadowCore.kt | 23 -- .../simprints/simq/shadows/ShadowCvType.kt | 21 -- .../simprints/simq/shadows/ShadowImgproc.kt | 25 -- .../com/simprints/simq/shadows/ShadowMat.kt | 33 -- .../simq/shadows/ShadowMatOfDouble.kt | 25 -- .../simq/shadows/ShadowOpenCVLoader.kt | 23 -- .../simq/shadows/ShadowOpenCVUtils.kt | 23 -- .../simface/detection/FaceAlignTest.kt | 18 +- .../detection/FaceDetectionProcessorTest.kt | 26 +- .../simface/embedding/CustomModelTest.kt | 11 +- .../embedding/EmbeddingProcessorTest.kt | 14 +- .../simface/matcher/IdentificationTest.kt | 10 +- .../simface/matcher/VerificationTest.kt | 12 +- .../simprints/biometrics/simface/SimFace.kt | 60 ++-- .../detection/MlKitFaceDetectionProcessor.kt | 133 ++++---- 39 files changed, 1067 insertions(+), 1234 deletions(-) create mode 100644 simq/src/androidTest/java/com/simprints/simq/AlignmentAnalysisTest.kt create mode 100644 simq/src/androidTest/java/com/simprints/simq/BitmapExtTest.kt create mode 100644 simq/src/androidTest/java/com/simprints/simq/QualityWeightsTest.kt create mode 100644 simq/src/androidTest/java/com/simprints/simq/ScoringFunctionsTest.kt create mode 100644 simq/src/androidTest/java/com/simprints/simq/SimQTest.kt create mode 100644 simq/src/main/java/com/simprints/simq/utils/BitmapExt.kt delete mode 100644 simq/src/main/java/com/simprints/simq/utils/QualityUtils.kt create mode 100644 simq/src/main/java/com/simprints/simq/utils/ScoringFunctions.kt delete mode 100644 simq/src/test/java/com/simprints/simq/AlignmentAnalysisTest.kt delete mode 100644 simq/src/test/java/com/simprints/simq/QualityUtilsTest.kt delete mode 100644 simq/src/test/java/com/simprints/simq/QualityWeightsTest.kt delete mode 100644 simq/src/test/java/com/simprints/simq/SimQTest.kt delete mode 100644 simq/src/test/java/com/simprints/simq/shadows/ShadowCore.kt delete mode 100644 simq/src/test/java/com/simprints/simq/shadows/ShadowCvType.kt delete mode 100644 simq/src/test/java/com/simprints/simq/shadows/ShadowImgproc.kt delete mode 100644 simq/src/test/java/com/simprints/simq/shadows/ShadowMat.kt delete mode 100644 simq/src/test/java/com/simprints/simq/shadows/ShadowMatOfDouble.kt delete mode 100644 simq/src/test/java/com/simprints/simq/shadows/ShadowOpenCVLoader.kt delete mode 100644 simq/src/test/java/com/simprints/simq/shadows/ShadowOpenCVUtils.kt diff --git a/build.gradle.kts b/build.gradle.kts index 7925177..bfe1e19 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -51,6 +51,7 @@ dependencies { // For face alignment api(libs.ejml.simple) + androidTestImplementation(libs.truth) androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.espresso.core) androidTestImplementation(libs.kotlinx.coroutines.test) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 15d2db0..c82e9b7 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,11 +9,10 @@ tensorflowLiteSupport = "0.5.0" faceDetection = "16.1.7" ejmlSimple = "0.44.0" coreKtx = "1.17.0" -junit = "4.13.2" appcompat = "1.6.1" material = "1.10.0" opencv = "4.10.0" -robolectric = "4.11.1" +truth = "1.4.5" [libraries] androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } @@ -25,11 +24,10 @@ tensorflow-lite-support = { module = "org.tensorflow:tensorflow-lite-support", v face-detection = { module = "com.google.mlkit:face-detection", version.ref = "faceDetection" } ejml-simple = { module = "org.ejml:ejml-simple", version.ref = "ejmlSimple" } androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } -junit = { group = "junit", name = "junit", version.ref = "junit" } androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" } material = { group = "com.google.android.material", name = "material", version.ref = "material" } opencv = { module = "org.opencv:opencv", version.ref = "opencv" } -robolectric = {module = "org.robolectric:robolectric", version.ref = "robolectric" } +truth = { module = "com.google.truth:truth", version.ref = "truth" } [plugins] jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } diff --git a/settings.gradle.kts b/settings.gradle.kts index e953f8c..cd8e076 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -20,5 +20,6 @@ dependencyResolutionManagement { } } -rootProject.name = "simface" +rootProject.name = "Biometrics-SimFace" +include(":Biometrics-SimFace") include(":simq") diff --git a/simq/build.gradle.kts b/simq/build.gradle.kts index 5b7e104..72deb03 100644 --- a/simq/build.gradle.kts +++ b/simq/build.gradle.kts @@ -19,7 +19,7 @@ android { isMinifyEnabled = false proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), - "proguard-rules.pro" + "proguard-rules.pro", ) } } @@ -30,7 +30,7 @@ android { kotlinOptions { jvmTarget = "11" } - + testOptions { unitTests { isIncludeAndroidResources = true @@ -44,9 +44,9 @@ dependencies { implementation(libs.androidx.appcompat) implementation(libs.material) api(libs.opencv) - - testImplementation(libs.junit) - testImplementation(libs.robolectric) + + androidTestImplementation(libs.truth) androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.espresso.core) + androidTestImplementation(libs.kotlinx.coroutines.test) } diff --git a/simq/src/androidTest/java/com/simprints/simq/AlignmentAnalysisTest.kt b/simq/src/androidTest/java/com/simprints/simq/AlignmentAnalysisTest.kt new file mode 100644 index 0000000..225edf0 --- /dev/null +++ b/simq/src/androidTest/java/com/simprints/simq/AlignmentAnalysisTest.kt @@ -0,0 +1,111 @@ +package com.simprints.simq + +import com.google.common.truth.Truth.assertThat +import com.simprints.simq.analysis.AlignmentAnalysis +import org.junit.Test + +class AlignmentAnalysisTest { + private val maxAngle = 20.0 + private val maxIndividualAngle = 25.0 + + @Test + fun perfectAlignmentReturnsScoreOf1() { + val score = + AlignmentAnalysis.calculateScore( + pitch = 0.0, + yaw = 0.0, + roll = 0.0, + maxAngle = maxAngle, + maxIndividualAngle = maxIndividualAngle, + ) + assertThat(score).isWithin(0.001).of(1.0) + } + + @Test + fun angleAtHalfMaxThresholdReturnsScoreOf0_5() { + val halfAngle = maxAngle / 2 + val score = + AlignmentAnalysis.calculateScore( + pitch = halfAngle, + yaw = halfAngle, + roll = halfAngle, + maxAngle = maxAngle, + maxIndividualAngle = maxIndividualAngle, + ) + assertThat(score).isWithin(0.001).of(0.5) + } + + @Test + fun negativeAnglesAreTreatedAsAbsoluteValues() { + val score1 = + AlignmentAnalysis.calculateScore( + pitch = -10.0, + yaw = -10.0, + roll = -10.0, + maxAngle = maxAngle, + maxIndividualAngle = maxIndividualAngle, + ) + + val score2 = + AlignmentAnalysis.calculateScore( + pitch = 10.0, + yaw = 10.0, + roll = 10.0, + maxAngle = maxAngle, + maxIndividualAngle = maxIndividualAngle, + ) + + assertThat(score1).isWithin(0.001).of(score2) + } + + @Test + fun anySingleAngleExceedingMaxIndividualAngleRejectsEntireScore() { + // Test pitch rejection + val pitchScore = + AlignmentAnalysis.calculateScore( + pitch = 26.0, + yaw = 0.0, + roll = 0.0, + maxAngle = maxAngle, + maxIndividualAngle = maxIndividualAngle, + ) + assertThat(pitchScore).isWithin(0.001).of(0.0) + + // Test yaw rejection + val yawScore = + AlignmentAnalysis.calculateScore( + pitch = 0.0, + yaw = 26.0, + roll = 0.0, + maxAngle = maxAngle, + maxIndividualAngle = maxIndividualAngle, + ) + assertThat(yawScore).isWithin(0.001).of(0.0) + + // Test roll rejection + val rollScore = + AlignmentAnalysis.calculateScore( + pitch = 0.0, + yaw = 0.0, + roll = 26.0, + maxAngle = maxAngle, + maxIndividualAngle = maxIndividualAngle, + ) + assertThat(rollScore).isWithin(0.001).of(0.0) + } + + @Test + fun mixedAnglesCalculateAverageScoreCorrectly() { + // Perfect pitch, half-max yaw, max roll + val score = + AlignmentAnalysis.calculateScore( + pitch = 0.0, // Score: 1.0 + yaw = 10.0, // Score: 0.5 (10/20) + roll = 20.0, // Score: 0.0 (20/20) + maxAngle = maxAngle, + maxIndividualAngle = maxIndividualAngle, + ) + // Average: (1.0 + 0.5 + 0.0) / 3 = 0.5 + assertThat(score).isWithin(0.001).of(0.5) + } +} diff --git a/simq/src/androidTest/java/com/simprints/simq/BitmapExtTest.kt b/simq/src/androidTest/java/com/simprints/simq/BitmapExtTest.kt new file mode 100644 index 0000000..b8e72ad --- /dev/null +++ b/simq/src/androidTest/java/com/simprints/simq/BitmapExtTest.kt @@ -0,0 +1,90 @@ +package com.simprints.simq + +import android.graphics.Bitmap +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.google.common.truth.Truth.assertThat +import com.simprints.simq.utils.centerCrop +import com.simprints.simq.utils.resizeToArea +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class BitmapExtTest { + @Test + fun centerCropBitmapWithNoDisplacementCropsCenter() { + val bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888) + val cropped = + bitmap.centerCrop( + centerCrop = 0.5f, + horizontalDisplacement = 0.0f, + verticalDisplacement = 0.0f, + ) + + assertThat(cropped.width).isEqualTo(50) + assertThat(cropped.height).isEqualTo(50) + } + + @Test + fun centerCropBitmapWithFullCropReturnsSameSize() { + val bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888) + val cropped = + bitmap.centerCrop( + centerCrop = 1.0f, + horizontalDisplacement = 0.0f, + verticalDisplacement = 0.0f, + ) + + assertThat(cropped.width).isEqualTo(100) + assertThat(cropped.height).isEqualTo(100) + } + + @Test + fun resizeBitmapMaintainsAspectRatioForSquareBitmap() { + val bitmap = Bitmap.createBitmap(512, 512, Bitmap.Config.ARGB_8888) + val resized = bitmap.resizeToArea(targetArea = 65536.0) + + assertThat(resized.width).isEqualTo(256) + assertThat(resized.height).isEqualTo(256) + } + + @Test + fun resizeBitmapMaintainsAspectRatioForRectangularBitmap() { + val bitmap = Bitmap.createBitmap(800, 400, Bitmap.Config.ARGB_8888) + val resized = bitmap.resizeToArea(targetArea = 65536.0) + + val aspectRatio = resized.width.toDouble() / resized.height.toDouble() + assertThat(aspectRatio).isWithin(0.01).of(2.0) + + val area = resized.width * resized.height + assertThat(area.toDouble()).isWithin(1000.0).of(65536.0) + } + + @Test + fun resizeBitmapScalesDownLargeBitmap() { + val bitmap = Bitmap.createBitmap(1024, 1024, Bitmap.Config.ARGB_8888) + val resized = bitmap.resizeToArea(targetArea = 65536.0) + + assertThat(resized.width).isLessThan(bitmap.width) + assertThat(resized.height).isLessThan(bitmap.height) + } + + @Test + fun resizeBitmapScalesUpSmallBitmap() { + val bitmap = Bitmap.createBitmap(64, 64, Bitmap.Config.ARGB_8888) + val resized = bitmap.resizeToArea(targetArea = 65536.0) + + assertThat(resized.width).isGreaterThan(bitmap.width) + assertThat(resized.height).isGreaterThan(bitmap.height) + } + + @Test + fun resizeBitmapHandlesDifferentTargetAreas() { + val bitmap = Bitmap.createBitmap(512, 512, Bitmap.Config.ARGB_8888) + + val smallResize = bitmap.resizeToArea(targetArea = 16384.0) + val largeResize = bitmap.resizeToArea(targetArea = 262144.0) + + assertThat(smallResize.width).isLessThan(largeResize.width) + assertThat(smallResize.height).isLessThan(largeResize.height) + } +} diff --git a/simq/src/androidTest/java/com/simprints/simq/QualityWeightsTest.kt b/simq/src/androidTest/java/com/simprints/simq/QualityWeightsTest.kt new file mode 100644 index 0000000..4974759 --- /dev/null +++ b/simq/src/androidTest/java/com/simprints/simq/QualityWeightsTest.kt @@ -0,0 +1,77 @@ +package com.simprints.simq + +import android.graphics.Bitmap +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.google.common.truth.Truth.assertThat +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class QualityWeightsTest { + private lateinit var simQ: SimQ + + @Before + fun setUp() { + simQ = SimQ() + } + + private fun createTestBitmap( + width: Int = 256, + height: Int = 256, + ): Bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888) + + @Test + fun defaultWeightsSumTo1() { + val weights = QualityWeights.DEFAULT + val sum = + weights.alignment + + weights.blur + + weights.brightness + + weights.contrast + + weights.eyeOpenness + assertThat(sum).isWithin(0.001).of(1.0) + } + + @Test + fun customWeightsCanBeCreated() { + val customWeights = + QualityWeights( + alignment = 0.25, + blur = 0.25, + brightness = 0.25, + contrast = 0.15, + eyeOpenness = 0.10, + ) + + assertThat(customWeights.alignment).isWithin(0.001).of(0.25) + assertThat(customWeights.blur).isWithin(0.001).of(0.25) + assertThat(customWeights.brightness).isWithin(0.001).of(0.25) + assertThat(customWeights.contrast).isWithin(0.001).of(0.15) + assertThat(customWeights.eyeOpenness).isWithin(0.001).of(0.10) + } + + @Test + fun calculateFaceQualityWithAllWeightsMaximizingOneMetric() { + val bitmap = createTestBitmap() + + // Only alignment weight + val alignmentOnly = + simQ.calculateFaceQuality( + bitmap = bitmap, + pitch = 0.0, + yaw = 0.0, + roll = 0.0, + weights = + QualityWeights( + alignment = 1.0, + blur = 0.0, + brightness = 0.0, + contrast = 0.0, + eyeOpenness = 0.0, + ), + ) + + assertThat(alignmentOnly).isEqualTo(1f) + } +} diff --git a/simq/src/androidTest/java/com/simprints/simq/ScoringFunctionsTest.kt b/simq/src/androidTest/java/com/simprints/simq/ScoringFunctionsTest.kt new file mode 100644 index 0000000..d48b0cb --- /dev/null +++ b/simq/src/androidTest/java/com/simprints/simq/ScoringFunctionsTest.kt @@ -0,0 +1,153 @@ +package com.simprints.simq + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.google.common.truth.Truth.assertThat +import com.simprints.simq.utils.ScoringFunctions +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class ScoringFunctionsTest { + @Test + fun rampScoreReturns0WhenBelowMinimum() { + val score = ScoringFunctions.rampScore(x = 10.0, min = 20.0, max = 100.0) + assertThat(score).isWithin(0.001).of(0.0) + } + + @Test + fun rampScoreReturns1WhenAboveMaximum() { + val score = ScoringFunctions.rampScore(x = 150.0, min = 20.0, max = 100.0) + assertThat(score).isWithin(0.001).of(1.0) + } + + @Test + fun rampScoreReturns0_5AtMidpoint() { + val score = ScoringFunctions.rampScore(x = 60.0, min = 20.0, max = 100.0) + assertThat(score).isWithin(0.001).of(0.5) + } + + @Test + fun rampScoreInterpolatesLinearly() { + val score = ScoringFunctions.rampScore(x = 30.0, min = 20.0, max = 120.0) + // (30 - 20) / (120 - 20) = 10/100 = 0.1 + assertThat(score).isWithin(0.001).of(0.1) + } + + @Test + fun plateauScoreReturns1InOptimalRange() { + val score1 = + ScoringFunctions.plateauScore( + x = 100.0, + centerLow = 80.0, + centerHigh = 150.0, + edgeLow = 30.0, + edgeHigh = 190.0, + steepness = 0.3, + ) + assertThat(score1).isWithin(0.001).of(1.0) + + val score2 = + ScoringFunctions.plateauScore( + x = 80.0, + centerLow = 80.0, + centerHigh = 150.0, + edgeLow = 30.0, + edgeHigh = 190.0, + steepness = 0.3, + ) + assertThat(score2).isWithin(0.001).of(1.0) + + val score3 = + ScoringFunctions.plateauScore( + x = 150.0, + centerLow = 80.0, + centerHigh = 150.0, + edgeLow = 30.0, + edgeHigh = 190.0, + steepness = 0.3, + ) + assertThat(score3).isWithin(0.001).of(1.0) + } + + @Test + fun plateauScoreDecreasesOutsideOptimalRange() { + // Below center + val scoreLow = + ScoringFunctions.plateauScore( + x = 50.0, + centerLow = 80.0, + centerHigh = 150.0, + edgeLow = 30.0, + edgeHigh = 190.0, + steepness = 0.3, + ) + assertThat(scoreLow).isLessThan(1.0) + assertThat(scoreLow).isGreaterThan(0.0) + + // Above center + val scoreHigh = + ScoringFunctions.plateauScore( + x = 170.0, + centerLow = 80.0, + centerHigh = 150.0, + edgeLow = 30.0, + edgeHigh = 190.0, + steepness = 0.3, + ) + assertThat(scoreHigh).isLessThan(1.0) + assertThat(scoreHigh).isGreaterThan(0.0) + } + + @Test + fun plateauScoreIsClampedBetween0And1() { + val scoreVeryLow = + ScoringFunctions.plateauScore( + x = 0.0, + centerLow = 80.0, + centerHigh = 150.0, + edgeLow = 30.0, + edgeHigh = 190.0, + steepness = 0.3, + ) + assertThat(scoreVeryLow).isAtLeast(0.0) + assertThat(scoreVeryLow).isAtMost(1.0) + + val scoreVeryHigh = + ScoringFunctions.plateauScore( + x = 300.0, + centerLow = 80.0, + centerHigh = 150.0, + edgeLow = 30.0, + edgeHigh = 190.0, + steepness = 0.3, + ) + assertThat(scoreVeryHigh).isAtLeast(0.0) + assertThat(scoreVeryHigh).isAtMost(1.0) + } + + @Test + fun plateauScoreIsSymmetricAroundOptimalRange() { + val scoreLow = + ScoringFunctions.plateauScore( + x = 50.0, + centerLow = 80.0, + centerHigh = 150.0, + edgeLow = 30.0, + edgeHigh = 190.0, + steepness = 0.3, + ) + + val scoreHigh = + ScoringFunctions.plateauScore( + x = 180.0, + centerLow = 80.0, + centerHigh = 150.0, + edgeLow = 30.0, + edgeHigh = 190.0, + steepness = 0.3, + ) + + // Should be approximately equal due to symmetry + assertThat(scoreHigh).isWithin(0.1).of(scoreLow) + } +} diff --git a/simq/src/androidTest/java/com/simprints/simq/SimQTest.kt b/simq/src/androidTest/java/com/simprints/simq/SimQTest.kt new file mode 100644 index 0000000..50a0855 --- /dev/null +++ b/simq/src/androidTest/java/com/simprints/simq/SimQTest.kt @@ -0,0 +1,266 @@ +package com.simprints.simq + +import android.graphics.Bitmap +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.google.common.collect.Range +import com.google.common.truth.Truth.assertThat +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class SimQTest { + private lateinit var simQ: SimQ + + @Before + fun setUp() { + simQ = SimQ() + } + + private fun createTestBitmap( + width: Int = 256, + height: Int = 256, + ): Bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888) + + @Test + fun calculateFaceQualityReturnsValueBetween0And1() { + val bitmap = createTestBitmap() + val quality = simQ.calculateFaceQuality(bitmap) + + assertThat(quality).isAtLeast(0.0f) + assertThat(quality).isAtMost(1.0f) + } + + @Test + fun calculateFaceQualityWithPerfectAlignmentReturnsHigherScore() { + val bitmap = createTestBitmap() + + val perfectScore = + simQ.calculateFaceQuality( + bitmap = bitmap, + pitch = 0.0, + yaw = 0.0, + roll = 0.0, + ) + + val poorAlignmentScore = + simQ.calculateFaceQuality( + bitmap = bitmap, + pitch = 20.0, + yaw = 20.0, + roll = 20.0, + ) + + assertThat(perfectScore).isAtLeast(poorAlignmentScore) + } + + @Test + fun calculateFaceQualityWithExtremeAnglesReturnsLowScore() { + val bitmap = createTestBitmap() + + val quality = + simQ.calculateFaceQuality( + bitmap = bitmap, + pitch = 30.0, + yaw = 0.0, + roll = 0.0, + ) + + assertThat(quality).isLessThan(0.5f) + } + + @Test + fun calculateFaceQualityWithEyeOpennessIncludesItInCalculation() { + val bitmap = createTestBitmap() + + val openEyesScore = + simQ.calculateFaceQuality( + bitmap = bitmap, + leftEyeOpenness = 1.0, + rightEyeOpenness = 1.0, + weights = + QualityWeights( + alignment = 0.3, + blur = 0.2, + brightness = 0.2, + contrast = 0.1, + eyeOpenness = 0.2, + ), + ) + + val closedEyesScore = + simQ.calculateFaceQuality( + bitmap = bitmap, + leftEyeOpenness = 0.0, + rightEyeOpenness = 0.0, + weights = + QualityWeights( + alignment = 0.3, + blur = 0.2, + brightness = 0.2, + contrast = 0.1, + eyeOpenness = 0.2, + ), + ) + + assertThat(openEyesScore).isAtLeast(closedEyesScore) + } + + @Test + fun calculateFaceQualityWithoutEyeOpennessIgnoresEyeWeight() { + val bitmap = createTestBitmap() + + val qualityNoEyes = + simQ.calculateFaceQuality( + bitmap = bitmap, + leftEyeOpenness = null, + rightEyeOpenness = null, + weights = QualityWeights(eyeOpenness = 0.2), + ) + + assertThat(qualityNoEyes).isAtLeast(0.0f) + assertThat(qualityNoEyes).isAtMost(1.0f) + } + + @Test + fun calculateFaceQualityWithOnlyLeftEyeOpennessProvided() { + val bitmap = createTestBitmap() + + val quality = + simQ.calculateFaceQuality( + bitmap = bitmap, + leftEyeOpenness = 1.0, + rightEyeOpenness = null, + weights = QualityWeights(eyeOpenness = 0.2), + ) + + assertThat(quality).isIn(Range.closed(0.0f, 1.0f)) + } + + @Test + fun calculateFaceQualityWithCustomWeightsAffectsResult() { + val bitmap = createTestBitmap() + + val alignmentWeighted = + simQ.calculateFaceQuality( + bitmap = bitmap, + pitch = 20.0, + yaw = 20.0, + roll = 20.0, + weights = + QualityWeights( + alignment = 0.9, + blur = 0.025, + brightness = 0.025, + contrast = 0.025, + eyeOpenness = 0.025, + ), + ) + + val otherWeighted = + simQ.calculateFaceQuality( + bitmap = bitmap, + pitch = 20.0, + yaw = 20.0, + roll = 20.0, + weights = + QualityWeights( + alignment = 0.025, + blur = 0.325, + brightness = 0.325, + contrast = 0.325, + eyeOpenness = 0.0, + ), + ) + + assertThat(alignmentWeighted).isLessThan(otherWeighted) + } + + @Test + fun calculateFaceQualityWithCustomParametersAffectsThresholds() { + val bitmap = createTestBitmap() + + val strictQuality = + simQ.calculateFaceQuality( + bitmap = bitmap, + pitch = 15.0, + yaw = 15.0, + roll = 15.0, + parameters = + QualityParameters( + maxAlignmentAngle = 10.0, + maxIndividualAngle = 20.0, + ), + ) + + val lenientQuality = + simQ.calculateFaceQuality( + bitmap = bitmap, + pitch = 15.0, + yaw = 15.0, + roll = 15.0, + parameters = + QualityParameters( + maxAlignmentAngle = 30.0, + maxIndividualAngle = 40.0, + ), + ) + + assertThat(lenientQuality).isAtLeast(strictQuality) + } + + @Test + fun calculateFaceQualityHandlesDifferentBitmapSizes() { + val smallBitmap = createTestBitmap(64, 64) + val mediumBitmap = createTestBitmap(256, 256) + val largeBitmap = createTestBitmap(1024, 1024) + + val smallQuality = simQ.calculateFaceQuality(smallBitmap) + val mediumQuality = simQ.calculateFaceQuality(mediumBitmap) + val largeQuality = simQ.calculateFaceQuality(largeBitmap) + + assertThat(smallQuality).isIn(Range.closed(0.0f, 1.0f)) + assertThat(mediumQuality).isIn(Range.closed(0.0f, 1.0f)) + assertThat(largeQuality).isIn(Range.closed(0.0f, 1.0f)) + } + + @Test + fun calculateFaceQualityWithDefaultParametersReturnsReasonableScore() { + val bitmap = createTestBitmap() + val quality = simQ.calculateFaceQuality(bitmap) + + assertThat(quality).isIn(Range.closed(0.0f, 1.0f)) + } + + @Test + fun calculateFaceQualityIsConsistentWithSameInputs() { + val bitmap = createTestBitmap() + + val quality1 = + simQ.calculateFaceQuality(bitmap, pitch = 10.0, yaw = 5.0, roll = -3.0) + val quality2 = + simQ.calculateFaceQuality(bitmap, pitch = 10.0, yaw = 5.0, roll = -3.0) + + assertThat(quality1).isWithin(0.001f).of(quality2) + } + + @Test + fun calculateFaceQualityWithZeroWeightsReturnsZeroOrHandledGracefully() { + val bitmap = createTestBitmap() + + val quality = + simQ.calculateFaceQuality( + bitmap = bitmap, + weights = + QualityWeights( + alignment = 0.0, + blur = 0.0, + brightness = 0.0, + contrast = 0.0, + eyeOpenness = 0.0, + ), + ) + + assertThat(quality).isIn(Range.closed(0.0f, 1.0f)) + } +} diff --git a/simq/src/main/java/com/simprints/simq/QualityParameters.kt b/simq/src/main/java/com/simprints/simq/QualityParameters.kt index 0942dbb..50a6282 100644 --- a/simq/src/main/java/com/simprints/simq/QualityParameters.kt +++ b/simq/src/main/java/com/simprints/simq/QualityParameters.kt @@ -4,21 +4,18 @@ data class QualityParameters( // Alignment thresholds val maxAlignmentAngle: Double = 20.0, val maxIndividualAngle: Double = 25.0, - // Blur thresholds (Laplacian variance) val minBlur: Double = 50_000.0, val maxBlur: Double = 100_000.0, - // Brightness thresholds (0-255) val minBrightness: Double = 30.0, val optimalBrightnessLow: Double = 80.0, val optimalBrightnessHigh: Double = 150.0, val maxBrightness: Double = 190.0, val brightnessSteepness: Double = 0.3, - // Contrast thresholds (std dev) val minContrast: Double = 30.0, - val maxContrast: Double = 47.0 + val maxContrast: Double = 47.0, ) { companion object { val DEFAULT = QualityParameters() diff --git a/simq/src/main/java/com/simprints/simq/QualityWeights.kt b/simq/src/main/java/com/simprints/simq/QualityWeights.kt index 23ead10..2916ad2 100644 --- a/simq/src/main/java/com/simprints/simq/QualityWeights.kt +++ b/simq/src/main/java/com/simprints/simq/QualityWeights.kt @@ -9,7 +9,7 @@ data class QualityWeights( val blur: Double = 0.3, val brightness: Double = 0.3, val contrast: Double = 0.1, - val eyeOpenness: Double = 0.0 + val eyeOpenness: Double = 0.0, ) { companion object { val DEFAULT = QualityWeights() diff --git a/simq/src/main/java/com/simprints/simq/SimQ.kt b/simq/src/main/java/com/simprints/simq/SimQ.kt index 9ff5865..e415f06 100644 --- a/simq/src/main/java/com/simprints/simq/SimQ.kt +++ b/simq/src/main/java/com/simprints/simq/SimQ.kt @@ -6,21 +6,18 @@ import com.simprints.simq.analysis.BlurAnalysis import com.simprints.simq.analysis.BrightnessAnalysis import com.simprints.simq.analysis.ContrastAnalysis import com.simprints.simq.utils.OpenCVLoader -import com.simprints.simq.utils.QualityUtils +import com.simprints.simq.utils.centerCrop +import com.simprints.simq.utils.resizeToArea -object SimQ { - +class SimQ { init { OpenCVLoader.init() } - + /** * Calculates face quality score (0.0 - 1.0). * * @param bitmap The cropped face bitmap - * @param imageWidth Width of the original full image (not used in current implementation) - * @param imageHeight Height of the original full image (not used in current implementation) - * @param boundingBox Bounding box of the face in the original image (not used in current implementation) * @param pitch Face pitch angle in degrees (head nod, default: 0.0) * @param yaw Face yaw angle in degrees (head rotation, default: 0.0) * @param roll Face roll angle in degrees (head tilt, default: 0.0) @@ -33,7 +30,6 @@ object SimQ { * @param parameters Custom quality parameters (optional) * @return Quality score between 0.0 and 1.0, or 0.0 if calculation fails */ - @JvmStatic fun calculateFaceQuality( bitmap: Bitmap, pitch: Double = 0.0, @@ -45,78 +41,87 @@ object SimQ { horizontalDisplacement: Float = 0.0f, verticalDisplacement: Float = 0.0f, weights: QualityWeights = QualityWeights.DEFAULT, - parameters: QualityParameters = QualityParameters.DEFAULT - ): Float { - return try { - // Resize bitmap to target area (256x256 = 65536) - val resizedBitmap = QualityUtils.resizeBitmap(bitmap, 65536.0) - - // Crop the bitmap - val croppedBitmap = QualityUtils.centerCropBitmap( - resizedBitmap, + parameters: QualityParameters = QualityParameters.DEFAULT, + ): Float = try { + // Resize bitmap to target area (256x256 = 65536) + val resizedBitmap = bitmap.resizeToArea(65536.0) + + // Crop the bitmap + val croppedBitmap = + resizedBitmap.centerCrop( centerCrop, horizontalDisplacement, - verticalDisplacement + verticalDisplacement, ) - - var totalScore = 0.0 - var totalWeight = 0.0 - - val alignmentScore = AlignmentAnalysis.calculateScore( - pitch, yaw, roll, + + var totalScore = 0.0 + val totalWeight = + weights.alignment + + weights.blur + + weights.brightness + + weights.contrast + + ( + if (leftEyeOpenness != null && rightEyeOpenness != null) { + weights.eyeOpenness + } else { + 0.0 + } + ) + + val alignmentScore = + AlignmentAnalysis.calculateScore( + pitch, + yaw, + roll, parameters.maxAlignmentAngle, - parameters.maxIndividualAngle + parameters.maxIndividualAngle, ) - totalScore += weights.alignment * alignmentScore - totalWeight += weights.alignment - - val blurScore = BlurAnalysis.calculateScore( + totalScore += weights.alignment * alignmentScore + + val blurScore = + BlurAnalysis.calculateScore( croppedBitmap, parameters.minBlur, - parameters.maxBlur + parameters.maxBlur, ) - totalScore += weights.blur * blurScore - totalWeight += weights.blur - - val brightnessScore = BrightnessAnalysis.calculateScore( + totalScore += weights.blur * blurScore + + val brightnessScore = + BrightnessAnalysis.calculateScore( croppedBitmap, parameters.minBrightness, parameters.optimalBrightnessLow, parameters.optimalBrightnessHigh, parameters.maxBrightness, - parameters.brightnessSteepness + parameters.brightnessSteepness, ) - totalScore += weights.brightness * brightnessScore - totalWeight += weights.brightness - - val contrastScore = ContrastAnalysis.calculateScore( + totalScore += weights.brightness * brightnessScore + + val contrastScore = + ContrastAnalysis.calculateScore( croppedBitmap, parameters.minContrast, - parameters.maxContrast + parameters.maxContrast, ) - totalScore += weights.contrast * contrastScore - totalWeight += weights.contrast - - if (leftEyeOpenness != null && rightEyeOpenness != null) { - val eyeScore = (leftEyeOpenness + rightEyeOpenness) / 2.0 - totalScore += weights.eyeOpenness * eyeScore - totalWeight += weights.eyeOpenness - } - - // Clean up - if (croppedBitmap != bitmap && croppedBitmap != resizedBitmap) { - croppedBitmap.recycle() - } - if (resizedBitmap != bitmap) { - resizedBitmap.recycle() - } - - // Normalize and clamp to 0-1 range - val finalScore = if (totalWeight > 0) totalScore / totalWeight else 0.0 - finalScore.coerceIn(0.0, 1.0).toFloat() - - } catch (e: Exception) { - 0.0f + totalScore += weights.contrast * contrastScore + + if (leftEyeOpenness != null && rightEyeOpenness != null) { + val eyeScore = (leftEyeOpenness + rightEyeOpenness) / 2.0 + totalScore += weights.eyeOpenness * eyeScore + } + + // Clean up + if (croppedBitmap != bitmap && croppedBitmap != resizedBitmap) { + croppedBitmap.recycle() + } + if (resizedBitmap != bitmap) { + resizedBitmap.recycle() } + + // Normalize and clamp to 0-1 range + val finalScore = if (totalWeight > 0) totalScore / totalWeight else 0.0 + finalScore.coerceIn(0.0, 1.0).toFloat() + } catch (e: Exception) { + 0.0f } } diff --git a/simq/src/main/java/com/simprints/simq/analysis/AlignmentAnalysis.kt b/simq/src/main/java/com/simprints/simq/analysis/AlignmentAnalysis.kt index 74c4947..ecef391 100644 --- a/simq/src/main/java/com/simprints/simq/analysis/AlignmentAnalysis.kt +++ b/simq/src/main/java/com/simprints/simq/analysis/AlignmentAnalysis.kt @@ -3,10 +3,9 @@ package com.simprints.simq.analysis import kotlin.math.absoluteValue object AlignmentAnalysis { - /** * Calculates alignment score based on pitch, yaw, and roll angles. - * + * * @param pitch Face pitch angle in degrees (head nod) * @param yaw Face yaw angle in degrees (head rotation) * @param roll Face roll angle in degrees (head tilt) @@ -19,19 +18,20 @@ object AlignmentAnalysis { yaw: Double, roll: Double, maxAngle: Double, - maxIndividualAngle: Double + maxIndividualAngle: Double, ): Double { // Reject if any angle is too extreme if (pitch.absoluteValue > maxIndividualAngle || yaw.absoluteValue > maxIndividualAngle || - roll.absoluteValue > maxIndividualAngle) { + roll.absoluteValue > maxIndividualAngle + ) { return 0.0 } - + val pitchScore = maxOf(0.0, 1.0 - (pitch.absoluteValue / maxAngle)) val yawScore = maxOf(0.0, 1.0 - (yaw.absoluteValue / maxAngle)) val rollScore = maxOf(0.0, 1.0 - (roll.absoluteValue / maxAngle)) - + return (pitchScore + yawScore + rollScore) / 3.0 } } diff --git a/simq/src/main/java/com/simprints/simq/analysis/BlurAnalysis.kt b/simq/src/main/java/com/simprints/simq/analysis/BlurAnalysis.kt index 4c2637a..7d3f8eb 100644 --- a/simq/src/main/java/com/simprints/simq/analysis/BlurAnalysis.kt +++ b/simq/src/main/java/com/simprints/simq/analysis/BlurAnalysis.kt @@ -1,7 +1,7 @@ package com.simprints.simq.analysis import android.graphics.Bitmap -import com.simprints.simq.utils.QualityUtils +import com.simprints.simq.utils.ScoringFunctions import org.opencv.android.Utils import org.opencv.core.Core import org.opencv.core.CvType @@ -11,51 +11,55 @@ import org.opencv.imgproc.Imgproc import kotlin.math.pow object BlurAnalysis { - /** * Calculates blur score using Laplacian variance. - * + * * @param bitmap The face image to analyze * @param minBlur Minimum acceptable blur threshold * @param maxBlur Maximum blur threshold for optimal score * @return Blur score between 0.0 and 1.0 */ - fun calculateScore(bitmap: Bitmap, minBlur: Double, maxBlur: Double): Double { - return try { - val laplacianVariance = calculateLaplacianVariance(bitmap) - QualityUtils.rampScore(laplacianVariance, minBlur, maxBlur) - } catch (e: Exception) { - 1.0 // Default to good score if OpenCV not available - } + fun calculateScore( + bitmap: Bitmap, + minBlur: Double, + maxBlur: Double, + ): Double = try { + val laplacianVariance = calculateLaplacianVariance(bitmap) + ScoringFunctions.rampScore(laplacianVariance, minBlur, maxBlur) + } catch (e: Exception) { + 1.0 // Default to good score if OpenCV not available } - + /** * Calculates Laplacian blur variance using OpenCV. - * + * * @param bitmap The face image to analyze * @param ksize Kernel size for Laplacian operator (default: 5) * @return Laplacian variance value */ - private fun calculateLaplacianVariance(bitmap: Bitmap, ksize: Int = 5): Double { + private fun calculateLaplacianVariance( + bitmap: Bitmap, + ksize: Int = 5, + ): Double { val mat = Mat() val gray = Mat() Utils.bitmapToMat(bitmap, mat) Imgproc.cvtColor(mat, gray, Imgproc.COLOR_BGR2GRAY) - + val laplacian = Mat() Imgproc.Laplacian(gray, laplacian, CvType.CV_64F, ksize) - + val mean = MatOfDouble() val stddev = MatOfDouble() Core.meanStdDev(laplacian, mean, stddev) val laplacianVariance = stddev.toArray()[0].pow(2.0) - + mat.release() gray.release() laplacian.release() mean.release() stddev.release() - + return laplacianVariance } } diff --git a/simq/src/main/java/com/simprints/simq/analysis/BrightnessAnalysis.kt b/simq/src/main/java/com/simprints/simq/analysis/BrightnessAnalysis.kt index 6630661..808721d 100644 --- a/simq/src/main/java/com/simprints/simq/analysis/BrightnessAnalysis.kt +++ b/simq/src/main/java/com/simprints/simq/analysis/BrightnessAnalysis.kt @@ -1,17 +1,16 @@ package com.simprints.simq.analysis import android.graphics.Bitmap -import com.simprints.simq.utils.QualityUtils +import com.simprints.simq.utils.ScoringFunctions import org.opencv.android.Utils import org.opencv.core.Core import org.opencv.core.Mat import org.opencv.imgproc.Imgproc object BrightnessAnalysis { - /** * Calculates brightness score using plateau function. - * + * * @param bitmap The face image to analyze * @param edgeLow Lower edge threshold (minimum acceptable brightness) * @param centerLow Lower center threshold (start of optimal range) @@ -26,19 +25,17 @@ object BrightnessAnalysis { centerLow: Double, centerHigh: Double, edgeHigh: Double, - steepness: Double - ): Double { - return try { - val brightness = analyzeBrightness(bitmap) - QualityUtils.plateauScore(brightness, centerLow, centerHigh, edgeLow, edgeHigh, steepness) - } catch (e: Exception) { - 1.0 - } + steepness: Double, + ): Double = try { + val brightness = analyzeBrightness(bitmap) + ScoringFunctions.plateauScore(brightness, centerLow, centerHigh, edgeLow, edgeHigh, steepness) + } catch (e: Exception) { + 1.0 } - + /** * Analyzes brightness of bitmap using OpenCV. - * + * * @param bitmap The face image to analyze * @return Mean brightness value (0-255) */ diff --git a/simq/src/main/java/com/simprints/simq/analysis/ContrastAnalysis.kt b/simq/src/main/java/com/simprints/simq/analysis/ContrastAnalysis.kt index 239517a..1f54b1e 100644 --- a/simq/src/main/java/com/simprints/simq/analysis/ContrastAnalysis.kt +++ b/simq/src/main/java/com/simprints/simq/analysis/ContrastAnalysis.kt @@ -1,7 +1,7 @@ package com.simprints.simq.analysis import android.graphics.Bitmap -import com.simprints.simq.utils.QualityUtils +import com.simprints.simq.utils.ScoringFunctions import org.opencv.android.Utils import org.opencv.core.Core import org.opencv.core.Mat @@ -9,27 +9,28 @@ import org.opencv.core.MatOfDouble import org.opencv.imgproc.Imgproc object ContrastAnalysis { - /** * Calculates contrast score using standard deviation. - * + * * @param bitmap The face image to analyze * @param minContrast Minimum acceptable contrast threshold * @param maxContrast Maximum contrast threshold for optimal score * @return Contrast score between 0.0 and 1.0 */ - fun calculateScore(bitmap: Bitmap, minContrast: Double, maxContrast: Double): Double { - return try { - val contrast = analyzeContrast(bitmap) - QualityUtils.rampScore(contrast, minContrast, maxContrast) - } catch (e: Exception) { - 1.0 // Default to good score if OpenCV not available - } + fun calculateScore( + bitmap: Bitmap, + minContrast: Double, + maxContrast: Double, + ): Double = try { + val contrast = analyzeContrast(bitmap) + ScoringFunctions.rampScore(contrast, minContrast, maxContrast) + } catch (e: Exception) { + 1.0 // Default to good score if OpenCV not available } - + /** * Analyzes contrast of bitmap using OpenCV (standard deviation). - * + * * @param bitmap The face image to analyze * @return Standard deviation value representing contrast */ @@ -38,17 +39,17 @@ object ContrastAnalysis { val gray = Mat() Utils.bitmapToMat(bitmap, mat) Imgproc.cvtColor(mat, gray, Imgproc.COLOR_BGR2GRAY) - + val mean = MatOfDouble() val stddev = MatOfDouble() Core.meanStdDev(gray, mean, stddev) val stdDevValue = stddev.toArray()[0] - + mat.release() gray.release() mean.release() stddev.release() - + return stdDevValue } } diff --git a/simq/src/main/java/com/simprints/simq/utils/BitmapExt.kt b/simq/src/main/java/com/simprints/simq/utils/BitmapExt.kt new file mode 100644 index 0000000..75fbf72 --- /dev/null +++ b/simq/src/main/java/com/simprints/simq/utils/BitmapExt.kt @@ -0,0 +1,43 @@ +package com.simprints.simq.utils + +import android.graphics.Bitmap +import kotlin.math.roundToInt +import kotlin.math.sqrt + +/** + * Crops bitmap to center region with optional displacement. + * + * @param centerCrop Fraction of the bitmap to use (0.0-1.0) + * @param horizontalDisplacement Horizontal displacement factor (-1.0 to 1.0) + * @param verticalDisplacement Vertical displacement factor (-1.0 to 1.0) + * @return Cropped bitmap + */ +fun Bitmap.centerCrop( + centerCrop: Float, + horizontalDisplacement: Float = 0f, + verticalDisplacement: Float = 0f, +): Bitmap { + val hAbsDisplacement = (width * horizontalDisplacement).toInt() + val vAbsDisplacement = (height * verticalDisplacement).toInt() + + val cropWidth = (width * centerCrop).toInt() + val cropHeight = (height * centerCrop).toInt() + val startX = hAbsDisplacement + (width - cropWidth) / 2 + val startY = vAbsDisplacement + (height - cropHeight) / 2 + + return Bitmap.createBitmap(this, startX, startY, cropWidth, cropHeight) +} + +/** + * Resizes bitmap to a target area while maintaining aspect ratio. + * + * @param targetArea Target area in pixels (default: 65536 = 256x256) + * @return Resized bitmap + */ +fun Bitmap.resizeToArea(targetArea: Double = 65536.0): Bitmap { + val aspectRatio = width.toFloat() / height.toFloat() + val newHeight = sqrt(targetArea / aspectRatio) + val newWidth = aspectRatio * newHeight + + return Bitmap.createScaledBitmap(this, newWidth.roundToInt(), newHeight.roundToInt(), true) +} diff --git a/simq/src/main/java/com/simprints/simq/utils/OpenCVLoader.kt b/simq/src/main/java/com/simprints/simq/utils/OpenCVLoader.kt index b623a1f..938071e 100644 --- a/simq/src/main/java/com/simprints/simq/utils/OpenCVLoader.kt +++ b/simq/src/main/java/com/simprints/simq/utils/OpenCVLoader.kt @@ -8,9 +8,8 @@ import org.opencv.android.OpenCVLoader as AndroidOpenCVLoader * Ensures the native library is loaded only once during the application lifecycle. */ object OpenCVLoader { - private const val TAG = "OpenCV" - + fun init() { if (!AndroidOpenCVLoader.initLocal()) { Log.e(TAG, "OpenCV not loaded!") diff --git a/simq/src/main/java/com/simprints/simq/utils/QualityUtils.kt b/simq/src/main/java/com/simprints/simq/utils/QualityUtils.kt deleted file mode 100644 index 7a3f3f9..0000000 --- a/simq/src/main/java/com/simprints/simq/utils/QualityUtils.kt +++ /dev/null @@ -1,100 +0,0 @@ -package com.simprints.simq.utils - -import android.graphics.Bitmap -import kotlin.math.exp -import kotlin.math.roundToInt -import kotlin.math.sqrt - -object QualityUtils { - - /** - * Ramp scoring function: linear interpolation between min and max. - * - * @param x The input value to score - * @param min Minimum threshold (scores 0.0 below this) - * @param max Maximum threshold (scores 1.0 above this) - * @return Score between 0.0 and 1.0 - */ - fun rampScore(x: Double, min: Double, max: Double): Double { - return when { - x < min -> 0.0 - x > max -> 1.0 - else -> (x - min) / (max - min) - } - } - - /** - * Plateau scoring function: optimal range with smooth sigmoid falloff. - * - * @param x The input value to score - * @param centerLow Lower bound of optimal range - * @param centerHigh Upper bound of optimal range - * @param edgeLow Lower edge threshold - * @param edgeHigh Upper edge threshold - * @param steepness Steepness of sigmoid falloff - * @return Score between 0.0 and 1.0 - */ - fun plateauScore( - x: Double, - centerLow: Double, - centerHigh: Double, - edgeLow: Double, - edgeHigh: Double, - steepness: Double - ): Double { - return when { - x in centerLow..centerHigh -> 1.0 - x < centerLow -> 1.0 / (1.0 + exp(-steepness * (x - edgeLow))) - else -> 1.0 / (1.0 + exp(steepness * (x - edgeHigh))) - }.coerceIn(0.0, 1.0) - } - - /** - * Crops bitmap to center region with optional displacement. - * - * @param bitmap The bitmap to crop - * @param centerCrop Fraction of the bitmap to use (0.0-1.0) - * @param horizontalDisplacement Horizontal displacement factor (-1.0 to 1.0) - * @param verticalDisplacement Vertical displacement factor (-1.0 to 1.0) - * @return Cropped bitmap - */ - fun centerCropBitmap( - bitmap: Bitmap, - centerCrop: Float, - horizontalDisplacement: Float, - verticalDisplacement: Float - ): Bitmap { - val width = bitmap.width - val height = bitmap.height - - val hAbsDisplacement = (width * horizontalDisplacement).toInt() - val vAbsDisplacement = (height * verticalDisplacement).toInt() - - val cropWidth = (width * centerCrop).toInt() - val cropHeight = (height * centerCrop).toInt() - val startX = hAbsDisplacement + (width - cropWidth) / 2 - val startY = vAbsDisplacement + (height - cropHeight) / 2 - - return Bitmap.createBitmap(bitmap, startX, startY, cropWidth, cropHeight) - } - - /** - * Resizes bitmap to a target area while maintaining aspect ratio. - * - * @param bitmap The bitmap to resize - * @param targetArea Target area in pixels (default: 65536 = 256x256) - * @return Resized bitmap - */ - fun resizeBitmap(bitmap: Bitmap, targetArea: Double = 65536.0): Bitmap { - val aspectRatio = bitmap.width.toFloat() / bitmap.height.toFloat() - val newHeight = sqrt(targetArea / aspectRatio) - val newWidth = aspectRatio * newHeight - - return Bitmap.createScaledBitmap( - bitmap, - newWidth.roundToInt(), - newHeight.roundToInt(), - true - ) - } -} diff --git a/simq/src/main/java/com/simprints/simq/utils/ScoringFunctions.kt b/simq/src/main/java/com/simprints/simq/utils/ScoringFunctions.kt new file mode 100644 index 0000000..238de1e --- /dev/null +++ b/simq/src/main/java/com/simprints/simq/utils/ScoringFunctions.kt @@ -0,0 +1,47 @@ +package com.simprints.simq.utils + +import kotlin.math.exp + +object ScoringFunctions { + /** + * Ramp scoring function: linear interpolation between min and max. + * + * @param x The input value to score + * @param min Minimum threshold (scores 0.0 below this) + * @param max Maximum threshold (scores 1.0 above this) + * @return Score between 0.0 and 1.0 + */ + fun rampScore( + x: Double, + min: Double, + max: Double, + ): Double = when { + x < min -> 0.0 + x > max -> 1.0 + else -> (x - min) / (max - min) + } + + /** + * Plateau scoring function: optimal range with smooth sigmoid falloff. + * + * @param x The input value to score + * @param centerLow Lower bound of optimal range + * @param centerHigh Upper bound of optimal range + * @param edgeLow Lower edge threshold + * @param edgeHigh Upper edge threshold + * @param steepness Steepness of sigmoid falloff + * @return Score between 0.0 and 1.0 + */ + fun plateauScore( + x: Double, + centerLow: Double, + centerHigh: Double, + edgeLow: Double, + edgeHigh: Double, + steepness: Double, + ): Double = when { + x in centerLow..centerHigh -> 1.0 + x < centerLow -> 1.0 / (1.0 + exp(-steepness * (x - edgeLow))) + else -> 1.0 / (1.0 + exp(steepness * (x - edgeHigh))) + }.coerceIn(0.0, 1.0) +} diff --git a/simq/src/test/java/com/simprints/simq/AlignmentAnalysisTest.kt b/simq/src/test/java/com/simprints/simq/AlignmentAnalysisTest.kt deleted file mode 100644 index e002a39..0000000 --- a/simq/src/test/java/com/simprints/simq/AlignmentAnalysisTest.kt +++ /dev/null @@ -1,104 +0,0 @@ -package com.simprints.simq - -import com.simprints.simq.analysis.AlignmentAnalysis -import org.junit.Assert -import org.junit.Test - -class AlignmentAnalysisTest { - - private val maxAngle = 20.0 - private val maxIndividualAngle = 25.0 - - @Test - fun `perfect alignment returns score of 1_0`() { - val score = AlignmentAnalysis.calculateScore( - pitch = 0.0, - yaw = 0.0, - roll = 0.0, - maxAngle = maxAngle, - maxIndividualAngle = maxIndividualAngle - ) - Assert.assertEquals(1.0, score, 0.001) - } - - @Test - fun `angle at half max threshold returns score of 0_5`() { - val halfAngle = maxAngle / 2 - val score = AlignmentAnalysis.calculateScore( - pitch = halfAngle, - yaw = halfAngle, - roll = halfAngle, - maxAngle = maxAngle, - maxIndividualAngle = maxIndividualAngle - ) - Assert.assertEquals(0.5, score, 0.001) - } - - @Test - fun `negative angles are treated as absolute values`() { - val score1 = AlignmentAnalysis.calculateScore( - pitch = -10.0, - yaw = -10.0, - roll = -10.0, - maxAngle = maxAngle, - maxIndividualAngle = maxIndividualAngle - ) - - val score2 = AlignmentAnalysis.calculateScore( - pitch = 10.0, - yaw = 10.0, - roll = 10.0, - maxAngle = maxAngle, - maxIndividualAngle = maxIndividualAngle - ) - - Assert.assertEquals(score1, score2, 0.001) - } - - @Test - fun `any single angle exceeding maxIndividualAngle rejects entire score`() { - // Test pitch rejection - val pitchScore = AlignmentAnalysis.calculateScore( - pitch = 26.0, - yaw = 0.0, - roll = 0.0, - maxAngle = maxAngle, - maxIndividualAngle = maxIndividualAngle - ) - Assert.assertEquals(0.0, pitchScore, 0.001) - - // Test yaw rejection - val yawScore = AlignmentAnalysis.calculateScore( - pitch = 0.0, - yaw = 26.0, - roll = 0.0, - maxAngle = maxAngle, - maxIndividualAngle = maxIndividualAngle - ) - Assert.assertEquals(0.0, yawScore, 0.001) - - // Test roll rejection - val rollScore = AlignmentAnalysis.calculateScore( - pitch = 0.0, - yaw = 0.0, - roll = 26.0, - maxAngle = maxAngle, - maxIndividualAngle = maxIndividualAngle - ) - Assert.assertEquals(0.0, rollScore, 0.001) - } - - @Test - fun `mixed angles calculate average score correctly`() { - // Perfect pitch, half-max yaw, max roll - val score = AlignmentAnalysis.calculateScore( - pitch = 0.0, // Score: 1.0 - yaw = 10.0, // Score: 0.5 (10/20) - roll = 20.0, // Score: 0.0 (20/20) - maxAngle = maxAngle, - maxIndividualAngle = maxIndividualAngle - ) - // Average: (1.0 + 0.5 + 0.0) / 3 = 0.5 - Assert.assertEquals(0.5, score, 0.001) - } -} diff --git a/simq/src/test/java/com/simprints/simq/QualityUtilsTest.kt b/simq/src/test/java/com/simprints/simq/QualityUtilsTest.kt deleted file mode 100644 index 37973d7..0000000 --- a/simq/src/test/java/com/simprints/simq/QualityUtilsTest.kt +++ /dev/null @@ -1,222 +0,0 @@ -package com.simprints.simq - -import android.graphics.Bitmap -import com.simprints.simq.utils.QualityUtils -import org.junit.Assert -import org.junit.Test -import org.junit.runner.RunWith -import org.robolectric.RobolectricTestRunner - -@RunWith(RobolectricTestRunner::class) -class QualityUtilsTest { - - @Test - fun `rampScore returns 0 when below minimum`() { - val score = QualityUtils.rampScore(x = 10.0, min = 20.0, max = 100.0) - Assert.assertEquals(0.0, score, 0.001) - } - - @Test - fun `rampScore returns 1 when above maximum`() { - val score = QualityUtils.rampScore(x = 150.0, min = 20.0, max = 100.0) - Assert.assertEquals(1.0, score, 0.001) - } - - @Test - fun `rampScore returns 0_5 at midpoint`() { - val score = QualityUtils.rampScore(x = 60.0, min = 20.0, max = 100.0) - Assert.assertEquals(0.5, score, 0.001) - } - - @Test - fun `rampScore interpolates linearly`() { - val score = QualityUtils.rampScore(x = 30.0, min = 20.0, max = 120.0) - // (30 - 20) / (120 - 20) = 10/100 = 0.1 - Assert.assertEquals(0.1, score, 0.001) - } - - @Test - fun `plateauScore returns 1 in optimal range`() { - val score1 = QualityUtils.plateauScore( - x = 100.0, - centerLow = 80.0, - centerHigh = 150.0, - edgeLow = 30.0, - edgeHigh = 190.0, - steepness = 0.3 - ) - Assert.assertEquals(1.0, score1, 0.001) - - val score2 = QualityUtils.plateauScore( - x = 80.0, - centerLow = 80.0, - centerHigh = 150.0, - edgeLow = 30.0, - edgeHigh = 190.0, - steepness = 0.3 - ) - Assert.assertEquals(1.0, score2, 0.001) - - val score3 = QualityUtils.plateauScore( - x = 150.0, - centerLow = 80.0, - centerHigh = 150.0, - edgeLow = 30.0, - edgeHigh = 190.0, - steepness = 0.3 - ) - Assert.assertEquals(1.0, score3, 0.001) - } - - @Test - fun `plateauScore decreases outside optimal range`() { - // Below center - val scoreLow = QualityUtils.plateauScore( - x = 50.0, - centerLow = 80.0, - centerHigh = 150.0, - edgeLow = 30.0, - edgeHigh = 190.0, - steepness = 0.3 - ) - Assert.assertTrue(scoreLow < 1.0) - Assert.assertTrue(scoreLow > 0.0) - - // Above center - val scoreHigh = QualityUtils.plateauScore( - x = 170.0, - centerLow = 80.0, - centerHigh = 150.0, - edgeLow = 30.0, - edgeHigh = 190.0, - steepness = 0.3 - ) - Assert.assertTrue(scoreHigh < 1.0) - Assert.assertTrue(scoreHigh > 0.0) - } - - @Test - fun `plateauScore is clamped between 0 and 1`() { - val scoreVeryLow = QualityUtils.plateauScore( - x = 0.0, - centerLow = 80.0, - centerHigh = 150.0, - edgeLow = 30.0, - edgeHigh = 190.0, - steepness = 0.3 - ) - Assert.assertTrue(scoreVeryLow >= 0.0 && scoreVeryLow <= 1.0) - - val scoreVeryHigh = QualityUtils.plateauScore( - x = 300.0, - centerLow = 80.0, - centerHigh = 150.0, - edgeLow = 30.0, - edgeHigh = 190.0, - steepness = 0.3 - ) - Assert.assertTrue(scoreVeryHigh >= 0.0 && scoreVeryHigh <= 1.0) - } - - @Test - fun `plateauScore is symmetric around optimal range`() { - val scoreLow = QualityUtils.plateauScore( - x = 50.0, - centerLow = 80.0, - centerHigh = 150.0, - edgeLow = 30.0, - edgeHigh = 190.0, - steepness = 0.3 - ) - - val scoreHigh = QualityUtils.plateauScore( - x = 180.0, - centerLow = 80.0, - centerHigh = 150.0, - edgeLow = 30.0, - edgeHigh = 190.0, - steepness = 0.3 - ) - - // Should be approximately equal due to symmetry - Assert.assertEquals(scoreLow, scoreHigh, 0.1) - } - - @Test - fun `centerCropBitmap with no displacement crops center`() { - val bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888) - val cropped = QualityUtils.centerCropBitmap( - bitmap = bitmap, - centerCrop = 0.5f, - horizontalDisplacement = 0.0f, - verticalDisplacement = 0.0f - ) - - Assert.assertEquals(50, cropped.width) - Assert.assertEquals(50, cropped.height) - } - - @Test - fun `centerCropBitmap with full crop returns same size`() { - val bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888) - val cropped = QualityUtils.centerCropBitmap( - bitmap = bitmap, - centerCrop = 1.0f, - horizontalDisplacement = 0.0f, - verticalDisplacement = 0.0f - ) - - Assert.assertEquals(100, cropped.width) - Assert.assertEquals(100, cropped.height) - } - - @Test - fun `resizeBitmap maintains aspect ratio for square bitmap`() { - val bitmap = Bitmap.createBitmap(512, 512, Bitmap.Config.ARGB_8888) - val resized = QualityUtils.resizeBitmap(bitmap, targetArea = 65536.0) - - Assert.assertEquals(256, resized.width) - Assert.assertEquals(256, resized.height) - } - - @Test - fun `resizeBitmap maintains aspect ratio for rectangular bitmap`() { - val bitmap = Bitmap.createBitmap(800, 400, Bitmap.Config.ARGB_8888) - val resized = QualityUtils.resizeBitmap(bitmap, targetArea = 65536.0) - - val aspectRatio = resized.width.toDouble() / resized.height.toDouble() - Assert.assertEquals(2.0, aspectRatio, 0.01) - - val area = resized.width * resized.height - Assert.assertEquals(65536.0, area.toDouble(), 1000.0) - } - - @Test - fun `resizeBitmap scales down large bitmap`() { - val bitmap = Bitmap.createBitmap(1024, 1024, Bitmap.Config.ARGB_8888) - val resized = QualityUtils.resizeBitmap(bitmap, targetArea = 65536.0) - - Assert.assertTrue(resized.width < bitmap.width) - Assert.assertTrue(resized.height < bitmap.height) - } - - @Test - fun `resizeBitmap scales up small bitmap`() { - val bitmap = Bitmap.createBitmap(64, 64, Bitmap.Config.ARGB_8888) - val resized = QualityUtils.resizeBitmap(bitmap, targetArea = 65536.0) - - Assert.assertTrue(resized.width > bitmap.width) - Assert.assertTrue(resized.height > bitmap.height) - } - - @Test - fun `resizeBitmap handles different target areas`() { - val bitmap = Bitmap.createBitmap(512, 512, Bitmap.Config.ARGB_8888) - - val smallResize = QualityUtils.resizeBitmap(bitmap, targetArea = 16384.0) - val largeResize = QualityUtils.resizeBitmap(bitmap, targetArea = 262144.0) - - Assert.assertTrue(smallResize.width < largeResize.width) - Assert.assertTrue(smallResize.height < largeResize.height) - } -} diff --git a/simq/src/test/java/com/simprints/simq/QualityWeightsTest.kt b/simq/src/test/java/com/simprints/simq/QualityWeightsTest.kt deleted file mode 100644 index 2222903..0000000 --- a/simq/src/test/java/com/simprints/simq/QualityWeightsTest.kt +++ /dev/null @@ -1,82 +0,0 @@ -package com.simprints.simq - -import android.graphics.Bitmap -import com.simprints.simq.shadows.ShadowCore -import com.simprints.simq.shadows.ShadowCvType -import com.simprints.simq.shadows.ShadowImgproc -import com.simprints.simq.shadows.ShadowMat -import com.simprints.simq.shadows.ShadowMatOfDouble -import com.simprints.simq.shadows.ShadowOpenCVLoader -import com.simprints.simq.shadows.ShadowOpenCVUtils -import org.junit.Assert.assertEquals -import org.junit.Assert.assertNotEquals -import org.junit.Assert.assertTrue -import org.junit.Test -import org.junit.runner.RunWith -import org.robolectric.RobolectricTestRunner -import org.robolectric.annotation.Config - -@RunWith(RobolectricTestRunner::class) -@Config(shadows = [ - ShadowOpenCVLoader::class, - ShadowOpenCVUtils::class, - ShadowMat::class, - ShadowMatOfDouble::class, - ShadowImgproc::class, - ShadowCore::class, - ShadowCvType::class -]) - -class QualityWeightsTest { - - private fun createTestBitmap(width: Int = 256, height: Int = 256): Bitmap { - return Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888) - } - - @Test - fun `default weights sum to 1_0`() { - val weights = QualityWeights.DEFAULT - val sum = weights.alignment + weights.blur + weights.brightness + - weights.contrast + weights.eyeOpenness - assertEquals(1.0, sum, 0.001) - } - - @Test - fun `custom weights can be created`() { - val customWeights = QualityWeights( - alignment = 0.25, - blur = 0.25, - brightness = 0.25, - contrast = 0.15, - eyeOpenness = 0.10 - ) - - assertEquals(0.25, customWeights.alignment, 0.001) - assertEquals(0.25, customWeights.blur, 0.001) - assertEquals(0.25, customWeights.brightness, 0.001) - assertEquals(0.15, customWeights.contrast, 0.001) - assertEquals(0.10, customWeights.eyeOpenness, 0.001) - } - - @Test - fun `calculateFaceQuality with all weights maximizing one metric`() { - val bitmap = createTestBitmap() - - // Only alignment weight - val alignmentOnly = SimQ.calculateFaceQuality( - bitmap = bitmap, - pitch = 0.0, - yaw = 0.0, - roll = 0.0, - weights = QualityWeights( - alignment = 1.0, - blur = 0.0, - brightness = 0.0, - contrast = 0.0, - eyeOpenness = 0.0 - ) - ) - - assertEquals(alignmentOnly, 1f) - } -} diff --git a/simq/src/test/java/com/simprints/simq/SimQTest.kt b/simq/src/test/java/com/simprints/simq/SimQTest.kt deleted file mode 100644 index da25fd5..0000000 --- a/simq/src/test/java/com/simprints/simq/SimQTest.kt +++ /dev/null @@ -1,284 +0,0 @@ -package com.simprints.simq - -import android.graphics.Bitmap -import com.simprints.simq.shadows.ShadowCore -import com.simprints.simq.shadows.ShadowCvType -import com.simprints.simq.shadows.ShadowImgproc -import com.simprints.simq.shadows.ShadowMat -import com.simprints.simq.shadows.ShadowMatOfDouble -import com.simprints.simq.shadows.ShadowOpenCVLoader -import com.simprints.simq.shadows.ShadowOpenCVUtils -import org.junit.Assert.assertEquals -import org.junit.Assert.assertTrue -import org.junit.Test -import org.junit.runner.RunWith -import org.robolectric.RobolectricTestRunner -import org.robolectric.annotation.Config -import org.opencv.android.OpenCVLoader as AndroidOpenCVLoader - -@RunWith(RobolectricTestRunner::class) -@Config(shadows = [ - ShadowOpenCVLoader::class, - ShadowOpenCVUtils::class, - ShadowMat::class, - ShadowMatOfDouble::class, - ShadowImgproc::class, - ShadowCore::class, - ShadowCvType::class -]) - -class SimQTest { - - private fun createTestBitmap(width: Int = 256, height: Int = 256): Bitmap { - return Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888) - } - - @Test - fun `calculateFaceQuality returns value between 0 and 1`() { - val bitmap = createTestBitmap() - val quality = SimQ.calculateFaceQuality(bitmap) - - assertTrue(quality >= 0.0f) - assertTrue(quality <= 1.0f) - } - - @Test - fun `calculateFaceQuality with perfect alignment returns higher score`() { - val bitmap = createTestBitmap() - - val perfectScore = SimQ.calculateFaceQuality( - bitmap = bitmap, - pitch = 0.0, - yaw = 0.0, - roll = 0.0 - ) - - val poorAlignmentScore = SimQ.calculateFaceQuality( - bitmap = bitmap, - pitch = 20.0, - yaw = 20.0, - roll = 20.0 - ) - - assertTrue(perfectScore >= poorAlignmentScore) - } - - @Test - fun `calculateFaceQuality with extreme angles returns low score`() { - val bitmap = createTestBitmap() - - val quality = SimQ.calculateFaceQuality( - bitmap = bitmap, - pitch = 30.0, // Exceeds maxIndividualAngle - yaw = 0.0, - roll = 0.0 - ) - - assertTrue(quality < 0.5f) - } - - @Test - fun `calculateFaceQuality with eye openness includes it in calculation`() { - val bitmap = createTestBitmap() - - // Test with eyes open - val openEyesScore = SimQ.calculateFaceQuality( - bitmap = bitmap, - leftEyeOpenness = 1.0, - rightEyeOpenness = 1.0, - weights = QualityWeights( - alignment = 0.3, - blur = 0.2, - brightness = 0.2, - contrast = 0.1, - eyeOpenness = 0.2 - ) - ) - - // Test with eyes closed - val closedEyesScore = SimQ.calculateFaceQuality( - bitmap = bitmap, - leftEyeOpenness = 0.0, - rightEyeOpenness = 0.0, - weights = QualityWeights( - alignment = 0.3, - blur = 0.2, - brightness = 0.2, - contrast = 0.1, - eyeOpenness = 0.2 - ) - ) - - // Open eyes should score higher when eye weight is significant - assertTrue(openEyesScore >= closedEyesScore) - } - - @Test - fun `calculateFaceQuality without eye openness ignores eye weight`() { - val bitmap = createTestBitmap() - - val qualityNoEyes = SimQ.calculateFaceQuality( - bitmap = bitmap, - leftEyeOpenness = null, - rightEyeOpenness = null, - weights = QualityWeights(eyeOpenness = 0.2) - ) - - // Should still return valid score - assertTrue(qualityNoEyes >= 0.0f) - assertTrue(qualityNoEyes <= 1.0f) - } - - @Test - fun `calculateFaceQuality with only left eye openness provided`() { - val bitmap = createTestBitmap() - - // Only one eye value - should not use eye openness - val quality = SimQ.calculateFaceQuality( - bitmap = bitmap, - leftEyeOpenness = 1.0, - rightEyeOpenness = null, - weights = QualityWeights(eyeOpenness = 0.2) - ) - - assertTrue(quality >= 0.0f && quality <= 1.0f) - } - - @Test - fun `calculateFaceQuality with custom weights affects result`() { - val bitmap = createTestBitmap() - - // Weight alignment heavily - val alignmentWeighted = SimQ.calculateFaceQuality( - bitmap = bitmap, - pitch = 20.0, - yaw = 20.0, - roll = 20.0, - weights = QualityWeights( - alignment = 0.9, - blur = 0.025, - brightness = 0.025, - contrast = 0.025, - eyeOpenness = 0.025 - ) - ) - - // Weight other factors - val otherWeighted = SimQ.calculateFaceQuality( - bitmap = bitmap, - pitch = 20.0, - yaw = 20.0, - roll = 20.0, - weights = QualityWeights( - alignment = 0.025, - blur = 0.325, - brightness = 0.325, - contrast = 0.325, - eyeOpenness = 0.0 - ) - ) - - // With poor alignment, heavily weighting alignment should give lower score - assertTrue(alignmentWeighted < otherWeighted) - } - - @Test - fun `calculateFaceQuality with custom parameters affects thresholds`() { - val bitmap = createTestBitmap() - - // Strict parameters - val strictQuality = SimQ.calculateFaceQuality( - bitmap = bitmap, - pitch = 15.0, - yaw = 15.0, - roll = 15.0, - parameters = QualityParameters( - maxAlignmentAngle = 10.0, - maxIndividualAngle = 20.0 - ) - ) - - // Lenient parameters - val lenientQuality = SimQ.calculateFaceQuality( - bitmap = bitmap, - pitch = 15.0, - yaw = 15.0, - roll = 15.0, - parameters = QualityParameters( - maxAlignmentAngle = 30.0, - maxIndividualAngle = 40.0 - ) - ) - - // Same angles should score better with lenient parameters - assertTrue(lenientQuality >= strictQuality) - } - - - @Test - fun `calculateFaceQuality handles different bitmap sizes`() { - val smallBitmap = createTestBitmap(64, 64) - val mediumBitmap = createTestBitmap(256, 256) - val largeBitmap = createTestBitmap(1024, 1024) - - val smallQuality = SimQ.calculateFaceQuality(smallBitmap) - val mediumQuality = SimQ.calculateFaceQuality(mediumBitmap) - val largeQuality = SimQ.calculateFaceQuality(largeBitmap) - - // All should return valid scores - assertTrue(smallQuality >= 0.0f && smallQuality <= 1.0f) - assertTrue(mediumQuality >= 0.0f && mediumQuality <= 1.0f) - assertTrue(largeQuality >= 0.0f && largeQuality <= 1.0f) - } - - @Test - fun `calculateFaceQuality with default parameters returns reasonable score`() { - val bitmap = createTestBitmap() - - val quality = SimQ.calculateFaceQuality(bitmap) - - assertTrue(quality >= 0.0f) - assertTrue(quality <= 1.0f) - } - - @Test - fun `calculateFaceQuality is consistent with same inputs`() { - val bitmap = createTestBitmap() - - val quality1 = SimQ.calculateFaceQuality( - bitmap = bitmap, - pitch = 10.0, - yaw = 5.0, - roll = -3.0 - ) - - val quality2 = SimQ.calculateFaceQuality( - bitmap = bitmap, - pitch = 10.0, - yaw = 5.0, - roll = -3.0 - ) - - assertEquals(quality1, quality2, 0.001f) - } - - - - @Test - fun `calculateFaceQuality with zero weights returns zero or handled gracefully`() { - val bitmap = createTestBitmap() - - val quality = SimQ.calculateFaceQuality( - bitmap = bitmap, - weights = QualityWeights( - alignment = 0.0, - blur = 0.0, - brightness = 0.0, - contrast = 0.0, - eyeOpenness = 0.0 - ) - ) - - assertTrue(quality >= 0.0f && quality <= 1.0f) - } -} diff --git a/simq/src/test/java/com/simprints/simq/shadows/ShadowCore.kt b/simq/src/test/java/com/simprints/simq/shadows/ShadowCore.kt deleted file mode 100644 index 8103f2b..0000000 --- a/simq/src/test/java/com/simprints/simq/shadows/ShadowCore.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.simprints.simq.shadows - -import org.robolectric.annotation.Implementation -import org.robolectric.annotation.Implements - -@Implements(org.opencv.core.Core::class) -class ShadowCore { - - companion object { - @JvmStatic - @Implementation - fun meanStdDev(src: Any, mean: Any, stddev: Any) { - // The MatOfDouble shadows will handle returning default values - } - - @JvmStatic - @Implementation - fun mean(src: Any): Any { - // Return a mock scalar - return Any() - } - } -} diff --git a/simq/src/test/java/com/simprints/simq/shadows/ShadowCvType.kt b/simq/src/test/java/com/simprints/simq/shadows/ShadowCvType.kt deleted file mode 100644 index 37be13d..0000000 --- a/simq/src/test/java/com/simprints/simq/shadows/ShadowCvType.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.simprints.simq.shadows - -import org.robolectric.annotation.Implementation -import org.robolectric.annotation.Implements - -@Implements(org.opencv.core.CvType::class) -class ShadowCvType { - - companion object { - const val CV_8U = 0 - const val CV_8S = 1 - const val CV_16U = 2 - const val CV_16S = 3 - const val CV_32S = 4 - const val CV_32F = 5 - const val CV_64F = 6 - const val CV_8UC1 = 0 - const val CV_8UC3 = 16 - const val CV_8UC4 = 24 - } -} diff --git a/simq/src/test/java/com/simprints/simq/shadows/ShadowImgproc.kt b/simq/src/test/java/com/simprints/simq/shadows/ShadowImgproc.kt deleted file mode 100644 index ecbda81..0000000 --- a/simq/src/test/java/com/simprints/simq/shadows/ShadowImgproc.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.simprints.simq.shadows - -import org.robolectric.annotation.Implementation -import org.robolectric.annotation.Implements - -@Implements(org.opencv.imgproc.Imgproc::class) -class ShadowImgproc { - - companion object { - const val COLOR_BGR2GRAY = 6 - const val COLOR_RGB2GRAY = 7 - - @JvmStatic - @Implementation - fun cvtColor(src: Any, dst: Any, code: Int) { - // Mock implementation - } - - @JvmStatic - @Implementation - fun Laplacian(src: Any, dst: Any, ddepth: Int, ksize: Int = 1, scale: Double = 1.0, delta: Double = 0.0) { - // Mock implementation - } - } -} diff --git a/simq/src/test/java/com/simprints/simq/shadows/ShadowMat.kt b/simq/src/test/java/com/simprints/simq/shadows/ShadowMat.kt deleted file mode 100644 index 93dbb05..0000000 --- a/simq/src/test/java/com/simprints/simq/shadows/ShadowMat.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.simprints.simq.shadows - -import org.robolectric.annotation.Implementation -import org.robolectric.annotation.Implements - -@Implements(org.opencv.core.Mat::class) -class ShadowMat { - - @Implementation - fun __constructor__() { - // Mock constructor - } - - @Implementation - fun __constructor__(rows: Int, cols: Int, type: Int) { - // Mock constructor - } - - @Implementation - fun release() { - // Mock implementation - does nothing - } - - @Implementation - fun rows(): Int { - return 0 - } - - @Implementation - fun cols(): Int { - return 0 - } -} diff --git a/simq/src/test/java/com/simprints/simq/shadows/ShadowMatOfDouble.kt b/simq/src/test/java/com/simprints/simq/shadows/ShadowMatOfDouble.kt deleted file mode 100644 index 651fe73..0000000 --- a/simq/src/test/java/com/simprints/simq/shadows/ShadowMatOfDouble.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.simprints.simq.shadows - -import org.robolectric.annotation.Implementation -import org.robolectric.annotation.Implements - -@Implements(org.opencv.core.MatOfDouble::class) -class ShadowMatOfDouble { - - private var values: DoubleArray = doubleArrayOf(50.0) // Default standard deviation for mock - - @Implementation - fun __constructor__() { - // Mock constructor - } - - @Implementation - fun toArray(): DoubleArray { - return values - } - - @Implementation - fun release() { - // Mock implementation - does nothing - } -} diff --git a/simq/src/test/java/com/simprints/simq/shadows/ShadowOpenCVLoader.kt b/simq/src/test/java/com/simprints/simq/shadows/ShadowOpenCVLoader.kt deleted file mode 100644 index 7f3275c..0000000 --- a/simq/src/test/java/com/simprints/simq/shadows/ShadowOpenCVLoader.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.simprints.simq.shadows - -import org.robolectric.annotation.Implementation -import org.robolectric.annotation.Implements - -@Implements(org.opencv.android.OpenCVLoader::class) -class ShadowOpenCVLoader { - - companion object { - @JvmStatic - @Implementation - fun initLocal(): Boolean { - // Return true to simulate successful OpenCV initialization - return true - } - - @JvmStatic - @Implementation - fun initDebug(): Boolean { - return true - } - } -} diff --git a/simq/src/test/java/com/simprints/simq/shadows/ShadowOpenCVUtils.kt b/simq/src/test/java/com/simprints/simq/shadows/ShadowOpenCVUtils.kt deleted file mode 100644 index 2d88c04..0000000 --- a/simq/src/test/java/com/simprints/simq/shadows/ShadowOpenCVUtils.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.simprints.simq.shadows - -import android.graphics.Bitmap -import org.robolectric.annotation.Implementation -import org.robolectric.annotation.Implements - -@Implements(org.opencv.android.Utils::class) -class ShadowOpenCVUtils { - - companion object { - @JvmStatic - @Implementation - fun bitmapToMat(bitmap: Bitmap, mat: Any) { - // Mock implementation - } - - @JvmStatic - @Implementation - fun matToBitmap(mat: Any, bitmap: Bitmap) { - // Mock implementation - } - } -} diff --git a/src/androidTest/java/com/simprints/biometrics/simface/detection/FaceAlignTest.kt b/src/androidTest/java/com/simprints/biometrics/simface/detection/FaceAlignTest.kt index a2aa060..9f746a8 100644 --- a/src/androidTest/java/com/simprints/biometrics/simface/detection/FaceAlignTest.kt +++ b/src/androidTest/java/com/simprints/biometrics/simface/detection/FaceAlignTest.kt @@ -5,6 +5,7 @@ import android.graphics.Bitmap import android.graphics.Rect import androidx.test.core.app.* import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.google.common.truth.Truth.assertThat import com.simprints.biometrics.loadBitmapFromTestResources import com.simprints.biometrics.simface.Constants import com.simprints.biometrics.simface.SimFace @@ -13,7 +14,6 @@ import com.simprints.biometrics.simface.data.FaceDetection import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.test.runTest import org.junit.After -import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -42,8 +42,8 @@ class FaceAlignTest { val croppedBitmap = cropAlignFace(bitmap, boundingBox) - assertTrue(boundingBox.width() == croppedBitmap.width) - assertTrue(boundingBox.height() == croppedBitmap.height) + assertThat(croppedBitmap.width).isEqualTo(boundingBox.width()) + assertThat(croppedBitmap.height).isEqualTo(boundingBox.height()) } @Test(expected = IllegalArgumentException::class) @@ -71,19 +71,15 @@ class FaceAlignTest { }) val faces = resultDeferred.await() - assertTrue(faces.isNotEmpty()) + assertThat(faces).isNotEmpty() val face = faces[0] val warpedAlignedImage = face.landmarks?.let { warpAlignFace(bitmap, it) } - assertTrue(warpedAlignedImage != null) + assertThat(warpedAlignedImage).isNotNull() - if (warpedAlignedImage != null) { - assertTrue(warpedAlignedImage.width == Constants.IMAGE_SIZE) - } - if (warpedAlignedImage != null) { - assertTrue(warpedAlignedImage.height == Constants.IMAGE_SIZE) - } + assertThat(warpedAlignedImage!!.width).isEqualTo(Constants.IMAGE_SIZE) + assertThat(warpedAlignedImage.height).isEqualTo(Constants.IMAGE_SIZE) } } diff --git a/src/androidTest/java/com/simprints/biometrics/simface/detection/FaceDetectionProcessorTest.kt b/src/androidTest/java/com/simprints/biometrics/simface/detection/FaceDetectionProcessorTest.kt index 5f8fc5b..321654f 100644 --- a/src/androidTest/java/com/simprints/biometrics/simface/detection/FaceDetectionProcessorTest.kt +++ b/src/androidTest/java/com/simprints/biometrics/simface/detection/FaceDetectionProcessorTest.kt @@ -4,6 +4,7 @@ import android.content.Context import android.graphics.Bitmap import androidx.test.core.app.* import androidx.test.ext.junit.runners.* +import com.google.common.truth.Truth.assertThat import com.simprints.biometrics.loadBitmapFromTestResources import com.simprints.biometrics.simface.SimFace import com.simprints.biometrics.simface.SimFaceConfig @@ -11,7 +12,6 @@ import com.simprints.biometrics.simface.data.FaceDetection import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.test.runTest import org.junit.After -import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -45,9 +45,9 @@ class FaceDetectionProcessorTest { }) val faces = resultDeferred.await() - assertTrue(faces.isNotEmpty()) + assertThat(faces).isNotEmpty() val face = faces[0] - assertTrue(face.quality > 0.5) + assertThat(face.quality).isGreaterThan(0.5f) } @Test @@ -62,9 +62,9 @@ class FaceDetectionProcessorTest { }) val faces = resultDeferred.await() - assertTrue(faces.isNotEmpty()) + assertThat(faces).isNotEmpty() val face = faces[0] - assertTrue(face.quality < 0.6) + assertThat(face.quality).isLessThan(0.6f) } @Test @@ -79,7 +79,7 @@ class FaceDetectionProcessorTest { }) val faces = resultDeferred.await() - assertTrue(faces.isEmpty()) + assertThat(faces).isEmpty() } @Test @@ -94,7 +94,7 @@ class FaceDetectionProcessorTest { }) val faces = resultDeferred.await() - assertTrue(faces.size == 5) + assertThat(faces).hasSize(5) } @Test @@ -102,9 +102,9 @@ class FaceDetectionProcessorTest { val bitmap: Bitmap = context.loadBitmapFromTestResources("royalty_free_good_face") val faces = simFace.detectFaceBlocking(bitmap) - assertTrue(faces.isNotEmpty()) + assertThat(faces).isNotEmpty() val face = faces[0] - assertTrue(face.quality > 0.5) + assertThat(face.quality).isGreaterThan(0.5f) } @Test @@ -112,9 +112,9 @@ class FaceDetectionProcessorTest { val bitmap: Bitmap = context.loadBitmapFromTestResources("royalty_free_bad_face") val faces = simFace.detectFaceBlocking(bitmap) - assertTrue(faces.isNotEmpty()) + assertThat(faces).isNotEmpty() val face = faces[0] - assertTrue(face.quality < 0.6) + assertThat(face.quality).isLessThan(0.6f) } @Test @@ -122,7 +122,7 @@ class FaceDetectionProcessorTest { val bitmap: Bitmap = context.loadBitmapFromTestResources("royalty_free_flower") val faces = simFace.detectFaceBlocking(bitmap) - assertTrue(faces.isEmpty()) + assertThat(faces).isEmpty() } @Test @@ -130,6 +130,6 @@ class FaceDetectionProcessorTest { val bitmap: Bitmap = context.loadBitmapFromTestResources("royalty_free_multiple_faces") val faces = simFace.detectFaceBlocking(bitmap) - assertTrue(faces.size == 5) + assertThat(faces).hasSize(5) } } diff --git a/src/androidTest/java/com/simprints/biometrics/simface/embedding/CustomModelTest.kt b/src/androidTest/java/com/simprints/biometrics/simface/embedding/CustomModelTest.kt index e4cf692..e133264 100644 --- a/src/androidTest/java/com/simprints/biometrics/simface/embedding/CustomModelTest.kt +++ b/src/androidTest/java/com/simprints/biometrics/simface/embedding/CustomModelTest.kt @@ -3,13 +3,13 @@ package com.simprints.biometrics.simface.embedding import android.content.Context import android.graphics.Bitmap import androidx.test.core.app.* +import com.google.common.truth.Truth.assertThat import com.simprints.biometrics.loadBitmapFromTestResources import com.simprints.biometrics.openTestModelFile import com.simprints.biometrics.simface.SimFaceConfig import com.simprints.biometrics.simface.Utils import kotlinx.coroutines.test.runTest import org.junit.After -import org.junit.Assert.assertArrayEquals import org.junit.Before import org.junit.Test @@ -32,7 +32,9 @@ class CustomModelTest { @After fun cleanup() { - modelManager.close() + if (::modelManager.isInitialized) { + modelManager.close() + } } @Test @@ -53,7 +55,10 @@ class CustomModelTest { val bitmap: Bitmap = context.loadBitmapFromTestResources("royalty_free_good_face") val resultFloat = getFaceEmbeddingFromBitmap(bitmap) - assertArrayEquals(GOOD_FACE_EMBEDDING, resultFloat, 0.1F) + assertThat(resultFloat) + .usingTolerance(0.1) + .containsExactly(GOOD_FACE_EMBEDDING) + .inOrder() } private fun getFaceEmbeddingFromBitmap(bitmap: Bitmap): FloatArray = embeddingProcessor diff --git a/src/androidTest/java/com/simprints/biometrics/simface/embedding/EmbeddingProcessorTest.kt b/src/androidTest/java/com/simprints/biometrics/simface/embedding/EmbeddingProcessorTest.kt index 3e31502..b64c642 100644 --- a/src/androidTest/java/com/simprints/biometrics/simface/embedding/EmbeddingProcessorTest.kt +++ b/src/androidTest/java/com/simprints/biometrics/simface/embedding/EmbeddingProcessorTest.kt @@ -4,12 +4,11 @@ import android.content.Context import android.graphics.Bitmap import androidx.test.core.app.* import androidx.test.ext.junit.runners.* +import com.google.common.truth.Truth.assertThat import com.simprints.biometrics.loadBitmapFromTestResources import com.simprints.biometrics.simface.SimFaceConfig import com.simprints.biometrics.simface.Utils import org.junit.After -import org.junit.Assert.assertArrayEquals -import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -38,10 +37,11 @@ class EmbeddingProcessorTest { val result = embeddingProcessor.getEmbedding(bitmap) val resultFloat = Utils.byteArrayToFloatArray(result) - assertTrue(Utils.byteArrayToFloatArray(result).size == 512) + assertThat(resultFloat.size).isEqualTo(512) - // Verify results - assertArrayEquals(GOOD_FACE_EMBEDDING, resultFloat, 0.1F) + assertThat(resultFloat) + .usingTolerance(0.1) + .containsExactly(GOOD_FACE_EMBEDDING) } @Test @@ -52,7 +52,7 @@ class EmbeddingProcessorTest { val embedding1 = embeddingProcessor.getEmbedding(bitmap1) val embedding2 = embeddingProcessor.getEmbedding(bitmap2) - assertTrue(!embedding1.contentEquals(embedding2)) // Embeddings should be different + assertThat(embedding1).isNotEqualTo(embedding2) } @Test @@ -62,6 +62,6 @@ class EmbeddingProcessorTest { val embedding1 = embeddingProcessor.getEmbedding(bitmap) val embedding2 = embeddingProcessor.getEmbedding(bitmap) - assertArrayEquals(embedding1, embedding2) // Embeddings should be identical + assertThat(embedding1).isEqualTo(embedding2) } } diff --git a/src/androidTest/java/com/simprints/biometrics/simface/matcher/IdentificationTest.kt b/src/androidTest/java/com/simprints/biometrics/simface/matcher/IdentificationTest.kt index cd2b1c4..7e43337 100644 --- a/src/androidTest/java/com/simprints/biometrics/simface/matcher/IdentificationTest.kt +++ b/src/androidTest/java/com/simprints/biometrics/simface/matcher/IdentificationTest.kt @@ -1,8 +1,8 @@ package com.simprints.biometrics.simface.matcher import androidx.test.ext.junit.runners.* +import com.google.common.truth.Truth.assertThat import com.simprints.biometrics.simface.Utils.floatArrayToByteArray -import org.junit.Assert.assertEquals import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -30,15 +30,15 @@ class IdentificationTest { val sortedDistances = sortedScores.map { it.second } // Closest match (identical vector) should have a score of 1 - assertEquals(1.0, sortedDistances[0], 0.0001) + assertThat(sortedDistances[0]).isWithin(0.0001).of(1.0) // 45-degree vector (second closest) should have a score of around 0.85355 - assertEquals(0.85355, sortedDistances[1], 0.0001) + assertThat(sortedDistances[1]).isWithin(0.0001).of(0.85355) // Orthogonal vector (further away) should have a score of 0.5 - assertEquals(0.5, sortedDistances[2], 0.0001) + assertThat(sortedDistances[2]).isWithin(0.0001).of(0.5) // Opposite vector (furthest away) should have a score of 0.0 - assertEquals(0.0, sortedDistances[3], 0.0001) + assertThat(sortedDistances[3]).isWithin(0.0001).of(0.0) } } diff --git a/src/androidTest/java/com/simprints/biometrics/simface/matcher/VerificationTest.kt b/src/androidTest/java/com/simprints/biometrics/simface/matcher/VerificationTest.kt index 12adf5a..d8ff641 100644 --- a/src/androidTest/java/com/simprints/biometrics/simface/matcher/VerificationTest.kt +++ b/src/androidTest/java/com/simprints/biometrics/simface/matcher/VerificationTest.kt @@ -1,9 +1,8 @@ package com.simprints.biometrics.simface.matcher import androidx.test.ext.junit.runners.* +import com.google.common.truth.Truth.assertThat import com.simprints.biometrics.simface.Utils.floatArrayToByteArray -import org.junit.Assert -import org.junit.Assert.assertEquals import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -24,7 +23,7 @@ class VerificationTest { val distance = matchProcessor.verificationScore(array1, array2) - assertEquals(1.0, distance, 0.0001) + assertThat(distance).isWithin(0.0001).of(1.0) } @Test @@ -34,7 +33,7 @@ class VerificationTest { val distance = matchProcessor.verificationScore(array1, array2) - assertEquals(0.5, distance, 0.0001) + assertThat(distance).isWithin(0.0001).of(0.5) } @Test @@ -44,7 +43,7 @@ class VerificationTest { val distance = matchProcessor.verificationScore(array1, array2) - assertEquals(0.0, distance, 0.0001) + assertThat(distance).isWithin(0.0001).of(0.0) } @Test @@ -54,6 +53,7 @@ class VerificationTest { val distance = matchProcessor.verificationScore(array1, array2) - Assert.assertTrue(distance > 0.0 && distance < 1.0) + assertThat(distance).isGreaterThan(0.0) + assertThat(distance).isLessThan(1.0) } } diff --git a/src/main/java/com/simprints/biometrics/simface/SimFace.kt b/src/main/java/com/simprints/biometrics/simface/SimFace.kt index 0e932c5..078ed19 100644 --- a/src/main/java/com/simprints/biometrics/simface/SimFace.kt +++ b/src/main/java/com/simprints/biometrics/simface/SimFace.kt @@ -11,6 +11,7 @@ import com.simprints.biometrics.simface.embedding.MLModelManager import com.simprints.biometrics.simface.embedding.TensorFlowEmbeddingProcessor import com.simprints.biometrics.simface.matcher.CosineDistanceMatchProcessor import com.simprints.biometrics.simface.matcher.MatchProcessor +import com.simprints.simq.SimQ import java.util.concurrent.locks.ReentrantLock import kotlin.concurrent.withLock import com.google.mlkit.vision.face.FaceDetection as MlKitFaceDetection @@ -22,41 +23,44 @@ class SimFace { private lateinit var modelManager: MLModelManager private lateinit var embeddingProcessor: EmbeddingProcessor private lateinit var matchProcessor: MatchProcessor - + private lateinit var qualityProcessor: SimQ private lateinit var faceDetector: FaceDetector private lateinit var faceDetectionProcessor: FaceDetectionProcessor - /** - * Load the ML model into memory and prepare other resources for work. - */ + /** Load the ML model into memory and prepare other resources for work. */ fun initialize(config: SimFaceConfig): Unit = initLock.withLock { try { // Initialize the model manager with the given config modelManager = MLModelManager(config) + // Initialize SimQ quality processor + qualityProcessor = SimQ() + // Initialize processors embeddingProcessor = TensorFlowEmbeddingProcessor(modelManager) matchProcessor = CosineDistanceMatchProcessor() // Configure and load MLKit face detection model - val realTimeOpts = FaceDetectorOptions - .Builder() - .setContourMode(FaceDetectorOptions.CONTOUR_MODE_ALL) - .setPerformanceMode(FaceDetectorOptions.PERFORMANCE_MODE_ACCURATE) - .setLandmarkMode(FaceDetectorOptions.LANDMARK_MODE_ALL) - .setClassificationMode(FaceDetectorOptions.CLASSIFICATION_MODE_ALL) - .setMinFaceSize(0.20f) - .build() + val realTimeOpts = + FaceDetectorOptions + .Builder() + .setContourMode(FaceDetectorOptions.CONTOUR_MODE_ALL) + .setPerformanceMode( + FaceDetectorOptions.PERFORMANCE_MODE_ACCURATE, + ).setLandmarkMode(FaceDetectorOptions.LANDMARK_MODE_ALL) + .setClassificationMode( + FaceDetectorOptions.CLASSIFICATION_MODE_ALL, + ).setMinFaceSize(0.20f) + .build() faceDetector = MlKitFaceDetection.getClient(realTimeOpts) - faceDetectionProcessor = MlKitFaceDetectionProcessor(faceDetector) + faceDetectionProcessor = + MlKitFaceDetectionProcessor(faceDetector, qualityProcessor) } catch (e: Exception) { throw RuntimeException("Failed to initialize SimFaceFacade: ${e.message}", e) } } - /** - * Releases used resources and ML model. - */ + /** Releases used resources and ML model. */ fun release() = initLock.withLock { try { if (this::modelManager.isInitialized) { @@ -70,14 +74,12 @@ class SimFace { } } - /** - * Returns the version of the templates generated by the underlying ML model. - */ + /** Returns the version of the templates generated by the underlying ML model. */ fun getTemplateVersion(): String = modelManager.templateVersion /** - * Asynchronously processes the image and finds a face on the provided image and returns - * its metadata (quality, bounding box, landmarks, etc.) or error in a set of callbacks. + * Asynchronously processes the image and finds a face on the provided image and returns its + * metadata (quality, bounding box, landmarks, etc.) or error in a set of callbacks. */ fun detectFace( image: Bitmap, @@ -92,8 +94,8 @@ class SimFace { } /** - * Synchronously processes the image and finds all faces on the provided image and returns - * their metadata (quality, bounding box, landmarks, etc.) or error in a set of callbacks. + * Synchronously processes the image and finds all faces on the provided image and returns their + * metadata (quality, bounding box, landmarks, etc.) or error in a set of callbacks. */ suspend fun detectFaceBlocking(image: Bitmap): List { if (!this::faceDetectionProcessor.isInitialized) { @@ -102,9 +104,7 @@ class SimFace { return faceDetectionProcessor.detectFaceBlocking(image) } - /** - * Extracts the biometric template from the provided face image. - */ + /** Extracts the biometric template from the provided face image. */ fun getEmbedding(faceImage: Bitmap): ByteArray { if (!this::embeddingProcessor.isInitialized) { throw IllegalStateException("SimFace.initialize() should be called first") @@ -112,9 +112,7 @@ class SimFace { return embeddingProcessor.getEmbedding(faceImage) } - /** - * Compares the probe against the provided reference. - */ + /** Compares the probe against the provided reference. */ fun verificationScore( probe: ByteArray, matchReference: ByteArray, @@ -126,8 +124,8 @@ class SimFace { } /** - * Compares the probe against the provided list of references and returns the scores - * for each reference in a descending order. + * Compares the probe against the provided list of references and returns the scores for each + * reference in a descending order. */ fun identificationScore( probe: ByteArray, diff --git a/src/main/java/com/simprints/biometrics/simface/detection/MlKitFaceDetectionProcessor.kt b/src/main/java/com/simprints/biometrics/simface/detection/MlKitFaceDetectionProcessor.kt index e941283..54908c8 100644 --- a/src/main/java/com/simprints/biometrics/simface/detection/MlKitFaceDetectionProcessor.kt +++ b/src/main/java/com/simprints/biometrics/simface/detection/MlKitFaceDetectionProcessor.kt @@ -19,6 +19,7 @@ import kotlin.coroutines.suspendCoroutine internal class MlKitFaceDetectionProcessor( private val faceDetector: FaceDetector, + private val qualityProcessor: SimQ, ) : FaceDetectionProcessor { override fun detectFace( image: Bitmap, @@ -33,26 +34,25 @@ internal class MlKitFaceDetectionProcessor( .addOnSuccessListener { faces -> val faceDetections = mutableListOf() faces?.forEach { face -> - val faceDetection = FaceDetection( - sourceWidth = image.width, - sourceHeight = image.height, - absoluteBoundingBox = face.boundingBox.clampToBounds( - image.width, - image.height, - ), - yaw = face.headEulerAngleY, - roll = face.headEulerAngleZ, - landmarks = buildLandmarks(face), - quality = calculateFaceQuality(face, image), - ) + val faceDetection = + FaceDetection( + sourceWidth = image.width, + sourceHeight = image.height, + absoluteBoundingBox = + face.boundingBox.clampToBounds( + image.width, + image.height, + ), + yaw = face.headEulerAngleY, + roll = face.headEulerAngleZ, + landmarks = buildLandmarks(face), + quality = calculateFaceQuality(face, image), + ) faceDetections.add(faceDetection) } onSuccess(faceDetections) - }.addOnFailureListener { exception -> - onFailure(exception) - }.addOnCompleteListener { - onCompleted() - } + }.addOnFailureListener { exception -> onFailure(exception) } + .addOnCompleteListener { onCompleted() } } override suspend fun detectFaceBlocking(image: Bitmap): List { @@ -64,18 +64,20 @@ internal class MlKitFaceDetectionProcessor( .addOnSuccessListener { faces -> val faceDetections = mutableListOf() faces?.forEach { face -> - val faceDetection = FaceDetection( - sourceWidth = image.width, - sourceHeight = image.height, - absoluteBoundingBox = face.boundingBox.clampToBounds( - image.width, - image.height, - ), - yaw = face.headEulerAngleY, - roll = face.headEulerAngleZ, - quality = calculateFaceQuality(face, image), - landmarks = buildLandmarks(face), - ) + val faceDetection = + FaceDetection( + sourceWidth = image.width, + sourceHeight = image.height, + absoluteBoundingBox = + face.boundingBox.clampToBounds( + image.width, + image.height, + ), + yaw = face.headEulerAngleY, + roll = face.headEulerAngleZ, + quality = calculateFaceQuality(face, image), + landmarks = buildLandmarks(face), + ) faceDetections.add(faceDetection) } continuation.resume(faceDetections) @@ -88,18 +90,19 @@ internal class MlKitFaceDetectionProcessor( private fun calculateFaceQuality( face: Face, image: Bitmap, - ): Float { - return try { - val boundingBox = face.boundingBox.clampToBounds(image.width, image.height) - val faceBitmap = Bitmap.createBitmap( + ): Float = try { + val boundingBox = face.boundingBox.clampToBounds(image.width, image.height) + val faceBitmap = + Bitmap.createBitmap( image, boundingBox.left, boundingBox.top, boundingBox.width(), - boundingBox.height() + boundingBox.height(), ) - val parameters = QualityParameters( + val parameters = + QualityParameters( maxAlignmentAngle = 20.0, maxIndividualAngle = 25.0, minBlur = 50.0, @@ -110,18 +113,20 @@ internal class MlKitFaceDetectionProcessor( maxBrightness = 190.0, brightnessSteepness = 0.3, minContrast = 30.0, - maxContrast = 47.0 + maxContrast = 47.0, ) - val weights = QualityWeights( + val weights = + QualityWeights( alignment = 0.28, blur = 0.3, brightness = 0.1, contrast = 0.3, - eyeOpenness = 0.02 + eyeOpenness = 0.02, ) - val qualityScore = SimQ.calculateFaceQuality( + val qualityScore = + qualityProcessor.calculateFaceQuality( bitmap = faceBitmap, pitch = face.headEulerAngleX.toDouble(), yaw = face.headEulerAngleY.toDouble(), @@ -129,37 +134,41 @@ internal class MlKitFaceDetectionProcessor( leftEyeOpenness = face.leftEyeOpenProbability?.toDouble(), rightEyeOpenness = face.rightEyeOpenProbability?.toDouble(), weights = weights, - parameters = parameters + parameters = parameters, ) - - faceBitmap.recycle() - - qualityScore - } catch (e: Exception) { - 0.0f - } + + faceBitmap.recycle() + + qualityScore + } catch (e: Exception) { + 0.0f } private fun buildLandmarks(face: Face): FacialLandmarks? { - val leftEye = face.getLandmark(FaceLandmark.LEFT_EYE)?.position - ?: face.getContour(FaceContour.LEFT_EYE)?.points?.getOrNull(4) - ?: return null + val leftEye = + face.getLandmark(FaceLandmark.LEFT_EYE)?.position + ?: face.getContour(FaceContour.LEFT_EYE)?.points?.getOrNull(4) + ?: return null - val rightEye = face.getLandmark(FaceLandmark.RIGHT_EYE)?.position - ?: face.getContour(FaceContour.RIGHT_EYE)?.points?.getOrNull(4) - ?: return null + val rightEye = + face.getLandmark(FaceLandmark.RIGHT_EYE)?.position + ?: face.getContour(FaceContour.RIGHT_EYE)?.points?.getOrNull(4) + ?: return null - val nose = face.getLandmark(FaceLandmark.NOSE_BASE)?.position - ?: face.getContour(FaceContour.NOSE_BRIDGE)?.points?.lastOrNull() - ?: return null + val nose = + face.getLandmark(FaceLandmark.NOSE_BASE)?.position + ?: face.getContour(FaceContour.NOSE_BRIDGE)?.points?.lastOrNull() + ?: return null - val mouthLeft = face.getLandmark(FaceLandmark.MOUTH_LEFT)?.position - ?: face.getContour(FaceContour.LOWER_LIP_BOTTOM)?.points?.lastOrNull() - ?: return null + val mouthLeft = + face.getLandmark(FaceLandmark.MOUTH_LEFT)?.position + ?: face.getContour(FaceContour.LOWER_LIP_BOTTOM)?.points?.lastOrNull() + ?: return null - val mouthRight = face.getLandmark(FaceLandmark.MOUTH_RIGHT)?.position - ?: face.getContour(FaceContour.LOWER_LIP_BOTTOM)?.points?.firstOrNull() - ?: return null + val mouthRight = + face.getLandmark(FaceLandmark.MOUTH_RIGHT)?.position + ?: face.getContour(FaceContour.LOWER_LIP_BOTTOM)?.points?.firstOrNull() + ?: return null return FacialLandmarks( Point2D(leftEye.x, leftEye.y), From 9a91db072e85b2b83347e132d2ce1529b4e74bc5 Mon Sep 17 00:00:00 2001 From: Martin Georgiev <3349414+Thinkorswim@users.noreply.github.com> Date: Mon, 27 Oct 2025 16:13:03 +0200 Subject: [PATCH 07/12] Make objects internal --- .../com/simprints/simq/QualityWeightsTest.kt | 30 ---- simq/src/main/java/com/simprints/simq/SimQ.kt | 167 +++++++++--------- .../simq/analysis/AlignmentAnalysis.kt | 16 +- .../simprints/simq/analysis/BlurAnalysis.kt | 27 +-- .../simq/analysis/BrightnessAnalysis.kt | 34 ++-- .../simq/analysis/ContrastAnalysis.kt | 21 +-- .../com/simprints/simq/utils/BitmapExt.kt | 10 +- .../com/simprints/simq/utils/OpenCVLoader.kt | 6 +- .../simprints/simq/utils/ScoringFunctions.kt | 42 ++--- 9 files changed, 167 insertions(+), 186 deletions(-) diff --git a/simq/src/androidTest/java/com/simprints/simq/QualityWeightsTest.kt b/simq/src/androidTest/java/com/simprints/simq/QualityWeightsTest.kt index 4974759..0f77d95 100644 --- a/simq/src/androidTest/java/com/simprints/simq/QualityWeightsTest.kt +++ b/simq/src/androidTest/java/com/simprints/simq/QualityWeightsTest.kt @@ -21,36 +21,6 @@ class QualityWeightsTest { height: Int = 256, ): Bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888) - @Test - fun defaultWeightsSumTo1() { - val weights = QualityWeights.DEFAULT - val sum = - weights.alignment + - weights.blur + - weights.brightness + - weights.contrast + - weights.eyeOpenness - assertThat(sum).isWithin(0.001).of(1.0) - } - - @Test - fun customWeightsCanBeCreated() { - val customWeights = - QualityWeights( - alignment = 0.25, - blur = 0.25, - brightness = 0.25, - contrast = 0.15, - eyeOpenness = 0.10, - ) - - assertThat(customWeights.alignment).isWithin(0.001).of(0.25) - assertThat(customWeights.blur).isWithin(0.001).of(0.25) - assertThat(customWeights.brightness).isWithin(0.001).of(0.25) - assertThat(customWeights.contrast).isWithin(0.001).of(0.15) - assertThat(customWeights.eyeOpenness).isWithin(0.001).of(0.10) - } - @Test fun calculateFaceQualityWithAllWeightsMaximizingOneMetric() { val bitmap = createTestBitmap() diff --git a/simq/src/main/java/com/simprints/simq/SimQ.kt b/simq/src/main/java/com/simprints/simq/SimQ.kt index e415f06..7f3bad5 100644 --- a/simq/src/main/java/com/simprints/simq/SimQ.kt +++ b/simq/src/main/java/com/simprints/simq/SimQ.kt @@ -31,97 +31,96 @@ class SimQ { * @return Quality score between 0.0 and 1.0, or 0.0 if calculation fails */ fun calculateFaceQuality( - bitmap: Bitmap, - pitch: Double = 0.0, - yaw: Double = 0.0, - roll: Double = 0.0, - leftEyeOpenness: Double? = null, - rightEyeOpenness: Double? = null, - centerCrop: Float = 0.5f, - horizontalDisplacement: Float = 0.0f, - verticalDisplacement: Float = 0.0f, - weights: QualityWeights = QualityWeights.DEFAULT, - parameters: QualityParameters = QualityParameters.DEFAULT, - ): Float = try { - // Resize bitmap to target area (256x256 = 65536) - val resizedBitmap = bitmap.resizeToArea(65536.0) + bitmap: Bitmap, + pitch: Double = 0.0, + yaw: Double = 0.0, + roll: Double = 0.0, + leftEyeOpenness: Double? = null, + rightEyeOpenness: Double? = null, + centerCrop: Float = 0.5f, + horizontalDisplacement: Float = 0.0f, + verticalDisplacement: Float = 0.0f, + weights: QualityWeights = QualityWeights.DEFAULT, + parameters: QualityParameters = QualityParameters.DEFAULT, + ): Float = + try { + // Resize bitmap to target area (256x256 = 65536) + val resizedBitmap = bitmap.resizeToArea(65536.0) - // Crop the bitmap - val croppedBitmap = - resizedBitmap.centerCrop( - centerCrop, - horizontalDisplacement, - verticalDisplacement, - ) + // Crop the bitmap + val croppedBitmap = + resizedBitmap.centerCrop( + centerCrop, + horizontalDisplacement, + verticalDisplacement, + ) - var totalScore = 0.0 - val totalWeight = - weights.alignment + - weights.blur + - weights.brightness + - weights.contrast + - ( - if (leftEyeOpenness != null && rightEyeOpenness != null) { - weights.eyeOpenness - } else { - 0.0 - } - ) + var totalScore = 0.0 + val totalWeight = + weights.alignment + + weights.blur + + weights.brightness + + weights.contrast + + (if (leftEyeOpenness != null && rightEyeOpenness != null) { + weights.eyeOpenness + } else { + 0.0 + }) - val alignmentScore = - AlignmentAnalysis.calculateScore( - pitch, - yaw, - roll, - parameters.maxAlignmentAngle, - parameters.maxIndividualAngle, - ) - totalScore += weights.alignment * alignmentScore + val alignmentScore = + AlignmentAnalysis.calculateScore( + pitch, + yaw, + roll, + parameters.maxAlignmentAngle, + parameters.maxIndividualAngle, + ) + totalScore += weights.alignment * alignmentScore - val blurScore = - BlurAnalysis.calculateScore( - croppedBitmap, - parameters.minBlur, - parameters.maxBlur, - ) - totalScore += weights.blur * blurScore + val blurScore = + BlurAnalysis.calculateScore( + croppedBitmap, + parameters.minBlur, + parameters.maxBlur, + ) + totalScore += weights.blur * blurScore - val brightnessScore = - BrightnessAnalysis.calculateScore( - croppedBitmap, - parameters.minBrightness, - parameters.optimalBrightnessLow, - parameters.optimalBrightnessHigh, - parameters.maxBrightness, - parameters.brightnessSteepness, - ) - totalScore += weights.brightness * brightnessScore + val brightnessScore = + BrightnessAnalysis.calculateScore( + croppedBitmap, + parameters.minBrightness, + parameters.optimalBrightnessLow, + parameters.optimalBrightnessHigh, + parameters.maxBrightness, + parameters.brightnessSteepness, + ) + totalScore += weights.brightness * brightnessScore - val contrastScore = - ContrastAnalysis.calculateScore( - croppedBitmap, - parameters.minContrast, - parameters.maxContrast, - ) - totalScore += weights.contrast * contrastScore + val contrastScore = + ContrastAnalysis.calculateScore( + croppedBitmap, + parameters.minContrast, + parameters.maxContrast, + ) + totalScore += weights.contrast * contrastScore - if (leftEyeOpenness != null && rightEyeOpenness != null) { - val eyeScore = (leftEyeOpenness + rightEyeOpenness) / 2.0 - totalScore += weights.eyeOpenness * eyeScore - } + if (leftEyeOpenness != null && rightEyeOpenness != null) { + val eyeScore = (leftEyeOpenness + rightEyeOpenness) / 2.0 + totalScore += weights.eyeOpenness * eyeScore + } - // Clean up - if (croppedBitmap != bitmap && croppedBitmap != resizedBitmap) { - croppedBitmap.recycle() - } - if (resizedBitmap != bitmap) { - resizedBitmap.recycle() - } + // Clean up + if (croppedBitmap != bitmap && croppedBitmap != resizedBitmap) { + croppedBitmap.recycle() + } + if (resizedBitmap != bitmap) { + resizedBitmap.recycle() + } - // Normalize and clamp to 0-1 range - val finalScore = if (totalWeight > 0) totalScore / totalWeight else 0.0 - finalScore.coerceIn(0.0, 1.0).toFloat() - } catch (e: Exception) { - 0.0f - } + // Normalize and clamp to 0-1 range + val finalScore = if (totalWeight > 0) totalScore / totalWeight else 0.0 + finalScore.coerceIn(0.0, 1.0).toFloat() + } catch (e: Exception) { + 0.0f + } } diff --git a/simq/src/main/java/com/simprints/simq/analysis/AlignmentAnalysis.kt b/simq/src/main/java/com/simprints/simq/analysis/AlignmentAnalysis.kt index ecef391..76f649e 100644 --- a/simq/src/main/java/com/simprints/simq/analysis/AlignmentAnalysis.kt +++ b/simq/src/main/java/com/simprints/simq/analysis/AlignmentAnalysis.kt @@ -2,7 +2,7 @@ package com.simprints.simq.analysis import kotlin.math.absoluteValue -object AlignmentAnalysis { +internal object AlignmentAnalysis { /** * Calculates alignment score based on pitch, yaw, and roll angles. * @@ -14,16 +14,16 @@ object AlignmentAnalysis { * @return Alignment score between 0.0 and 1.0 */ fun calculateScore( - pitch: Double, - yaw: Double, - roll: Double, - maxAngle: Double, - maxIndividualAngle: Double, + pitch: Double, + yaw: Double, + roll: Double, + maxAngle: Double, + maxIndividualAngle: Double, ): Double { // Reject if any angle is too extreme if (pitch.absoluteValue > maxIndividualAngle || - yaw.absoluteValue > maxIndividualAngle || - roll.absoluteValue > maxIndividualAngle + yaw.absoluteValue > maxIndividualAngle || + roll.absoluteValue > maxIndividualAngle ) { return 0.0 } diff --git a/simq/src/main/java/com/simprints/simq/analysis/BlurAnalysis.kt b/simq/src/main/java/com/simprints/simq/analysis/BlurAnalysis.kt index 7d3f8eb..5fcd37d 100644 --- a/simq/src/main/java/com/simprints/simq/analysis/BlurAnalysis.kt +++ b/simq/src/main/java/com/simprints/simq/analysis/BlurAnalysis.kt @@ -2,15 +2,15 @@ package com.simprints.simq.analysis import android.graphics.Bitmap import com.simprints.simq.utils.ScoringFunctions +import kotlin.math.pow import org.opencv.android.Utils import org.opencv.core.Core import org.opencv.core.CvType import org.opencv.core.Mat import org.opencv.core.MatOfDouble import org.opencv.imgproc.Imgproc -import kotlin.math.pow -object BlurAnalysis { +internal object BlurAnalysis { /** * Calculates blur score using Laplacian variance. * @@ -20,15 +20,16 @@ object BlurAnalysis { * @return Blur score between 0.0 and 1.0 */ fun calculateScore( - bitmap: Bitmap, - minBlur: Double, - maxBlur: Double, - ): Double = try { - val laplacianVariance = calculateLaplacianVariance(bitmap) - ScoringFunctions.rampScore(laplacianVariance, minBlur, maxBlur) - } catch (e: Exception) { - 1.0 // Default to good score if OpenCV not available - } + bitmap: Bitmap, + minBlur: Double, + maxBlur: Double, + ): Double = + try { + val laplacianVariance = calculateLaplacianVariance(bitmap) + ScoringFunctions.rampScore(laplacianVariance, minBlur, maxBlur) + } catch (e: Exception) { + 1.0 // Default to good score if OpenCV not available + } /** * Calculates Laplacian blur variance using OpenCV. @@ -38,8 +39,8 @@ object BlurAnalysis { * @return Laplacian variance value */ private fun calculateLaplacianVariance( - bitmap: Bitmap, - ksize: Int = 5, + bitmap: Bitmap, + ksize: Int = 5, ): Double { val mat = Mat() val gray = Mat() diff --git a/simq/src/main/java/com/simprints/simq/analysis/BrightnessAnalysis.kt b/simq/src/main/java/com/simprints/simq/analysis/BrightnessAnalysis.kt index 808721d..c3d9a36 100644 --- a/simq/src/main/java/com/simprints/simq/analysis/BrightnessAnalysis.kt +++ b/simq/src/main/java/com/simprints/simq/analysis/BrightnessAnalysis.kt @@ -7,7 +7,7 @@ import org.opencv.core.Core import org.opencv.core.Mat import org.opencv.imgproc.Imgproc -object BrightnessAnalysis { +internal object BrightnessAnalysis { /** * Calculates brightness score using plateau function. * @@ -20,18 +20,26 @@ object BrightnessAnalysis { * @return Brightness score between 0.0 and 1.0 */ fun calculateScore( - bitmap: Bitmap, - edgeLow: Double, - centerLow: Double, - centerHigh: Double, - edgeHigh: Double, - steepness: Double, - ): Double = try { - val brightness = analyzeBrightness(bitmap) - ScoringFunctions.plateauScore(brightness, centerLow, centerHigh, edgeLow, edgeHigh, steepness) - } catch (e: Exception) { - 1.0 - } + bitmap: Bitmap, + edgeLow: Double, + centerLow: Double, + centerHigh: Double, + edgeHigh: Double, + steepness: Double, + ): Double = + try { + val brightness = analyzeBrightness(bitmap) + ScoringFunctions.plateauScore( + brightness, + centerLow, + centerHigh, + edgeLow, + edgeHigh, + steepness + ) + } catch (e: Exception) { + 1.0 + } /** * Analyzes brightness of bitmap using OpenCV. diff --git a/simq/src/main/java/com/simprints/simq/analysis/ContrastAnalysis.kt b/simq/src/main/java/com/simprints/simq/analysis/ContrastAnalysis.kt index 1f54b1e..845b9d6 100644 --- a/simq/src/main/java/com/simprints/simq/analysis/ContrastAnalysis.kt +++ b/simq/src/main/java/com/simprints/simq/analysis/ContrastAnalysis.kt @@ -8,7 +8,7 @@ import org.opencv.core.Mat import org.opencv.core.MatOfDouble import org.opencv.imgproc.Imgproc -object ContrastAnalysis { +internal object ContrastAnalysis { /** * Calculates contrast score using standard deviation. * @@ -18,15 +18,16 @@ object ContrastAnalysis { * @return Contrast score between 0.0 and 1.0 */ fun calculateScore( - bitmap: Bitmap, - minContrast: Double, - maxContrast: Double, - ): Double = try { - val contrast = analyzeContrast(bitmap) - ScoringFunctions.rampScore(contrast, minContrast, maxContrast) - } catch (e: Exception) { - 1.0 // Default to good score if OpenCV not available - } + bitmap: Bitmap, + minContrast: Double, + maxContrast: Double, + ): Double = + try { + val contrast = analyzeContrast(bitmap) + ScoringFunctions.rampScore(contrast, minContrast, maxContrast) + } catch (e: Exception) { + 1.0 // Default to good score if OpenCV not available + } /** * Analyzes contrast of bitmap using OpenCV (standard deviation). diff --git a/simq/src/main/java/com/simprints/simq/utils/BitmapExt.kt b/simq/src/main/java/com/simprints/simq/utils/BitmapExt.kt index 75fbf72..bdc90ba 100644 --- a/simq/src/main/java/com/simprints/simq/utils/BitmapExt.kt +++ b/simq/src/main/java/com/simprints/simq/utils/BitmapExt.kt @@ -12,10 +12,10 @@ import kotlin.math.sqrt * @param verticalDisplacement Vertical displacement factor (-1.0 to 1.0) * @return Cropped bitmap */ -fun Bitmap.centerCrop( - centerCrop: Float, - horizontalDisplacement: Float = 0f, - verticalDisplacement: Float = 0f, +internal fun Bitmap.centerCrop( + centerCrop: Float, + horizontalDisplacement: Float = 0f, + verticalDisplacement: Float = 0f, ): Bitmap { val hAbsDisplacement = (width * horizontalDisplacement).toInt() val vAbsDisplacement = (height * verticalDisplacement).toInt() @@ -34,7 +34,7 @@ fun Bitmap.centerCrop( * @param targetArea Target area in pixels (default: 65536 = 256x256) * @return Resized bitmap */ -fun Bitmap.resizeToArea(targetArea: Double = 65536.0): Bitmap { +internal fun Bitmap.resizeToArea(targetArea: Double = 65536.0): Bitmap { val aspectRatio = width.toFloat() / height.toFloat() val newHeight = sqrt(targetArea / aspectRatio) val newWidth = aspectRatio * newHeight diff --git a/simq/src/main/java/com/simprints/simq/utils/OpenCVLoader.kt b/simq/src/main/java/com/simprints/simq/utils/OpenCVLoader.kt index 938071e..34b418f 100644 --- a/simq/src/main/java/com/simprints/simq/utils/OpenCVLoader.kt +++ b/simq/src/main/java/com/simprints/simq/utils/OpenCVLoader.kt @@ -4,10 +4,10 @@ import android.util.Log import org.opencv.android.OpenCVLoader as AndroidOpenCVLoader /** - * Singleton object to handle OpenCV library loading. - * Ensures the native library is loaded only once during the application lifecycle. + * Singleton object to handle OpenCV library loading. Ensures the native library is loaded only once + * during the application lifecycle. */ -object OpenCVLoader { +internal object OpenCVLoader { private const val TAG = "OpenCV" fun init() { diff --git a/simq/src/main/java/com/simprints/simq/utils/ScoringFunctions.kt b/simq/src/main/java/com/simprints/simq/utils/ScoringFunctions.kt index 238de1e..9fa9913 100644 --- a/simq/src/main/java/com/simprints/simq/utils/ScoringFunctions.kt +++ b/simq/src/main/java/com/simprints/simq/utils/ScoringFunctions.kt @@ -2,7 +2,7 @@ package com.simprints.simq.utils import kotlin.math.exp -object ScoringFunctions { +internal object ScoringFunctions { /** * Ramp scoring function: linear interpolation between min and max. * @@ -12,14 +12,15 @@ object ScoringFunctions { * @return Score between 0.0 and 1.0 */ fun rampScore( - x: Double, - min: Double, - max: Double, - ): Double = when { - x < min -> 0.0 - x > max -> 1.0 - else -> (x - min) / (max - min) - } + x: Double, + min: Double, + max: Double, + ): Double = + when { + x < min -> 0.0 + x > max -> 1.0 + else -> (x - min) / (max - min) + } /** * Plateau scoring function: optimal range with smooth sigmoid falloff. @@ -33,15 +34,16 @@ object ScoringFunctions { * @return Score between 0.0 and 1.0 */ fun plateauScore( - x: Double, - centerLow: Double, - centerHigh: Double, - edgeLow: Double, - edgeHigh: Double, - steepness: Double, - ): Double = when { - x in centerLow..centerHigh -> 1.0 - x < centerLow -> 1.0 / (1.0 + exp(-steepness * (x - edgeLow))) - else -> 1.0 / (1.0 + exp(steepness * (x - edgeHigh))) - }.coerceIn(0.0, 1.0) + x: Double, + centerLow: Double, + centerHigh: Double, + edgeLow: Double, + edgeHigh: Double, + steepness: Double, + ): Double = + when { + x in centerLow..centerHigh -> 1.0 + x < centerLow -> 1.0 / (1.0 + exp(-steepness * (x - edgeLow))) + else -> 1.0 / (1.0 + exp(steepness * (x - edgeHigh))) + }.coerceIn(0.0, 1.0) } From 23aae84fcada9393a978b54fa8620b0be151e796 Mon Sep 17 00:00:00 2001 From: Martin Georgiev <3349414+Thinkorswim@users.noreply.github.com> Date: Mon, 27 Oct 2025 16:34:23 +0200 Subject: [PATCH 08/12] Add ImageAnalyzer OpenCV abstraction --- .../simprints/simq/analysis/BlurAnalysis.kt | 46 +-------- .../simq/analysis/BrightnessAnalysis.kt | 27 +---- .../simq/analysis/ContrastAnalysis.kt | 36 +------ .../com/simprints/simq/utils/ImageAnalyzer.kt | 98 +++++++++++++++++++ 4 files changed, 113 insertions(+), 94 deletions(-) create mode 100644 simq/src/main/java/com/simprints/simq/utils/ImageAnalyzer.kt diff --git a/simq/src/main/java/com/simprints/simq/analysis/BlurAnalysis.kt b/simq/src/main/java/com/simprints/simq/analysis/BlurAnalysis.kt index 5fcd37d..08063bf 100644 --- a/simq/src/main/java/com/simprints/simq/analysis/BlurAnalysis.kt +++ b/simq/src/main/java/com/simprints/simq/analysis/BlurAnalysis.kt @@ -1,16 +1,13 @@ package com.simprints.simq.analysis import android.graphics.Bitmap +import com.simprints.simq.utils.ImageAnalyzer +import com.simprints.simq.utils.OpenCVImageAnalyzer import com.simprints.simq.utils.ScoringFunctions -import kotlin.math.pow -import org.opencv.android.Utils -import org.opencv.core.Core -import org.opencv.core.CvType -import org.opencv.core.Mat -import org.opencv.core.MatOfDouble -import org.opencv.imgproc.Imgproc internal object BlurAnalysis { + private var imageAnalyzer: ImageAnalyzer = OpenCVImageAnalyzer() + /** * Calculates blur score using Laplacian variance. * @@ -25,42 +22,9 @@ internal object BlurAnalysis { maxBlur: Double, ): Double = try { - val laplacianVariance = calculateLaplacianVariance(bitmap) + val laplacianVariance = imageAnalyzer.calculateLaplacianVariance(bitmap) ScoringFunctions.rampScore(laplacianVariance, minBlur, maxBlur) } catch (e: Exception) { 1.0 // Default to good score if OpenCV not available } - - /** - * Calculates Laplacian blur variance using OpenCV. - * - * @param bitmap The face image to analyze - * @param ksize Kernel size for Laplacian operator (default: 5) - * @return Laplacian variance value - */ - private fun calculateLaplacianVariance( - bitmap: Bitmap, - ksize: Int = 5, - ): Double { - val mat = Mat() - val gray = Mat() - Utils.bitmapToMat(bitmap, mat) - Imgproc.cvtColor(mat, gray, Imgproc.COLOR_BGR2GRAY) - - val laplacian = Mat() - Imgproc.Laplacian(gray, laplacian, CvType.CV_64F, ksize) - - val mean = MatOfDouble() - val stddev = MatOfDouble() - Core.meanStdDev(laplacian, mean, stddev) - val laplacianVariance = stddev.toArray()[0].pow(2.0) - - mat.release() - gray.release() - laplacian.release() - mean.release() - stddev.release() - - return laplacianVariance - } } diff --git a/simq/src/main/java/com/simprints/simq/analysis/BrightnessAnalysis.kt b/simq/src/main/java/com/simprints/simq/analysis/BrightnessAnalysis.kt index c3d9a36..7597320 100644 --- a/simq/src/main/java/com/simprints/simq/analysis/BrightnessAnalysis.kt +++ b/simq/src/main/java/com/simprints/simq/analysis/BrightnessAnalysis.kt @@ -1,13 +1,13 @@ package com.simprints.simq.analysis import android.graphics.Bitmap +import com.simprints.simq.utils.ImageAnalyzer +import com.simprints.simq.utils.OpenCVImageAnalyzer import com.simprints.simq.utils.ScoringFunctions -import org.opencv.android.Utils -import org.opencv.core.Core -import org.opencv.core.Mat -import org.opencv.imgproc.Imgproc internal object BrightnessAnalysis { + private var imageAnalyzer: ImageAnalyzer = OpenCVImageAnalyzer() + /** * Calculates brightness score using plateau function. * @@ -28,7 +28,7 @@ internal object BrightnessAnalysis { steepness: Double, ): Double = try { - val brightness = analyzeBrightness(bitmap) + val brightness = imageAnalyzer.calculateBrightness(bitmap) ScoringFunctions.plateauScore( brightness, centerLow, @@ -40,21 +40,4 @@ internal object BrightnessAnalysis { } catch (e: Exception) { 1.0 } - - /** - * Analyzes brightness of bitmap using OpenCV. - * - * @param bitmap The face image to analyze - * @return Mean brightness value (0-255) - */ - private fun analyzeBrightness(bitmap: Bitmap): Double { - val mat = Mat() - val gray = Mat() - Utils.bitmapToMat(bitmap, mat) - Imgproc.cvtColor(mat, gray, Imgproc.COLOR_BGR2GRAY) - val brightness = Core.mean(gray).`val`[0] - mat.release() - gray.release() - return brightness - } } diff --git a/simq/src/main/java/com/simprints/simq/analysis/ContrastAnalysis.kt b/simq/src/main/java/com/simprints/simq/analysis/ContrastAnalysis.kt index 845b9d6..f6aaaa0 100644 --- a/simq/src/main/java/com/simprints/simq/analysis/ContrastAnalysis.kt +++ b/simq/src/main/java/com/simprints/simq/analysis/ContrastAnalysis.kt @@ -1,14 +1,13 @@ package com.simprints.simq.analysis import android.graphics.Bitmap +import com.simprints.simq.utils.ImageAnalyzer +import com.simprints.simq.utils.OpenCVImageAnalyzer import com.simprints.simq.utils.ScoringFunctions -import org.opencv.android.Utils -import org.opencv.core.Core -import org.opencv.core.Mat -import org.opencv.core.MatOfDouble -import org.opencv.imgproc.Imgproc internal object ContrastAnalysis { + private var imageAnalyzer: ImageAnalyzer = OpenCVImageAnalyzer() + /** * Calculates contrast score using standard deviation. * @@ -23,34 +22,9 @@ internal object ContrastAnalysis { maxContrast: Double, ): Double = try { - val contrast = analyzeContrast(bitmap) + val contrast = imageAnalyzer.calculateContrast(bitmap) ScoringFunctions.rampScore(contrast, minContrast, maxContrast) } catch (e: Exception) { 1.0 // Default to good score if OpenCV not available } - - /** - * Analyzes contrast of bitmap using OpenCV (standard deviation). - * - * @param bitmap The face image to analyze - * @return Standard deviation value representing contrast - */ - private fun analyzeContrast(bitmap: Bitmap): Double { - val mat = Mat() - val gray = Mat() - Utils.bitmapToMat(bitmap, mat) - Imgproc.cvtColor(mat, gray, Imgproc.COLOR_BGR2GRAY) - - val mean = MatOfDouble() - val stddev = MatOfDouble() - Core.meanStdDev(gray, mean, stddev) - val stdDevValue = stddev.toArray()[0] - - mat.release() - gray.release() - mean.release() - stddev.release() - - return stdDevValue - } } diff --git a/simq/src/main/java/com/simprints/simq/utils/ImageAnalyzer.kt b/simq/src/main/java/com/simprints/simq/utils/ImageAnalyzer.kt new file mode 100644 index 0000000..0b90082 --- /dev/null +++ b/simq/src/main/java/com/simprints/simq/utils/ImageAnalyzer.kt @@ -0,0 +1,98 @@ +package com.simprints.simq.utils + +import android.graphics.Bitmap +import org.opencv.android.Utils +import org.opencv.core.Core +import org.opencv.core.CvType +import org.opencv.core.Mat +import org.opencv.core.MatOfDouble +import org.opencv.imgproc.Imgproc +import kotlin.math.pow + +/** + * Interface for image quality analysis operations. + * Provides high-level methods for analyzing image properties like brightness, blur, and contrast. + */ +interface ImageAnalyzer { + /** + * Calculates the mean brightness value of a bitmap image. + * + * @param bitmap The input bitmap image + * @return Mean brightness value (0-255) + */ + fun calculateBrightness(bitmap: Bitmap): Double + + /** + * Calculates the Laplacian variance to measure image sharpness/blur. + * Higher values indicate sharper images, lower values indicate more blur. + * + * @param bitmap The input bitmap image + * @param kernelSize Kernel size for the Laplacian operator (default: 5) + * @return Laplacian variance value + */ + fun calculateLaplacianVariance(bitmap: Bitmap, kernelSize: Int = 5): Double + + /** + * Calculates the standard deviation to measure image contrast. + * Higher values indicate higher contrast. + * + * @param bitmap The input bitmap image + * @return Standard deviation value representing contrast + */ + fun calculateContrast(bitmap: Bitmap): Double +} + +internal class OpenCVImageAnalyzer : ImageAnalyzer { + + override fun calculateBrightness(bitmap: Bitmap): Double { + val mat = Mat() + val gray = Mat() + try { + Utils.bitmapToMat(bitmap, mat) + Imgproc.cvtColor(mat, gray, Imgproc.COLOR_BGR2GRAY) + return Core.mean(gray).`val`[0] + } finally { + mat.release() + gray.release() + } + } + + override fun calculateLaplacianVariance(bitmap: Bitmap, kernelSize: Int): Double { + val mat = Mat() + val gray = Mat() + val laplacian = Mat() + val mean = MatOfDouble() + val stddev = MatOfDouble() + try { + Utils.bitmapToMat(bitmap, mat) + Imgproc.cvtColor(mat, gray, Imgproc.COLOR_BGR2GRAY) + Imgproc.Laplacian(gray, laplacian, CvType.CV_64F, kernelSize) + Core.meanStdDev(laplacian, mean, stddev) + return stddev.toArray()[0].pow(2.0) + } finally { + mat.release() + gray.release() + laplacian.release() + mean.release() + stddev.release() + } + } + + override fun calculateContrast(bitmap: Bitmap): Double { + val mat = Mat() + val gray = Mat() + val mean = MatOfDouble() + val stddev = MatOfDouble() + try { + Utils.bitmapToMat(bitmap, mat) + Imgproc.cvtColor(mat, gray, Imgproc.COLOR_BGR2GRAY) + Core.meanStdDev(gray, mean, stddev) + return stddev.toArray()[0] + } finally { + mat.release() + gray.release() + mean.release() + stddev.release() + } + } +} From 1919a39dba02dde412053b737b2289e9dc72ac6e Mon Sep 17 00:00:00 2001 From: Martin Georgiev <3349414+Thinkorswim@users.noreply.github.com> Date: Mon, 27 Oct 2025 17:42:20 +0200 Subject: [PATCH 09/12] Refactor paramaters handling --- build.gradle.kts | 2 +- simq/build.gradle.kts | 6 +- .../com/simprints/simq/QualityWeightsTest.kt | 43 ++- .../java/com/simprints/simq/SimQTest.kt | 255 +++++++++--------- .../com/simprints/simq/QualityParameters.kt | 30 +-- .../java/com/simprints/simq/QualityWeights.kt | 14 +- simq/src/main/java/com/simprints/simq/SimQ.kt | 52 ++-- .../com/simprints/simq/utils/ImageAnalyzer.kt | 14 +- .../simprints/biometrics/simface/SimFace.kt | 7 +- .../biometrics/simface/SimFaceConfig.kt | 31 ++- .../detection/MlKitFaceDetectionProcessor.kt | 225 +++++++--------- 11 files changed, 336 insertions(+), 343 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index bfe1e19..ca425ae 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -38,7 +38,7 @@ android { } dependencies { - implementation(project(":simq")) + api(project(":simq")) // Tensorflow versions that works with Edgeface api(libs.tensorflow.lite.support) diff --git a/simq/build.gradle.kts b/simq/build.gradle.kts index 72deb03..942f493 100644 --- a/simq/build.gradle.kts +++ b/simq/build.gradle.kts @@ -24,11 +24,11 @@ android { } } compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } kotlinOptions { - jvmTarget = "11" + jvmTarget = "17" } testOptions { diff --git a/simq/src/androidTest/java/com/simprints/simq/QualityWeightsTest.kt b/simq/src/androidTest/java/com/simprints/simq/QualityWeightsTest.kt index 0f77d95..2d592a6 100644 --- a/simq/src/androidTest/java/com/simprints/simq/QualityWeightsTest.kt +++ b/simq/src/androidTest/java/com/simprints/simq/QualityWeightsTest.kt @@ -9,16 +9,9 @@ import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class QualityWeightsTest { - private lateinit var simQ: SimQ - - @Before - fun setUp() { - simQ = SimQ() - } - private fun createTestBitmap( - width: Int = 256, - height: Int = 256, + width: Int = 256, + height: Int = 256, ): Bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888) @Test @@ -26,21 +19,25 @@ class QualityWeightsTest { val bitmap = createTestBitmap() // Only alignment weight + val alignmentOnlySimQ = + SimQ( + faceWeights = + QualityWeights( + alignment = 1.0, + blur = 0.0, + brightness = 0.0, + contrast = 0.0, + eyeOpenness = 0.0, + ), + ) + val alignmentOnly = - simQ.calculateFaceQuality( - bitmap = bitmap, - pitch = 0.0, - yaw = 0.0, - roll = 0.0, - weights = - QualityWeights( - alignment = 1.0, - blur = 0.0, - brightness = 0.0, - contrast = 0.0, - eyeOpenness = 0.0, - ), - ) + alignmentOnlySimQ.calculateFaceQuality( + bitmap = bitmap, + pitch = 0.0, + yaw = 0.0, + roll = 0.0, + ) assertThat(alignmentOnly).isEqualTo(1f) } diff --git a/simq/src/androidTest/java/com/simprints/simq/SimQTest.kt b/simq/src/androidTest/java/com/simprints/simq/SimQTest.kt index 50a0855..e9d5f27 100644 --- a/simq/src/androidTest/java/com/simprints/simq/SimQTest.kt +++ b/simq/src/androidTest/java/com/simprints/simq/SimQTest.kt @@ -18,8 +18,8 @@ class SimQTest { } private fun createTestBitmap( - width: Int = 256, - height: Int = 256, + width: Int = 256, + height: Int = 256, ): Bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888) @Test @@ -36,20 +36,20 @@ class SimQTest { val bitmap = createTestBitmap() val perfectScore = - simQ.calculateFaceQuality( - bitmap = bitmap, - pitch = 0.0, - yaw = 0.0, - roll = 0.0, - ) + simQ.calculateFaceQuality( + bitmap = bitmap, + pitch = 0.0, + yaw = 0.0, + roll = 0.0, + ) val poorAlignmentScore = - simQ.calculateFaceQuality( - bitmap = bitmap, - pitch = 20.0, - yaw = 20.0, - roll = 20.0, - ) + simQ.calculateFaceQuality( + bitmap = bitmap, + pitch = 20.0, + yaw = 20.0, + roll = 20.0, + ) assertThat(perfectScore).isAtLeast(poorAlignmentScore) } @@ -59,12 +59,12 @@ class SimQTest { val bitmap = createTestBitmap() val quality = - simQ.calculateFaceQuality( - bitmap = bitmap, - pitch = 30.0, - yaw = 0.0, - roll = 0.0, - ) + simQ.calculateFaceQuality( + bitmap = bitmap, + pitch = 30.0, + yaw = 0.0, + roll = 0.0, + ) assertThat(quality).isLessThan(0.5f) } @@ -72,36 +72,31 @@ class SimQTest { @Test fun calculateFaceQualityWithEyeOpennessIncludesItInCalculation() { val bitmap = createTestBitmap() + val simQWithEyeWeight = + SimQ( + faceWeights = + QualityWeights( + alignment = 0.3, + blur = 0.2, + brightness = 0.2, + contrast = 0.1, + eyeOpenness = 0.2, + ), + ) val openEyesScore = - simQ.calculateFaceQuality( - bitmap = bitmap, - leftEyeOpenness = 1.0, - rightEyeOpenness = 1.0, - weights = - QualityWeights( - alignment = 0.3, - blur = 0.2, - brightness = 0.2, - contrast = 0.1, - eyeOpenness = 0.2, - ), - ) + simQWithEyeWeight.calculateFaceQuality( + bitmap = bitmap, + leftEyeOpenness = 1.0, + rightEyeOpenness = 1.0, + ) val closedEyesScore = - simQ.calculateFaceQuality( - bitmap = bitmap, - leftEyeOpenness = 0.0, - rightEyeOpenness = 0.0, - weights = - QualityWeights( - alignment = 0.3, - blur = 0.2, - brightness = 0.2, - contrast = 0.1, - eyeOpenness = 0.2, - ), - ) + simQWithEyeWeight.calculateFaceQuality( + bitmap = bitmap, + leftEyeOpenness = 0.0, + rightEyeOpenness = 0.0, + ) assertThat(openEyesScore).isAtLeast(closedEyesScore) } @@ -109,14 +104,14 @@ class SimQTest { @Test fun calculateFaceQualityWithoutEyeOpennessIgnoresEyeWeight() { val bitmap = createTestBitmap() + val simQWithEyeWeight = SimQ(faceWeights = QualityWeights(eyeOpenness = 0.2)) val qualityNoEyes = - simQ.calculateFaceQuality( - bitmap = bitmap, - leftEyeOpenness = null, - rightEyeOpenness = null, - weights = QualityWeights(eyeOpenness = 0.2), - ) + simQWithEyeWeight.calculateFaceQuality( + bitmap = bitmap, + leftEyeOpenness = null, + rightEyeOpenness = null, + ) assertThat(qualityNoEyes).isAtLeast(0.0f) assertThat(qualityNoEyes).isAtMost(1.0f) @@ -125,14 +120,14 @@ class SimQTest { @Test fun calculateFaceQualityWithOnlyLeftEyeOpennessProvided() { val bitmap = createTestBitmap() + val simQWithEyeWeight = SimQ(faceWeights = QualityWeights(eyeOpenness = 0.2)) val quality = - simQ.calculateFaceQuality( - bitmap = bitmap, - leftEyeOpenness = 1.0, - rightEyeOpenness = null, - weights = QualityWeights(eyeOpenness = 0.2), - ) + simQWithEyeWeight.calculateFaceQuality( + bitmap = bitmap, + leftEyeOpenness = 1.0, + rightEyeOpenness = null, + ) assertThat(quality).isIn(Range.closed(0.0f, 1.0f)) } @@ -140,38 +135,44 @@ class SimQTest { @Test fun calculateFaceQualityWithCustomWeightsAffectsResult() { val bitmap = createTestBitmap() + val alignmentWeightedSimQ = + SimQ( + faceWeights = + QualityWeights( + alignment = 0.9, + blur = 0.025, + brightness = 0.025, + contrast = 0.025, + eyeOpenness = 0.025, + ), + ) + val otherWeightedSimQ = + SimQ( + faceWeights = + QualityWeights( + alignment = 0.025, + blur = 0.325, + brightness = 0.325, + contrast = 0.325, + eyeOpenness = 0.0, + ), + ) val alignmentWeighted = - simQ.calculateFaceQuality( - bitmap = bitmap, - pitch = 20.0, - yaw = 20.0, - roll = 20.0, - weights = - QualityWeights( - alignment = 0.9, - blur = 0.025, - brightness = 0.025, - contrast = 0.025, - eyeOpenness = 0.025, - ), - ) + alignmentWeightedSimQ.calculateFaceQuality( + bitmap = bitmap, + pitch = 20.0, + yaw = 20.0, + roll = 20.0, + ) val otherWeighted = - simQ.calculateFaceQuality( - bitmap = bitmap, - pitch = 20.0, - yaw = 20.0, - roll = 20.0, - weights = - QualityWeights( - alignment = 0.025, - blur = 0.325, - brightness = 0.325, - contrast = 0.325, - eyeOpenness = 0.0, - ), - ) + otherWeightedSimQ.calculateFaceQuality( + bitmap = bitmap, + pitch = 20.0, + yaw = 20.0, + roll = 20.0, + ) assertThat(alignmentWeighted).isLessThan(otherWeighted) } @@ -179,32 +180,38 @@ class SimQTest { @Test fun calculateFaceQualityWithCustomParametersAffectsThresholds() { val bitmap = createTestBitmap() + val strictSimQ = + SimQ( + faceParameters = + QualityParameters( + maxAlignmentAngle = 10.0, + maxIndividualAngle = 20.0, + ), + ) + val lenientSimQ = + SimQ( + faceParameters = + QualityParameters( + maxAlignmentAngle = 30.0, + maxIndividualAngle = 40.0, + ), + ) val strictQuality = - simQ.calculateFaceQuality( - bitmap = bitmap, - pitch = 15.0, - yaw = 15.0, - roll = 15.0, - parameters = - QualityParameters( - maxAlignmentAngle = 10.0, - maxIndividualAngle = 20.0, - ), - ) + strictSimQ.calculateFaceQuality( + bitmap = bitmap, + pitch = 15.0, + yaw = 15.0, + roll = 15.0, + ) val lenientQuality = - simQ.calculateFaceQuality( - bitmap = bitmap, - pitch = 15.0, - yaw = 15.0, - roll = 15.0, - parameters = - QualityParameters( - maxAlignmentAngle = 30.0, - maxIndividualAngle = 40.0, - ), - ) + lenientSimQ.calculateFaceQuality( + bitmap = bitmap, + pitch = 15.0, + yaw = 15.0, + roll = 15.0, + ) assertThat(lenientQuality).isAtLeast(strictQuality) } @@ -236,10 +243,8 @@ class SimQTest { fun calculateFaceQualityIsConsistentWithSameInputs() { val bitmap = createTestBitmap() - val quality1 = - simQ.calculateFaceQuality(bitmap, pitch = 10.0, yaw = 5.0, roll = -3.0) - val quality2 = - simQ.calculateFaceQuality(bitmap, pitch = 10.0, yaw = 5.0, roll = -3.0) + val quality1 = simQ.calculateFaceQuality(bitmap, pitch = 10.0, yaw = 5.0, roll = -3.0) + val quality2 = simQ.calculateFaceQuality(bitmap, pitch = 10.0, yaw = 5.0, roll = -3.0) assertThat(quality1).isWithin(0.001f).of(quality2) } @@ -247,19 +252,19 @@ class SimQTest { @Test fun calculateFaceQualityWithZeroWeightsReturnsZeroOrHandledGracefully() { val bitmap = createTestBitmap() - - val quality = - simQ.calculateFaceQuality( - bitmap = bitmap, - weights = - QualityWeights( - alignment = 0.0, - blur = 0.0, - brightness = 0.0, - contrast = 0.0, - eyeOpenness = 0.0, - ), - ) + val zeroWeightsSimQ = + SimQ( + faceWeights = + QualityWeights( + alignment = 0.0, + blur = 0.0, + brightness = 0.0, + contrast = 0.0, + eyeOpenness = 0.0, + ), + ) + + val quality = zeroWeightsSimQ.calculateFaceQuality(bitmap = bitmap) assertThat(quality).isIn(Range.closed(0.0f, 1.0f)) } diff --git a/simq/src/main/java/com/simprints/simq/QualityParameters.kt b/simq/src/main/java/com/simprints/simq/QualityParameters.kt index 50a6282..76eab4e 100644 --- a/simq/src/main/java/com/simprints/simq/QualityParameters.kt +++ b/simq/src/main/java/com/simprints/simq/QualityParameters.kt @@ -1,21 +1,21 @@ package com.simprints.simq data class QualityParameters( - // Alignment thresholds - val maxAlignmentAngle: Double = 20.0, - val maxIndividualAngle: Double = 25.0, - // Blur thresholds (Laplacian variance) - val minBlur: Double = 50_000.0, - val maxBlur: Double = 100_000.0, - // Brightness thresholds (0-255) - val minBrightness: Double = 30.0, - val optimalBrightnessLow: Double = 80.0, - val optimalBrightnessHigh: Double = 150.0, - val maxBrightness: Double = 190.0, - val brightnessSteepness: Double = 0.3, - // Contrast thresholds (std dev) - val minContrast: Double = 30.0, - val maxContrast: Double = 47.0, + // Alignment thresholds + val maxAlignmentAngle: Double = 20.0, + val maxIndividualAngle: Double = 25.0, + // Blur thresholds (Laplacian variance) + val minBlur: Double = 50_000.0, + val maxBlur: Double = 100_000.0, + // Brightness thresholds (0-255) + val minBrightness: Double = 30.0, + val optimalBrightnessLow: Double = 80.0, + val optimalBrightnessHigh: Double = 150.0, + val maxBrightness: Double = 190.0, + val brightnessSteepness: Double = 0.3, + // Contrast thresholds (std dev) + val minContrast: Double = 30.0, + val maxContrast: Double = 47.0, ) { companion object { val DEFAULT = QualityParameters() diff --git a/simq/src/main/java/com/simprints/simq/QualityWeights.kt b/simq/src/main/java/com/simprints/simq/QualityWeights.kt index 2916ad2..167ddb4 100644 --- a/simq/src/main/java/com/simprints/simq/QualityWeights.kt +++ b/simq/src/main/java/com/simprints/simq/QualityWeights.kt @@ -1,15 +1,15 @@ package com.simprints.simq /** - * Default quality weights for face assessment. - * These control how much each metric contributes to the final score. + * Default quality weights for face assessment. These control how much each metric contributes to + * the final score. */ data class QualityWeights( - val alignment: Double = 0.3, - val blur: Double = 0.3, - val brightness: Double = 0.3, - val contrast: Double = 0.1, - val eyeOpenness: Double = 0.0, + val alignment: Double = 0.28, + val blur: Double = 0.3, + val brightness: Double = 0.3, + val contrast: Double = 0.1, + val eyeOpenness: Double = 0.02, ) { companion object { val DEFAULT = QualityWeights() diff --git a/simq/src/main/java/com/simprints/simq/SimQ.kt b/simq/src/main/java/com/simprints/simq/SimQ.kt index 7f3bad5..b50bfe0 100644 --- a/simq/src/main/java/com/simprints/simq/SimQ.kt +++ b/simq/src/main/java/com/simprints/simq/SimQ.kt @@ -9,7 +9,10 @@ import com.simprints.simq.utils.OpenCVLoader import com.simprints.simq.utils.centerCrop import com.simprints.simq.utils.resizeToArea -class SimQ { +class SimQ( + private val faceWeights: QualityWeights = QualityWeights.DEFAULT, + private val faceParameters: QualityParameters = QualityParameters.DEFAULT, +) { init { OpenCVLoader.init() } @@ -26,8 +29,6 @@ class SimQ { * @param centerCrop Fraction of the bitmap to use for quality assessment (default: 0.5) * @param horizontalDisplacement Horizontal displacement for center crop (default: 0.0) * @param verticalDisplacement Vertical displacement for center crop (default: 0.0) - * @param weights Custom weights for quality metrics (optional) - * @param parameters Custom quality parameters (optional) * @return Quality score between 0.0 and 1.0, or 0.0 if calculation fails */ fun calculateFaceQuality( @@ -40,10 +41,9 @@ class SimQ { centerCrop: Float = 0.5f, horizontalDisplacement: Float = 0.0f, verticalDisplacement: Float = 0.0f, - weights: QualityWeights = QualityWeights.DEFAULT, - parameters: QualityParameters = QualityParameters.DEFAULT, ): Float = try { + // Resize bitmap to target area (256x256 = 65536) val resizedBitmap = bitmap.resizeToArea(65536.0) @@ -57,12 +57,12 @@ class SimQ { var totalScore = 0.0 val totalWeight = - weights.alignment + - weights.blur + - weights.brightness + - weights.contrast + + faceWeights.alignment + + faceWeights.blur + + faceWeights.brightness + + faceWeights.contrast + (if (leftEyeOpenness != null && rightEyeOpenness != null) { - weights.eyeOpenness + faceWeights.eyeOpenness } else { 0.0 }) @@ -72,41 +72,41 @@ class SimQ { pitch, yaw, roll, - parameters.maxAlignmentAngle, - parameters.maxIndividualAngle, + faceParameters.maxAlignmentAngle, + faceParameters.maxIndividualAngle, ) - totalScore += weights.alignment * alignmentScore + totalScore += faceWeights.alignment * alignmentScore val blurScore = BlurAnalysis.calculateScore( croppedBitmap, - parameters.minBlur, - parameters.maxBlur, + faceParameters.minBlur, + faceParameters.maxBlur, ) - totalScore += weights.blur * blurScore + totalScore += faceWeights.blur * blurScore val brightnessScore = BrightnessAnalysis.calculateScore( croppedBitmap, - parameters.minBrightness, - parameters.optimalBrightnessLow, - parameters.optimalBrightnessHigh, - parameters.maxBrightness, - parameters.brightnessSteepness, + faceParameters.minBrightness, + faceParameters.optimalBrightnessLow, + faceParameters.optimalBrightnessHigh, + faceParameters.maxBrightness, + faceParameters.brightnessSteepness, ) - totalScore += weights.brightness * brightnessScore + totalScore += faceWeights.brightness * brightnessScore val contrastScore = ContrastAnalysis.calculateScore( croppedBitmap, - parameters.minContrast, - parameters.maxContrast, + faceParameters.minContrast, + faceParameters.maxContrast, ) - totalScore += weights.contrast * contrastScore + totalScore += faceWeights.contrast * contrastScore if (leftEyeOpenness != null && rightEyeOpenness != null) { val eyeScore = (leftEyeOpenness + rightEyeOpenness) / 2.0 - totalScore += weights.eyeOpenness * eyeScore + totalScore += faceWeights.eyeOpenness * eyeScore } // Clean up diff --git a/simq/src/main/java/com/simprints/simq/utils/ImageAnalyzer.kt b/simq/src/main/java/com/simprints/simq/utils/ImageAnalyzer.kt index 0b90082..d1384fc 100644 --- a/simq/src/main/java/com/simprints/simq/utils/ImageAnalyzer.kt +++ b/simq/src/main/java/com/simprints/simq/utils/ImageAnalyzer.kt @@ -1,17 +1,17 @@ package com.simprints.simq.utils import android.graphics.Bitmap +import kotlin.math.pow import org.opencv.android.Utils import org.opencv.core.Core import org.opencv.core.CvType import org.opencv.core.Mat import org.opencv.core.MatOfDouble import org.opencv.imgproc.Imgproc -import kotlin.math.pow /** - * Interface for image quality analysis operations. - * Provides high-level methods for analyzing image properties like brightness, blur, and contrast. + * Interface for image quality analysis operations. Provides high-level methods for analyzing image + * properties like brightness, blur, and contrast. */ interface ImageAnalyzer { /** @@ -23,8 +23,8 @@ interface ImageAnalyzer { fun calculateBrightness(bitmap: Bitmap): Double /** - * Calculates the Laplacian variance to measure image sharpness/blur. - * Higher values indicate sharper images, lower values indicate more blur. + * Calculates the Laplacian variance to measure image sharpness/blur. Higher values indicate + * sharper images, lower values indicate more blur. * * @param bitmap The input bitmap image * @param kernelSize Kernel size for the Laplacian operator (default: 5) @@ -33,8 +33,8 @@ interface ImageAnalyzer { fun calculateLaplacianVariance(bitmap: Bitmap, kernelSize: Int = 5): Double /** - * Calculates the standard deviation to measure image contrast. - * Higher values indicate higher contrast. + * Calculates the standard deviation to measure image contrast. Higher values indicate higher + * contrast. * * @param bitmap The input bitmap image * @return Standard deviation value representing contrast diff --git a/src/main/java/com/simprints/biometrics/simface/SimFace.kt b/src/main/java/com/simprints/biometrics/simface/SimFace.kt index 078ed19..8b175b0 100644 --- a/src/main/java/com/simprints/biometrics/simface/SimFace.kt +++ b/src/main/java/com/simprints/biometrics/simface/SimFace.kt @@ -33,8 +33,11 @@ class SimFace { // Initialize the model manager with the given config modelManager = MLModelManager(config) - // Initialize SimQ quality processor - qualityProcessor = SimQ() + // Initialize SimQ quality processor with optional custom weights and parameters + qualityProcessor = SimQ( + faceWeights = config.qualityWeights ?: com.simprints.simq.QualityWeights.DEFAULT, + faceParameters = config.qualityParameters ?: com.simprints.simq.QualityParameters.DEFAULT + ) // Initialize processors embeddingProcessor = TensorFlowEmbeddingProcessor(modelManager) diff --git a/src/main/java/com/simprints/biometrics/simface/SimFaceConfig.kt b/src/main/java/com/simprints/biometrics/simface/SimFaceConfig.kt index 6eeac9f..d74cf31 100644 --- a/src/main/java/com/simprints/biometrics/simface/SimFaceConfig.kt +++ b/src/main/java/com/simprints/biometrics/simface/SimFaceConfig.kt @@ -1,18 +1,31 @@ package com.simprints.biometrics.simface import android.content.Context +import com.simprints.simq.QualityParameters +import com.simprints.simq.QualityWeights import java.io.File -data class SimFaceConfig( - val applicationContext: Context, - /** - * Custom model file to use instead of the bundled one. If not set, the bundled model will be used. - * The custom model's inputs and outputs vectors must much the default SimFace model. - */ - val customModel: CustomModel? = null, +data class SimFaceConfig( + val applicationContext: Context, + /** + * Custom model file to use instead of the bundled one. If not set, the bundled model will + * be used. The custom model's inputs and outputs vectors must much the default SimFace + * model. + */ + val customModel: CustomModel? = null, + /** + * Custom quality weights for face quality assessment. If not set, default weights will be + * used. + */ + val qualityWeights: QualityWeights? = null, + /** + * Custom quality parameters for face quality assessment. If not set, default parameters + * will be used. + */ + val qualityParameters: QualityParameters? = null, ) { data class CustomModel( - val file: File, - val templateVersion: String, + val file: File, + val templateVersion: String, ) } diff --git a/src/main/java/com/simprints/biometrics/simface/detection/MlKitFaceDetectionProcessor.kt b/src/main/java/com/simprints/biometrics/simface/detection/MlKitFaceDetectionProcessor.kt index 54908c8..5a2d3fa 100644 --- a/src/main/java/com/simprints/biometrics/simface/detection/MlKitFaceDetectionProcessor.kt +++ b/src/main/java/com/simprints/biometrics/simface/detection/MlKitFaceDetectionProcessor.kt @@ -10,49 +10,48 @@ import com.simprints.biometrics.simface.Utils.clampToBounds import com.simprints.biometrics.simface.data.FaceDetection import com.simprints.biometrics.simface.data.FacialLandmarks import com.simprints.biometrics.simface.data.Point2D -import com.simprints.simq.QualityParameters -import com.simprints.simq.QualityWeights import com.simprints.simq.SimQ import kotlin.coroutines.resume import kotlin.coroutines.resumeWithException import kotlin.coroutines.suspendCoroutine internal class MlKitFaceDetectionProcessor( - private val faceDetector: FaceDetector, - private val qualityProcessor: SimQ, + private val faceDetector: FaceDetector, + private val qualityProcessor: SimQ, ) : FaceDetectionProcessor { override fun detectFace( - image: Bitmap, - onSuccess: (List) -> Unit, - onFailure: (Exception) -> Unit, - onCompleted: () -> Unit, + image: Bitmap, + onSuccess: (List) -> Unit, + onFailure: (Exception) -> Unit, + onCompleted: () -> Unit, ) { val inputImage = InputImage.fromBitmap(image, 0) faceDetector - .process(inputImage) - .addOnSuccessListener { faces -> - val faceDetections = mutableListOf() - faces?.forEach { face -> - val faceDetection = - FaceDetection( - sourceWidth = image.width, - sourceHeight = image.height, - absoluteBoundingBox = - face.boundingBox.clampToBounds( - image.width, - image.height, - ), - yaw = face.headEulerAngleY, - roll = face.headEulerAngleZ, - landmarks = buildLandmarks(face), - quality = calculateFaceQuality(face, image), - ) - faceDetections.add(faceDetection) + .process(inputImage) + .addOnSuccessListener { faces -> + val faceDetections = mutableListOf() + faces?.forEach { face -> + val faceDetection = + FaceDetection( + sourceWidth = image.width, + sourceHeight = image.height, + absoluteBoundingBox = + face.boundingBox.clampToBounds( + image.width, + image.height, + ), + yaw = face.headEulerAngleY, + roll = face.headEulerAngleZ, + landmarks = buildLandmarks(face), + quality = calculateFaceQuality(face, image), + ) + faceDetections.add(faceDetection) + } + onSuccess(faceDetections) } - onSuccess(faceDetections) - }.addOnFailureListener { exception -> onFailure(exception) } - .addOnCompleteListener { onCompleted() } + .addOnFailureListener { exception -> onFailure(exception) } + .addOnCompleteListener { onCompleted() } } override suspend fun detectFaceBlocking(image: Bitmap): List { @@ -60,122 +59,98 @@ internal class MlKitFaceDetectionProcessor( return suspendCoroutine { continuation -> faceDetector - .process(inputImage) - .addOnSuccessListener { faces -> - val faceDetections = mutableListOf() - faces?.forEach { face -> - val faceDetection = - FaceDetection( - sourceWidth = image.width, - sourceHeight = image.height, - absoluteBoundingBox = - face.boundingBox.clampToBounds( - image.width, - image.height, - ), - yaw = face.headEulerAngleY, - roll = face.headEulerAngleZ, - quality = calculateFaceQuality(face, image), - landmarks = buildLandmarks(face), - ) - faceDetections.add(faceDetection) + .process(inputImage) + .addOnSuccessListener { faces -> + val faceDetections = mutableListOf() + faces?.forEach { face -> + val faceDetection = + FaceDetection( + sourceWidth = image.width, + sourceHeight = image.height, + absoluteBoundingBox = + face.boundingBox.clampToBounds( + image.width, + image.height, + ), + yaw = face.headEulerAngleY, + roll = face.headEulerAngleZ, + quality = calculateFaceQuality(face, image), + landmarks = buildLandmarks(face), + ) + faceDetections.add(faceDetection) + } + continuation.resume(faceDetections) + } + .addOnFailureListener { exception -> + continuation.resumeWithException(exception) } - continuation.resume(faceDetections) - }.addOnFailureListener { exception -> - continuation.resumeWithException(exception) - } } } private fun calculateFaceQuality( - face: Face, - image: Bitmap, - ): Float = try { - val boundingBox = face.boundingBox.clampToBounds(image.width, image.height) - val faceBitmap = - Bitmap.createBitmap( - image, - boundingBox.left, - boundingBox.top, - boundingBox.width(), - boundingBox.height(), - ) - - val parameters = - QualityParameters( - maxAlignmentAngle = 20.0, - maxIndividualAngle = 25.0, - minBlur = 50.0, - maxBlur = 100.0, - minBrightness = 30.0, - optimalBrightnessLow = 80.0, - optimalBrightnessHigh = 150.0, - maxBrightness = 190.0, - brightnessSteepness = 0.3, - minContrast = 30.0, - maxContrast = 47.0, - ) - - val weights = - QualityWeights( - alignment = 0.28, - blur = 0.3, - brightness = 0.1, - contrast = 0.3, - eyeOpenness = 0.02, - ) + face: Face, + image: Bitmap, + ): Float = + try { + val boundingBox = face.boundingBox.clampToBounds(image.width, image.height) + val faceBitmap = + Bitmap.createBitmap( + image, + boundingBox.left, + boundingBox.top, + boundingBox.width(), + boundingBox.height(), + ) - val qualityScore = - qualityProcessor.calculateFaceQuality( - bitmap = faceBitmap, - pitch = face.headEulerAngleX.toDouble(), - yaw = face.headEulerAngleY.toDouble(), - roll = face.headEulerAngleZ.toDouble(), - leftEyeOpenness = face.leftEyeOpenProbability?.toDouble(), - rightEyeOpenness = face.rightEyeOpenProbability?.toDouble(), - weights = weights, - parameters = parameters, - ) + val qualityScore = + qualityProcessor.calculateFaceQuality( + bitmap = faceBitmap, + pitch = face.headEulerAngleX.toDouble(), + yaw = face.headEulerAngleY.toDouble(), + roll = face.headEulerAngleZ.toDouble(), + leftEyeOpenness = face.leftEyeOpenProbability?.toDouble(), + rightEyeOpenness = face.rightEyeOpenProbability?.toDouble(), + ) - faceBitmap.recycle() + faceBitmap.recycle() - qualityScore - } catch (e: Exception) { - 0.0f - } + qualityScore + } catch (e: Exception) { + 0.0f + } private fun buildLandmarks(face: Face): FacialLandmarks? { val leftEye = - face.getLandmark(FaceLandmark.LEFT_EYE)?.position - ?: face.getContour(FaceContour.LEFT_EYE)?.points?.getOrNull(4) - ?: return null + face.getLandmark(FaceLandmark.LEFT_EYE)?.position + ?: face.getContour(FaceContour.LEFT_EYE)?.points?.getOrNull(4) + ?: return null val rightEye = - face.getLandmark(FaceLandmark.RIGHT_EYE)?.position - ?: face.getContour(FaceContour.RIGHT_EYE)?.points?.getOrNull(4) - ?: return null + face.getLandmark(FaceLandmark.RIGHT_EYE)?.position + ?: face.getContour(FaceContour.RIGHT_EYE)?.points?.getOrNull(4) + ?: return null val nose = - face.getLandmark(FaceLandmark.NOSE_BASE)?.position - ?: face.getContour(FaceContour.NOSE_BRIDGE)?.points?.lastOrNull() - ?: return null + face.getLandmark(FaceLandmark.NOSE_BASE)?.position + ?: face.getContour(FaceContour.NOSE_BRIDGE)?.points?.lastOrNull() + ?: return null val mouthLeft = - face.getLandmark(FaceLandmark.MOUTH_LEFT)?.position - ?: face.getContour(FaceContour.LOWER_LIP_BOTTOM)?.points?.lastOrNull() - ?: return null + face.getLandmark(FaceLandmark.MOUTH_LEFT)?.position + ?: face.getContour(FaceContour.LOWER_LIP_BOTTOM)?.points?.lastOrNull() + ?: return null val mouthRight = - face.getLandmark(FaceLandmark.MOUTH_RIGHT)?.position - ?: face.getContour(FaceContour.LOWER_LIP_BOTTOM)?.points?.firstOrNull() - ?: return null + face.getLandmark(FaceLandmark.MOUTH_RIGHT)?.position + ?: face.getContour(FaceContour.LOWER_LIP_BOTTOM)?.points?.firstOrNull() + ?: return null return FacialLandmarks( - Point2D(leftEye.x, leftEye.y), - Point2D(rightEye.x, rightEye.y), - Point2D(nose.x, nose.y), - Point2D(mouthLeft.x, mouthLeft.y), - Point2D(mouthRight.x, mouthRight.y), + Point2D(leftEye.x, leftEye.y), + Point2D(rightEye.x, rightEye.y), + Point2D(nose.x, nose.y), + Point2D(mouthLeft.x, mouthLeft.y), + Point2D(mouthRight.x, mouthRight.y), ) } } From 6567b5931871142edffa2df88f13a657b39481c1 Mon Sep 17 00:00:00 2001 From: Martin Georgiev <3349414+Thinkorswim@users.noreply.github.com> Date: Mon, 27 Oct 2025 18:00:01 +0200 Subject: [PATCH 10/12] Update low quality image --- .../detection/FaceDetectionProcessorTest.kt | 4 ++-- .../res/drawable/royalty_free_bad_face.jpg | Bin 377115 -> 129872 bytes 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/androidTest/java/com/simprints/biometrics/simface/detection/FaceDetectionProcessorTest.kt b/src/androidTest/java/com/simprints/biometrics/simface/detection/FaceDetectionProcessorTest.kt index 321654f..7175886 100644 --- a/src/androidTest/java/com/simprints/biometrics/simface/detection/FaceDetectionProcessorTest.kt +++ b/src/androidTest/java/com/simprints/biometrics/simface/detection/FaceDetectionProcessorTest.kt @@ -64,7 +64,7 @@ class FaceDetectionProcessorTest { val faces = resultDeferred.await() assertThat(faces).isNotEmpty() val face = faces[0] - assertThat(face.quality).isLessThan(0.6f) + assertThat(face.quality).isLessThan(0.5f) } @Test @@ -114,7 +114,7 @@ class FaceDetectionProcessorTest { assertThat(faces).isNotEmpty() val face = faces[0] - assertThat(face.quality).isLessThan(0.6f) + assertThat(face.quality).isLessThan(0.5f) } @Test diff --git a/src/androidTest/res/drawable/royalty_free_bad_face.jpg b/src/androidTest/res/drawable/royalty_free_bad_face.jpg index 37b98422c3e0176ea6b0f1ac60978e09aae3fdd9..97e29ab076fb949f52ecaac449170448bc476059 100644 GIT binary patch literal 129872 zcmb4q1y>wR(C*;w?gR}UJi*=FH4rSgOK=PB5Zv9JT`XuIkl+rx5ZnU<*M*PwyZ8Qp zTXW9LoSswNPghr0SJiaCEWd03xJq)0asV709H8)e0WVNM8bE;mkN&$Oyb>ZZ;(vsS zjEsbghKi1khKh!Uj){Ybj)9GVhK7ZQg^h!Yi-(JjiBEu!OYr)R`(Gt+|8XK9qP{ZX zVxVEXmi~XzOFw{zim-q{ivULlz~jLo;K98N0aO40kMN5274QEgICua7@jqlJub=I3 z0r=OJ;Su4HQ4kT((BY`y;PC*2H;DM$lA1^abf1vjP*8b7Q;N|D>7|+nW{7yT{#m4M z5|c3SNvD;zo|7`l=vZ30hlQ8S&XF-|dkp?~%kLHWt&B-P&hu+V%X?W}J!|i_`R&)H zDB%7NlK+R}^$7?6ACmuY2;l**(t~>if`Ebqz#$_1_Yn`_4L2gbB$DPU4mV_;e}weB zuSjNyq_mnh2T+Ll+@&qfUmyS`!fVZV2zY=v@W5Zv0sb3fXHkNvvIY8ji5U^Tyl93c zNABh3C<13nC~%WXC(k<}a8T{kQtk!z&UN*l<5pkCU@j(zMc%Xo>5v^$Y6|@J%MZQD zVF5>d+(1tXX%ejtX{$eK7mYbocd9@C&VF?wc?xC1bw0c(Ig^wQY3_E7ZP-wbBECN+ zM9O@Wz&=+=j8%FMCCx7H|2knD2&Jiah1L>LDSQqa}JLkL-pFH83zF<836et*72Z_Mp#bn7#gr`Sl? z9?0r(kT8aY2t7`tFD`SN4mKKBZF?Wwln0j9;$eXz-V$E%+iY;V?``^tbP|2gU~A8cd(F6 z%5T$mRY9J;(xIJ+{@xYJHJI<9Plqu1QFsn;rqtyxCi@M|ueG5{OUZtp-JWXdBfci~ zFr^EQwzV00)pLj18N2|oEJ%G^^V+U|ZObPr$OJ}=Kn*}{ILpXn=~si__w8ulN?c=NG>qk({%^n?JgTo50znjnIUa z!N+`X|823rV9rM83IMsksgdnjQT;89OjqV>Mb+IaXTQ_w)Zx^-T--ae)M?u4M2_wx z`fIPA6S&SsspQukEBIWjsMgs zER2{&R3G8C|Hgs`O+@#XTd-Rb%I~+L^AeI7%(wQ190dvnlmnIbQHnU8kdAdrZ&!IG z)6TjZThmX5y z5ZL}OPWh7vm{ZolL*)d*EMiU6@VwjP5%{Ey6Sg)*kHDYY`fNImY|&LCH`;zU4eQ^~ zl9zklET=h74$Ncf#+R(DY6U%b`KvI9$SG{Sb&i0<)*H>y%O}UKZ?W>~3(=YxRm`o) zGLFS~%$5Yto+xRiOUs1Lfhh0E6Hyu zCsMn|{z^4xA`&IL8#>8)lX+OboL9`OiIfld^f}oo(gm?eQDfPhdgmoi)a{SbniA?) z&+leHV~A=0bUbhHLOU&8Db@LlSX+`f39(Z&PZ|4^t!~bA5xLk2TpVY?ci7XbpzRCvf}4w~b&#!iIYo{W8in&A zd$$kq&sM>CjE&lOc2=O>KnH&H&d ztIx5^aWkE$u2AmYAfY=IbY+tDw%FOWja}e~&&cNmSmC;=L5Vn!$rZvN9?{%w2xgt` zFI9d+zdXmWU{bv^*`4OAOYYKDDS^T?W^|P+qzjZ9y(|<6gb$>P(D>PGU za~WT~xqSHuL0aPR5E>9=uP`n`Gq}=cy_sVriu0{+w)meJ@+H#?@YQxD>5PhpX4g1% z7mN$&{r$nmX`)L(PCBBb%VjRFzk~O0UuaV3q0gK(3Qh;JvPn0p0S(USq|=8l2b_Eap?POOhq(S zW(IF2p?NwNRvF^mo-}k3X{S(C)UUQ+yi4*6oLUvueow#Q5~}1Rj&w&K@+t}_yXBct z8H@%-^ULfOV}ls_WVh+98U2{igMifW0<_BEErvoJA2R&Yq`q}F{Y`4#Pnucp=SA2^ ziW>dD(KFYlH9m076I!PzGGOpL^8= z@Qbv1k0(l(Ty2ofROs0=yh5^Zv3*c^@ckj}V0$w?F>26}=Gi+Lh95{oycT=_-Sie6 zi75%^dypi`eYPxf~5y=h23nbv_f8f4T3C$KG`uw2Fb@ky& zW~cBLd}pFg5x_K>1cO}f&CvT`Kzo#(i%u+1I=2b~GBc=}|0U5sU-rook1`*uZ$>84 z53(z~0Bg0{2ZaY9>H5Y}mx%sOijaS~Vs(>&{KuR;RdBz#=|k-6i{q=}U0Hkt#1?ig z60Vf5)M8zV=)VB<0&q{>OLeQYk%+`(VE^h z5GpVEo?p2KY=KK{QGU*NN|kaWQvAUDz$sxG1l;*k{tR1vwHmdszd?yoh0Ggfi16b6 zl8!F`>vaOgO>$yyiv09(DEx;r#YxTGIFJ~60MDT+4_%ldkSe6tLYSoW(7kAeEhw%h z*V>kh7{;c5OgsuJ@2S6gCTzDFrQUMGTl!Gq%x#I6GOvT>eOs=<>K|WtsN(dFCxO9V zb0=;cDcI33?3wUr!hw-N)415$rJ8!fBDBLKqS;XrwpZ@0;88{4hvN*=+xDpJ5l=aM zl=foITMQ*}n(7$FFv0L?3U6mE?J>yQkqogDH`Jn6>#mGERBp;!HAlNCX-t91`B!X0 zfFkUb5OHcdpVc<+7G%Z4(Pz-7KFeIYjw`%j94Vz}E;53{XF}>r0U+5u ziQEkLVgv8e(Pi(narMb8Q)^)fz^C|OxWW6OTiz%_) zPA!0^sz{b2cv;@5^$Le!o3zRXgnE3sm>TNuu*e#7%zB? zg0n(6mWUIu7RIb2=LqZ?e$!h@>~wmYr-S}eIT`1&0!{OC)+v07Oh}2ugdQg-Pbf?{ z(XP+1^)aOLnJ~B5{e7^tR=@y`dbupJ{YZg(Qat_Lg25+jfs|Dbd0=r2 zY147nin^yNL2F0uaEmp??aYs(3S(Bz-q*^nKG`TuF$zPHy+M(d_NGF)n}-ljfnVUR zD-=y+C^n(`5*x~vbWXFY_Jqd8_(P8yz$xTQa{Xfq0SF6p&{kU^CF{nPPV*yLEDqlk z9HH0j?`rk6aNgf9VAX)tplltthf0J^x$%gxY#q9?XJ0xYK;l)oCJ%fX#183a8~Q4k zEU>f0i`-lkt+N|0$6sQhWT+P#HQr}fIr9frlZ8i~uB&tY5K@uIm?|yuM-X{WgjP`v z+Iq~%hgzhQg47fxF1wIbefnEVzJl7HQYU5sId&DHtQ<}XqxiuQdY>lu0Pm__yMFZ{ zGk+?N1t>^xi>b&{A8=AqH^2<_JV!d83qR@l7TCt=6{|6J&9Bf{2x5Oby2o$hRsFR} zBy&|oX)N{?Q+Sx`m^hIOvaJ3wvNEr9&Sv$oKpd)yRq~^XdML=V{1%KWuXa_kPF+Ot zr>J{3mCHEkDoTko%_TWY`)$!eZIu)+u)q-n*_u7IgvQcA@fbr2#5{G2{HS+lx9yAQ zKAb2NaY_E}Zg`1$C1u01tZ*p5DvJby=K-QCUXj(W;EP%Vk#D$Y92fa&zz+7}w;a^|_ zA9|*n>qHjfhaP#sRdVD+HBf>6l!3oExgjmzL(yK}f%GlOg0)d>&|>+|+P4=VMPp(L zgzhKr;GA`^S zf+K#X?|T0_)k~@B518XM1a+|DaAt+I3DZk910)@{xg}OFiOF~=7yQu(MqK=;?JGFn zP;X3ACNW9~+q|zJY5p2MuByLhtbuBwjQxRI0_(ZHSQbbp0bPGWf^*&u)oqcls!RM< zJV;~Osl8|y(^5qS zhPF!)?mq5?5G!%|wMavl9AwmQ#%Bs(e_jZ=hp=Ym7 z;CnG^jbAbrp}=XF>>!TrMl53)vI_>+Lw&i-{5B%j z7ANKk=25$CBUPd&XuI9#<3eC-V%thak2@cd^0b!QjJS$mbKQ`X#odD>6*7cZ-(Kl@ z?P6HZd9}^_A*zp0KULCLkR7fmGF(KHJYsKy_7Pn==<-3s>2_xt?U_D@ZBgc>-q+X{7XZF~tBhnoflzQBDld&Ad_WQ^W^TdoA=3BNUqr$oT+HW*F z)z=oo)>+?V(&cmF5~Fk^tl5G~0^fd3TQAokJH@p@(RkZ}Rq0@pnICFVDrVZV7oM9j zUX7=VF`4CVB&>5uzKMuR_`G3~lPbSrcQPAx-_A1wWAT=VuoIb$YqYm=rmBcg4q<0K z8mPZieHd4}dViwhd*XQ_o7Be#rB$Z3eT;?039fZ=!})7oY_obSR$qRc5hj&)zEZ0m zmkJ4-pupnDp!i!ssd%Pg*0nt?+EFu@nc*`9LcYq@r^~@wpZ@+fObv^r#|x(h^^8(i zT4RkPEa*#>;3{JGRvg)&8sk1>UK?R4~v$-Vn+n;=2Z zr1}~AmX?=@DvIcnx_sHJoiCyR!m98oWe%cAdphrlPJ--kx^>o*z3&putlZ2ZlISu? zP)jZ%%NnF4vnK<<2})N07vYnu_aJq9uS5z*Ikz!NEL_;WNn3EK1R?b@oEgwVb84sj zBRLX^u0`fi>6hHqFN;x@y939w-N!>NKEy_87_(N$d&CMbGsG=v zVj|5@pUbTIN3w^(?F?%b7tYUU#8v0YY^NyIhGyP7{i5GfmF->JG_{sT)D^EM9sGPz zg7Mus8QG%X_|xQ=v3B>Itzv;ahNFDd{+}9FlE?NZ+qhl1MKUVenhlEL-RXyx%5vh~ zT&b$@bKS^JSCxJ$Bsl}zN>SU#Fz;6}jJauX8aw^|TufxN?)j<19NR8ovEvhkt#|@< zfBW?}`gz)$a>y+O6F^w8NZXXARPR0m`BSXOWrHA;0$Zo`uDF~BsI0DOb)9^(LLEI~ z`1GK7?25O=jjp7tpWo<675Xu)0O=o|`E^#oDtK*k{P)zM1!?k>2-5XW!!uOl8vYUe z7cqDz6SUa-UO)F^qsHaf>%(W?mT#b%llcJum?~~fRO;zXUj61Y{P$I1$AusS5I5^T zgLY~ml}pv8rp!cpupI8p`TUORo0?MUr-D1V2g-FGKl zOGUJNEmLJ?L1VGrZAAClG>l)r6~3*DPazVydCyQyR5)%UmWAtTKcqU>kxf0{0XMwl zsuM~@tE16ksIYcXvr;e}lk86}>3xQ|EE)lCKcQH~cGwBr9?G6|zat*^zpX)a$nG4{ za2l1=0^k$SSL{%Ye1J7>g(Z^^+7r^mpXn}Dh8Bh$RgWKbS!Geh9yAf>uuM zEq?p2GGWN5>Tkbz@&d0W20nsmU8&Ckn0wMMCqOORlwt_cpaL)L`I>F#c3*Hk?W__LFt4 zp{Vy@4tQ-tW;H}!v{u+&_XX&ZQs-GNLEgZ?W$s~a&d8lRY)d=!(0G&oTf!MjM|B4` z1tq)ExQfsjOSJ2m4;{?k-K{n@6w1p>WQMp z#}VRo;FQ=V+quQ!$O$EkCD^D*Co`S?R$bi35AIZar5(K9IYGQm@3R3qEBU2h;fKu{ z33lE+sVV%V;$&i`o6J;VwiZ|E0GB<%`JO~1`$?31FK4Z3Kte;2GEWZ#t}#yyl507r zkD4uZ*9j45y4U@E8u~RZyqNF#2WcrZ6MTVmh!QX`@P`~qppechY0io*{scZ9dM1kGeJ$9s%+`4iVrr#us z_?(ZSC{rI(Q1S~6d+{xDQGieEQc^6A-ruTZA2zJfXVzHXsuIX^99z8`!1bfKAb9JlyJv=ZM$wJ&;aPrV zYj<)#z;lvSwFBB2On%q%0{E;it~MuC^brxvfARS*%IrLR0Z#89*18IxRsXO8FTi*k zPw>Ip)1ZMz%EENm3ovkF`^SMDc|*RFw0fWa*L67MkpA!s@Ywqdo})i(9acFPqQZLt z4*1q@g94q}W&0{z2!>FDai*KIrkaFz-b_yS3_K+csHzvlB1=s=nI z75rM$iT*K`*H@`Wg`9|VbCTCQh*2+x_)_<=tXsbPT;s4JD;eEnbTUk5IOXtmuSWdi zdVMEdQ2z6q`&=W*S3%pc=%b2TD9M_^$Rp#iXR}WSEm|sI5oYje;%#^ z9g&6$D}$p=;N{NfRS?y1Zgpsm=U$^MoVms!T**g)tD>X_a;L{4SYi;l*piEcs0!u_ zP%fD#U*4Z|6%nB6(#X6xj$t2E(8~xJ>quAS+{}9cMrV(DyI=8+H7Gpz+*K2z;(8vb zcfvB6|CPHe2REz#kcVv7hc@x3yW7_90%zY_mvipYUjXmh#g3R4Ab2XaZ=dh}1t_j% z5B$;#CQk3W7kbimZGv*%V9%`vjTLUn`?TOJm)+Ywnmez&C()ttE*E+MxMod_gieXh zC15_!V0&@9tLt+eFIati@Qj}2_58zhmx=MZni--KdrvE8sd2J!Cg4ZkXI2s zzW^JLu3Yr_C%z0GNAOu|;Ps1G=4$?PEV0+Tml3{CaNqh*^C1FQ(d#$}>)|xWFMfk3 zc-5+HwHE-U@v0g}(`Czr^31z5PKi~9!iL`-k*oMId=`47{u7gQaD)0{y7~*yhVyeH z_13d@A+SqcDNmsGn^I|H<_+_Y+H2-X=gMEp6ZKz$81|9`JOL;x|xEW6GRYA_AVl; zrFzN&(+X~y++M$*OF8#H1=)v2{+VgRgVdTDDv}V69w7yYF2U@cTfoEhN-%RV@vhWY zjX#5JGRU8f$LzJ@)VnMyO*U*Uz|4b0(8Iszo*%c&^%LBO%X@L8z5vRp!TG_`r>;I7 zKHS1z2#4a~!bK(mMCJk=o?GJVCJT>I&X-BFq-e-G{+5PG(q}(aG%f}@iM8Y?>yZYE z!f5|orupQESnSQNe=qV3C*9}EEBq>cmB|?R0zhB8((X{*X`bAlPQ6mX^|3b)2sOh3 z(HOn}b-Bh4kfh4SG7RsqI);sYH3!*y~SHXSWJ!cKIczp}5dp(CfSquM5gPG3dFvJcpLPVcWgig`N7Y zGRH&{MCWN8i?yvAw0D;ExEziglI=}ixBU6wP1H)a4bLFa9~xb(_N!0sn{Vc;>du|g zbpye!AeKbmEqIMDu4tr{#BILhU|RIOfF7fVy0 zn^vGxL-Oh{uAz<;hfUdq`DUK790Iyd#|!)d*` zz6x_O38{72qS#dYYrb*5tn(&cbpb{5fXvT3Eyw5MvwCM$JDq8+=&-c&U52dl9nm?# zpjfk+fp@d}eoWwpKzdWix?Rwl`EN-DM~%Z`EwAHa6ew0?^6>HQpHY|KAxKb+ZlSJ; zk_GE%Xgh`o^;${Wt>o~TVk`-LOeDrEVdduWI*P`Q#^=jG1^lI7R@#XfW)Stm&%jS2 z%DQbZv4B8l28^CVyWsr5;E;U~+^5iwtP zrnr`<;O6+6cBa(=7vI677S>IqQ$LNp&ByHiJ+{q-^}3`*;u%@>$`>H1KB4=3dudcW z=B9iG_W8M4NH~*U|2h9zbiuGKH-rXvUH0?7U0$9#m8>BpY?UtifpF_^B3K>$~fJ5_u}P43BVnhhiWz15?p! z=EJ`2quNCLR#z;mG24j`a^kONLMT z?qP$bXvgf#Y^Km~2 zqE`D@{W`5B#_Ks>OgJ~p=>=Ga{>c)#5iOc-t(m2NPGGC#hmqaD@=p>*Ww3h=s0=@W z;IdAJ1C(Cf*|B40zZsOnrEPG0vWWfBh=*=cJ@cZ}NqcXhS|4>wbtDbcr}=UMqxz$! z;DJ_;)hjaRsBHYdRx|EfN@?)D42RF4LPLk*`o_8a5w`fWZ5(lLAwB;-W0$%I_>9-p zfr`RiPd+X$Y0$3j@Q$8K_M7hQ`i0n9zEOx(%>7o8cR(vVGTRnoQhnj#dmtyNj%JqW z!ma%$_H>YyZsoDVbuGx+8K-h8@h0E4V@i3^c9Q{oRY zU^TJKxhr%z_PH*;I9;Jp52iHvUOFx>#yV_Frhq|vA>UD#6I{Q)=%w5E=ON&3w?v2Q zrkl)mfR5*_Z*70y%*DrwzRsJ!9|dKQfq;XsGKCItO8p_>7r+Fk?g-S<_qrNW!QXopL-p)q91l)pHJ4>9W-A}VRyxaY5iTao;9ruellH+OM}Z|>W`FH z52KLm-PAKR&h}y1MQs-?jE(Cl^Y#Tmfod&=B=nP>>4Fyf-^ja(=Le{oz48>Dx?SC# zN1K1G$+vyeCF8iyPjXy&U82**4igEm<-}2)fIzLd^JJjUyy{ypR4%1g|C13m1qPon z-+g^LqB3lI%nPfGUmCi4ID*+DbP3Mg4j&DgQ{1Se%sn^C?%o1~^`IPCDDxpX3PxWdBND5h$w$ z2mcFfyF?RiFd>*$v-eGyXg8qTQ4P>BYt&zyrYb#L+9DVano@XOlum668_gD%L&6WC zTYL~Sc5PJ-<`*FAs&p$5&d>Ay)NK8U#=g%KO!7wBQ@AQ_c**}g^fLDD)e8COFAj0l zzOspU30(aQ3T~+-IbOd8Lr@+c10)bF91oe#FYKxxXN(1rWhx&_>>E#pIC1mE@4gxe!T@jjLe;?3^)(u!mt^l>B*~^ zn@*Eff<3IBIPHu!THnL&<)vYNGc)!28YuC|TxH^xyC;NBecQ6!w)Oh&1H|k*d*fVV zQo0Q~`k|-N1T!8nOMo)-BjWnw|0)rLsO$IdA;y0Bk88um`~1VOER0i!d;Nu^ttpzj zv!lx^|MT|YUKanMC(Gd{Oc;)9A-l+T4G%08eFd0ZrZ+PURn}se1Yk*h|oV*vAsI3A+S=m zN-O_PJRKRV#vwL0TbZLFdu)}m1p5{kF~#IWDqRWcy%}cZ7Rjow#yHgF9!i<8oc84? zmHA$3r(tzH%-!ugMyNXAo6MBEj=<&by-;TI7KRdhtb3p2ffIVdr~ez-Jd@5tPrOQT zYFAm|1D&6xEwV?B@+e9jccfBUh5>};5G+QWON;Ae!z&J)gqp=se}aLIymFzEY7 z+RGOJsntxt1&9bjrJ#Li@unK}p)R-v#WA$8n{K z*2u469_FaySC`>$^99)wWx$;xH7U%p!&s^!X5tblP1_2JFIpBTA%Q zx}ly%q|EPC zBbTc6bx4)7Y@E!?g+CNFsGIy8o92w>@RcmJG(29SdT&(_PP5(hv9^2!B?~u$EuBG- z&i7tBsBWX6p4wa+n#VR3tea-#wivwZ1M&! z_myq=s`o&<0-9LD49R(x}&kK4*4N<@=%0)4IJz z&^C|M5~*lgK{}>IHU4z;DFP=MfFiB7@ii{+EB{Aqm4wHkumS@?41rp=Obo&keUG53 zLE18LD71#eC)aj4k7krL}f#AyU%Ft)7b}O zd#rq3C}W6eRf#!%DUizJP*^(m(VxWAF>%znzFo{4>aTb7%?EL}ICE%k71@ z;!S(T{;3QP5uO{$SIMmC%X!#bEyz5$v;Sv?F%GAy-Db2iWsmS;*M_3-&vsIwwkDTB z6Us5UM<725@v;Rv2n5?`5SwPe#G6}PfIRwLRw>`|9Su+OANR*)+r(wT#1gv^HxbuzmNYG$4vDdja}P zU&_}P_^Az>66G^!oHyXYm{YnbuNwq^yl$n!(vQY6oqcp%MXU)E#7h-tJswzG6|mT@ zf4uB=V`UhD9PsjWdHp+%-0fj%*e)OY*Wau)gfM*`Goj72jgz7YvW#@BF*NeJZfvd{ zex_UGsJtjx7)Do5-wk!rxrT6?VCZ=noyZmZsZ{)|!x^EGSZNQXLX@F#GtDia*aSP( z*z;v-ofiMD%#Hz~d4Jke&#e9%96afaxt#D$XSXyZZK_9X!|{a?~by|zu5kHh##V=0FJ&{ z{1u7t_dRu<_rS34$(JP)FyAd7_^&aUMwoZ=51JclZW(c3t{B0mn9osvmxDk5Ao=(l z+&t9dx{Am%fJI&KdDpZM?Vs>N4?i^L@#o^S@w}CZHtETI;B~w7zvm=L_mvLp;s)>_ zN_APxhQIE__8*e+&Z>XMo7kCSR)W+vb8-TYLw&W_)=S^eWp*voQ#Mb- zC!WzzOZte9ygBcgbI?A>tX^d*wWh`OuG?YkTRZ){T+k#O^@5i?m7Esz-P_$GrVA+= z*8LX%(=VN?Ud*c;b;H+o=&Q-+5AU!oI)|xmiZfPZBad9yx$Li4Dw=ENO%{?JJLP)Y z6V`4{-la;0a+6Zo2ohoL93by(^nP%XxmZ9-G*YE8|EGxi84Gv6e{$y{$he z{~3FlFWQY%FSh5!=D2Yke?!-5gkJNPv(sA-$xpHNHEJZ`8+b|sp=OU3fHX~)@Tl<^ z{&DjQLi9OLWzEa!X*bBmr@Jd89pU>GL;AgH7XnIq;5#U7te&c=moL=UZf+lwVtH?&}Vp!XT1P%StKH%$Fld%9)&| z8npr^%NCM|5&P`{=&`A`xnXk5ZP@vo@h$n?Y6_EZXL>2NjoH{)?u#y0(F&6)&Tv%n)|jx~=eczkT%pxgN-zt7Go97iQYawt4p|Cp1h;?e#oU25kP znQ> zBx_u1+MZz}Nk+(FYj;B9*jujZzO{d%$zVe5Uw4PQ z%=v81-WnR&21T3a0gMq^doH+p)W(x~=P#ILLCAHw1B3au%`^ITdYJ0_5^>rZF95H)^Dn!OQ-d3mXF~C6#JLSOw+1OAt(5sonIhE|WmRO5^U+^x z`ZitjRqzVa*3+SWld;LSgNX8Go0Hi)4FH8wUkXb4rve3J_3yEY&pUl1QZup7>my!) z(kKcDd%6GS>f$#X&J=Hso<884sJ^SxXh$&yPf^V8Fj)7UCZFn;E&43B)4S*iT_1M+ zc97T#Pe{CH87;FoYr2?ZmpDRDhO$1%=2XdXydn)mj1%$o_eS#E(nM{I;W9F0jeDvc z6vzf+8~fBt^uXWgp@qM7mlPZ4J<$>{?YNxQ@yUA|C3}SEQtmZ=ovaB}#?eRw(V!Tk z{40I97{4XbVbS_5{4ETXFW&HL)6{QPXacLxFYoX!clt72V?k0@#ghq~P>{MbZHQG0 zeNk1)dpqWWpHWp3tN?u{w+uG@-Rub>LH9V4g}kPbC;8YPnt=5dg^miV?7B^z{Bc_O zZ3Q$8jC*vgSo>@%9%agJTZg49;v@3c+|COv?KeADV%IxfLSvBJM!(H8j}wB+n$1KB z-L+|KmOQ@pB9<&#Y}PzeF%ja8PX6nH^7-pu?6YmL^EJ&M5Itj<;;I>NU02a6byvkE zg(rl*wYw5q|AL*;_k4Vg#3Ln2?R0(tW<#VlS_udcM+h1ILW&i51mOz5&vA#g+i9$# zl?+DcegN1{c#K0>)b`@f4^ff^>ma!yn1eDgRoKgp)gKvDv}@s*w5`mW-o#MK6Cn>4 zvF6WO#|7cCjLI|SDUu~JrQqclR71W$suK!It%bJZb%u?cSGZ%i(0%T#bg&oTNtGaA z3VqW6Kh{yW_I_MPZ-u$Pa=z3pnLF)F3t7dovr?cR`W?6a*`|Dy`kM{({X2#^f1L>R zR0&$Neo9%!)WrsjxW`J`>k@+D7aJ*j2*) zM*A*;2lxE)L?+}bHAQNPwZ}j)z1^=>oB%DxHFJb{#C|4}_1QZ8jAAC^0u% zDLzh-h?qONnZqfT3!M$kYkl7IPkg5_oah2!oFrE1)bZ{%!Q=B?OD@Kj&dJhz2$Vk5 z^WN{MKbM6b{+b}1OC9GlfwqhDo@hFQRZZ6IOhKN|s(u|;2I@ZXuCA^)a*QsYo}lw~ zuNke`I4u&9<`be2Q&bUfTU}2F{rbLXBW`mK2NeM$bcr1*h^A3Y&chofdQ|Q4#yK{=X3Z$nubhKewQ)Spa0+tF;uwhNDUSu~ z`zr<;yPEpYQp5s`0DypN<&*S%p_d)PGzTTu_v!OEDKbEX3%%@rvgdUI5t_zSNvU5C zOtw~b*DXTk=ze`sEiJmgI{TPr>>(TUvrsW;H{C{WuGZMlR)xg|C1y{ajI6=uE8eF5 zSu10W43DK01}lBoMh{m%a52N3Gj6vSN!zQB>BtO}{*=u| zi7TF6>+~gm3a=~2e`1%e1Noe~$~)%vKr}+vU%GbT&L^#1-4FJ&+pAy&57pA{JrKfN zN!LmKwa-P#>4<~BJ437nVNHi-mvj}-S(N`_0yV7O}VxyiM=S`^ouMN~$0TK!(?G&uC@IzBOr zv>~H(sP0R#!|h16qaEb8-C7opz%-LzLF;1q3Ta^IXWu#1r=gjk~%J)Q~rv()tMs ze}CA^Pj@D;b#ll=fZNHI@WGYyCEYn!>khK*!LrIwxY?QeH-YX8vXuuorxSBkcs@)+2;<^%IBT~+18c{hS`yYdSR+y#*k zcpqoFiHg9ncO5xXc;H*UQx0SQ3{(xmpKE<@nD-UiGTj+b1TWgvM~;ttM0iK$G)vI= zbKG2$`0i^+Ic8`T4uCLW*uvO3mT0$MZcfG0b4!kSS&B274OK`a0mC&scg{E;aoR7K zzDiR0JPF5M^CeNJSOxSk_C5Vst=`%3gTQyb{=>HN-Z4tc6Mr>c9sYl7^%X9L*7E~$ zemTNjfkwoA8xs}_P{HYRhY-?ax()6`R|nL&#z>Oc=jOm4Vc-QPXSvRifc_H`XeP+d z-!D+N(&5+w0ugf<_%rJrkr%q&rs_wyU>~3^U)t{fs_5Q>tr+&%;i;ClN&7mJG}vZx z4kKwdS$x;;?;p@?DFij_`ZkdimdD(6Qr~|__87)!Y;3N+DBvfL`)yE(8$8II@dD6w z3aN6OFtu#0%>S7?{IjXdKE!s$Jd1kpA@xhcZi0BE1HEo}k2CDp4smtfkL(fkc9e&9 z-a6(rVFNRC<}C5GG*SKX0!%R_h{u4_R9)?_PW!_$@uz`2FZ%bVYz4hU|4ts!Z?B1m zYoiV4EB2+61@=)I+)niDKnMow)o}%CUDt!{jxE2Ze6wg+Rb3+N_=Iv7|E%Y_C_8== zvqHARr^OstBQl}ef^?P2=~Fhv=V_}KmOkd|d(GHE)i)o66(r!YBsb)l`}n73kMS=} zg^rV4EZ%99MO(a+SI@g(@G74x>MS$QX?5PzxEWHoUA1$x2kBp(6<>JXCXC9Vqh#}j zy;ED6WUcdAx4PJgvj0fFy}H!{YOYildvv-iV{L>e>^$8yIJbCC-g={id8faL5_zTRUQ6s;BuKs@ zOgs9EYGbR_K|}~P!LnfFH0C%UIeN^k$GN0-HO_Mv^S)y>x%S5L3*495leLSV8)a=0 z7GKUTYdpQFPZM0)oQxw(E_Ak2PI+%NyGAnu!XB3g5XlZtREH}S8t^^KPtEKC7Tl>M z3=q@c)z51hfEr>+Xgqehcg{p)%WbwyV8XCf*cV!_np0yo_&H)^#%g}3O0Lt0HE}v= z_-;nzXjWlww&OjW$qzP3Nir(?ZCeZpKsgQG4WUQZla2FAo9zP+Q$@M8Xiu$e=t=S! z)^qgQ$YjPDdgb^)MoNe(g?%Hct2#HNejd5ob=7oIAw%rRCQcz-wG_8yNRpz6@|uPf zg#T~~@~2SY!ArI+w(1brjN+S`KkuehIrMl>+jB$WDPh#7nPjQIVKVW|!Qrt0?8%^Pt z4EIww`dFnJB&!vnAn>hVJ4NBp5x2%Cj5oT_wgN~s5^aS<9=wGr7xBnkAc;5Y6n5&a zE-VcOdAS{po3puoP! z6z^iGGXuWB2I`?4@Rg3$nXz5s6D|TlQo2IJQYu}uh46&!Ow}cBYs@Mlwf#44CNZy| zETWEgwAo?4#ca#HBM|YbV~Sv%sZwO+h@>0Qi80>7C4M3pM0M^_T_GO*8Rr_;y7OA; zfu9zweG^h^^_bvY(bp>kHTOwwU99MMe?MnveQU|lQzKz`Q?r5u=CBK~*;R$xgG2w< zgQKZx?ey95^wZ>ajDtF?OKzjB_#UHRVPosCzBoVEdr#~A!JLXD*^m?eNKfLa| zno9DbZQ;`S_};Ou+lb-(p86_#Y2fMY^Y>QzOizkb)ReOcM6yhda763{r$L!WbHy+N zva-*Ra#D9WOCA<6KDB3yHzEBjk$6)?1egZR^zG-RG5txsWu#N%bB}1aRFODUms&t7 zGWRfzN(l1ykZ1K_L6E0ti7@ae9L=DDeNEz-_KgZLRk4DnKg8=CC&YWU#0M~JH!6MNUV29l zN$2_mHRniaD{#|n=gx=`ZI)q^j0yckRRf1>kab&<9t$OM?Z}(Mu-il86ezILG2^mJ zw&5nkCpL$t<6+Ro07Bq!@XZk>coRzCvkxST;T4n3J=FGy31zNs%lnrQ8Re!i6`l@o zT7`?$KemyU`30JUGO+>@@k2jtAMtxa^-xx_n9MKLE6q7;g>hpg-|?R5c5W}EOkWat zb^A1iY$CqhNk(F-US{rM?T~y&tE^6Nt5+`=b>D#S9UJbDUs~V*h1M-G9WuQP1`}`L z4oTAH)UrQn)|L#ms@}RLe(d`JA}7J{<4vKeDW6;YVnzEjMRdrYkrZwFbgQKz)o$28 z)LpW0*_8ZU+JpKU)0cAl=S*eI;io9p6Bkg1;XnUpwXHO#lE7*aQE~kRP*05lisk&@ydT}@*r{Gc-maUVbFQG}jG)VvyV;fGAI%Nn~c zPXpCz*_+I@Z2%_Yv4Eq$%lg%tokf+hscPV2$OFen#%p1_cGis%3JZ?P;fjJp834~p z=j$!mH-*5fWX4f`%=IJZL|VxHVpEF47x4V@cXXEgCrUI|!Sn9^tg1n{7_(+)sE!1T zd)F6Mx@{wQiZ|YAGtqsjn>ww7ZM$V;fW&e|b#3@6YEYEAtoFCz&k_HyR^}~o~`oj)~5+u63n?o9cKpPDzcRo;#VUG3SKU zqp8*Uen@u4U)1GjydT6=Nmdq}3b@_@btmkJ>T&p1opzqipGSVimcY7!?c;HFEe1ho z0s-xe1J=ETo7xMy9X+&BZH2IoJFw*a=Cb&%k+11LQqk?VXLjPMpcW??J%0MCJ!|gm zk~L4!qZ~?DrFuD9Zw=Mn(kd;RqW=J@9V{iV$8J=y%*e##^sZ>pUOLNfsuz_@`p(lR zXADUDKyqMvS6{`o8kD;Fw=7d|B{vmapg>U^06!|o-allE#{j*)md;`uuTOfl zWR&+6XwN)2F?^Y1(>h-ieI9u4!1|pYtKxkC(&@ZYOq$;hdskNdtzDLA+!+TT#WZJ4X64N-o6bDI*F3LU6NM6_0wzvJUTaRf;&$;L1HIusBW_m98`?{)y65WG zKYG&op;GVfV1Pg|lU{JL-L-Dcos|?Q+@uLDJ^J%ktCH@Lqb6Cy6uWUd{{XYEqVXBf zyXv-`mu;I!kff0!20btdp7@}T=i7F_qOxW8hT221IFT4Ql;&KHmgs0(CQk{ zbY*E$S_+UNA_*UTX|do|E$M~9ZEd@RDxmJ&@9pxcXVgX!`IgRxFHM$d);VbN`X3b6 z-?I8GW|ePmye?a7phd6&l?E^lI`plY)zWEiY8yd+O!>F zcSZo~@~(cd@0ruswhx?}SQXq4y=7fb#FaHj=u6YTX2-c(`y5{iPde*expT~WKekkP zmS8~u6V#sdUx^F4Yu7)qz-<$-^B_sw*(!a(vS4PumHE8dm zCA6o@7q+Ap3Lp|sCT624FU=%hf*sKKc;&N$;fl8|U9uKM){U;wfzVbfx{ID4t#-24 zEERpIROUW)=(V;iX)Y^Rwk`x4rZGR#g}WAYdZyKCEGjcwNJGRxi1s{+QOg*olC)Kq zrJS5_Mf}Uj#IdSfLlx9L@Qs)9n`v>?XQcO~(OeJW4X3kXQ>4<~Odz~nBtXG|F&y*W zy>IG%A8$<4p;ov?7_Re!OKIo5vK2yD8!f02w>kVyNuhO7?P&!4GHWCpR34y3HfmyJqd}h^cMu2`W@T5I8lH!j79qr@e0CU$f#HO^uE{3$TE~ z_H8)~K@72o@9$n|2B_Z_bnNU{?GnVm`I?pqTpIpmJ#vmLvB@3XqnT_qj}Y>gb<#v! zk%0YTI(ycQUWu(Xmr^w-EnIzswgtZPO|9_u@Y{ikuwo=hs`XbcYBZ+iqUO_YHq&R? zo=H7xYL|0TPe-4eeiD{Ei)(3n7P8uA-(^n1B};QwvXT2pV5T@7YM%`M0EAmxTMpo0 z067)a@xS;Doh^%M$}TB!yPB#}si+$9#ZL>&-6UXgE_!YVD}#*HObXn40EQpB)6f~G z2Ib-AGh~R}QG%#aMrI?psU(sqm(J`(La0Ft>S-`DM7s-NQdP>3#(5QM3q@yx)YUV! z2n0bqktS&+WM@&*DssjA%aX!o3HzwZuwMDaT9(Tu`-c-7PhWbDAbNn4o?|s`n=5L} zS6O5T$T=M<1Qv+7a^B@(xCy}@bvq(%CL|FbFO@|KNHYPmRxS+7a&4KVknU2z6EY1( zmO!HrBCgqOfdHHdli&JMvH=8vBae8eqPChvO0pyDfzMf`C`jl!(>nmt2R`%|m?4n- zi0M*PRN2?NuhPH6_HrXY^8`&9jCblPW@etMh}#MRU_=6E{k0f^52&2y6y-{(00Ic>K!w8Oo`)1FToQNW zfJ6ZYq|nC)zE3pHr)Y8{5tsiE7q2U|qm-KEe$aT?cLl}(z0BCA!`|uD;U1Cjt0{VhnR{Es< z9;~dcpTq~b{{X%^n*9Xjc92?6Km|0;E@k`4ea2D(dUzw}RkxB`(~E;9I#Q|@QdUBq zVxG~p_7Qe4@7AA!x3nowRO(rne6T+1zZ+)T2%d(6TnU@pd-bY7+)1}9H66Vnw?%#t z<}Zfn-4#qA26?T5>dt0;>kot%{X)RDx!5`4x(3l4z$Tlg$eVrz-1j{pOmmY+ZTV(K ze)=reZJ$^ylv&k)*^~35jSuc1b;xl9(z6BxEP=*q(P$Aj027+7;)NIkieyti0)CbY zI$!KBqa$|vt?{ezgKpZ|+^!A1F73}FYzT}Q_OF`vj{sW$j(zLtAL(Rr-W&8>5;l!T zjcyh4mE(A&ixi(gc5zO2csmL>&9o zyMY85BtTJ!imgbDa%51O8(sid;aJFA0Zp}(I07Ws93R* zPB9!&cfi_6HvJ?rl?Q1>Nv@Eku(bj8bg7&8E<S^~NS^HdyZYxNXa=Vk43rhSAtiF~`#sQuLg={Z> zoo5=PkS?i+gE@d}QeE)N_SV;>8aFl8l1c0-FX(JNrq4E9G{V__w@F3_wOLMZf%$#VT|HC3Ww~ttk(Tk zs_kDl^*cT%sIjdby18uTmlsFxJN^rbgnwG6ZQ&* zA7yw3hmyfO&oFJ{X#RbwO9nKGr|MlsNq0rp*z9Wjb53;YYR8&&7MMw72HTmL=Mmej zaBelW^(I>564=6-%zIN63Ow6?WE@UGsLaS}p;C;bgVY=lX|3JTzpb?4cM~e3(g(L%r%!eC?oFUKv4isMPi_nOc8<|- zzzldFI&au;mgtt!-<=H50L*`$YfI}dgKUj!T|k>q6ZTeq&&#iB7eei1V5_h|1|~;i zR2vLXvXOxd3FtrVsI-}9bB2-Wycbrt^}nrnma};(6*sm(90=(htI|J?=#;ICcN1)F zFf;f2=DZe(Uug7zq)M3Pt+l0Ayk6zkozQ(%&&|_EB;2IWL(zJ+UY`=j2(7+Pd2_@x zdMjVGe>JrzO{7-^Vq>s(V*1=q?{pk?M$$ zM9<)B6|48fg-5x)KsN2O*Y4u|i;nT(>daqN-m2XFL!@Ltm zZC3sLLKg;hFp&Pny2+yO{{RouhGK2pcyxW(E0M=s*N@Y>I4iw{z$QyTid{yc{oyw* z7V^*{%i%{#CxUb4L@@e}9-cQ0O3y+4scPNBX6RQ&J4gp4cKKGZsnF_fdE)ACFaf|A z#A6lYg}aKILxP1vmFRwS_b%!$D_mwQNtVtFf7uk@PO6ilxcaQru5q*1>hCVX&vX`G zWX)snpVhT4%-W`cvl}>Wf@g~0TDx_v7B4XvC#74aM14ROwJmK4$(ReD%v593_Q9(y zpQ(Iov67Cxtn>eu@FFI;x@#I^s%xWZVA8KV4%No-B=Hldy0$NQiMWu%tyiYg z>n+{~Ayk4;zG}!|QHy=tnKJr|mPH?jr1?7jJ*RC;i|W}y82%NDL#Ffe*X^h`FAzn& z=h8coSv6iN6f#?35<>!bBehxKI*VF@!u{c4ZHW!nJ*w!!aK}u?KBEq9s{Fo9Uk=*a zeOCIAZIVO^Z-`RU>TReO9{UeK={;hf!u1N8@K~L@wuU1Hc&j`^NLyHzjo{!Umt1Vm z6k?_jFGbH@Y);ewy|7w7Z3~GJS`7&u}TddM@u4+=YJQy>_f=Y}?V?X1cOb zoHTl|is7+KXx7k783uC^#ZD6Vjk1jRz7!&#+^@`1GD+M-M^5z$*Y8kO9E&`O@5Bu${n@z~+jg0$rT3>}eZt1skd4e;OmU zNw-FKaDh& zE(pRgJEyHe*glb;dMFSf-vQ1tX;?4>{{V#ZL|=j}HMAcsh}^t<=rNB@pco{?QmP&I1_TJGRY~0>cb;kk89j3pR6&-4dqydd&{0m|9r-I(>4-PL8TCxZ zT19Dt1WKpLa8VG zQG-NTTb`}H@zRIu3vBFbWjA7aee_dXDs{sJz}9XlWNU!pI*!$NBH;8e9>SM+w*jQc z`y(?;<(3rqkF>=5 z)S9wR#Zc~Hniiv5P(1|CzA6>Cgs?k@YEyBZ0xSwQVztXBm{h|-q+;!p0CuZYJwB)> z^Qx|b0W?wu+CKpPmPB9df1>t~59?ksKj`$e^KSHp^$pR1HS~k@v9bQj`Y#(y9Z!t> zr)HMEZ`~*y3zAl3fPbAQ$=1XC7_ZkX&R`7n8KKfb{&Y(cNIZ1K4xr=ZL)gg@HsnVb znsO8f40z4k|aRX^P zqLi2i6Y{4*Z`^=MIL|{I(_l^~H5(A2gySNZgCAr`jLvC!p^LQO&!&I^2yxbPOwc2@ zQPP1YJ6T}=00B*FV^oH=vodqg1H}v;hnf4SRSwd@U`$Conqp(GKZO(*Ugp2Oa?abDYHcpTM_XxkoQZ6FaQ zCnu#+NjWA7$*XlFQ%@YN2IDiv-~eMhQZ>dbyLPEq607`cMx7GtA{A}G`iRIN*Q@cb z0r1;i4X4yvw0y!K!OK>8=7uRKKPLX4)AIG0=b8`lt2}ZslK%i{m=Px=Rllg}+e~k* zr)w(GU=jv0#y9{(nzu=$yL$fslWy5#8Lwrb4P(IX+4WeraGN)p*@98VN4Pu@OQ_HA zTCZ~MgVW{KDJJTZuesyABVVrYtwGdje4%io+j929?nY9sgdU8fgY&H(72x*uZm)9L zTO;j2>(GDOM%RXI@qg5f-Jr3SY)JR*HS6>`Ht_pDtNCx{T9$idNFa>o?y9s`2PSJ=zKHadVL*+zk1TW)&dD1W3L|dAKF$dDpKUL{U%*s zTH%LKd;U*nnooxHgG|>im9uEN`HbK4W2=4@$hlzKK3myqX5Jx`s}bCe@n6wAWsTh( z?IpX49_(P?FU*?rT3-Ov_?@wJt=v}Jqj^4(zb>!oZG)P;O)rZ*FxWfJ;>Cx^;>0#Ynw?Y8G+BWR@z*b!wl!b z`<$k@6q`_5(Sx+-G2XH*me}R4L6`%${{XVOLe;RqNWp=)e;BG^Oxh}WjE-leO-QFE zD|;%lVQ0%Xl5ix5{{XU_Y1eB%mcTiHSaLtlTC>RV-(h7!hlb8-+gC4JCGE1Qk_liB zPBTMjQHGatD!FH37F7jfG268=3pVdRsVYUDYuqI7rvdia4 z>L3bBXp^YTG-`W#Vnc5Tz{c2+e)^*2g|_>NSv@yNA3DC)oZKaz;8pHu`4);DoA=;k z11GP`+LF;ZLCsr5T0()1vn;wZN6?C%qCtMudeJ8?yHrwG6;cXVET5unL1k4_X9czBK zS^C>pDQH`|mhwpZUjFrMj|59>_ix-H6L=(KLB(@*hf=29+t;_6vgys1C(ZIfKqe+@5wSY3wvfqDEf_3&S3^ho(`hd=TLphtGrOL8 zR-X{e!Y-NzVADv`qR%rwtGg{WpUP(AQ5!e}s9e@!*t(h#twmqnz-b)ZpHy$ec zkW{YTVx&>q-N}umiGdWbq9Y{MhPTR<1GzO>lEe<3K;%^7=%P@jSLz^=um)m?0D{DV zX`68atPEm_K%hPb;UjGg-pI68I+7xYfeZ}BM0BDg3_&~}YJ{=DB0E!BV&QBMV{ya@ z6ilGO5%`LRbNK!B3kVyOH_M82CICsy43Em2Z>s|xD3zQ*Tuje2(7vL3K%u5JzCcl< zG0fBx%!#8Q5=bU0Y{nxa2BL&ZYGkYlIjb~-_Ob!yfLw{=t~jeS+lAS;9-=U6RwTGS z#eR>4H$JI<1+LHlzv9AAapD*2^k^j{sP>xt-}*f+vi(y&4&0EVSK|VD5BuSIzen$9 z9*{qkNgQsXzATs3mMzpPClSn?iXLa2TH9NdJzJWdP&sT7z@jc(Uq#i&LMW=)Q&t#j zUaNN1zC#rS)w>&x)9+KwK!0T}-p3z(5QOIT&`x-wuaPZi%i!u8!*u6yRthU&xY4wU zBdo<@@PvDw9j6U&D*0f?Qfqh!KX8G?4!n)ns)Uf&9LKds0R56d=|PZ!THW86G_1_r zuH1K;Hkfh(&X^z{<4Xmy=Mlg)XjJ6M9jd#E2>U`sG?m#Oq4WFnvEB0YUqzq{3*I#3 z9-~ln%9@I;T*hCQ&%)5%K9l7N2 zDppIiBDfHGZSCHjnV1$_fID$R63QA$#IFbCM0tRK7aheRq(EF@g!K2QWmE<0$ch7r z+9Y;40+@|}2M}AZ$fLW$3ikr3ViYJOk_UM_3ZAAi+^B*8kMd{&AWDcC$ML9}l$Inc z98dG7^QzN12OeLJ>@}g7^wKEx$PmKes6*jQ}holN1kpW}x z%|LKvi1wo}Bmu@x6ugb;5hEu!JOi3*gKNW`ppDZKc*Q6!xHF*(F^+20i=oZNCHDGf zB$3nb{uKBc+Sy5l`wt$US9z^EZ9`hKa>B@Kn4ZG3s8Z_NLuMoX+UaVvR;kcb8T2$ z9L$NR@QF3wY4C;99nPw9fEoV)KZPa1v72KZgv!n*?xh!qAF~@_w;z{SsLoh01h`%g zwMi#p?oKparLl8Yd33hh`^Fz=_31-XqQ9oR+FO>J%}zv2R-Xw=o_gvFDxw*ZM?Ipw z55)c&j<&o@PWx_c48=}OXP$MBDudzw0NK&O>F=oNWtu;lHT@1hfoYoK8_i>SsDiv= zI#;MVYk#WPvih>*+hMfu1anw?D$1{i+C^Zlq_wv^PgOP5aBS(Un;H_$u#<-0n|G~-ZO#C;vIOUVE7f?`i&^3NeN*_4j4AOeR$EPJZG>hoZZ@jC!-H%NA%Gxe zAo$G&sjqxYZU(uw*#I@R^#Z&y_8`HpLGfqA{u|=nE;X9HJ*y3HTfeEdrDtnxsus3x zDBoq+sAq{;Y#uiC|gRi@NFiB`^~KxekZ;%AUO;%h%sj(zb@gJ-67Fj!}ib7^to$Mre7 zon75hAJ%n>=UP+EQ4*-1XBF6W31zJKavOr)(#ou%it!2w8=86!nXfhB9v!K_;*qQJ z$C!p?z#(}%ef_Ja;=@m7<*Uhd^{Z;ZSy^`}1B3IWk}J9}yAG2){tWXqPmikl{{ZsN z&w_k4uK3#ili|%J-8GB117CH0O4_}9OszK&8NCAJeUQ*kNjRhQk@Qb@;m;O(9v7o) z8e6u!n+baA3$E4z$%VrgMp8+SR_p>|y!MO46<=Sgw|wupXshmA74`$<58Yiw@vj!~ zi<&Jir^R(zt5$3qRxRARSRpZtp1^(swQ7ccgN?yQW_k43y3C4GcjNof;y<&V#<^{3 zbk|ncV9uz(IZ*_F#1IT%5-Zl&@ZArKct4x_Egkc9n$QTuDy*G@fM!5Aj7}@5`lDad zS{G8qr`-F2Qzm8{_uWSdWHs_Y;(=;nTLSbPUtYf+_OZ;;AB3c_c;dRAWP&ker}>h@v9 z)%GrAnaA-j3G(#^P_|#lEw*+x)o73lL`fNgn%LeCYWIg*Heg*QL5Pa#>h3tu>NLCG z%6ARr`Gl!q!HI%EBu_lm`dfeS7V_*1f`;KcqhR!^y$imwK2ewm46oL>!pL&DtC z+_P}4#r28a4?mr2x#4=t77fd~V$AHLOcjCi3I6~I;Gg!_W5qO9udup4*dUTeAa|~f z?K0l*+j@J9h`wIMz$HO5_Zh7#tA!@f&0dc;ImJE}j|%Cj)u}dg&f?w}q7$-sz|5cH zTCR8}i}*$Hrtyyo*643J#l2pg?6XD=(7;T4Qd}CX4yB&ab#b{t2av)H&v92NxqXG( zgb?AA0Pk~waO|wIBOi9T708+gG}1XiKWxpYmCPh(E6L%M^o+XQ%CT(#CrWp z==?LmHM*O&ZuxhurK!1O%tNm$p5m}uzWRIXa@*{5AgCNn*1rw-r{WI>*5B56SBvX3 zcQ4_;SH4s+-5{RuN$0uEM-q+v#*EXnk%X<=S2h+>1mzqsi6U{vMP4nopjsBv?bdQ( zEum&}*a4D#s{7i{4%PU2*&Y(9t4ptT=BaNL-mMr2Js`->PSII(#ggvjyKxGiNen?# z?0Kg(6zvhj-FCkxXU2XF@vj5cuZ8&MhMgX<6&~%cIT@^yXJx>ofY3ukoDuI=rMp^2 zOKEJ)_8}ZB?rt$3I^o;7e%r-{xK`Fk40foewXC~s8}&<|>KKL!S^)se8me%N<-QGg zbF2$X=KXMXwVoN`1YNzPw|eH6Vx*J^#k#ns)c(~vBfj0!vDgIN!sL=b>DsJ$I!s!Hwn_Az zPgJ|IX?=dDjsD8`gF}l}2uq){Wj7N(!#?%DPvE{d+Cy_mqTA&y$8~p5Ay!WW{yb6f zKZv#3olVkpD6&jK435Mazr%ca9?{XQuiEMqCd34QMoa)sKPuCXIJ0;;UEj0G$Ghxs z^nVF_L8iV=uftl^-O9U5EU0n0TLzdW+2EKC4{lPBAbD~F)?w)^Z;kWjBWq~-&NZ`;+Wg~t0tqud{W!DouRm{KGz5DkzLW^Ykt_( zBa1=Fwo+yrBp$;Dr?p}6FC5ehAZhNUtBTOd1jzO@yK&!=a-|Dw=rF}QVuz&NX6+PoZ`wJDl>KjANkHR{)GcxtV?V4e4` zrL|%|b!6qEAa#RQc$dQ7IpMlB)@!^h+OXMMhV`--5D36&9Q75h&&D1nZ7d~`Wch0c zoV3Yl97uuf73bXUGFTEo+{A*=DpGLphWjBOmu7fqC`llQG1j_13Gm;FcZ9@QJ7grnWC>HHtWbvJI= z)9Jj&w(5))>R^)q12EEKir23APsVf`&Z5<#Z76%Hw?QZ*4D`V0)f#?b3 zR__k*Zy51qzx|!z*R?CBLibzFk7&9-4BDOoByPjvrA^EWYEd z)m4U)dV886UAdMURB$Omh7eeiamN(IUAA&}FSkl7*rhk*ZLB4%I1TxV9%&!mBp;O0 z?<9d}XQ@3Y!a$c|$F3Gk#QGy{#j%Wf)W=FL}jjKX3fW~G(?aexs21o=SdM18B#9;lI@D%hB4xf* zeFxw|2XF!RrhwDApaB4F{xoDW5%xq-4Tx4G9%rRYjd>uE0D(0KBu7KdNKmFs#yS2K z2_Q)z{OJQ2s0V4p7&R_HMG(D6j!)0EMHAESq7?1*9-PoMwL-w%mLhYE)%rIA@~G4K zj8CT|MNqFMS$(OMf|Khq2qPJ!_#9<&B7(O7ID^Oatrstw*CCGSJvgeo`;5!932(dF zf!wEQatn)Dto;684b`&&$A(U^;l&Y`Fi?42a)hAc33|9D(?ml_`Y@PEo{|z zMU?$Ww$)`|aB*I1Qmf&9F3WGwtsuyOp4I8B4MTVu-?x2KD;5*XR&J~2ai6^%KS*B< zPYdNHnaJ=P)-Gw^Lv`70tHVH&rheDGb-Zg*_7II$zD=ueijWD$E6@Bm_bzzG;7CG! zQaPo2=8&jmvUb$yaqjvJ-d6zj2HQ2M@SA0`NZtk20 zzi@hs4nT&!ZS8GMO`svVJS5|V&Nii}&J>*Zy zwd*vR+t=5`biP9!X`O>LRL-1xo+Ln za;1YRunw$M2?P-;y{opq8v4Hv)45d_0ztZFMOCWs{ceX`H5x@jwI$x*-W>8UYpLOS z?KRyct7&vQ76J&2_N?7UP~{lPJ35}7&@4G}V$9uFpTD{0E$J-jHKFu{wPlnC1${}8 zBzxkz-YekG;#RE@e2X|NI>)tc)%bhdxQ9!0Stt(DtCm0Et`Ca%_N&45%9wjsEe)ZB z3F}c)o_80G{K%Z};piba^(*9UamV=^UE!%?OjAdvYj-THvylOS`O(wpynJ|mt6Y3G z&AU1SrH+e|p#0?OE~tezN_oJ0h&E)%5=D zdL1^IwwvU!A#y>$uQBlcr@~WEmv7uQUfQ#6x=SU@jjI59ct1HDSEIe-+DjL0-P3Dr z+u?vhWf&iS<6Qo)4N9@C9luHHl<~ZsMD6(5Zl_&qK!(}9y_{~^qn~3~v|5i9y?A;0 z1=>slwheF4+O?@?)j#cg@;4XBo_9&$=kuVH<=5mw?7KvC46>sR<*uT^@) zYHdB6v+E7ao~E+vb++_>vulfX2?0-El|P5-G%fpGKKl+p!QdJspTgSmD9%5%_eNeR zqWgsrUuah(z@Ot+g#DkS4Zs3B0a?6IxYH``Q@w#8C)opoyWX$U0p)(q=()4f#(yE+ ztCIN>OuiGmvV%t-$21;cON(!xv_R`hJUm(O<9o>$FFc|lSt5U*YU}Ehw#y`i1j(xJ zfpu2V2hyf2QAQ7tG(DS=F*M-XWyD;y0C5tZB(0F_*c<Vy;TH7vtR2@jv3N1>p7kkYo03WXXZ?!dj}wHlNbnV zB4daI(-&*wfkP26M06C^y-graB9awBfDdSN7S-k-M!> z8fR`wh|OGB2*K^o6f{jv(2&Sr0Ae#tQrTnIIVP4&nIw;H^nP7BP{kBjs-4DWN3~5F z?6@FgnfVF=o)X+0WnzoEv>GG!`xC!TLOAk;7;AjaUXRSlh{{~ zBOslhXnWH;2$lk>X18+#4ee0M2)Vhat9BReLnQhPQk|nLWX)QvtR-<(T-f3y%u}%E zXV1^l#Ko`-lhZr zIFm`8Y%ljQ{dr{s1|*UMiIY(ZnA|q}sF;%@)IF(51_WcNp>Rrq%e8^Q??7Od1DXdo zfJbUD0F2KOLeeG68DC?osNl%!O66VIq|iWh+K&PEW~H6K-+R{ zf+my<0tp<>GeixrN#=l3v=(K~0G{T6g3?@*F*I2S7&$cxv=}%C@t}2V0DuLsqZ}Te zIw+({s4YEe7Enkj_kTJp4$#5}?#EN_MKn1X@V7m zV38kI=c%hYflL7)W-&RSO<7n%6ab<}&op=?cJWM4rgsK|fGL&`hA_lt4_aYV z{({=L49d?zk7_Ld6`p;n53)JNNi|?bxdQ@B0!#t@DPHZ3CsbExk-j4%B-0CIxkpe7 zL70+0?zEBufVsvGN|y-SHnS2iryu9N9zy6+HqHi5@T&-%nd320K;VNj&uV8`CJ8+W zp#od5CfO62Fb5gwTRbM+v#4d%DKH3$h&?M3q7pYLGIAy-@2-}IO@B?OvvS}T*6=$? zz#^&2*KXOjq+h&FtuBA`*Q@ZW{ugj-bkGqQe8nbAoc-dv{u``c5Y(v9xU^o;7Xci6 ztCy+NTC;2Qjb_`g{nH@zDUKSk{4;XE*1fxrwRW&m^A*p@2bU9XlzLvDEP7t5II-$7 zYSrz1y{un}64H2*qFxsYqAL~Zf30@3I&{6@)^u+7l^KaKkIK0^ttGDxxR+bZx=A3g zf+ySZt^WWI_=c?bo}W#rhOmxz5JCJ6JgV_U#qchX#vNS#D%|y6*1>yId%_9RX!I&A z6+g7)v(9U0fgtf)Dw>NAzS|Z?EzETHuT67DVbH#v700O;agrkF68&0|;RkR%? zLpDQItK*&+*IvtB2yL-ajCvkwvwy?h>fKwm*vYj8hEIB>%5#ryL}`q0Lnp<Ax|T2Meu zu4E1mIjekA#r!K(;df4!;I(s3!(ay_{oL1&)oLx?xabrpb|(Xa{KY75D1|_zC^A%G zgx25Kpqi9)&MNipp{Zk=QcX2)pVyPAr}&q~^tfG2!$_RdHltnfHT!k~k2cy7JWsH! zz7=c3Z|g;`61#TF?*nLD894@c5!a_|&x0PWtGC>vnKjUq7g77B!%L6$NjY}T{?Th;;~jz7%=AJt z3b@S2oRQg=U5_Nz9CF*> z(`Ue~YOkGVh!@;Pp&|m;MHfk@Q*Es&JU}1DpI50mfA~7x7YP7{8G+ilx8D8zIkRP$ zU2a-3C#_ZU<^0b^j@&&eeUZ2Q+ZFZRZPsKXU}!4JHkc8L)n@LM+#f6>9)pRd(0Foa zkXyK+?hJ=)iTA5+{;g|H$7;zFBtRXF6O?58Vi>XHitotRy&T^XxwBbldV(twT%M5; z9DCNgkP7S`Uh0{j4%-Bk z0C(j5^=FEBY1IX>s&*b+Z41C1F;_x=2R6(Zv3}Rme6icw`<^!PGLm-~atCRp(*<3@ zTO*+DU9X6=b~L(sHthOYdXb1e{p*imcC?lgn2gA-o;;rt9mkjIa6X$qWVtRDr80U< zMr%OR3x1$gf#9D`YMU#$;D#rbgU7vC%)3K5ZlI3i=SofRPCd13xz^&3Q?LUo2Q@CO z{XkS^p7WWex2ac5>U}g=D$5;LM1s)!Cxr<4Nezrtob(s`xi=T}uH@;5cF{ zrGDn0!gMCxm`#cR7|(j+jdk#XA3XubT4mp=-KchJj^}6*Bcz{drdZ`Cb9zR+S@GhF zSYz|QCQV+H>Kxuj4{&<72EeX`twr136sxKm?D?#|z^q6E@2$F@2hww6TvQ%B2wl{e&0(jZ-;GbT;En9E`I3gT#;_) zfOwN>fnP1b%SRs7?yOow0@5E!`bBbnA@G0KEP3{j8>u2X!K$!zjnA_u4As{9L}Q2J zbnE9^{{SF5Yd#~TRdfV00#7kKMR}hP@K*5ar*e>h!uR{@(EK%Zn#YlKVeMhT1D=sx zJ%5MW*4QC{AOju6ICT%E$l&-Plc0yGbjvhX%}0P+o=n;e0fCA(z&@tS49F7|X0u4v zbvrhXPZgM6x~;Sb0}?B$nwqqENnR;-%(>0LH#26U8*Kqzf1lr0Iaarko=NXn?c7NM zL{4apv^g~iB3`z4mSHo9HJOFR$3ZcUD$}V1KIip8>Bym{DoET6e=4zBMp^dGRE4&O zen{hk(w*%w;H)0>*Gd9j7?wHrr&Usgv-i<{M;vSNvpZPz5&$uX6+EXfpp2Q%`OREG zErNX_Gf3n1kQj_`PZaD<2^2lH`!SK%r8k!-PTjp=ioFadBX6gYM>Ng>Ja^gu$`Z_Nm`lTA8ZukQd}x{P`p^3-^y-c`HynF>s_5`=I*;PZ?#Bwkb_LHQ)1sgzF3bfoLZ z82l>eUk|ZuhVMZ1*0F36xm3q$%i*Nj(O6?@K}8Y;Y~BdnCm)qQ*(v}ebB+SkrTwyI+!2sqx$m9 z?5bNoDj49v=qJ55EO#*-;8MWB$nQr5mtX^MnUFb}Axub+0P1Q7UAbJ$?w)FAi0jgd zB&cIBCO+yQf?-4hOMoG`nj}sXj`W5UdumLs=>%sH_fSxv7!#U;a7l>#s5a8yW<@oz zZ^%KD1pvfTOpXXM){_V4@}fv07@p#lP;dZF=04Q`GCjIN30~5gFn03tjg-V3j#0+44 z^dEw(pb&agEJB0Vsg5XyGdw2lc?0Ybp(*YBYa zkhb7X;y{U5>V5wJIxIx>`Eg8^u3bKos$xu-AB{sJ)wB>eromVPFoS{8MRau@E2-C6 z(^f12ux$a(3i&?OHVU~2^rP1BBrAALIFd}kbpOt4NZR2<~n&Tc>y(6tv*rjXS*7}J;o8@qI*T?lX?Eb5E z&8x^7eM2lKsp@)9U@E&_KIwU{Euf1yLBv-s?4uNQWpG9a;zcP0Dyl4#+mTcKo*q{u zU#MqIB`yzJp!n}qrBI2aM^z=@oYN1F!`(}ld^9=%3^#N4*N#+u!)s)S`>E9!1!h7d#dc{-b-?zHryC}r{^;uSC zf&|0}t1Vc$eTrMm0?cOu2Q{Lj6-PDX$(C+S?TK?x?$Yi{2m^7PQC0zgc@xglnt#77xQ>T7{#3u& zO}+)Vkp%UqywKpfJsxYcj&oeJ`yIEdHXODmwY3AO@xTbec`T5r8@O@LR@Ur2K zd(t<7YG4#tXzC19UQB-Ezh>%VwH8wP-A(9Q_Zgr-EP8gJmyXwSA!a5p54~t_3%tQV zvR30bwiE~id-gR;>2($^n+&8G+C=r5ad6=hlFxTE#oT3XvpGp4cfVRbcovm{d4;io zF+)?OyK42zH@QZJ0LYQp&|5CI2bP2pEF{#DiCyGOw%)Z$i%iTEHt5Iktv0o2ZWi-) zAyQ13pJ4-Mb=B9$?@Q= zp2Ng`AhV;s`gXM9><_i>IsSFk(0H$hHMYBVS!lh)St>vPk81vHsMHp_zR0_8a_u0n zJs^y7Dw()qKngJ(YN`5kCmz)3-H-7md|4dj6)$7@r}oB*@Y*#tz)}7#Yc{g}k5Wa8 znz^@ugEQDy^P~kv@X`c&z57?9@TFU}m5-#%FO!l>NxcEB^o^{C7WsoYpW!0BAI^I1I2+jf}w)wZ0!Bt*ahrtwii>ihK3)wi

w09`&ZjgevK+>YCtULEN+aDed@r>KtxjP;x6XoE4o#hbv25 z@Mb!(umuqi~wsL%{P)HynjaSoO@DeHA!n)sd4vM zbLtI%!n!^?Yr=Oz;#X?iQJZHSC)7Lj?NLzd$=LjsWXSrCo#l(%UhVAfX|D!lWnw^q zis&E#w~z@~ATXcAS0BM`t*Zv}{eouEC!p_KzYy{5WvyF2mrzZxe;Vfg&n%f7VE8>G zJw_ca2<6PV@OH1*v!m3T;DB!P0~M`GYy?3O$9nMkpC8w1OkBAGAmXjH<6a<^fU|QU zVM)*BS|!nBab3@59DcdesmVewwB7Lzk;TpGg@X^CYtE&iZT!N#{vg)PX1~TRSlsty zH)CAK)n6xbumnJu=e=|~d{c}mv(9>lQ->yJk}0pcIsjU9EYk{P_m67R;eHGH$`-f* zlj$|XU3KrVBW&Xtty+H_*VwX6tE{RzNBN4J@Z?IMQPcIEGn#o*Xkn&XI*mq-;;3ja zdsbU003&S4=lIecP2Fwta_az0l1C=Heiz}oYs#kQsir`fsZIP9aw^3I)y+o|)w7h= z&O+xLRi0QD!jN;#dW&8GqaZO{pL)mQ9u=lRxm18pLsUnrgxwtp`c7PNb98z5fM9yP z>XW#iLvw*Oex)v1b{N_YDfCutYBsCMErE}-THO0%+;YAfo==9kGo+EUj7CisB6b#G zA`N>@AHrHYwt>3OByb|N-1sZPSwnu%A7fZ$>NsNQotSn9H7U)270cF%K@4Q zkqiXMn6GiF_(#L+TXKy50A$8^uP3RrY`)MTMlw29oIOl4{zIGAdRAVBo>aDGw1gg{ zZUoiZdu(q5l>p3tDze3^Y&RAXa4P*ZpDE!?hB@}DT(?G8;cZ(!vVM*Cw%=8+3bniz zPl!BdZ6~Me0RI3w{XW}gY{4IWeqa3@$Pd+j!$DXh;x8E=^vPeS6m1=ATvy7O<@%(S zdHvXi+~aYHn4Yz2i)uoE3lm4o0@-L#swPiLsCidc1eqBlAB7DRc`hU{BH#cFOwdqQ z`=`fA7^GWhfNy7L?~@g9{{TS1?kPQT22TsRS4CwM7CQuvm8)drZJvU&cza&A;r1HR zqYZ#CCJ6Txqj={t+9|$tDzF=jr(>80ul1r_FA#f1XsNkyLm+|Hp zO6u&^eHa4-oi~jb_VYBA^Um;QcFshfohmxGAMRuN@@9WY%#7xP5=1FK!lB6`PBR^< z8IcE(&~ZcHvcMZ)ILz@t9lQt};+je4r&ytp_Om?Dhhc)JCUcJT(o{z@6ku>;AkoP? zcfclnu|<+5)h8n{)}nwiNE4bM5TKKRI20d=5t=Mb1mZ z+$AmyZe7xU?4yBl?T86gAcAM8>lDRR$W>$PW11?E#zb}zz^y8Zyv9WF#X?StaY3@Q zwnV9t0sLyybbXSbM1l$Cm5D2zz(~Z^NI^2h12I+dYhNOyHRmj`00MaT`SVl|(m)`n zs~gJNrFU=TrXqyKVN8N>Gm4s2RVQy^9j)q;4Dd|im@7%#Ju{D;HM>FNz$XT0rDzDE zcX3I|v`!eDwr00%T$Le*FnFtctC&S2h{iEm5Kirb1HUz@)q>A10{}W0s-=>)Y{$~~ zD)MI2cx&B#>>vTsW-Fkc9;@jHyLWDw;<{QbFPJwv?i)Qmue118p`+btlnCIE4l&$T z9Gy$Exzl=TQB5O=bS`#~rU>Bm#codydzR6i2?dA*hzGn^V^5%4m+aa%3xcGQ7l;}B zD^gkym&}>$0rnM|eM?J6TMwnH+Bv`3C~aF3<-yMHvIk1rW5VqQ$yH#oH+7DJw_COd z;KX$ma@yOHgpx5I#;{MQlRH?wKO7y=j^2*gQ#Q*n`zN+)(V@1;q69JZ5IE01^}PYM z%IF}e6n0`a0(q()cAqCk9V9)DW$y{nz1CDyZ*d@G{^r)t~nMcT_>DZ^Y6U?{6IxE))nzsUv{#P4^erp~70E7@U zBW=Myb$cHuiJq7=MX+t1$uYnu0QIXO*W`-i%|Arxa&Nbj`Q!X2e7Lu5lur!Jf%C3= zcs8=o{hhXvGw(dt^#P+-V!I|*aanJ8b%zqFxf#W3$Le$c0CCID_*)FO1Nn*3-?xYW zzyhJuUDJd@DBEmfLpJ6(7LGdV4tOC zi`qE4T^PK@Nn=06SEJDA^>z;SWOTX#Cj^}L@A9Fh@ODR4S5yZKSYUn~E45 z(rRv{wLVjV0LjFT_0I5V72p)x9~-wYJ87+e63MO6&AW8}N2>AJj|?L7VT z0`~Agg8J9hYsu>M9wBLTsi(BcxQYH%=QWpYA_Wp$nI<`-s9~|UIhD;|7Y*Z(Tjx~Z!5Aw> z&ayM{(0XI-nh+X`GHtTV#W|i}b+vt7Y>eE-H&iyHYMa zvVe#=!RcJnrwj>umFwJ< z*3RP@imcpbuoX!i#a6D^1=~0P;+Wfuc_VPoJk{w^rgP;q+i_G25hTnKB+ox}dM^jK zlBAXd`(nJ+wQ~NDdg3|xS7XC3n@+oSwDcyc>Lc9~SEl9oSrcchu*9xfYbLeK9hixq zdK!IO6jDfO5N4^?x$?wi%{hlfW4)A25+tx89z@aqhSF$I05x;r-mI6l>0nN%zR z{{UrZWtoNhtIN(;CfW5|IJ+^?#qryoR*~OqkRu)I`K`<1?bi@;cs2bW;#Di4xdM8~ zujWVtYFntB<2Bs$xUR<|zj0eMSK7Ram%M<^-PI>cBy~ z2GS2v?^|i!&MHf@N7dia!+cx%vS`xb3m*~qzyyvzX>9)hI{iG%uE%MS>}&G(=;Q_d ztomSABjR5d5P$UTSLzb0Za~CWMhW(##&v(kpWTXW2F#coiN!Ltv>`|$a3Y|-p*E$% zxPIv7jEjx5q3ul066=t_fCd9{d(;DPJ2wvTLt@%8RIvHg%Hh-%BmvT5qxnF~;f2>p zX)U1#%MyB4sGd%Lg;k_mhec_vxcdTDImI^cc?7p^l=t9O?iVblAe9}cd4Pyt;Y2Hu z>tP+J?2MtuYE-V+{EBUc$se67f};yWycsJ)bH60TI}<*6ewCsd#D0t-K>bt3NBt(6 zzIonQY;N36X1<61mCit*7OmPE#o2`8D)F=)?JW|os!~6)p*CukHoVOnN zqNPAGv)IvqWVc-LKy$Q^bDUD}Sym35{{UKrP5}Gl@kFZUXg-)3s9{OZ;3y?p2v!6s zAZHaKL63aWl0fI4X^&GsYo}^_0thew!JaB|xPmzbpumIItwo82BOPf4gL|&*xt0s+ooj%om)f=mJJMW7<{CQtLLKxtqg%o&KK8wOW7{Ah{& z;vmv&5~NFZn(JWZ52)}5CWA}=_Nj1~*?>XLd8VVXZzimB<*mTdSy*)up0w76>x3+cT#eB^{{ZZ& z3p$P@cI`|YM1{c^0MP6dqvX_ywP9j@QHs%S-Ln&j$?G-GTkga$zy>Px)Lc_4!e_TV zs;NbzUM#Tl!PL`O-2SD7`B!UAqXCxfwF)Emd6pLblj5 z4bt0x(O$IIJ~V4raiktw072b7CMUd9UqRGY1=#(2py#;umeo~bCIw!Zzzk0U1$c{p zNJ-8sY2yohAHK zdeW+-g)<#{(J3kB0MJZNN$p-yevrH|mQ9P^nVtsdqWUhQ{tTM+o`LCQkM%tuP_vffw>1{nxU!ajIVU`im2k(#z6As}p^KFa0tp6s z6Vv+DwmvHGo8&K@Imn3o>JO&R9%9Sk>Rld3QOLik)oV$%4&r~6Bk9sU&$+CB?vKL* zLuvp6l5+xSZv0W<2+(y(VC@njM|vZNH-yPctLb=iU)0h1sT+!}2!jKqC+b$zgN{2^ zQ}I`WOn$bR$Q0}GAB9~Z#;HgkfJOoSwPJ@+9#biOM@1+3Xb1V^?qW7&ld2qq@7AY0giahNk=NHiy=InD^8}rsyH4Y;q2_r zQ*b=S4RJLZHY8>gcIoe4vhR!dGZPx?KoCUl>0H~_JS~K#r5q6>YX}GYit2Rvrj<0$ zE!XsTCi|l${ZBS6kt#q8vk*SlxvY0?ZFqZfAc2^J-n*LHRxYV+C?uvCgGkR9t~KjK zkfPU_xWo$SCYS<;(AONy1db-dYvAvuoKEiDj?oZYi!pAyt1ztz+T>+WkE?MQbb>h3)R@kyw=ve38{xa)yfZxy)H zZCHr)6W*hb8ourcbsa>~QRar!n|ELKPy}*oIdT9^(gEfv#iFsiawdJ~upz2VHt>ZBp$tmU8q}uHWEzZBB|_;ake?~JY_;&=v-v;UhCnj z3YJFG2a+PZMw-*T_}RB{bL0NyZ->v+JfYi9~1bn>ofZb{Z6-TINHiKjt^S=v-&q# zkJYg81LB_+AN4i*pB=?*hN6!f)xY1*?#EkV3vJ2o{HX=fysi&fsH}sSEj%$ll^xDc z*$O&Tn)fKK(bo3l1yq1~H$Qz%fy|YN>|&q}ppc=5PPBZ)Vd`z9362FX%fQiIj@`qh zv;+XEGe71lL|TG3ef=tpEwOV;WrLMvQ39B=90knt#YNwMu&`wWf*ns|Kr=QKNFC2K z%8}}K`+=y%AA=NVHUa=J-1|~Gu*#ABY7)xP0QR8_J&B(@{{TwKKiWS!>p1{nO2T3;io@4~l&lDgy&W;{=o6&C?3`>v)pvU<1s9gGUEb5Ab99 z@=!xWLFYd@8*>1~2AS$Bc(`HBmvD1tG~4TsIwiQ#%Sb9fwo&DF+TK2G3m%A zGeS?=EPIb?JGxAoDUw7!kq7j4!78CV=j$E5L!dnZwBJ=5Ft!SYYKdl7z;vhoGNY37Knv(3J)UbfS;Pd&>@~(?% zbf(oa21aAGBN;xZ9cV#RGD&^1az|dZy3MvQHwaJ8sIg?+-rIzz1}3*4g$vy0AC+gz zC*a@HVe-ohJCJ}XuMzD_sBvuU-7qAqRM>2A6k*%A$dx>>hX(~uK zG6;&U)GUj)E-EzPBal7*>bl09-4`yUz%~!E!vcNy6!E8%Qqnn4tjXqN@U=|RqoLDEQF{KTQr@b`vbC6o{( zaR61i8@mA#0l}Hbt6JHEWg*d8a$;hs8?A0YM%RKw0z`50t&OQFIQ_2_yN;EeRH@r= zj6?&{t@9o3TK%&Y`!Ymq_7%&p>J^ZgZbpA9(6@uO`>MpgN&a<9hq101oT|@VrO@cS zHEu1fO}m$w3;CO8Z{5o%>3)qrny2b z{ZST!iRUEr$1z;ok)9b^+h?Zf=ZC9@Wp<_G{{U>|exrG48Vn*`BK@He@R{Q$R9m_;pZ9qHAI|+#I70A{bcCTB!EqRuZ$&mz#w;y!>05PAb z?Zq0#{*C<&I$a&h*R1K%!Y~JR1eWhL-SOL2t@wIqG}b?C>^1}#_nNE1S5K$2dsu{& zVi*tbp41b>Zfkr+bo+v_0nw05cUsAj%6Tnu6Q_q3JY7Fy{Mj_V-$Mq!!B2d`h3!c zHB@%3cv5)cOKTR~{{YGDob;@k{{Vw+>5#RpLp8!q!QZ|+RvUL$NIz?S<(t6HTM^h* z$H!9T(l@!bTbY9%^mb>AuN%=*%h2SFbr7lh*}&DU%_ZQb;V?RIYNWVB?YM>sk~kIB z)!x$U66v-8a7hMhk8<6>a?|cQS4$lGme$WV)Z_S5xI0Iy@ITcqkdI|cj`^=yV@08G z2-92RK9OD%;lpqnEd&BcnID+1d!#I=6d8f|*ALVajP%cS_<6%NFPbRi{72z>U)7n? z$dv{mYm@NJogSv^==C~VZtIm|Cl%?uN?P07=NXTB@tR#l-wW}JOqdM&PI(5W(>Z0q zC|=6FN;vvnwi%p$SEr-Z9|!R7?FF_pmcdj60wf>0y4rt+yc#p%)=3Ad)jD-A;w^T0 zQO7mhu&^XZu3mikB9c;PsOY*Lo^Dc<7e2`4U+_N*Hu0mjF%TBK4~gjXX|B6%ENw+% z1XuLkScUB%$F+Yq@d97OF9FWx0})$&GbE(jY~ubU>9J#kJ7Tu|k%U>coi_gfhygUq zYShO06N#&TS9ZvroDOMipe_}YKgPP<-&4taI`N@=wy;{|r7hT=MQgF+I{iCmt91%^o4+`ptd6D(%40fS_|+x4Kv? z0tx)7id!cJf1NDbz}jcpwZagBsH!mz&t&06%fnrGe>++xI(@;LG zmqVBf@o$TAf6=gO^={c57(HgS!l?5-LjCN%>|&6iq!IJwy!AW4KYJ z$Z}1p6o}1MzybD$c&HeGBQ&rETdpFHB5e8P`c}6O7Wy(UVCZ~cPyW|UUp{phc_WSm zeF*(4Z9XsbVvL4AQSpd@*Ur;d&wJ)ck;NN)9c&BtG5vWn9D0UmoZxfZ&@gk;iiD9Y zPI_mGd=pzlB>c$hObKWZ2#@nMSRhCzj-$stZo2facu z2bli=B9{t)f@JQ_7R-F(;9q zzLSkR1uBgoBs*;^7pNq~Ew&Ouse>cm@26-;X$Kg<%?o!n+!sMSn8W~n>R{K)K?RD2 znG5Ne!1kh85{e`kiB_cyB#9<7pW{HQ`gaJKBd#gF2Ob76Hxz@RL{Xf4Y8z3Cm9p>ql#4%Bine$oJ`2+qGwCQmoe} zl3`=|*83Vnb{K3PWK?C7wHM>*9!7I4X}3Fohl~M{TQvR}BWPT=IO|@QMc`#^UcA-_ zWQ8C&AWw15d)4-QJpqt|9`I`pUacpix6=AEX*nKsJRy-vz=M;6{OfJ6hno67sZ(S^ zG0U;-UWIfdF+f2p0K-jbx1&XnEzW0|5m_bIG{b; zWBesz=}~AhgAxhE*Q~XqUn~@9bNhgC_tn<)ye3dwWfOgJjB{DQQ{Xn0!#$8cdkWeQ6IIQOo5>4|vGM3Y{K_!D2g zQqG@l`6#o2*h#7`cvZ`IQ73O&x;bLFW*og1S#C(;Eu(DjP+M|+qTW-60sl@23|d?JszV> zpR7~MaeLs+J5$XHL!PlBDBCuIv0!D?t4u`uRlY-7*>>Ru*(L}%`4Q5p)SWxYwSaRI zTURFvQBjSup{0W;eH>MYp`~JA)U@ajFmOi%PATm#n0BaL&&03*eCTcYAsENO+3=lC zgHFQNh}!ckk5a5-cfWe<+PPy_w&j~B6-ZVIchJVS|qBpIez^`BMJO(cvCA zG`bB=hUI|P)Ru0O?Ok7n^w#X9-F3)NeM$kwdQEwI8lzydxZ0NtKHh7mrSU7)G@{yC zW-1A`2#`e?@V6GBt0T~LsY(wkzSQWRJ9_Q=kKzX3p!yMj#yPG3psYd3>p2?S?@(!Kuxhh0{(tga64<6MtYg}&q0 z{u$~%Uc*+k{RGJv>0TGcAIsJGkY;C|Kc#yub@H~z1|VQW*NN7!yR8a9^)v%Z)8kgj z{vpbwlvg%;kA^Q^)Y@D3nl~uN%DrWl{hWg}=l&nCE$J;N0}3-yA%uC`ZSaHC0g+qsytD_gQfsuB_AhLOD<%1LXR#FtS5?5*e09v*(hf*3~46x*V^_8b`JQ4saBxa`v zqdsLtPm)UY2a{Qi!b#rHIK^LalzO-Bk@!|}815&7j+J~83RRhoN|bcQ7HKE|`#^ciplG3+VquzRJ< z5j|>DS1E9PT>To7KCRl3wOAjEd{QTo`#m*&u2Faov`GH|3|Hk3(W2;nt~#+N_J0=m zkZkofbf@{(>mcCqn$s4VN1EzwW|gljDnY?*r=agjcSvO{P^-Zuu6=;R+~Cu|5FLv*&WtHg6L81QlW|D}cXsY6eTLX93u4WqbipVf8oP92 zF;(f=PMX>{{m~uh>}bayI!}BH?gm8-y&yFKx=!X4K(?X)$nQ{<{pyNoaxwx4fCVGN zOyJQ152KE>2bLrgk@-}(1DtOr;h#a}^Rm*sIr^d zaFC$-SwzU-)F|Yqm;qD}KwYLgO+DN8?W-tISWj9St%-MIusc;mj01_NDM-3e$67ME zO~jBrfzB#6#xu;CEb;=tfs6>KA0b2nahkPRN0Jl-LjDyM!sV4uPge$*TyRKCNE7Y_ z6kxX*$|&qMf(1po*ayx^5`I?W9wvu}n|A~=|>>2}SswuAsD zn3MCYxhDJ_UYn+kT-ljC8&!R`DN{TWaB0VY>hCVlps~o#E2nPlgthCvY!C3vN8MX& zYi$-$=B#uWtn$y2JR_}()B0&WzJ8|;$HP7%rN3r}{4#U*R@C@cUKBHJCB(0*fyH+1 z>MWMU!L*nxItu98xn-ZrwR?D&S;Y3NbL(>@bai@vMd;p>{^y-vg>`P|r7eaAG1j-( z_-_4z5v{6_eL}moTHgfvxcOGGB!a|}d8|2l?5yr|-iOjgnnycJ;hL`^>Z03K!!+`G zK>X_KULSlYMg>rrFe|C0aEk0yGM`I(AL~{p*j$;ca_VIHI@tOQOGxFWfz-%I9qQE3 z-H490)Iz}+dVN{rHD$nx!^>$0@BaWMsd?nhQR$$xj#_DNDFsxGycx|~XGqRTWOD*= zGd}gvE4J8e%2>_^AbZt;OOb7ELXPLsDyN!HlEscGXy%PQ!TXqF`P2TY!yym3u933p z2Jz`91R3Mrt+tXtCu*L&fmKT*T$52pDCq7Y?ly=HIU|}=V&rWqN`u2{C@fTiAP`4R^qyw;La3vJ+9qPb5R{xxYNq#xNS3#cabBNlkfhrne5%21LEN^~ z$ef9&{?y{bvMp@!E#U>gDQw9d1!cM5q%m-j7~;M1>D14l5IKrhv1Vh-1pY#Atb~ScF7Em_MAd06&;M$#i z(WkSqSm18KuB;}b9_I9UT-`oN&$24n%^+-m#0Z(<54V4vU8KKu+}YiWfNmg3KkTnc zevZ6hn7zieFbND~pK7oD@BC#hZVPBJ5&?M;RsP@8Jt?AV(LF*EQus{crNXxt1oQ?g ztz*V7t>ikF4yXwmy5owv-@%?Prf#AzQIB5~bsq}&lbi$?A9YgmV4M8N-;bj83^wBi zzme0>c<+bYv|8$-JOWh5sLuk2iFn1NwySEwv2y}IgB6`V9(^sPL1`ZI5jPJDRNeS$ z+Ao`{@ktRe2NjaKe(Ox^Ir@*n?35Mz@n3s9_Nj)ZQN03Xd#? z{A(YG>GYasVWQWq&CF&*RT^8@Y~2@$2Wb%_(r3MN)O(_u;PS424sypXUzOnKSn&J4 zXh-s`tZo~+kDXPjbT>$|a75ypSK=40TWu3uw)xy$PczbcRyMh991YRXn3^FOJ;-^d zjtjRJ^E%ok(yQD4&_=mzFhc_GvssVv|X~(m{hcCbMP6vPWk}rOz&#GI07Hvs>Z<<*=K9Ety*2Shm`)6-k0i zM;!-RZA)JA)CYn2)BHNB{vtUizw@di1&14G=;hA(&Y}>K@{j306=Ykms-hMJb(KgP zr=G&GcyfNtcAf`ATk9rrSQR(!oO-NauLD14(&^C(v>275u-$T@|ifDjG2z zd9UgID{?f~3CP-TdROz)qY8{{iIXg671;E~qmD`WJb&U`a+gt#QSg~!6SR>8AIgK? z*aiRuLB&&Rb)`1922x2p)V&Izs}b$n=Uo)7(dXRXZ`g0v0|GY=IF5dGTU;RuxPl;n z3|4Ks+sqRj;8ajt#COk8R;Z+7mRUU%JZ$gW6+L8A$1Bs z5D1)(O=wYzqn{~BHknb_#GU^Dk4g-pK;AMiM>HqQ+@OLe+^GtzvZr#1Q=9!+78VU4>MLfkY*n%Qr zp;U3}1bq0VmjV>44nAMjmn-ECbW0}MTDD3-Wf|xy-!RT1I`*ox_fM3FR5zy{*rqmw zWI-J$YTkunv9{(QgWtUkfkEB4k~-7xfwZpE-1Vq#0qHq0LUpPdc12(Y59L)n648QA zO+S_l8bSieP(F0%O!@EnR=ma4{THcnRO!5E!6qln(*FQnYv-NdOH6T$SI~dbwRyj_ zevDUfAZWZ{`0sa0Kb3s=z3OAM7#X6@z7OC>_2j2!d5HWdVm?$PK%CDs7=bczO0APm z*qurL05L=vB+PqIfJ{%gsCWV?k_iWClg0%{@A?SttjwBls=JM>aFPqa=;|zbIoS513Dm30Wr9o55BKe832>gYl)THv)lBG zwmqoRVJ=*>?6)D77^vzy`_Z>@=oy$DXd;!iA(YQC(yX&=cg1Fva&)nGJr<)}iQpX7 z<(&@JVoXd;1-8b>pRf#l^vZ$<0&!WVM#!d_WutL}H<%Y_;Pv@c$#J$7J9&`Nnypb) zOc661WBJvB+Yn4*sgq2#AfdU`n4EU2*LWL4b)~kTh76~118JB7tyFd)7bL(FfmP0# zC8Bwb6neNZo@tHiz%W-Z(YOPOK1l($6;h-K>S>L*C3c<6Bmw+tu+taMy@BRnW}UTH z_zm))w$zeYgf1hkM^FT=ed#o;ISJJ2R^djFL4r7%QL4J7$RJF|SgCT@{nEwf zs}OxMK#?6N?Lbqhcf9^(#wCf#?^Ly|tlNkr7{zM1fSsk4h7Zn=r}_Yi@A=iSmw=-i z>4&S#Lx}_m!Kl(BF2aN772h_L+G59=!FJgPjxqA9F=c44CMeBQJdcR@8r}pf^CU+! z{{Rm7VX?0seZNpRlfbV&+*JhNa}znN*9`h#%=WJe{{To@@Y33ATMhvenz(#(e6Rdn z8ak=O)|KgfOgtFh;!jV>r7!GytN06o0m!Zg#8(#HiRRcWc*&Z={{R?WWsfCyPXN;D zd{ax}T4l3)O#WdqLYW1Bm21P(WyK{aBL`XPoi|sGP{l3LqvqawYi+LF zB0&JRVFU83wM$?#Y$QW^RPrc3mfLB@p>Gc`9NYet+)`Am@E;0&&Wb|xpaUD zXB(%8KaESeR6t_HR^m1NK(?N0=fNG zPlt`!=)E(iT}M+HCBf-5BoF~S04BA}bo}a_GDLbn9cuSfE0H6t*O;4K$I_u5*rSo- z%^EwKSg1Ap{`LE|S;&GWAat*H@d4YUxwUWy0>7Q#V%G`VGJ02c(-pzl;r{>=2#{p-cNCUf`DtxII1@Yyvu<&=X*FWHbO3zM z-Q%qWP`oUkY8%`bAORgHi=CQ%sjIpg*f)0uXch+@>52z3!!(RaE^$Ru8S~5Zts<|A zeHhDU^*G2oXh$7#XMo03;9ykv*siAjtv;PHHiO5yu&+mggD4pg#lh zppfCC)L%HvRCadt6`9QUs7Iik)i)C*xtX7OLH83Z&;)=f%N}D9)`H6rRG+?@;+cR! zj=d>8fky~Bb5TnoI0{bhNRIUyLX~20e#z*2(L?Y6 z3ri}K9l8&l0rrb06N&9b30dkQD#S@5dY<%fiN-zJ4X9!Ww~#mokyM+MIs51m z@K#}Gf_l+Vsq4&+YIUNEwmqQ^17oi_tM^=cfmDD1;O7-enEjzrJ8Pq|5vy(lAb9$52dSp^sI+}GL0mvP?)}@WP9^CO+wBV2;J*O3}(#R#oB2TI& zxf82Be@(%oOs?8_OFocEX6yd|WnXPTY=fTFR+{a^ux%kwu5*dw-nQC9=^*2bR!p)< zXzE~&tckdTB7LgWN&8ssP^tMXI*AwtvbTFRBtvW{1dwD%Ao267LKQnn1RlNU0H6;~ zs2rKcwK}VPphgT$R>>A9{pN1GQ-Lg68ahn?2~fnT4ZsIK0Q5i$zkOSYltL8nDycdh zj1_#dyZgXI4&$vjwuAx+2emVh=1K)SM*=1)+kTD6z%XIYYN~Vai1D(YDnO7(8JdM) zf1)cy2#Mo}q64TmEyyDqqcvZ5xZ5$@MnGYNp4?Szf_da-whK}KBOuUgTepHFp0fk+ zsm5Ssduki@ZGZs;_M~MyK_>?|tp?g~24kMpUzT=~Kr(8@Gz!e_X4&;Y?Htt?GOCbd zNS=rJ)~5z%1!owl?rq@}wv3EP{AzKK%y&awxzxGD3`wl|gK^NS0|3DT6BV}Qr$R$1 zRvGzKH?KCxWuB8Com~kP$yw(-M?{wn;12L+yl0DPuX)#4jO6vre?-*V21{q$aBIx? z_Kce*;vpatHQVSqhM!|RpRV)~oE}J?4&}JHxB?WICNVvz*}1}nAdh*)TYb*v3xOM8 z3=!68Z3}8e(SlEIMS3*#v*&Idv-wMGmIs5A_t#fU+8fr>PPavpPwiNqeT8zwmxAg+ z>}vZ0%IX5@6cioLU%IHsyN$g(`yUH>*`vg?J{P0YgQvLnF0qhj(kibF(PL!{QcnL4#?Wva(KO?QYc!Z@N8}%d^2_$?=pD zt`+|Pb2aq!9;?l~9*zqoDG9S$7>@3`V(qZIO~eBjsN2!)=v-U`G|> zz8gbw@0pTkn)fgLo?Xk9@F1LXF<;WPr)oP!Ip)8d_@en9BXlZ>Ew~Bd zyS|p*(c-@pMO-EPj3lX2N-4}7RY6o4EGO92_k(@B7|Q|DtGLK5sT{90*^Ryr86=|i zRQFVL8iq8V_(ENGv_6S8xyy<5Qy?r*iri z27*S=2*4EjV%x{r1mxnYl_X*@BCpd3x*%ej6XhRNe@0jh^?LD06aN6;cDjH2Urk@G zlob$7enb5kcL@5v_`R*Mx8mJdAAXxpU#_jRu4Mbxh&>!Wxz>4pycZ)hK{HjBM=-qi z6nw4Vm?UyV6@8>ANT*e^CGLoJtA5l;6=1koOhSRwe>$z4p@z@5Q%7K7ATXnlZi8&N zw2g1~`T$$#tfIT?}ze-e}BDS~?E3~tL5!Q%Ouu+D3MJWuY zIS~S+=h8{{idO6?Fz-B`dR1+>&fqiBYR#jDIgTkV6B9V?O)A*-eDwV*0Y{1b84O9% zc)NenY5xGFeE7SyiC{$k0Ht3+KT635#eR%WPt^QaLE?Pd74zosl2jQVDv8*@>jZyZ zN>x`xiRX`^rnjlSQCTKwkTln>}naA%ytzs zIG?(oATfx?H9vSqBc9a+9L#$hRNeMT0%?5)#*zLg=^ZKzZZJI!6)F&bOPZm+}>CY7Fv5n7EmNK;~5#P`VA1b;uhBJ#3D}U zVlfA(tXEYY`vefXj0Q4ksiw3k;&59k0N@^+X0+G^*;Q8~+N(C(a3Bac;zexI+hsF} z?@-AqMvk8wa!H44sLV>9Vm{QKuO5<586Mv%%c;=ZzTjC*h0LB! zXIT?;bn^7`>{N2D5fhl>@1z70O9&qQYpA{nt8{f`A%OG&!8D)Pn(+awOm&!p-mO_- zT$tZUo$s~(07IU#L{2NCq_ufw-q01mo(LkX9u=(goA%VHIUz^!t?6N`rL<_-yL2A) zR!q_V0BN_T=;ocxQKLm>+HES3NY7g8+7QUn4&fjUk>9mqw8+6(3IYc_MQc`83eYkm z+PRr7N2%#zv8^+yYT$JP1bdI?T2=}~W;0oALnlv2mdsY|G%)m_Ut6rW8#E9!yvi%Oe52o`4ROo$rts`Cuts(g~UQRf--q$qG!;fWN#6#v+(AM&Zw6 zP;bDP08=tR{&bjbMAi7)+D8Ps$S!*8Cg#~de2JBdnELXVzynJ z$>Z;=w@Dkv|a3`rq&r0L?rk~8VM0XhLU8~z?GZXlV=juhW2mp!W)x~r$ zNybT|oz=l)gNyQb?MK3T+sb^6I_`5O;bSq-M-f?<;SUzHyG^h=$^QT`UgqD3==91G z?ezqAZYdkZ^fw8*b*RR9-8IvXsC67xzQ>!Npn7}xr8<9fcw3(h>#SKbVYiNxc9D+; z2jIUua}!!NZ2-hhIjMIQsMv}&!!QDPCbxQu zddvYa*0OC$E0fswt1YhaA7%zBx%|eQR|C|1EqdLzZN*kba~1BicWt)Pt^^6@zmnRy zcGy<8ak@y3D|+~rtzqoka7R$z%DFvXLi&k!Cr7aKpI%;{i9%4iKd;-kj6}Hhf+{`4 z$t*t_{zYTN{6gKyeNEs&INW>I>z@&89>}xivd2E7Cb_coiN)$ip~d*O45M;`U(o)8 zt|-b#B0hEe-^WaNwZepS+f?20PZ1)2T)I^BEm&EuUAZrDnDZvOJs(9bowp}vp7ozw zhp5Iegj%QcFS`5Sjlw!r4{s8808eUtEw9^~Y{bdxX1%wCcz%`i>TcLqaR(x_X3rj- zS#gBB5=s45)SQ?~uIGbzQ4{*5 zqCo!u4rpGmuW=zS!MS{7U)=sVa?qS&IW(71RaD6&cH+OTUGNVEk{d&APXa3zv*F(g zHrr;60RjXHzCN*zPx7+{f5E*(6KZSwpUg<~uH(9K^NP1l331kWuAhu}eVsO?t)k%Y zBZ{j}rA4&2CMWN%q;n}o*OSWR=`v!<;Vx126ZB+_-&g+t77@qAy3W7(zMj8c1pq-6 z`2+N1xL=@;9!$sktJFtt__m(EUZjllHLfku=Q{YW+9iLj76zGO;78yni-O}u*$0zD z%MBnvKJ=lP7%K?rJt|aWvEU()vyLg2;3F-x4xOnP_P|&tuWD~BTm-s-nWWW%TNcu@ zY3;gPBOaxu48t1;Kb0n#E;1*mDySLnintNP&%G!A0QLpT6efLb9cZ*Lk%LRMl$PE| zJq=8g3J9L`Zo-$4Zeh|XNN!{S@~b1cny%tANd`XdX^8pf`c{wq_4+bY`$I+I&G_B1 zUp}sKL}cLNzJh+0P=B?)jZB~TkBbcd0P|}V^X~6BY43`Rj>k{@82-Gnf@X3tJeooz z0r`q%^q2ra%|bBD4+AvT%SGED^gZZ63xzwnM-)kuGx*Vu-X?wGjsQ?kSO7)UY0;^&ng91tG zIHCa}T0~-sL2PxCJ4QuWAQ>3U8mtys8@f}12?U-eijIlKREso?r?;)Qb5&{H+UIIC z6YW)>Q#nO|NrBptm9{e}{_oUJYBt%6Vkf*(`;v>{7T8vB10S+`e>(1H?5VfBk|4+f zr`~Iuq0_l;8$8!&q?>l8Ai)EzW9lbvk=*p`RJ-J8@|0OOH>%3Pt{$@O#Js>>ha3`k zuKv3EE|ev(L&vHIU!8etyV$cVoJ$y*tEX3On|)488c~T`Yqi4R0{ILKVAa-jz96bY zYFu@Rtf$uGDvH%%cm-e%^{R1-TpXNJ$mRK&(6Oq&bb7BDID%_bT=NaKxFtD*ApP}4 zuyrEbSQhQsSUXlT-1jx16fV+(bVQHy#bcc(qqT>+OKj6&!Y0NDcL>OmJ;!Rk%aEmf z!3UTXjoZ?0D}e?I^)*e+Sh86y7AKJ%{pzmAE)CB-aV2MC1>SD8G={vY*L#Fj_hPM;lS=6z6g%M@BZ}9xP zR@*lTf=I6yW5t;?w%Dz~a5llXl?UJ6yINluEJ8d;fCw-vpVV}dNc0^Ss^QDdk4%!| z(=2*`D$8KI1Xfi9$Ey|0((CPAjgQYjYjWPU?THxbWQyg^4jiMk42pl1nte!ih7B0p zI5fyajlxG`#Z_#ANCrC7l1V0KrBcgzFGXA#BQyR*XkdciHra?H)LXq}1VpjxG1j!I zxJ7b61mdZkiD}y%7@T&+I)^z5Ob*;sQ68oedd)ZnHt%2vg9fOv5r5IodUq=V7CwDx z3WUdAxv0fpPDMq93<`ye&s@|bI3SKYP?^LG)MEo9B8^xFe%OE`tygu1M?7&+#l<6V zfJB4-%0_ZQ3eD=l0P{|%l1|o&+>$mm$cZ3DP{15GByxMx8DZ-g9OELC?P6D~NazpF zu8OvY!JhEU06-ZN+OpmpLC-az$%rT3v)(c=!ehN?g4lR5UqDrfAQj+FO<=geWR+4m z&lSDolj{3iR&8Sh)2+5pO76{W!}*MP)9thQ@5Gl2>dY`uI5ow!c%lVXkSnRAa$=>hNFpD@@~1g^-^d{hj{_mk@M+5gu8T?aF8HE&g0v#`OstL z7DWm@iRO~##I`)(K$yXb(G+v$+eIj<#GTOw0>)3hTCT{ZT+Do`t9I9txS4}MwV+C| z1d*7j^61S5;H(dI%i+%)4z!cIl_Z=@(P5JUREU`AQrwg!52qaRb5o>@&ACf#C{ojt z3%O$y$IfNkl2&>OR8@BMAq4a_)Jtl%NQmHj{OY;Ri*aIe)#&F7WDJ6*7>Z(-3^PP+!ypm3sK-+7X%FzuJ9CBkobqgtZ12UShBX(V3jcy{R;5J#MhDdqz2ON z^5pKw?_Ez%&p(KhXP@=%ix=#&lwy-#L&7t<+$&x|e76UqWQr3d)q#tQwb zO9%WDUSaMzF|$2sS94=@3V*QRU+hJ4_1?bSWoM&*j{Iok6q0cXR5!-{HFyvj(d!#4 zg41kmEH`I7)l#@5v4c79Q(Ybp_@g}ibJQO>U-dWY{99G7yl!eX_QgJ*Si&p_+Aw3i zVF~9y?8KArS82f)NZ4eaxvdKv5~Opb)Mb>Mo3_uX-=ib;pFqAiz=;0!0uCf2|HK1QNv0%bI0p zak!`p#Q>_nkVK3Lq5DN)zaaZ@Ov_iu@>F^t`&9D~$#VzZqaE0{COXFy+W^hR9@Mn? z3a$mQX)ai_=)^El%^5MaGv1|(VXY^a>l;J?R=^&ehCB77>&UCZ5l{go$vvt@;BlIa ziW*S;-6=q3IRQs%Hn`tr>8B$L4d6abJ6 zPh(Mx5;*HbG2obr6QaO-wn?cCImGp-2?vuip45AhfOsaP00s$;+|lG@kUm_{G8Bj- z?y1QHi37D708deq*A%8fCv8941+yQV5XJgRZpO4J zb-4_sT#W7>yX|B;l{AaGmfP8te+MQ@^&N9=Y(|^{R|0cT~ZX07=v96ABNjop`AuVaaQTPD^P?f zw%`CDkzHlB@`bQ%jiaPh8G3}YnZKjx9GaBk3mO|1*J7m4C#7C=c3440EAppCg)I^Z z=C56)lnjq-PxP*I=O?>8E-X0Gri>T-H%$6-VB3SZ6*Gk&D&}iEGgV-2Pg?c|FVZu;l4O8u|&8x zD9&T})Yf=ar(u|wm=7{jP|5g5=3%hiF`nR zx}$Hvxf|5cFC8<|mI{(F^BriG*#V$pd898Z0iev0+L}xP%s_@vLCl<=`zn+6q$uW? z-nX-8KnVTdd8&NmX~BV-oib4jk_jLV!n3~KBRox7?3*XQzZIFEin2N-Vz41MfIuGD zthYn3B~(I*Caq#~0D(EI*P)Ca4QPoLXSxcR+%O>44P*YvrLZT8*?59sag5hD#BTv& z;VcHlz>J@jZowOpqYqa#3{A7Z_?xl1#f0ZHngsJV9grKL$Q53u;kkX_WY0?I=xv0u z9fGhp={4#lF33^y2uI^*?l_u(YR;wPu|Q#niHgWrUM33_1jLM*==ikTcU4eB!P~SM z9jhg!RkmcoIiBBjX@t{?XDd7!$l$mX1ywR2OoC5uYRF14E4B&blZgIRb?xX|)TT!0 zQX;BQw}?~z?xc(Kx^GA-o0yErn$*Arovg(5n2JjUl>=?r0wf&O*BC2pK*S#7F zbab)fQH2>oqK&0N>Q5%DSRgYl;|4($Sut~LKsn!<5CafQGo#2u>%}eZNZi`4^1sV@(4Rc`y!NxEs688X98+wv? zrdUidB=z>F(tnr>EhVPY+uQ(UP-ndfa3D1M^`UKTjjZfsfdKTYfruLgMbhL~d=;op zL6cG8xu8{9rEoGCp00Z%3$NpDOUp_AwV-@rp^sFln6Z$ePNBmF5KJYH->*v+N05aUv8QH;4 z1b<#xOAG=8`_hJyoQ(YG-_kHdeCb(05&#q0n_4C;6T#<`H9piG(;bB!#(BqXl>jP8 z0zl6+)1U`DpMGeJdZUhNFH%IGok*N@6o3#6`*)ynMUMsD8Y4r6yzX%^yZgk|IPj`PV~FxFR#5JI7ED;aKgJf$B3e z6}L*hV}}aRc@>W<(c0-_^HM!Oh1*?$`u6v(){4&ifmDseOfbZI*DJ&JDuoe&m^IY1 z5+@kOYk{5IkD~NA>l#Ltwjx9b>?+k#Aax&oB9p;CI=a}CxQYH1&zomz5YYk$mbhf+ zF*L@=Ai$ylB$X<&)1_LfV>z7FZL-xA%;!!I3Mm^*xb$<viy)fDf2~&bWn$vdE z#^feP1XHMmUCGBVVrl$GK(M1X>g1kNA?G%TT zpL0p2L}{{say>aUjOpzul~4$+_xqA?IGV~q6OLjbeXN`t_f z%z&!FJYZnvjmB+@xxG9ntQ5Ft*YzdceZ=DDUi?-o-Y=?L20zA<`oB_RJ#g`zQ8OYBwKDjv))TV;!7;^o`*-11=bo$xkQB^(>ebZ9BsM1^ zYMFG9PlH}QySZJRuEh7VBo`nYg&zL0Q}Pn&!T_Gz|J%YL0h6F_LT0_?_XS(laSD5Hl6y1>Z99 zWpEj=(kB(#>D$k8p9hBZC6A(Uh80rsZ8|scE5_@cr-+KntkS-XwlR=#n(6p^Ev1Kd z+D~pP4~n?CeEPBbt=_a_l$5)C9PHSk@O~%znUhW77j?y*Tt{zu*53(g_U{*MfH~=1 z9|=$`fULWK2e_-;6pnN1C5@U^?W1$l*geg5H9jw4^p>nx zw`oBht*mngtXH2)K!b5e3?L9rTjfloDcDzQ5A?V`)d}K^ns32o90f~^0R&0Sa(qhJYi$ENdskV6f;(0nVwOgkIEbsTOSV>L&b#2z{Igs8Jx$Gv znIPi>-npUGuNGku(reTBpN8LEMf;0s%05Z|0Bw2emaUBa=&YRY2-^GILj^nUZjClQRG^*vB)IL42*J@)1fv-y<=aHqe3?;1j{c zOvbk^2Tjaj@)TB^1bNCp05<|KD>ww45JH{?KMK*MZTALO6s(nY==ziTG42EO5#y>% zl=!PsBj=~FU$4{xBoRM4{CD~>m50!0kL^7CRjKs+wDv3Z8YlRTXpaXEuKxh?CHnAL zECd0#^gXGqpcyO;5KtyWimb1zaxjyasao)3tK_wi5CA1eIL<#B8=P`CMmdTM8te;% zAnZETv26fQH)AtVb>ud1T#fY?PymtYpT>^i8+L*zSkOxV z*dOexWJ$(iW~v)x2n5XJQ?U~;AdZx%lB+JT;Q@iuwO?%sM!3X?!0T0j%*n)vt$tW` z2!2@Nvd&erqlXh}iou<#${=;>YpJ0;ZRwAdX0fOBZ6^o4bhMgBM=Tf9)B(k2%{0{= zj)M&QlV^X!CvUBRBLZuuZNAT>NUuG2#2dq{ZYepy990@$j1=4o)&TFC5=)*ORyLg_#p?YVk8&T^Gc5E--sxf#R^_>2j^K zc6xtQ>2iFrnmq-nDZKrYk|as17iR8Y8s(>nDLaA!J?lbiu?)GanK8+Hr$-)GOKF?J zhF~Cr7#{SYS#T5>!Nq18k#Gtnu2q2sVk(shGT!8BAZU)Nm?>Qby8v{OZe>e`r&Z4_w6~?F0?Ij!qBXTH>^k zmQ}WcU??OMW|57(4Ro}~83sM;51pqMpJ7{M5CVctbac1v?EpB6r>MB-y9G69)(@nS z$>ynY03hJiv$;;oc$~203a;&``!Yc4Yb;ljL5It0*EXOt(=k+DZ%?KKb@r`qZdFv; zP)95|KGl}%1yZF4&#&WJ6IY_Q?#$0&ThvGs&{reIb^t7r06j)xx{rJ*Fk*3oTyGg- zme%2PG6@;~05M$-nMui6#`PIOI2p&(rJGlg9tmtn8T;#Zig+fP)_`g(GVkQ~u2-11 zVed+SU=nj$uIokBTLGHt@BlT`l9k4td!An&Ob!!MT<~-BdaY)igQzcUPC!4EbTs}h zx|@Xx`DE}3u7-odt$wcFWJ_evHNf$0BH6yzQNYF_qJ=DZSYwepUdMY+ zuGxENG6p%W<-6OIdVx|VycdSw)M_$Oi5LI_{A<_vdotKnVYH6*ldHm`UgulVI>~17 zqoi(30td?`vt76hgM&S2mq5O(H$x_}>u$D@cb2xr)<9oTteCO3^ma4nSmN6}_r#jD zH`31h46x{Hinf?HrQj2|3b#^j>osILGPpSoA}c~^zzU?s)04^jtG$hUC@7=nx#arH z(#rTA(FNV$6Wlz>d&Mr&(_Q!4@tNvyXJ`OtVhM_QC!J0qEQMMUlR zRgrGW$t0d@rvMm%#bwfz@&G`h004^684Ct8x;oc8Ey`AUUY8j3l7EoxPdLC~7> zckPt*7n2~xdVd+VP=#fQ5+~lg#-UgonLJH&dQZxEzg9_QGTqo%5YM>tJPIphUGrk{ zp+qhVhC9fQNPu!@69We{tjvrKCx{|wpD-jVKpDmi{OfW&?6$==SST_cdC$FAZMC;6 zb4>fTOn-;om5e9^iRw)V5LvH5Y#1@Rhqei-p{+Yjx#SoJ=U$`15eB7qh;GDW*Ot>2 zJ3SGYuVvsCywahJGDJ+)KC!64?RqR8Ov=5{?Yun(#oE7hb*zCLXYh*U=`Do{rc91U zLtSe?g#aJUyl!^8kFj*>po>%hO!T0|j!Bv-061KBnavV16qr2LV^tNf!~yx%Yobgv zebuUB3}jY&(q=~>^{K~XWR72tUhu6qgj`ktTq;4HNw4Ks?bVUf=~vl1PJD9Nc0WB6!AYLf%&UJCEN~?tRQlcLGlp zd{RbSvbxv>vg+JIFzQ`7s z2Dh}HPtK@hV!#0dk=)hRfeZxhC$$KRb+hU>=)t%T&~L;lN%Z_zs5A4^Sg+WK(sS30 z*W<6zi)=5@PmeUt{{V`$91r~7&3?p4SSRzXF%auv{m~2U-hp8dc{L#19=RXH~X1P-R9Z^$1!KT5Xa;{O0f#E(zvUMu+dntJ*B zcc})xgMO7zqh0iB0UN(o@oDRiGf!VWH5h2_b5Uns2k>M1^2*zE@5IOBNG1b}Prhl4 zsM~@mIXij^Nl|UzA%&7oCV|9(@~BL}CyD@rA`LzSJ+OE)lNl7G$Q|Y=h97IFsBi-S zAW^{l5P(S{AP$uY3i1XGKwy*CsqaAKlTBZeGUq{HAc9VFiW~?76jT<42Pg8PLauVe z40flW#?GOpy|L)X4+YF%y~|=0uE&n}c#E@~Hhm zBG3Z*iw~6&TL*U|r%I}E&StI1E9&HNM4ckY(=WCHko&SY0=9+>cMv8zo@*VUwGHyt z;KFS=Zud?Bs!k8HCS)`7h32Kg}hfQ+xd8s50Ol1Al)P+SO5Zu;p4^yMCZaE&K zfH|Xb;KPzklZxj}+^F=uG*%pH`45O)2TuwYWJG4X?Uy9Wl0wW*MRv80uViLm;wy(~ zTYEqeIjuc9sI#Bf$?qn4<2AIZ&+ODH@dC2x_yeVDKoz0Ss8^rL^nC}Xj*vo; zAQCb7(b!@Jd*YawHEz)46dOlrtj=25vaH0~a>f=1X{@@P3Nr$2i5+XQEdmPh)`Mx( zi2`bH&f>~4bkWGEo__C#yJXtj7m|7kZ7qRpkR$=pW^1>1O>Y4d$5}H~CY>aL42rw< zmemwTpp0eQjNvRSma>LMB%FKD2&&$jg-GmcYgt_2V*?b4r$dqtek!+{Muml~89!GI zbll!l4gtwOeO0JJxNpQ}w_F~B6^B)!wS12>NSf7h=~71c-S5p-x|HFEzjIsT-5sNonPZ>JGYfbYlH^E&2TD`$ z^_-hbLGL_QP~Wt|AOrKO1@W~|#?g@jH9wD$c_{sdrI-6r%+vTzw$K1wkfwR6^-w2Ac92K_{$cxz=sm(O5goshEQ`Y^NTfcP>nruus$F*(Y&19}#%ArrpKT>F+R7 zWc=$ji#pe|UhbrZPBLfitR5+KwR+N6$EyI>TShHe(HmyjU_p_(C-1I`g2#;{wt0t| zU0+o>N$bJM(~H-2gUq-Yiy17^N%yZtEF+0FrZ5b1UT;CUwSi3Kv7Rf{+1j?qRc*jh z>SW^4XQjnTF8$6(%Q&Caij$E^v zxjO)27%_zz0~F;G%ZM^fQl*zKXiOaDNTAE+5FpRWn`V2YSS|Cu0X_JqI(vBlhmN3P zmy1R~V;uFXE%|#rF2nd53C1hREK4@jhGhT_GsSxU0EUF1GI@;GklIT6rzZe(uV3)4 z;Di^L#2%G{ul^C}Jqo{Tilf_U0E`}$(YJxmwR1F$08DoK>!D^y%Sf*ymy_!_T}4rP zk{AYoM1ossYE>b9QTWjf>XX~0XD>_KR)~UR)mKz)i0L(Kudrxx906_#399Q!lMxV>QaS1+_JawI6rpyV!GU4LF>t_wA%WwqSoUX)#R~2Z85F9jME5Zh zK|o`+G2X4o01OC^x{(dZ*%kiEjw@Y+Q;5%KtY|o5KqIAS)3)1zw;1ESDkT|LC)BUe zl1lvq_~L=I4~j35{{Y(dYxV-VnA}I*Uyr{=QmcIhc+m?d{nP3v{$kC3zh6vxX0*eE zaXRn+03u(n1MMt6(F1}7HKS<;)s;LM6gR-!41Wp**5QR;zA2d7u1kv~{?V}9V>BS- zqc8;a%`c@ITu(`-S0(^*I*N;R$Sv?_w&!S6k^mg>Mmm90b-`^}2w*^vDGk6zaNVff zcn(O;N7@@eq%Lu^&&sUhW)TstUZpp_WR0k0}^r!;PSMs4INQlKW zl4Jr~6ViKBlE9KkgPLBD0h)#)KM^^pQ{+UFzh+GHiez@T>qa2K$UIQM;Pc*!q~IL? z02&zA&_YCs%;JDKgZEK=qZ9thfq>)=deDVvkvRq`5XU_GQkRG0{j@>O0TbSvv=)ad zzPn$@p%OHj&0#bdGoPqXT2t6{~NGfVfByc_h) zH?O3O#GKcu@S=9E>tGNJw^LqIO}^Tz5$Pr%8ufk|aTqK#EN2ymto*ck4@LeV-m=62 z5eBwfDpV3k{#An8F3}uT+awOT9S>UIW zrrZ&OHIi+mqgq9QPy;n$pg1EH5FNcHX~6)JS2as)wIxMYQDsM3tH|KSXEm{Gz3i+I zqDeg|4WP3Qq>iJH&YF|0g(D+c5=kHd)00%ZtPn9A16wXMND&_@%X%Zy4l-(Sc17sL zd884$>wwde%#&N)Q$aZU+^f z2{&c!nF`0K^VVw~tX;nfoB@p1`=Bo~BZ{Ks-M*qEA8ON%RQNOHk92A9d4CnPs6w_y z@;4lj&0w>q*S?}O_sg4kAc+xOKNfLkR&SPtJjm%;d@E4;J!Rcey0TvH{A;<6Qdq7i z@x4SLE~~aprGES)J+BkFq_{0>)6~pBZlHUPmDIJYvv5s^7dqhNS2^@w+P*7t?;sh$ z=DD~0{{RHmI$KyqJhp0o3K^X(O1LQfr#DEur?^{5`8|GF5ZG#imE1%S0c-i0d?z{GwvirxFIQ})j@y$iOK91t1MCmkx%w#vD-ymLKku{kHB$6}1Jt6oI#R4sV6*#YMhiuD$QM&JPi zL{2M%@cO>%n^Y7txb^v0eNF-)+XuH5kE)k+^mY9z31G92<0onm7I7vGdE3O3&Q3m6 z=)8D(Ou;-zuQ#f70DBDMn%mMf*p4r&I?DZu6^8j?mB5M$&i4Qr_U}U2Sz^m0sLm;v zZGuTw9BsxcVZ%+;mRXVv2!oS6RC0dKOo(54sY?kkNSTw;h_uW@Gf870Pzp_|L@Y_# z*^CM*jOtVpdx{NjW*p*;k?R0wwGTvT-7)Q>ZDlGVCW5xhfGhx~uUfq~GkSQAO=Y|y z;o444Ok#xWoa5M&Myre+_W%Gq1>(IY!nfElNWuJhuOu!s0fQZLT|WcYKATdYu*rh8 zpQ*>+jiaIIy;{T7MqUr0 zLhR`IxS7DB*Of-#XP6bwxvRHrOEHoU6%_}5W&R>NHc zjBj3kboUF(Jz_X18MW{J5vzjhr5*@gGUlVEA23bp5|v zoYvoFY%uj(Flvj;ZZ!TsDs4`zU)46G#_NY7pj2Q)WbkXb6xSz$oRqFGcE9-WDz-ob z0o?YcEX;KwuaSYc$JeJ?ll7cKbhlF)eP-sUM>n^!*5U`X5YuQGf6M0E5}D*p}`S z$eR3j`Z3fWpsySwG4WQWXa4}0S+Ce)Rs_}Y(m7pgyz>2c9c=C!h(7eegaI2Om&{$H z@8hLK-E_{_q++ing~H$x-Ni++UQS2fLut0MpnK+M`JkC&1ab-Dju81Twq89Tg#b=z zwy*fcX?D%Ebht(`CYO60Z67(sE%*kISh5IjP#t>E-dOrXd(&k^x8XpE5`c;l_YL?J zg2$*;H+Ko!#6~HJU_DbbfEMdg3idvFew9*BiG3SMAbzFdqyCo7eEGdQo980FgMO8Q zr^P;v5pv(C_^HXq_qHqN&G1VYX+376M_&cJF~8Q?oyjl;DMn7i(m|r^H+p7gtt}5n{FSh z;L~9m3k{F7&pZ*u2_(+%xKmuX*IUfF1&`xN>yCq^E!M&Ft^mPVhUU*o21&`7%u}y! z-RWDXAesEB>{PiSBta@*@lM;B&!^QKMq;Z4%mO3~12n*yFb{szN$hAllrS+Loe;>p zueB*MvN?~wXon>NNQKNt^QE#$(J)wcCZ8d9ZIC^>`_+Df8@CUT&0LopSvG~zs!Wmn zX-k2{TQ0S1Tt$0(*n#UMa1UzJY5cpMUKo+g)*m?A2HJ5s#ae)p8S?`bOrvJ(GpQ=% z=m2hd1bd3tr_#O9SONmfVzT&lo!9O}k z<(`r_ekSa$EsWJFtOCX+sk?oyTn)I9KW4OBD0bUtDw*I+R;3ph(aUpLCgf|-pW2{n zTj1nOW3_sp4`S{GyF>$kCS%&Xu9tt9HnevW`pw?)Gf9U6d;v1Jf~DZGff` zq#mUSTt8H}6?)rKxy6=a%^B3y|xk~&g)z49h1p!XTdhE@Rg!L3$pv1wx?f$du# z$rCb{#Ck8%+Q{F}LMy7M0gw+JOq$Q9)50t`ZNs6+t*2lRtF!?f=DGQ1+cm)>HRvo% z0DZWu%$tr{0Ie*z-M$!-Hum?b*hi$2am_gBW?Pm^WJWUt#bMN;SSro_l=QB%fLAU_ ziLCdnEyaMDJ!a4yCRe zcCI?1Gb<)4t3CmK`%B$z)0wOB;*Kf&SxDz~Jw{ykzh=jZj2;%(lKEnb0Lw}5Ueil? zf=FTsz>3Ff!K~X0=_IdHTP>hdwo2_7HD6JhIk+_XUq_dtPBUU_u8S64+Wj zsnj;2=qx9ICcBbD>>P{<@;x;WUlGg7O3_#rA#Qdso$mCU@ zr&!_L^bdk*&6I1co#r|IRnaWlhGT9%VzYQvvu{ZxsmUaY&`h1sNalJ9t0Qi0nmSml zcp{8`Jl6jJR^FR;@c=}7p7rE)HvY6N1sReUPpgu8R^!h1Id&?o=}kMI;7gWK2)5PdnM z2I39OWqr*mWzwsrXLV~^<)j`eTDfspFeRgUs#x z+C5LDejv+(AH$K{@vj*1MsnI!{fO#0u2z@h9}uw3Ztw!!# zNL}6Lw#g%>TAm)C9d=44e^BeXg)fhfBfsoV5Y}n+K)g2jGI*N9X=dt%AW6n5v%@rr zIp>b9Eqon!&GB>w;^s`a}%hV$Q5Y!Wz8 zS+3o=d;7;GdF@C-001N9OS5)PeMDt(OHbT;`g=hKm3>^EK;%@g>jg1~i#7KyqYDy`tOuflY;*Boq4%E-emE~9t{b(-P5YyZWFr}CY;~A*%T;1{rX_7>A z%{pvl8;qH%^CSQVSf@Y~KyAe1+M84mdm&aFnUA$Kb%1va^qwhYLb4W_{{TNaZ8#Kx6ZzDQ@B`DcIl) z&oqR-K_ll&f9)FjjL7PJ4I`*D31$F&nj!$_aX#}T|IpIya;TZ&3y^|D$Ewvo1j0N{zIfD96FJ5rE6FnH}lUQs;(rA#m9 zQHwF%yMdfhh-sXjPqhJpr-MrDZEP{R05ch=a53-FiG?6R{3%!%=d4ru4}tR7Ka5nC zfVtc9pd{i?-9*Ur?Gez;M_{-N03?X_p>5egDzX}R6ai5(497~D9OvajUgJy~frtQo z^kJtM`OuQWR6)lFnk9(^k6L%^3+gN?nV2UrM5>=u{q#f+vG2^nv0 zCK3fqtG?$(`(i9;=KjG)x0fb+_l06BZ|eFFK(mB+vqweWPcMTqHEIGx8c9G zyud!wf_hg2#kJ3^-G~za1Hhx=J|lBf_+nRxu2!Psl`WDdX(p?|g{R*>O}&3x7Y~7p zQD59!S-P9OK@SAYYPW4mfwl~j@~kQgHed{W)wb4R+Y`9)n%5?BI&JBjbj$$|JrfxQ zy;p(WvJuVgs(*BIBfWWTIue^wikFYt`|34b%qrDs`C1h zqtl+Ia%!7JpcW=O$4b)iRaviz0=0y2H(Dfo=f-K##=ME7$cQXUxyNYq@b%OENL{>G;fTTQPD!`Tx1{y zKFulBYB9Rg1#hx@*84~l$x0U?n2@CO^>QmRoP47Cc4o57-12>@({CH3Pcb>AVnoCM zJ?Mf7ii;$;39^hOu4Z5;9MYXSsU#WusDQzD9^?$sWiihfniGCU_A|bb9Y~Q`Zg@qz zgp$KP)wR|qYZC*lXJE&yADvklNpQ;L2+LAA=fN#3#mGM{DU-s|*q!U|HKOO34%sqk zA)nKdXO8uuWXSZ{O2LXdNTIZ5Ne&N6q4eV;AJVkk^tQ)%Dh!yC4RX9oR@!Yn%ZhzK zNUNZyCXzGfo;*==ehy!Y_-*C9b#HuZRgk8+nqL;TY?E}8oKmle>b26Ei|oM28ROcz zS|1D0zMZ_=d%o!gyDRrl?aFw&eNJxvlV0`@?W-4t%Tj*or&G6EY*@GIB;=9BU1P)a zV(;vgK;Tt+#9c0_MY4r~;28#^4#fUK%#SmJdD`}LYF#_%bly`4fh~&5XIW$to6b%N ztrsu5Y2l&?=~*plkX!|c&q8rTRo`&(NyWuu;)$q)Ron^(izGK4oVTi4(zPHKe=DL3Gk+7W=(F|ZWXrpeyYfQ}s zI#3$tGJ%81AQ~36C(3(lSFr6*=Bu{hfQ<3fY)M&H0atn&P{YfB< z$)~bc?2ojQfhMU3UgzOdgbOIdc)| z9Mxp6A!K~&YANz(oT^$jCbHlW=QJ9n?i)Da=dZRBA>%i31^h_ zz^iZ)R7@P2fCF=a1of-!UqqizBj;2C+qVK>o(&z&%A6w+k%A_A_Nx&{UCh($Dc`x5>Ofqd*@(|Ia8>1r-R()V zusZ<;IGR$-7b;|Nwxe(TpTXrO}k0U%%wX|U3}ar2;d8)#SsVE`Hg6Ck{f)NjD< zfK&|IZ_0*P%NVC!i#tS~DmK;tGy_MF204IZtx)P1$S^sl*|&outp*6A1Wa*EP5U1` zKT5J~*Zmn59O-;uW7_7M`q$5$LmkjFHS{C&tX%`devB4yG@dhv{{YHqtLMe`^++Fm z4C~6w*v|R;LQZIDIx$~de8@+MtO zaOxsQT1i(U21q7w4lzO*lmQrQ`_l(Iq5&}(=};0E)dc*h=pM+1W(OjqNr;Lh?mLw2 z?f|G*7*i+jr9(wzFq0#<-Ao_}nd?xWL=}P1nt*^kN*IcezQ6=q9RT^z0G63Bb0dl~ z0GJui9MJ|z0R9x7)u05H;EZ*OP#Cdo!<A#svV)zXk|B7n(}^jD<$%i6io$ z;0Tiu(sF1BEX0x^Vx+#z0B0HMC}0u;Vla875~pV*_B2NA)5lXo)L*Y0no)d?h8vq~ zf(fnqG}GD(=1iVo@mX!%D4_X3pYa|?e-8_np!}%j>c`NXp%(4 z3fZP1wh#d@b1fFtA*Ec&yuJriTS~}We35;i{=DHRS5@2;Bkyv!& z0gM0-YTT&E&_FUI8Ll=?bbBt9G?BJ#F5fEiG>oeZf&FUaVmUu5%BCX&babbCg4u=} zNz7JB#@>#sA8Ok+rPTsS6k6jI-XH>Fp0$B55=5aOXXj400WcZ|Zq-Z2TPCt!29t5U zOD8!ZxqACy*ByQ9r0-~ewym&e^=4|ewu~|XpW{~J`6Xp}7sQK4oqOI+7#vl4e-Kt+ zp@b^HmD~|`M&|M4_LrFQF)!nk- zw+aaWU_h@W;Tnkw#BS*`UXM?F6fD3H1alcYS1YQ-)TthWq|5O!sU1WMxk~`imRZDA zOsW<`0h5WW>!@G=W5=~d)PsUXcs})ywVMfa5_aHbX@^!(1Eke<+!9rk8N{B3tqKfI z3{!7gACe4=bM4-XTmAATGxMtgg~&Z4G@$h)L8{Ywp_Gs?3i0_>Pi+X52j4ZKPay#W z@@lJrKqLc`Gt#U;%eehj4m`-yqu+gn$0eMfQSV-o$VAhyNFLno>xLQ?t}tOr*zuo%c77&Vi`)H5q7^#j|AeKw?S2{`^#o+uD1yeS+>oKY275M`2| zPV2y?@wcT?O0ZclDJ;0uGTb*g=o^a8w++h$O}|JTIU=gl+&08GBW_1o6{E99Ip?`6 z;OXny+NnibdxRbH1bbJP@e4(7`J{cQ`>WC2*?Qjjf<%)X*Bf5J>@~fh+$ZfE;;iZ4 zYcl$rR!Fw~=;6DU1TYalh^Sm#GEb%;N#didIot<)3Oj*cSOD`A(z-f)9$i}G7gXDI zU`fXVr3gvPpOrZaFjNpa$^JDjS+#9d?L5v8wGU$KZrTvML=o2j@+wbVOerYcQnf@Q+){F4%6igh^H7&LW?pqm9GF)VYpx6IRS^phZQ1ku}} zsr=N-7;VgEIqoXAxi|x)jLj*y^R?ALIn4zU1SlignvId3TU3SJ0J4HiPH2V=f}%Q9 zoE#Gv;*>JscF8=|v}W$1jvR=kID;es&Qk-6X~`C=$4p6OK>tqz~v9a6+>IJ-g7}0`6O2PfF+Y76fiTD5D}|&T4L5qtP+bbwEM= z-aYAk7^TQPAG{mM`}KU@-nkX507zL^v{sL#<2{TgZG)O zI${Il6VsXoq#bkx|xI4xi3}K^Y|b zQhVAT&{x|30NwLID=C+syi*H`FcuFU^%v7J)9jha%_(7Q zKp8!0jQQ{SRg?Z5^kPeKrSY%&%`JTPzqpcRq;X$C{{TwH=kY(I5r77h#=q+{we#x# z0NNxe6GKN=2k>M1@?>B^ARL}(0DFkw`_r%zBPRrkMnApVpOr2NxROA?8R9zBh%$XK z(24*aKr(vKWw;^+dYUbfnQlrWNTK1QGbiOBNi zrAZ8A#GK<57)}Hj_oVC+@(sm^Dlt4BO(Xz6nLmv&{{Raa`I!5vZ3Oi_jMRke8@8bh zFnBaqe%xex{{R|0v5dw!sp=v}ryq?$=$NHk!Je>sQQS-rNFyIAVV-_;s-#852X5|t z=xidrjR;lHEM#;!Calw;-@qMyRhr9rSBBOiPuh+Rbdjz*`IlSN-9U+~`6b$Px^?j? z%PiVw-7=mOj_^E4al(7y#o2w&{W) zP_DNy2|18!8M^If%K#J%57`qnZjqD{XA^*W(wex?uuHclk4d7o%Awql7)TsVcC?DC zv@-=Wk~3TlCEK@LTxTQz2dlMuJrEZN8%{)Ln&fpYquTmyPLevd6`TdOHxZl(tu~Z_ z0F3qGve>u5wg@18?QgUTawi;-TzuEy_FXz|th>uDSI7m)6A{<7QvQNVpHRW?S2PCQ zXcg_8ilXl41Ub%0J!+L#M!8x=X7E{u5%Z_Fcr-%hW(9C{`n%d2(tTEe=e26nc;&4~ z1@6w#jBqPVx@mUzBbyIVhkM5-O?#e*<0lE4@OI#)Ye zs#{3z;S>Ql5nAzMa%m({n<9j6TpVADb?v6p3ku4wdlFAd@do>g!7R4c;Gg3)v&DQs z>or#|Is$l4knSrMm@Umrl5?3A>bh(z4kP8BtJX`d>Ra)``yIV1lor$`Ny+AG&@cx{ z=@E{-YlC#9uPED6pq>ezzPn`q0Kmy03{7L|9kl+ZZ=j_aL+EjIjb zS&9_A6Kv$?{PeAgEh}9Nt{jBV-;VEto2`IDDwqS*dLQXoRjq_! za1-hDfO_|>ZlRZ9xzBpSFD<455U?jKC+>>djoPD!pHlAk2z|DIl?+;Ulb@9Zxo+5F zaSO;hVYof%SUZA3$ejNGp0xplG64keYRWSAQxqM-W+3DWjQjAm_L+`orL;#5PbZGl ztW$OrfH(&=D^)}vxZYj~F~{3zroLL+L+ge_E0%e2u?wIT8nc zC*U%0$>i*rCnst z9CW8@s2bkF1Qs19J!l>b4hV_>G{`eP^=FhogP+cny@4+%3nU5Zd)BK3OJlApFRDO2 z1!~hlFi>Rk*iivjgX(|i&O*OHJ}SVE+I&;1G1z$)2lB7ih#+J^ugL!ZqdCa>0r5ct z)A2^A0)6aRuh&7ha(dN~c46xO0F5u@{{TpEL0Bs@KmZS+po&wtjiI1*#XYfT2vw3h z()*cp;9&&rxZ>T6%wL?<8_sk{UBfS|XSpi}CB z_)|5aJ#ZW({)``Me{2gGEYK7YJq;WgV*zYl0MGa1Q;~3qnt)3{gmFoc|r=w1dc$Q)Q4CQO!PUb z_NQ`cz+^~i$6Abs8}dM-a1ckeEQpN!smaU}nfz#4TemJj8;Cgo{#6py%@!#RL&5F=dV5wbt1oPA9q&u&UP*S# z$l6;sQ`FH15gb+z7&}OXX%Wsp?XN|D%0L|vRzL;`HRim2@0!JJlROB;VZ$$pKcU|1 z@vJ>NN$lf2#=QGv0t_Cs_bi)MnJ->tl@6#f8|McYt-4(hww`6k-4l$~U1BS6Rzk^+ z2eGb-$h)Z?Zg?dacTbjKMGQ8!NzM&5me@)Fx!|0~%9+%w3rbdcl`<((+aU}C5)4NM zt-o^`i@hD+4r$sM$9na8MQs4KaMS$Ch=0Ox0nNHwCM#r)Zlw~9l-n{;*+vsks@p3&-u->unT~3!H;PYOs)2Tl9!N=10 zhO6EQ=P-T8*5`x7j<^l^Eo?|lBE2|tk2+uw?34FW0>hzJdp&~H>l`Z`SI|2PKVZ`m-l&Nx4% zse8lTN4*LRR%k2$JD7ra5hAnRxtYfu>ZWzsJB*TKcB&rYW^M)kb$nrDB{dW+`@2wm zsh)ZY@&5o6c(MllOgjWW-V`!GuBVT9>S%QAmo8=qRqbET9{tTmt={>PPuk}uyS|^% z@8ZkB;(rnPykNg(#`gIyyKn_!6rOpE)xI2`wGLHbdFfg2oxwo>Fc1h4F>Z8g-mQA(i)Y2f|U)oZ2n=1-{eHO8<_$W#k4h3i_y+peNF zZXVUn$rma|qv^7!CjHKSuqC2*u%3df@b^|*XqV;sh7ksn#1h`n9Y{U)*F7E4LK^#uo`wxrijhebrX8S7n+kf)rqGIRddg z-PtUr2YS^QTC~0Lff$Pup|;_KvOXXoYW+- z>^t|Ns|zjjSY=QF7z9-F%*aeZHCPYqW&vVU8-zGL}87I$UBwIUw>)ZM07LQO~y&)uB?B&#FJ8M!-K; z&3(X6tKw~B{{YQe75d;V)#kq?evM0neP4CNGi$OakM>!l&8ypfadxJw@`%qwXrdC-2RtTemFz}$ul46_|k4_?xvVpaS^`o{_ z?2${J1BPo1*3ovT$e9!k(L1LaWqe)2=x2& zM3})6Cp4-SWK5bUj_d>0e{=@oO+{ythXbt=pfrq6CWwGKNX12yp-Mo&fM}@%ZQF^W z4gn^hfYCj{%|_VL8EjfJo11 z%{bu>-sX#!N2g^|Zsu!NpFwCSM!G_b^O5~)1-Bv8t47{Q?_2F$0D$FO9OI|8XPT9A zbh>|p2ysuOyX4$;W!HRdzRIfc*UH zopFdUKPauZa3vZzU2mvPbF;Mn01>mI+qb3w5zup7_tzVs?nMH5?O6A@0gC|~0W}nc zJGPQ1in=&s9|kG)xwF@EHrl&rG2R_aLdSXF`x<@4ou2@(<2d{3os6mK5HLuL`*WJm zl6I-d?@^Yvi*dI34xY<-o0jJ$XSI6I2Dj)|-ij1)5E%T0d8aF&*n4Q+Xq!wdrz(39CJ7GdK)S0s!nQU9xu0?l`V)lJeZP85%(nO>9Py0LE*B zk`lT;gVW?r38P1tNEVr!Z0?SS-jrKnHz@>~SSnSU_qg{JeXtn%7)c@o#ZxZi^lFVy zkq(~YdOJKdO%Hzpwx=eXu z<27fQ(|k9pwU!F<2=#tdvrXYwEh7txBn*7(zU+kq6`YaGR(7AVP>Jb7>oQMFs~@Id z#raN6-wL&;U6)W35^I*<47!rKS8z$duTH>EImb#%$_q+*K*$p&r4FYgeCRWJcTbmc zTlYM|Xna#n85-K3-7Pt;hL82zMp*z~opha402E~NG^!-S3}-btbq;@-72@b4gK?7{ z)#f8OXwPb}T!RGQ8RweMIgZ&hR^U=#1M{joJGO7{rOlcKpyaE>_ND!10R^KO9M(&h zKuyLr%s@O<7cXr=ah-O~0Xh5Xal+YL`jr!V>QG9C#~$@f&0Vzxi3&b=t|q(2ENQKh zN`sSwlU_^3ekHwqjk|6_a6sm^VD$NAcDOj6q4+`%r5kW*Ad#Hnv-#w&re_)5T|9o16z)#XFQ4&#Op$6argS`4#O`YK zM(>#gSb??-e2rwcaYGg?z4P9vB|s){Ffp1?vUvP@*IF2q7i!@0Svra4o5?Ossdm~K zxpQ>lIju{p7u(EGpb_c{Kg?Gc$E*RF!RuO8)d(6r>KQ;Gk6yBSRA-O4o*t#6zopi_ zfF8quV{T7Mze%gZ3x#Ch8RERixq3~te@_Rs7G_7~Ky zH8%@c1gQYXR_;Y}SvP{V##Bj@iotJHcz{jfRZan|wr+XgDMn$}Y2RLnF~CIxm57eGt6-F# zjCtoQQE9yy+W@lXq}6_Pz^sx1Y<$HMHrfmcs(dtV`kzsDKpea{3>Y`cRmI;0)Yqs!N*hcsQCeuZ3mz; zKJ*S`fJ}3aD02lt+tQtR6}|(KJuo7P4IvTL&m#vWkTD_$Ji+TyKmd2fDANuGCE1C& zY_l#JD6w3`2*ezH^nG?11!yag)P2;g`$AzsCQQ-hg;Yji0i!?XG|pMpQB^?^^Po1B z0zfgG!4(gv13f41sVWseArc@7k@x;oN!m*gWb~kB+l3Nwnlmawo!H_aQRE*01oA%_ z=}HL)bk1r6FSw8?%9FN0F^QmxVn?L3h!Q?jNf;c*-9TiMg_DWJL$nY`GvBzTL}$6U zt3CSaoguvHx6P4ze?Ao9;`+(Gg7q4EAV|*{Tep+{a&@L0F&`H zwtnQdU#(R@5I7b2AM|JvpI6O(_GMr9Ppm5+`WEZ;!YeTZNd~00j(=F!$CLYi(i_YO zGIP*Vp;!AtfVDoNqD2t5%i85Iz_fE6~6ercHoK!SOiD)z^~pcek{jGihJ1JlQ~LS0Oc}s0wB` z1N>^M*PC%Tk}xd_JdL4%SHPimuv-Ao=IqqO<>Q1yJ+;Do!5LnmQ3_YR@u9<@{4 zE<>|1Ved*=S_&|UfG3It!(b7ERVZw^O3`NZcu@%e$sp#cW|;t-3LEDgX-jn^MLH97 zM`5)OivF&p43WDX3|7otGsyID`ma-t2)54Fr^KxymJB1_xSl2P z2FqowZ6!|FCJC=UtMMDRrO9Rla}~_Jcg!-ohzB{YuTRj$J7cd8*|wgVE>N82 zs{u@wU|4$|JJC{x0C9}RLMgCcQIb#=W0RAPY1w-1WnRblP$gR9IaLYF34!vfWV;Dn z@B)F?{@R3@WFDxYcMZ-9NARmH+81|kf0ueon~~swxk&|2PilL1rAsQDb)@tVcIdrP z?SYsXY3~&JJIc2N-SX6eWXb!gyGGjqZ)qkV+NX zol6(3YD6)E{A-V_^R4QxB0vHN2Q_M3duP`r=RVZ8ZE8ZcpxZ2@^Uf+Thhwx^n=8)* zt80@3`G`p>GuwetiByvujtw@UgAmFDHXt06RqX&n4CZFFCuro)O`wIgP!hzn%ya^Q zErlXSPQsKB9&jhWN+)gxan_Hq0s?qu$5`w0qLJm3yCB3KO+o^JB+14^RD&{c9nA}4 zsv#Rj(Gk*w6c%~)Aio1#Qf(A?qblgM{2l(QE-S)9P zD#av&DJCFEh@*5xdx7^`CP7d~?`B0!;O9Ba@ijMa81u~%VMMg`7^!G)V!0rdV0ioE z=R|_ALV+ShKqLXUFLHZOJ5ZOW8bwm!4W%MhJbK7lTfHo z0R)lnLRtWvPZL6027)~&0zP!Y2_!c-r2q-^;EJ17rN1tQhS(%oHo)|-9>*ez2*45} zrB=!sHW?sAHL^nm$iz(48uCgn=vX|m*a8HM_n=ji)yOmj$iQDuwkE80QUb(d_4ZEPY(A8PEHo*U#Z@zgQ_C zVCKIlevQO*`nkAkWkY;Luj}n@zgM6*nz3+l^RM2^?jJEgB6HfAOFl@+6*le64AdKu zq~<$RYKq5(Oa&D;uTpsHLwEQyG{pe}bOL+Qe>lFzwow zt`wi6B_xkej2=Do)$_viZh&TZkc z0xR{)Gu!|P0R7Z}g9kDxm_W$sfGKeTW`s)U4F}Q>&MFc^3}ZB9XRdHf2512AC}X$C zPacy{2{=6VsHA}e`}{72Lp1GZe&Ri5ZBX1TQ%6(w@8#T$64}upZ`=0|VY&#McB!?&5d;$;(9#6xJHc53O!c6pO9gOasTnatZg8?Y%|jfS zjy_a1dLMOdmMze+E7KEDT^ps(f0a~GPDGG%Mc7>=w3azB12qR4WwFY}a*pTK&q`Oe z0W21I1KZw%mGs+E4(R(`4LG=>-}y}0=`ulM zfPLztbOs=_lZ?efxwB8f#|_z7-nR&43nYkK{uOw+Y!WVAlfg4Jf$lh9cs(PasHktg z+jhxfPgf|eU-NY40Ihn>ZRgd8MhBxOXf#**OshEcxl8Ln%Sq=w*XgCs(a(*HNw-2mv@xL z(Y(ua9jg0iq%#0a1IZu{dd)mWh~4NE=*}AP-0$)uC=eEC!zD zvsiKHVIO^K4y;K#d*DTK@>1mWSh(aVb8z(nGZ9RzPyw`!++&}5bOV^?u9Q1T5&(cb zs)sadj3oDFcV$))EyS3Js$JOP+MMQ1Zi_|6@OJWGaaFQg$WYQxGtCNV?uPM8+{P_} zcU%B~KFBalQf;VNi5=#*Kx{IMQr$!f!P#em2l1M=IU8j%#Fo!D;=1&(4%6zG1Df)h z`^|dbyw4JNiuafF+Cn{6cQ$1ES2tUt@Vjld$+AcIfyc||U0$0sV3kDjUa8P!%=a{r z;NJ28cUva};6$FEb!56)G=m#m^$pE_m!K&ADCX6yVP>U5q(9)zRX5 z-kIT&i;{m}Hq!-KN#``Bm6>u~(9?Gl}HYsPD0bpf;0} z0DaWIWJcAWZcSNi6ZC67$Om!E)kN)f3cwDB+O$Yz zB}tMh47M$BXC9~6!!t5PX|=lF@9k2#iO8zFwp)tW+Gnr%iqe*}q zIZNtwu6Q1d_(J%Fy-?oD2~TfoU;r~-*TQ@Z+VD`CnbMTIxwmuf?2)iit2dxjp_6{A>rN|uDDqMmXqs_m6xjT$t8y$Cs)$`4^4)B zXH!(uOKRWpJlBqRecuh$ZEcg13K1EuSW9Bw^Ku9vZR+0jvtO-UW#zc4W->{v%n&r) zIONAs?OjYtU8zfx$@O0jd8I60l&wr7BNLN7Gm4g&so%61959eQ>5=@lEp87Y2$%+n z6l-!>WHdkrj`d^Fohy1FW@QRMCyA=!_DbZebrYXzy5idb6*U9YvcQkBes!HjL7ee3 zNd`vlhAhfhT)`)TA`KNdBlkhznk0?Iw-93|xuq(lKmf@06Nn| zfI-1L(a5{3QMz(SCp2KN5)V_F85}ebnt&FGB$y=oP%2D0+7*u-jS#E$fRX$v0Hn!c za|BTeL4gJjN&#{VZY!L9(ke2QgTU%$gL<++2j@@{L;=CbijLUTAj!at%~*;Rgn(zP z)k<6(k_TF024RQHQsfizUK9{Q@TUMCX;^M>Nf;eXR$a+32YD1XHsUeuB55eHPHE{D zB*=_*?OOD}8;ivI8pyAZ8=sadUYO0!-!9bC1dptLqj-V!ZC$4$;x7=HiJ#fm>X1xV z%Mhu!_%eyUtzD#dhi`il6nuW`lOk+M0a3Uj=~^{Bf5h=Wl1laN?@ zQYhb%&gDLq80sn)A84tQz~+K0xC*n5q*Z}XVVvWrrAhKM+Tha29YH|^2alt(R?M}oI_G#C+Ev*U>KoWiGIE*0!@1-GDO}6{0C_J=hiYs;;i?oayJ3~Z@ zW?~L0T3AfeLub$b0MfGZpGG!&{{U?t&rM%D^&l2IL=S5EA^KJj`Cmouf5qcK$4~gJ zeDBm2B*NlidqodgI=DZBAJ>*=d>N8H>Z$=40!Ct-%S`8)p&=F`M|uggyo)3V9ed+7 zCO|RAN|7J~(0(*PDnHCn3q)BE7(l2AS%Z!!4^c8nI3IOP5=kTF?NLO64&n}d>M+co zf1L?{HiHMP4bvhH4r!*CT@aE$5KQFal=4W&`Qn=*0Ac-V1&PS$d&L|g6=2=zBrLZR zG(g=L$m>9`QLz?3oY6&cVSQNQqRB335CoiOnKUL?mFY~tg8)WjQY<+pvIRfz;ijN+dpYKg$w0iXj(mFpD)s)Oq1r&@4JtN?v7esvBxERM--lnt)j z9tf=<3x2Xg1{ggL-O{L4540$q$2DUv){X$iY7V>_vFTe2F;fkhADsvLKrFWzJkL-o zW|vQIR0XojDh^1hb($Bnp?7_dPv1~dUEQVg!6y#%tr%WF5y?IO0F^UsjliBW-jG3^ z#yE(~)q~LBs+i;0)wilKQ4&>Tv}YnKN(BAY^-0{*$f^MY6PccPtJFQ#YnLB$6C|30 zqfRKb!KTn8F)CF+nd|edC|D!{B#eVu?1p=DY{&u(o@=3Q%bm#07XZ)ntg~yAtJA@~ z0>r7_QAHJcYfg;LR+;;h-fr;oaD}+g9{*wO(o=XS$%qM|$#JC#-AE%W2r4Ir-Of;%^kT$70>J zy5N{e^mL5%uPLj%jc~P#J12$h_x^R+=`ggrql2s5#{T9#PM{c!M1l$A_pI%6 z)d7xpo+`_?-3OE&-Qc9{VzUJHq<8dNMF4qYk%}OZJ0zT&b_?$BbcZbO!JcUd z7!qTth>vQQoR&8pOE8_nkrb0M(nRK_k|=KZFSLbOt|}XeZA&oSwg(bTDv|x#fVt`3 zm5^If%t2;FE40WH(9v6JU?WTcJG=E1HVfGWp8^4uIW=SghHXrN>SAzyRHjlQ2|RR) zW=A4a76wTm^{Bm;B}&;;EWpZ<(zPw0IHkQkhPeF16EV}}R3h#O`;VwhoC@gpKZ>6Q z)h@2pl(?vfi2zb4x3zy5F#tl-#v&-c&*xX#nI%?MZh_cG3&MSX=18 zz%^%y_>k4>PQKC=-RglDtgove3v3H4bu*fbZKT<5Nn=uRyRI2!yYFt;ORiaC0&9Ji z+<|Oe06qu@_}4t_fMQtl1VF0n+1j%+*lIEA5e^HVl2QEM!4)(X)VxTdjVTh*~NS|RFFtANSGL_ zt&~;?cH;z@a0lUz^sjy1+Ah^qLyf8j<}zxgV$xgHI5Klnf>N z$j;iNbB{bn-)`Au3?z<|z@)e? z0zps+IRm{YE{VBb0VG7pqsShh4_a+jh}vqwwB?!ywE`rP0FG+VSJdQ@aDABKkxLZ` zCKrV#y%+2zkP3Qa5tH9Pg+w7na%PrE#Ka!BrwO@1Adlv1Nzn(lpb|G39Pv=RfHnX+ z)F#-081L4Aa7mFeAYv$L!|phnj=S5`c+WI;xZK3xeCY{Ez=ItRKaCybu`HvAid+mN z?`UE@G`ItB{5`5}B0%G=XoflT1B1;vY<8IgKr_$tr~?+0#QoF{q0d-68er4*L<7wy zX^}|)vqTaHS_*wwFb};jcmNcG!KIJ{PdI}@e&EvZI_x78BCW!R19wAN)&~U08TK^$ zk0+qxij0=Vnu^$1Ad%K-WSz=+?cSByw;c43x`PlP4!wICX*w0`y;*k3f-#xvT6C;D z!61*mu>cgo#8%xSC}OOV#vq1>{TNce}uN6Y)V{ZcX{b6=GI z07lZV`nFnmo&Nw3c$EFd-F~c81WDvohci1%ET7alCyf48VuGVBCZH%*GCk;RWHP2_ zy$LS`E&GfH;V961RF(s4DL>Al+cz-G6?m&bwiXDH+*Eb`;QJRo!T?|p_nv83I49J8 zbuH{i9$_S&D#vJ;fFl$(3qq%s2c<jP<8s{v#2JLLl^`f@J$M?b4toBpeu!C=v|7 zC*{(Z3=(mlzJTXI0ywF(fsCFh!P?tn@}yw9$r&8Q9!IpcMeM^Pnvpp{&q2)q3&7%GKmvQx>z)RBBUtb4&)I-c83>I0MbA$zqAIpE;(idmohQdfO1}4Hw7aZ$fj_L zvu`7*id7SpAdwU#s2#QdM=CyG=4u8EWc}Xt8Ks~s3>sCDw5Ws0jt*%rn?h`0&c+pF z_K)+5R%siWK@HGy1v4=oqQp-om6SklbB^7rD??(bD*J+Zgu#jFSLwo$jqS8a5yeo< zq<~1C{VCSv%X77{a|b-pKcPHtwb`Y8C(y^7^cm?^GQGw=oy{1Esu$8`XAmm;C--JZ z;shF{o1?uJ_)?X-B!B3hes$N>+_7)~Qyp>lRvi_xw-mCNoqQj;>Hdc&QKho3LW~oW+dV3Pj3q-1@gggJqh_f$+z74*?yLyorDO8S!SgrC z18M#>syrO5*wU7`8r_}jHb@KhvodQ=!Y#*^PU(Tv)tWSSySm(3m53Af*GBf2cAPQ; zCxU;RRWiv^rfuo^XDB%%onva?f($?v+|p@nxK%}9zyjI+b;&l?)BV0jAa$WJa3dgOww~?U^=>QSLbrtC09i`y;rhK0xZ}T$`ny|rbCjcBt zC#m+R4&$_2JivjHY7b80LELa7j(X6N43a%35t`Lk!O6SW_txdOwR>p_3j#S==t=$+ zRkU&mGYSSrU(TB7Y4dItVA4$W`{<|=8OeZszY29rVre&E+Moif>Ku;sE;v;S92xl^ zYEuej1`I)_Wl^-jXPINu?xpt^1B?5Vdc57d0x_PIVxrt%EG~JFdJd7-G%c*6h)_37 zk)OJ?*h?0Ga=@10XBAwfTSlx{+tV!5=|Q#WMj>;w@f@0}^{b3S1lkCZjB{HJ*JM;d z5Fn^IBDJdNg}A)LTUj>OciBHboo4urHrdi$JZBn-#!E`d;e&!_X%UQn3d?Zka*d&R z#w%W`>m#z-A_3$Xn#7Jy;L|KJImKv&wQS~QQH$(ER8eou-lP+i>M2psWwyZRN8v$$ zDgju>ApSKR{>&&unVIT;?5kQvZs%Gpv#NVuks#tk%+`n0UevZim{1@tV1F9GisXQ* zOLQ|I#iAwwPU|wtpLQyA8R=L zYTItFc$%Z&~yM+qE6a;vx^f z0-~tc(!>xwAP!Icm2rqvac^{D$rz`|n;leVdzAu7 zfhXFOINAVQ`*ffOR^|ycEP{PWBA0=A9s+`|&$dL;EhYC8TC~q9m^2B+PTg zLRgXu8Rmq5p+bQJB=w<-f*Bl$lTc!D_t6A2k~c;GrFd2=$l{uM*z3qZl30S==9g^z zhf&&@8*T?3YJShF5CmYFPwFmsCjfv?;Y95KF(jX1L8O7q9+OI-fiVD3Dz&k#h#zYw zfl-b@JCDwk0(<@x(SZ&A(MpDq3=(kJ!Ocb536f)q8*w{GCjt#J05BF$Uuthax!6!- zHa8D`m9t6%IASX(T>Y%U;nQrNY2{3hhYQldC zSIEHo%}bISiTDfjtdQDIqXV?!=Z$=(G?nwOQ}&K?GDUqB{VO2b@XwkLx;ZJDl5d~uplAi%{jBdm=66s36$bXon%fwF2Y;0?vPqD$iqQI{WgoIwn3#{c zsJnUYIVqdVIh z(8L@nfgX|8DN9@X4o(dRJ4k{^{uD%z-mDra1&Yd;h0jR*>8+J5zifj&c%Vn5$MNQ@ zvYVNeomN4Dcr-WVjdP;#$ZWwvSRQ){urap6>Zsf^o+`CvKnV)b-l3OM1Be{=>s3*@ zGHD&n1E#AbcQj;7L{&Z_)|$kEeC23@aTU$bYR;EX7#Rl#HEzD}ecM!=ZzOaTnd56E zofXw7^ws2~kjMdGGxyNsf?gqHW~{YoiWwkakO9XX>dif}QIP-}j2Ww&?N((`b7tQT zLKp@l&)V+>yRD={X?I?QIUosxHOk{8ma(g^1~*1rKo8ilqcR^cU_sIowj6F=5~B^)|PiOB6ntX;J906LYWJCJTum?C|RSOLO;fyE`+f+hzwA37|R zR?c3w;7!uRkh3-7JZPq&yv@L{C(;20K3DU2)4fP~{XU{oZRc7TLLg zk~295yHJgAc#Qdb-o$_j+)rPSp$oThBRGP6Tv23n!3JVPoI#-K0}(1c=M`(d41)QW z8Fm&VDUdo3dUn1Z>ael`00St*&_!8fVYq(l1Ht}u2|@_kO9LR!PSnyOlcHU?90h`@ zh*6Kf-23}bw$MWysOKE!i#G76Sil35#8cZUP_R-t^%``;{l%BBHTK;m7GOpdX8-}m z-AB#^vcv*137D#FxVGD$aR&w>pl@E|CqI2w<7C!GwrU!uwVP*daKKe>sCF}P*b*Zm ze)yyZ6SOk+HCify%;~s*Rso1T{r*&x65A&%vU)^2-wV8vnH?xe5=a1#^AsF1L3{zm zD1|sAk5^9hH0c?sx3CZt7EA$&=AO$4+DAUo6=4$KuGRklMmUbOWu&wKVr0bUy)Nx+ zx-fm#irD~B3R(vTj%ZxE9IEU^D!3}KB6|0$uU-vjY<|$=ilibpAgO`Z6&_0`SKARu zK3oL~(tSYYJ5_NjwO4Q_tWVChy{JIUCIkX1fJpR(00t&P=1A{Siz~?&dny5BvnjxU z2YOx3s8xXpx?p5XRj;^^RX80DDu6>5=5S*bJFZGQZ-TVJ7=zH$re1Em2K!A1p71I) zzbUr>PTZ4Fvoe`&!eq@KVha3;nI;J*GaP$VA%-|6j_Hqakxa7g5R>f&o7Vuu1fYW; zoKaT<6#zDQJ?hnE3n2)cgH?g%Ho_p8Bt%fQ4?==YOvu3O2lc2D2IC|Ho`NZjr#`){ z>Fdx?RwW_egX!XqMfVNHjO`g|p0vA+1ttLEX|}`?FgOv-MI^9ZN6R9M)`Z&xf|T~Ik~@!Anjs4)(>iR^4B2e-lCRO$>;E>LcT!FD^EzJkG%*RhI`P0 z2c_V5?Lk5zk_l>X(?eML{vmHf)GgSUsq3SmYM%O8Z6t z%Z<$w+M^jTBN)X9E~G%mIH*@?;wY`z9^ptilNA`9rU&0doMe6U8T+O?)R80b59wNB z+7F`s-gk|0#O%{o&b>nVi2#sCdipQ=R`KEAMZhjwQ{y-tyuCGi=f2rxIHh!Tu>SxC zKd&Zcl5lzIDRz*@nX6mUBoImMRpqh?1d3ZE0~`p=1Q{6Qb4)T0?ni#K2##2Lb*6!@ zA&3J6V+N;~NGZ39P*^|&ao&uX5g$5K59mmNApUg#C2&6;^q`WW1exNP#?vPw-->*W zkpTeA8Tao%pG*Qcftrztg9Ehz3_uMN#y^D{pz;w0CzH&N#)tw-0%E4=W9cI~nkv#{ zoP6pI=#ohXCN~2V9LK01x}j--6BMi!xs!^DR7y|Su6IKQh~RgoI49Oj9^BD@7o6|` z>rR%*186zsowP+oy_E$#;z)?7fG{W3&q}#fVI5m>BZ%Yr(eiGV*sGHR8KmXqmMm@Y zvoSyb5KeikQr*q|kie0gbm}XorSOtSwxV5tfP2-aPPTU=4bQ;#>6)flmxE?LhJTt` zIj^-@P{}{at2kYsWWgQgwdyQ{a9qjTkyy^=0I8Vv;-?2>GQq<|dr5{P6Nv9xQ5#U; zGj#1Dj-Nq#{{Y!VU=B)|71U1-8g(k)Yb0lij$El|v!>~CWPE7ESk z5^FBQfre<6_BC|7C6lJ_Nt-xM%k8u(=}tr#Bo%+h$V?W{`F#_4@28;OR2Xc z@MbA4$CgIrkY+lXdtjWB0g9tjgD0mn;kgjV`(vZcc=NFgxEMJ-E6BVh$7dUYnIJbl z_3FHS<)9q7B#*PiPrZ2ypqDno2|v3W_ODIRNB3vVJ$6@}nDrY$-dGqJ1E=z=fnB)i zGn&(MqTAcGgt3!6ilLv-e6$#xgEiEG(c|+;If*g=cQOPCnF54*@+JlcaYQK!8(^8^ z+JPr@4!MvftVIo$UEGMO_O|ZI$&x|-Raga%;%0kwru2jmtXsSY+x&T@2uPE+2l1r6 z#@&ULl(JmGQ34_(`qH60La1UUOyZ{1`z$7VQ-xiifLIB^?@shb&5vlN*W3XtJpd7d zRhUv#fMiDD!KVy1am*UEP!=XSWFG$jI)k)YmvU4fbF^9q(K#a-?^+oa*xaO+n30h* zE!#_@X@E~w1_o)uwY%O>Vpnk+fQcRIwquJ-?k(sPIivt;?vcz;+$F(pi#wEXmR2aqfb%oot6P2M3wrw0UmUwkm@LOBE76 zRZ^qd^z4Gi)JIRcx*i&fafPr;FHzQs%9CVzY+dr~e4NmXPwf#x$hs&sMIqpwz8_Q zPVzeO9M-#Wwi4nGPE7y-B(AG(?pFo}~hiiNij1;~LE)v+{It&N1h7@|NKFVA5_fXji3 zP_vRLqBo+z+n`84bWth}N|VzZ)q9wL02rp+V|1AvsYz^-VJb311NU=FJGkL_sU}G( zaljpZbU_LsNd|H{Q)}3Qr^q3laKL-_qGatMkK;peAYjiV^F-&7n8bCZ!1xAuUQQ#u zFa#uE$2iR?J4oA!5k*emGb7ra2b(S&gZKN^jVx{kddJ^c1HloV(kot@ECB;F*CdkB z^|$nL5`L^68=gFO#lP#texX@0+P^XWj)Vv5v*3=agX2ChN&f)zn6J~Nw#Lv&rgF1y zEQS`KNssj17e2 z>}if`=eNYZDW&lXs&w8FYe^iGKWe^?{*w2dPHj~w%^O!zJ1R=!z9V1&q87- zmJHFyy%V+u)7G|G%18;d3=bdz5Ddz$DiOM1ag0)e z>PSwMR4|z!{{Y)j-;hqp20@b}r4kEziOK6ss=_2>j!#NbVnCUtd!f~7kf*#5dekaQ zPUs%=q?460I6l-!$4X&DWdOk^G}}EO6BB?%AR~f7_wQC9ff2zJolxSFbOug^q6CrN zo69W_BX8$QNjaDY5-JyYg_2E0@JV*w%NEnKr~t|0tz8Y)EHQ!Js2AM`AdqR7ReStc zJqD5iBAj+}ADjS6GPZBOlI@yz-&Ukl0d2 z3{)N|OY<{A>Y>WA=VG$<0{h@SRA_ySIFNM)}GJ=b)_B^e4sZ#++-4a zS6FIUt#2-ZC5-ePYXf-1UfX8g;0HbHJaT1|dOB0V(&Db?$!43wJga;5jngb^sba)H z11CIH8e8{WH(WssIF2h{nb&j!fI8M}lbdwTr%j6#6~zw{r)bAskyel$Nfy8>jAm-F z1`bSQ&MNOS)NTX-9suIAGpPig+ZAjvWOlW!->aingqRU0Lx3H?svZlh(0X)HT4@3c~IRV-;{-p!3$V zK5D>XMxl3sy02f3XWDYAY^=vQFBcB+j}!T{{T9K zVHWu;bDHp5cIX7R;wv#?T=k{6ZCkR!34S**II8WsuqHnoRqGm~GtA`a=-cKHqzL); zs;)S2(%V2EiS0!%6}HLdGKL>#_fO1H9jv>F^#}q7BBG*`vT~D>qt5u|jNY(WNgGI* z9V^GgYHqE$*kx3>0F|6fb+73;`|;T*ZL%~ z$0~g2;OZ>6c1B%;p_~(0(!+p5+ubHn4as3Hudhwj}s=T(g#9a)aV2I6sLrrgjtBZ;f*=0G~fr`U> zTi_b9E?!N{pf9KrK&KA2fAC~7`W_^;nl^ZFHnJUoryw4_^*tq}5Qu0&h z_d5Gx(n<)GQVI7pg6eo9F2!TIcL?oTBh^~2)^qZDU&G(Ti~eT>6dfWaXT1OvtmJ-m zyHjq>$MX)j_uGLk>w1#bj}APMOvCia3+W7O&5SYO{GQJhpq3y8EC*f>wOymt+_D;8G6cf@rU0Gah*^{lrN@m=Q77{UJl7ji1xc>7f| zKU38#lkbNoqtp16x6=c1=*b|7$UVhp)M{*5By3V9Sj})ix}UU?2SMJN<@R7bT%Kuu z&Z6xx%hcy6RF=`ZQ+Cr^K3QRzG0kDQa(Uz2@k*}na{_zwL@NLthIk(Ja*t`xo>!HI z!SyKsvk4@VGJU@4(*d_!Vd~;Ksj94?7Xcl<{{WR}RX%P(Jqh>srIGBn1b$tBX`9RQ zn%G^#1PUh2yOxC7JEPP|AC+9eor-yrx3Iydb8QoA861`5YOx|_UZf*c4zdtI~YfQTbn;VIoHzKTZ?OQ0vi@skk1y=2q185nb7zHw+pp18| z7cSdS6seiB^oRP3)aRd&NWFC;8E38~K4e3J|5CjDMcBCBYq#W7Jraj=a%=M9u-?D3#qI zU=9yxsk$&n-$P?d%M^hdRimkjB;#W=f%w!AW=C0xn4ny3jjzdrw-~q>cMW80McE z65BqxevX!7^;z(3(+9@9V2_vU0>4hHNdhbLU+C|&2h~&I&`6){Ul{)Y{G*EfDytI& z%?C3-@npWE1XGZpp49`H^$7N$9~jB)ObasZb^E%}eZ^c1E;Pc4_8e3BLG!mKr1MGv zMH^In!Ku6Vi$~1SeY^rzYq#b&z$&1}&X|HQ2%3#;Kn#vz1cOM<5my*R{V~lYVP%^+UbJl<)M*e$65Yv-`G_~wLMIZ*4 z=iaO`B;$@LK+b;(bX71&G0!ncjxn-tW&sq;aB8+BH!ynEgagVvW2vg{C?2eLs3%17 zM@XnKm{T8hKuHil6F3xi0Cy<%h{Z+`>WR-oRwh%nDMLNv)2U?;1bocUlghVFgYu%R zNWdR(q3n{^1X5TA2zdB8VO%heTLvd3Po}YCzvwB#-A7?le-b*TO&4d@7}qCd3fK6m?NcEbqAOZz&=Obs`yE}W{=vkV_znX7rakfs&b~|F6>~& zCc7RDrFXcO9UuV$I{Ww;?rep-|!*&(Mb8VjHJv}0# zt`rTt`%v6K+*mYVEnGna449x%7=qFO<|-|s$BnK8QE-M}30Z*MD$8VT1(XsdPg68P zk~XVK%)vDF?Z-37sJE&`(2u!ol>lwYAJ4sPw!`e1j8zupJt{droYlLEoreq#V>Oz0 zBcq0*i$j3Gz%Wb$nx)to=np-rHThLm+m5~Fv)^Uey{-bpNLA!#tqKg3@+hLWyX84D zr;(h4RJP#69!Z?iTw+KNNW{ews!3&>lK`2D(zK3rq~$Fa*&CRMV?27etNgqyf&o8h zj8zt}AQ&gDXcARK_2R2}5Iw}q;>x*9GRAn;WC8q0scZ4>Ia zKx67)vQNEwBVb(+%^kjUo?~^qC+}1az*CPu6#8N162>MR>k! zXOmV?#FBB61`pjppD_7h2IAjqtahuf+Dj}z%OA8OH9%r9x72bEP-~?ZYe$xy#ng)K zp+;cR2<1qkj1&w4In6D{dxVRUS~)arhhk6(UcKsEBCaL!oh=uP>-07*S<>DXlJP7; zf!m4g6@va@x3d;pf_nb|wwbmxZOEU#uQriTDu~_or>=Tcbr`nN+cmjl%LNAQM~|U} zt^!p`f-%Q5$ZjJA4YPcKxL_%!yJ;5D+N2pWWSE^-KfW`8QW(s_)c+Y@u_fGIsK2|o91v1|w|RKPO{j8igz^3Y&a zmKjw7lMrSN7rYUR+B;Z{zt*d}HugnE%*;YCZikHIR=aMnZm|Fb`(Rc_09)K!ApSLF z#!;jNKnz=K&JW!~RwzlqwrE?PVwfR@k#NMVT)S#@~_J3$;1`PI6spbst#gURjpRy&u=M$$gv#ZMi* zvYw)FQS3#!3s%@0qz$4#hU-sy@*yzbu=hlne5vEp1 z+*rWJ-9y(T1Uq6*F-{PU42dV6wFH7dZ*fyj^oriZ2w>m|&U#St*r~@AWNx3~NI?X8 z$m&HTm^}lGw-dlTP-y@!UutqNFh?geNygBi@xkV$VoSkTRwHmHoX1L=TM#BVnlcy> zx;?0Xdi?X&mFRUq5QHDN`%vMaq0T#Ip_TNO_nLKm%MfHzzbJLwFgf`e*{2&>VMNv} zD@!+S1#Qv~P-1$?Bvh8wf?Gbkevbt5{;MAkGXi(`w~L=|_{@JQ{V=4S3|HpQ(c;SA zRZoXA$BFp3f&T#IZC|9|^yk`*S0AVSKlETh$k%wl25}x%oc{nS`N4dh&_TxswS6A_E6z`W{TAB_KjXeK z-}E|a`N4c-pT3dT!Mrj3c_?BhF~?qL0;Gl_MLuRsp7mM~Fbq$%MV5IXCAl&8QB*%{ zPii85$s>uaz8m5LLb`$F7yV+;wm6I#AcN5Lh&UA+9AcZsEwjA%N!;rLu5Oz-~&PErH3%C-~J@HspiOMOehE1S$!c=Bl_Pl4Jd}qK7d$ zM;|&~;vkxUJdV>uga8#RW@c*Ag|Zxx3lYeoqyx`9fj~Ct8)%^@Pba6bqVyh1KvG5u zsULMQw9w2V6io#RQKJMz_p8ww>zhGj5iN{WJ;u0W?=xFlj6Df6$gQ??Xl>5ZyOZ+i zLr=EOpxR{wH??oHpf=6K5O^F4qb5&dXHC;5xpTptw92;2WD+Ff6*Nr5-Dfh`6Zclz z)&kkd0h)N`D>jrbsYD5Z9qO+4D7J0*Dj6cs+jk>8sEqrzcoj+9(`{r)lbX?SmfS6| zAmfV6_W}r4C87zZ4nlpaO_bfZ8AYHDGsb7ZZ&|p&qWfCF}G18etf9Qk$--uYnPD1 zi(o*HdGAzSXV?~GWQ=BM%jRYeQ%P{|AP9f}KJ_$0O*B&iL@s8mQIK1L2?MdEwgI@K za9O~gvsT>R7T=hF5V*u*nOZ~JRoWR;ll#E;_N^A>57{22gEgMnLnUxe1Po%YR|QB0 zNa{^hlX^8`N{O%mxCo!lvg&PbQV5CYdsfx~pn;mM@(rXU#8hD=c88uF@uqpbMuBWz z{cg%LFlivRHueI#R&`djAi9uR0FKdDJ*hj7$Qb;q2CqoFyxSKZ-PJkT2Gd)+{xYdE zh45cQ+_9}bQPJ|qNd`qO0^m2fu2s(+Iv}H4r!sN~%9?wAF{8SWZz|$pu}k3OO6x_d z)H-=O?xt-vOC9KvX=dj8RKF z6+Ck@LEb^x9-N$s`@7X=QbMvQUUQ18dtBT?jmHK=;0Ze?hM`z(+tqimeENab`h?Bbr^om@fIB^TjUVEz&uw zmXVrrw_`K!%LxF^G5OLfPGh0q(IW~Gq{pgG38;V=7?b%_)gr5JmO;C8vvb<4`vY*# z^q{a15;z}y5CMl$f6|@-sBS}59tgWn*_k6W7QkkbaB~K%*lm?;LGMJeK_REMd8FTh z#Txv=?i&o_GgE4y$4_cgDo9}64IRL#UiAB4Bzx1)t^hIZFgjIs_JCwe@jTIU1h^zm zC%rTtI*vW6Y4~LxK>$c$!5ma6xCR9F+ec_5@Mi{kQUJh`8zb|g{fA!RmE0v{4%na= zh$bo$(aM9`h$Lhv&om23*oBBDWDt4^ZbzqaVV){FksEUZtxc>}K_u{V6xz_!rdCMI zNe2>X?Z`MWBZ#Fc(YUThIHD9WAT+e&G@ld;+^`e77(9yCq}*Hy1P{WoDByMLTeON+ z;DOg3`KKRYt+VUb=<`Es>aXzADu}t_J}qZkCpr;TTd z4{!M8%KaWPFu)=;4Mx-;N(=eZL|jGq*9eEKGa1g zegc41MpyEq1*Mvewm~6anl4O76e$tN$W#vD9Oc0dPm@I(z>cV1L(nu z=k@OzAM`q6Yv%p(B!V;AzL0*E=40T$MhF+uHNG-={{YD8f31Ap)Qpq(iY)73{tSPg z{gm%!7%(Uq=PW&i888bG1k#cMnU9r0vc>fnC{-Ty3iF7bv>|@dl0Y~V!27|D5Avm; zv6E=SPX;l~S-);jz=`ivh%*LfC)$}*mg;A%CmPu}$-NBhA_yj`AVGq2T0F3_XRT1{ z>0)!cA`K|J&`mY52OgioiCjrB^XWz~41X#Cip&A{)r&}_QXI%B0& z;+<^K8Os}PwsbGtw$|i4<0Fd5x9!>zuy*l1D>yed?A^3aA3CYf`jU4+IbO6!5=w(7 zRVLF*X1kiNG=&F&#Kvio+h28tRRn3U4PRK9KsbRG^`=zIHBAd?+Ucdgk}8?2BNj42!*^yrpHq$$VdD#hC1hUp>z z=D8VjIlb_E9+RTS)1?^lT8#j2KtUUE-`=eqVO&1{-8%IrgKt{gs0w@Tf|aov|3rR%u!bH>fi9%+LlTKs-=WwW0?H z6W6^>;I`BovMA?4Z7T@cJD9~u8@cDFYN)x~XTJiWWh9O9KKxT?N@csi+zi3#JkcbA zN@s2fII2k-cY;YHKHk((i48dbNfQ{QMAXX}lmjqH9LE$c1|xDt-jXR6>n`=d3?Rsw zRd;AnaEXuvz|S=6+%5SW4jgQp6#(X}ce!>v*W6bGoS(j_wvD^{z0s07K<1sC7xb># zCJ-J6X{bp*1mj*y6?R-J22L~lYf7mpBas|dR67WnAdwm7wHA;P^2ela-5F?z_6Qbs=8LlP@vD+py#bUo?vamt~it3RdvyG{lu2M)BIfGx(e2Zij6FoiZr_-5; z$FRk3hhE~Uw0YjA@boju&Qf-GT{nezjq&BVx}KaEnKRe0qQ4Jn7u3WZ*d$lEZ72vD zA%|*Fq+PPWk7?^uexm#$rTB9n4Yqiv_*VIJAcCwjitcE<2F;J!-L@Hwne2UqcYKRr zkdg;E=7TM?8x$SADyj9EGAgrQPw1ULO)mO8?~3Uy-6Y6Ribw!+?Os2`bmrCV%0N4? z1Vww_6}9^Y+jrDVM0EMrht?y8Hh^N&Jn>x~igu4P>zE@MT^KH-yMhyGCN_+I1EpVM zPkbVfpd8O{zPISSDC%_xrQ2wY3usUOUU> zq(k!{$Y4+9S=^21_NAsE@DJl%KN8a@b0SDENblOYL_-o397J&yuN;(;XA`J{$2S%* z^FS9=2$;+fimVphDg=YnQ4C53+(4KeGf=0M>2I|;6IL!ZQC`C_l0aRclTkvQ%vMi9 zLvH|>1WZjZ3<|I;06c+7=oZN0*%($*a!E5aZIN!%%ZLO>%$g+^b24sV+-~ns=^Uo~ z$YC+fD^;?^2`7A-N~3!1l5sfd1!c6Q?!a&fKWNq3OT;UqT9*COI3F=pvlcs*VDlhE z{HhApi>B1lkuTh4`%bOI`+HVqB;>61rnpPC)4=V-)OKeranJ^C*axLrmW;BMu}c{y zJwu-K7Gg*OK;+QaR%Q&xzvotF+mLVvV^2gr;+{6136f6$cc=8I+8cE7_i;!>4W|Tg z#W4!lLT9L&6TOl|65f^ssOQyJTa2&YH9!S^%K(20irFj{I_Iq_y`YP&nvsw!G?SiB zS)`q?yFi#VT9yiM2XaPei7Z0e>xznqGPHm>KGeH>yfHb3zqLM$!k)lnDDL?y0ek7=Sy) z5D`SFo|HXqMG2?D0y7QH!UsWC0;Fe&>SBIW0)x&y%>XU|wMdU~#T=~#dzz6|1YImi z?kUgN$i+r=U=@HTy&zEnCO&k2ZUXB>3XMKkApEKjMD9O*6m<=>7{+QeNE0HDAyy6G z2#QB-;E1byuwq9QTaB`NQ{Wvl@IUEYwin^wqbsD1!^AvYKs~&TJpTXzUpDV#M1@={C@Jis}jJBb^NVx`#tWJv2s z4(zdzaUJR`pB$EDvAR9zsV4-P?MkB=JtCP#A_VbDheerYf_i+otrk^+u#?A1qTKET z3{|MWoB^Ie{uK#7V@@d6!Eo&m6cH0ym;eg^WahS904`sim6`iYagcbT1arq_d!&dT zaj4ED5Hfg?)|wO%+Bv0xz$X=Adngo{Y>aWmFp1h)aX`o-05WKRNzXjfptDAZZoY~n zNs9C~Rb70LWPvckyzYeU)I)U7^sfDd*>F1;AbNuJ#dG?nTphnlbf49lKU7eP%n4vW zdy231HbxE$BQ8Nx$GvQ|vF+@2E40WY@juqC-a>-P8=#Jri{dnQ*G&nlXEb2`>NCrQRZwdQGU5!8DBL=Lqr`b0P!952CkBKGZBhllN)JD;*wF&zb z47_{%>utAo`$7Pi=q9lRYga|c9>DdjNqt(^+A4TCthqj8rPH+q+w5rskOUYRB0ANk zRv3uKB;u$`tG_H;*z;DB83MJUWJDUzC1*+w_%tY1Qw(x5G~fUiYcxc(frDA>G2TXU zCL*+C1={@N$MCA2xi?~VtaZZrfzMuQ5&`A`#F3gp?FtHl6ySvPU z+MBls205z6;ziF-+T(DE9@JV4s6LaNcdE_BnC3eQlCK0MkuF$CWn67D*WRMA89dc{ zwtxWZ8KMhdnIU>~rdRP-2(U8lBn%OsdWt|iNHnF7suV#TC`7+a zz;b=5E;z#lFf&jV2Ml1I@j~ciRaR4xA_pV-QtcX%U?mn*;GX{gl|Wq_qnPW=%?Y+b zx-4J@>z`_ZPT)j>InF)kYh{sk?CDuscWgWFRVV~|{uB|E$Eat$U>6A64J1UyW9M2e z5Z1wuX{u!h?rx0Y=+;;fJRfR1gh)L0st7IW*#P7Hw9wH99cn#^7g*D{nE>@5ni15I zz#P(ngSd>-V6S|0QXucaHUMHkk;$P5yFvLFt6i1K!oUCw3Q&^79>0A>HDIHyfvxTZ zcp$`0DMsW2@~c%!#(l;po^OX|#A1dg&Da#~wj+I%o zfbIwn&a93_g7Y^eR?(;ce2wzk_VumTvF@9kYzMIt~I$nh)b zWe8q*H9T{aY~rk;O1B zo~0yCF^|5FAl33HONsy%*bs6eD1zev!92|~8;lm~yD(sVMW-X01(b;+C$OUY1yUil z+qO2*24->i)N;g-n?Q)i6oBCG6hR9hm<)1HYAtXs06`BDJyLW0DZ;@pVsitf2jsFZ zrf1%vAj4)zGfRR#<(q>NXD@uU_yv}K|!e~h6 z26F?Y0Knk!(ublc>?CEju#8N9oKqHr+9y28s6ZeAx<_7uhUnZ#1RgO-+a1#*2qFza zzv7V`cBwPRAYy5Rm7d4%p$tY4G56FeAQ3t1L?2NDh8)IfG=MWF_|%%P(?XOdfzByl zn8^V1Jp~d(3FdHUf=7_l#-x!2&TtR!;cO6$Q2+?Q#M9 zY15YhrOByR$pH<%b0;)QN2nPc>Uo>g0VHwqplz53ZfP}RY?3Y*3m?jeQl<}Hv=yVD zOwn^EYLI?Lk2EXQkh1|C(mw1?DYo{Yefm=cD?bDNmL&`DuhD@xKia-AAN{RjzHHwo ze2y#WFX?3e0PtVvypR6?ig?dG{{U98UpB83zCeinG`^=_2k>H2R%K4p9Vt~qum%iq z^QMEAIf_JP`$lBv=vdK7C$~xU8ps>dRm|i={>DH`qrl( zwQO_u*K_+bSUeE;&HZ4uNgFM(%MSGnlb$-ZwrJ__V(NR8BK}oxehx|SJ#-dSQ{2rJ z@Ev;+%7DP)YiEh;ELyi=JU3f%;bq-*m`AIytQNdqU2E)Jk;l?GUJSaNpC z-`S>(7Q7E!m%v~by!5WcttO!iY=D#%)~K6l9UMtZ zMGt9%?ze)n1Z2~B1OdJ$*kZ0i>R;C-FiGkuu7Vgd;zwT9Uv(Ep6jsA%fI*BYtLw{d_6PV}V?Sg@5n`K8#=>0>`CXK7LE7|eUrTJT!mdZ`sE z+j2a@ReO#|_MlZj4JLSwF;j7Xr|ll}0}==`x@3;^B#J64L!%RHmQW)gj4 znCnaKB=1OUz}&nK%AvgQ6i;#OO|+fOwXvQ*jT?x@;kX9IIf2DNvs%6c-M3<}FeE_d zG{D>djp2G6#Umr!D1k{VL}m=lHS1`AZ`@qAM`7K@+m zLlAyusY{5K?u~@*SOC-6x>oAC5DwT7I?`ymE}o66bO8j32emT3?pa`*Vyjh2!pD5o zi?2Lw!aqqOfUA-a#11^X}~@TVBT7~>TNNegl( z3+ajg5srRz#!F-$x`7^_wIowp1}lJG5lkNSMb%W1xJbc+HECfIe$X)<^_uPApoSs_ zW4&7yZi;frC9>tSHQmBcxA0)z|R=Jwd|0j~20{w!-8RavQJ8 zybp?Nn^$1~5-QeL&52;kji3Le2?{43S98 z#@M&Km0woglSE#)N0+>S1S}purA?Kp(i{mlP1 zTmc5sz_9f81}W82G6%@gK_yqyCAt3qJt_dE=GBeakDU!R7848V0~81%cPNq2{vwIq z4#!N21OY5h1W^6Oc88KuM+1??LO{0!2?l=>C|r>QMD@)qf|6uVxFW{mcI;0S!)fOj z=7O*QgdC7gI@Ac#WD^|Iege`Ws7<-SsAfokkH&}!z(>xYUEbdDNiq*(Pht)#Oo$&b z6*=Z6G4D-m5(qs7KgCAFXArfXs%=M_-@<|7FaDYhdS~QBqz}h*i z@wAxDYSMkYb%?2g+u8O*>J?-Us+YiyzrSx<#P^+D+WiIzKs%cJ{{Zz6+&-#b0Pi{d zUsQh`Rm%MUJy;@=c5^zF`{_TZLlAOks8=$ik8#aUD`%|99jXh8M%9HUr7z3LPNafD zC)xy_Gm3EJ4@n;`l$(%xPDrRN?#Y-vJJS5z2OOIjZdyKt1RhAJTyq&6DkZ|h&@skp zZO=KWG@24k0$HRofGBJW8$gO_gDwpL>oTClA3?1Hc0K44PqbBlf<`*hKcJjun9spK zrHm-}L+HE@wf(W;?f(GWmaFEi<18^Uc@^}l^sw7EJ`wsdxF>4(&x)z}oh76EtLCln z1I+Q-k=4Qc6lXFZ0#AI>smWL(2PT}z1fG4UF4AU1^{V`q(F;g})N}7nC8bo6-hfaK zBO{6`rzA{~6)gg=fCGs?hgxVb8Y3hcAPEW}`_rVO4&CXept87==@LwH+Mi?`@;@qN zP48jpnUpMUDV#Vs<$p&aHD7h;188X8T0`>9C1K}CnOof zo+gvwSa&sbzOBm>%>*bWLRZ4D-7u{=p|cd_*|ubF)ZdxYF*RZzo${7q zKv+G8N?T~5KzZw!>q&95LetT0rCp+W`_+*LX=nq86cI@g07!{FDC_`+1dMVxs<|~U z%cMz2BuO6Bj2mzOPCoi;e9T0ej|7M@_tGTxR^W0ZG3yksz$i?#begi_nG(`sBX1q3 zDFL?wBaSgsPKxCcpl&U}Wo;d#OwU>3ol|Qvm4YxSnj8Tzv&VXv5Rh{-O}zwh+usFc zO1wcM-@O&G*BEaY6?j%*00W8^t+*s$80*@h+*|NcV_PI!*cgSG1KxwFSQ9@km1tPP zj=83|xSR+eL}qFZUJXh#sLOEy0nFgQo|RSY*S^yd0NdPvI2Co&zzP9k!ZF1e4oM5o z5uDTT6}l_h8137+m`qM;BJg(xBO*t=S!ms~Q&NT*TW;@u)nP>#B25=VQB1rIxq^N| zoPr2FK7A^r0Y~?xfsjcY3cA{ZnkNRniHG=a`@RkM|oB28Er0R!Y_k*$Vp^T%qGXoQ=s81)*3w?31fdh*^g z@fEu_uGvW{IAe^(daXv0FM3!Jo|Wf(U*WAC@ZKTf zTCWhfxtPGjPv=<0yJT;G8X4)jm=RH3< z^mwNSsPKHdtHGNbobzq{#JPIiy*Jp%I3-PEEF7^c4-rjqnAs}E7C}8JRBe=0EXNo% zcWH)la!CLHS6~y@YR(2{OmvCs4m;yK>tv>DQ1Sr}ETCU($ zFeI^p0Hl+$bCt%CSOlHUT1h0&H1WI{Q;xuPfYDt+6OU5J$+pxwM1YlL4rX5@F*z#q=*OJm>~lR2dEUgB<%)R4)iPK zio(|jZKUu&$)Gl?9m}2vYK(?wdB;fU+MN&(K^$?4FH|kqpb$;~#wUtWj0`Mba%5Gi z8h1}p3=U~W24;KHjS-gw2*LxOlpblFSf5lGGtNy-utX7xBuOB^k&2dxwgQnL05jK` zAV@5L=Yvn`AVAF29d`(xlwFHLrI)(FMY8PJ+6I2=wAgzEh08@49BvhEgH?M&sJE&? zxsoGru9uAbLVR(Rujy^0AltYIs%0suq?gKS$BzWC%2J(A!mU5%ae|Vg9Gv!|MkJZ` z_M-&#$0Cmqt%|vsQ}WGz6XAFKUsg0)RrSAK-u2h<{{VvZ{s&=oEX#Qt?QH04C&OMe zJQKui>Wa$!mK@^0p?K%S9unRKa`@ERy4Nj`s18XYxjkP|)M3vR1@g1l`ZuQfZ&~U2 zXP$MIHu>Y*UQgsqtOQ^lqH4A6ob>Bf-5Z=_nat9K$pnviuC*t#$jbYuLAr52hZUzs zhX<%`Dv^#Ph>FprfWy)zdVJ}tqDs6UX1=3VK>DbC9hQvfFR}Ulvv$9`&p;x-g#AbX zxAj;0JVrnM?z%uDq10Tj?)LXEG$(wV&Z&O>e|Am5avDBW09%GxHi74Si>7-O$WPcZ$J8>#%1Y{#p$I=(>I=;Q1eT7mJzo+Gsc zEWnt7PYd3MzCi&&A{^p_0H@H{G)X9OC)$)Y;s_B&!;lh22&pn9hvQH4s@&v?W375ufev5`!Q4npe!*@9T}EN40%3{VUe@eINZB-Y_=&L*faO-$tkTSIpb| zk;tTV@P7g=ezwg1qcQ;Er0fu@#XuVa01k&V>Lkf9J*q8RCIcj8LG79=xWscbf6*MC zwD#6xA}6kC=?44+N&8Ac{xxcir+EfXVZ}pkBWlxy44|BesJ584gbEas7%|ppKkXyMV&VMRtF<*eF+`CvGVOo*o zuFwG@D>7SfOu+*tcobISDH}wYs-+t=;?3E~*RWwm$uc5qqhZ}t3rKf2Utw5uPX$N{ zz>cQ7Bg8E}lxfz=tGDlT`>UIoH0qB}(bJD}l?`ED?Cw$PJP|Wn7s*8ck&zHO3aZxa zke4?E&ln=FKw*yHN{Eh?lP5nzw}qs>qw74SwY;CP8+w!S6m;$9B0En!_WWv_r8bh= zivj6_?N6gBlD9ommD*%~va_{OH)6<~?6e~Q+>I9QEbeqN4j|&8JLC>?N~G)rfh1(pHt-kl$g0gyV77UK(u-{{&;(RenJkea zD7s7#41QG~C8{j01e3d@&>?{ea(%cpaJ1jLGxMOxM1hGJ#y^*Gc>mlm6?(;@~Aa#$<~Z_kh_hbshPp)Oi}ibXPkq` zsQ&=oY$P220NYKyHyI?D^niNJS+b>9Wf#Yna7!JtJzyU7Wv#@szTiopx{jjiGBT)H zCyoUwxnilk5kNbhU~@%T7SvgK!MXMT^qzXv!U}Wu)^MvcY$$2lj=w6;V7ekI9`xIzf)_=dkrdCJ(j4sr+OTuoi8$QtF) zV}NF}lk3M(S88uP#6)*uqaPz(h~w@ih{a(O45W(7Vdt=lZ-M$tX9lhUklZJafd+cu05nT-B)h>8d&FbB?#(qw>Rr8c!> zdxZe*Jmg^0uh|8Q98sANK!7KX{`BY+EI{=Rl!7T(rS?ueG4tktDqx~PVJ0{f#K)z2 z37~)$FvC3d6zz>66crGoGaz@Vu(xnQm^AR92ooG)lqdup<~^!ay@(3d%WWn%7$kP4 z3KWtgsDUJNMM8nNNil$GeU%bpzr9B2ekcq*K#oUA?@D(Qup9v*1y~T06J}!rttQEw zK>%bLdwXJh01OfbH0mVC&)>}eA%50J;Y9>Vzy!uAr(BTWi~xfpyitJy3CBsJ20$?l z(kB#Pu>%=6Jt(9r2Ej7i^v-F8upR-3&)rS|GGl|@hyr^U#S}%cLJ^aZ&%Ij4&`8>6 zr6;R&FBHOeawu`VjY_nHWs{RZRx%8GMO>?y3mE)pLrkBXMroujMA`y^etD&7nE>{u z3y-x2wOMIVn{C(H2<_ID(I}@a6-Wg26gLgBX`0(X+IXN=Bnl}KdqSu`R_nf80?RH{C! zKSvTr{{T`X{QT>c{kW45IO|`;ex@pIeOLaDmDGZKATXbMu50^p?md9(LCWe{_|t3M zkTRH$!k8(4?^#D_#Sj;7q`~=64B(CDt{_pz1w845N>0ECsLVFZ!5uoyP0r3rjD8bL z7bKDa?rAlAitB@8TT*2o-YH38`=g$;skxeNG@j8`5W7f*=b53k z2HaA{!6Bx4Q~=x~aRQClxB(0X4k~ROOncRZLiL(PQ^+*#_zpQg41Sg6C+O4Y?5QF? zB-Z`^0PrgLi+e0UAC-MT{VO(|{)+wqz6c&)#X5w^{{R++`2PS_zF^)2H}j)sXQ$Q( z*XwM~Lo@>i8OOar0f+!(XWE$V5@Y2QNc%88@;$RD!S)dVQv6Az#Xc&GRQ{V zl&zKw5@ej>n0=xQ;C#o*><^iM&7XbuIbgkEP%7o;Mlh$d-e1JfcG$GW$AOjs}?Xktv zvu2ziRbu22C)4?g=vZJvkV^m{f-4rEPjUA3BznE8tENJ2pD?Nf5s%*Xu6AgigQJsc zM%_C#qzXpkKgzU(2Xhc(sEiZdtI|WEHtm)Gl4Qvh($Z*c-c-2PiXPJvE1#7(?VgjQ zPbDN~xTNXOx!H&S4!=HY4Y6}h(o6z)9j3cl!)WQsk!+PXB=Bc7$+#V^ZA+LYOd6vd z%`PVwOe?$859u5B5JIWd?RKIiE?Pz zyGW7GZYg}SxFnjo2Gwh8w4SqrK~8M8Q4kA6Nx>qY%VKee{9>5e2fy5NNRmqQRkGZI{{Unj1|(Eb0D=DiWnB?FfRop? zD%oOvM<*}^94ljW;G~l>r#qfTIfG|r#2V8I9kC}6Pz+;=pDT}9l5ROLzO+O&4)=J&N_uD~Ne zW_|&m#zigS-bfpG5;MgW4#_cy$sK;`dxGugHytF1^!4fdsYPyrb8muL+~s$Ah9jPO z{ne_`Gv%oy44+|G(GKXiyCFt)@_+0Vs?$0c+*g83WYUyqzZO;Gys_X64zzcIM>Cvv zp$JT?NFqi!KJ@IW!ANYJkVHrIs{2u;WU&JlAxvcVt5HmD5H^_4GgZ2USu#FCr=`x| zTNx}xN4EA$;!v$~9)rQE-%wN%MtYiZpoSojpz==!yzh_rqv+VC;DG+|=~rUF^3Syx zdfvJ{9w(Aq9X(#U(ze~=O!cl0iu^@mPDQY!;s_Pyu6UlbhTVM#e302AmHASZ;cy7D#Eb^xuN||=I#vf68b65dm6U6lh%dROez3L`@Z_T+B;3Hxc%&d z_*0uh(uuH1-3oaFsr#tk2yG^2QG>8To&o+pDrHgVatKz#F6bsXin(;pyzS21z#z>K zjcfz^G8#tM6Z5A{>d3lI#B|*)ZUW8}nKfWrCctgqv<>zGnIC;MyGLjNL>_`En#nF* zEtONi2m13;rdO^}oWwB$9C1v5?F7#PGgg}{vanUTAmIJ1$i zp{oV-C~c)O7!pJtk=iP4V0sB7p4ESoam=2+^*p8k0zT>$39Bez0(6tsfCRU&?OH+^ z9+5Ni0+oSseK3CtYQdt2l0y;Oy*k_Uk}3R_5k)oO*fXn zV1hxbR>*D858q6-T<~%+OpAA-y|_HgQ~(k}j+Lctp$5+9(#p zf=_v;@{|$+&$V8*H(D-85Pr!snk79UgpRz3qMebtGcBFcz`z}1nNdqI!H!RQxmB1S zNF@;UpqzSw4-%N&dpKKG|yi#6SZT{D;xJx+e=dpP+L zQ-5%7B!Ck>^ubwI)=cz@BWoNk-+EFRFmwEAeTZ`QF$Wt7$2}-D!bEv_;(~@_JVjZx zVD3MEYBc`k`ID97TQA`f&OI_y_9=@b8CwFZ6`|GP*wu*Z%-$>D$8f->TdfytcRM zZLKS{jv~K^zv#jGv|KX2A@qWyi2nd|NPmrrI67FmtZ~MnF9*qQAj!cX(|)c&h?yL6 zYwI`v02>GD&l^-z->W{~EpL2wq?z2m5deN)-0@LAMpxCLBmNcf`Tqdym;V6x z(dR{mp{URtikM~Bu{6eGIu5A;HK*zmYx*g~Op%P#dUsFfu(fYUp z2gJUR7i2B{gp~8is#j0mzVtym50GKNTjX2 z6Z!V1e-60ns8{{Un8)rw2XD|xV`@=5;yL**a#2C;$4F1GhS?vTlE`KqM;jt{H56^|46`wO%W_esF*{mnv7_$QAx z2<~=#vbFH;u{6(hh()*|bI-ii{{Rj6JH{>xh=`0VS{JSn!l*q@e{O5)d;LKEgs*Az zx+|VP@%gc$pC;e?piQcJllu()^HWRp0Qv{gTWcxepC3K9AhMr{7=|OfTNRFYvNftY z_`OS@gHGl8{%6i#3h+M(@Xrpn`s%IAmyEenAP&G+GsJv9PPg0j5@UCyL;w%HeK0?x z`{)6jT>WR`k1%8Z0K!Y3{0d|B0s01D6}3Mc5Hb(@q-&1P-Ih_9h z_{QCScIg-Nc>P|WgQ@u3je^U10IFXdr_16q{{Y0QAL$vr(WQPl^!v9Ne?|UJo9m~z zID_pJ$z_U=&GYFs^mKlYKcHBV;{O02xa@unKUyO0z;#^Ft9>^AWT=$ z*Zm*AKu&iD_|bk}6I}jjL4QZ*)%Y?`i^xqjbx%i&^ zkNw(l^jyi^uj~H+gmQjA^vNphpY&hk`H0#}>vh#gatJ+Ok@@^jsE^@SuS(0suh;T9()?}E%l(r6 zi~OH3#+{9jEr1N-az82~Lg9#OrB!jbj=h9*ucxE*eSKXJLg@Z4+cS@fH6PM}{U0A! zH(kH0d}N>cKNM;)`BGk$l|E4a0Q=X|-!Yf={{Sb;Up|#qg5&bA)NG86y-u)dvRxLyu{t5A2?!K>zbzjPS{ECVo`Esa^D$ zE4v5ySJ*}U8=q9^6YyWeM01~t_22wDC-iXrQ(_z84~YOBzAM*%@T-4gT%LRO{0(U{ z4P>eD72gX$9BjTNZ{{Rkw{Tp9YMuI*C@$JHJJ}TGs=lAGoF@D`2W_)fILY=Q9 z3}cZ~%OpxBRz#oh{{UM18b3zo)hS5Z@F$Od`d8u@{{W<>AES5bl1Sh1KaL)e{_3^= z0Q^#fk{9i;dTE~=j+)?I!qM8(1StZ5(q6g?`DKnaz{sz%pZsoLsyJPb@CS`J9UJ1W z5hL*PYA@*M`l2QW(U*uY_xPK{r~bNyu}iFnvpzao(}n?7+bIA~q6g3Kqx!2rJ6Ztg zUt?GFc70K#fATWdi0$z=iGT5GhxB!QQHw|W-FUG70PLg0KlrT_NA}owPxbuIj(@9M zApXs>nLN}QM#w2R=qv0|{T-iFl_38By~l_)e|zFz5y$;CI{uGes&CmJMmnMge~3Il z&;2zC5?y9LDgM8i@zCg9fGcT$f*hRAtM36G?ivpzTer*L4}e&-Z_QMYRCQSY0D8;w{{Z(Fi2nfbYJI68F1H)yGvkNqY$7e3=ZYgo zae-ixBd%-gWB!k?s!lwwqWwz2=l#(5jQ;@FRVVa({Zr(R_p;Q+fBaza2>$@Cp%3=l zYr{T0Hi7N21u%NAO06_E9RC1xQKM5 z2zIXFiTT!X@MnyjJL>J}4du2Zlu*S$6C`sL_6Je*IQqY9bZgcgfd^?#%7ZL;8oEAbbJNe7WWe-yqXXthoq$;G<*pC41fUJmuRrX+eN zHB0za$%AdDgNpk8-%%f`!X4JWjV==0?(y#tC;q#dt-hhZRhOSP=+5AiCOmh-&8{eySuAevI`ddN;%#B1!)MrlP-4 zf2v{u{{YCOxg9Qe?}<1607s(JCc3O??K9)u-w(XUDA0e=immiFAde}&VQcJo`igy2 za2x1vL683cs(6S002ik}QGcpY5WhnD0)6~X#0dWYuc%Qq)?@Z(#)Z&c20W(Y9*S1b zToX1A;A`x&eMEk#ET(>jJUk!%y7-6X`+BJTM1HC#AMZEe`Ro0sub=w*X*~Sv7W$+BRQ(Bf zUPMcHj<}Ed`YkOIhgXd|rg}fC0)DOac=|ZBP=db==%f+;fUoJqNDK{N@Gpn_C*fZN z(EK^@=7P?P!u&GAX>^)n zse&MkQV>z08bwD!_NF9lfGM}6XCtjvtO?z1%KYd~#{HPe7miI5tJ;xS6-jc_ z(keCEW01@`ZJ;}LFe*44QN&3D+N&EmP1Em8r!vIPN@Jvk2(6hkcBI77CI;X!^QC=_ z8%{+l0ikxxaY{stK%iW(QE=nsRwtFT06_=67hH?%EKVYb2Lmxi;kVF{@}!42E_TpG zzo8jcb4C=92$SB5HKKNj#!WN%ao6WGUxG_$kb8bqAV@PxH|_MfkH(F$Zy>gR3S!p* zA%1j3N2FugjHiFhRd_A?Cg<9f-ve6YZNGI$NQzY3z8TKr-iau1)AO2O@4()}C$%Y6 zKWIVhO(8b-dK}NVsR}ah5sXke_X$u8(|URdqFUbo@!pZVsr0-w_N1MPsCk?fBBs!y z7ONzWw!jaSFl%9bEi}TD2mo?u?gn5Os>|EpTmidO1ntXU_n=xs6;{bKLMSsqO{Ks) zzm-PV#&Sd5sC#tf(0Nfe#?!q+G&$yNqIe}Ur~@K98rM>tw8q3hA=vsSr*Ci z-*7(E32TwD+MrnzJko+UdhTbS??-Z&SSE`a*u!GrO-F_uL8ZdC?AT2yEa%qH2TCkW zrs!zeywMwYJk;E(Ho^Po62H3e-Hi%`E3vWd_)=^WGa`huVcG}Ej_YZWEIXW2V^!c~ zRRSmQqR=7*A!K2KRQu3pxCjylyisEqpyY~OndjwDG693Q)N+J#9`soqjgSm1kCiJ4 z$i^v6#|yPguNbI-NfO!Qiay}qu>hW+Q(;C1c%^Ni;z;jHBob2Q>Q*h@$0!KwO)l2p z?IMQYOx(GjYGojdoOGi7$xk$fZ_~{z?PKM>MHxURB%jEu>|3WqWmE%T!s`5DRu*cP_wWBwt?+NLV!ko`fFd9lBP(C2ac5-h7r4I z_oY^Ihy&iAJPMVEX*igr2?rpUr(Pm=AC)j(rIbg#8U~x-to*16GunwW!I-E42Rs@m zBE ze$Iai0-6{EGck%AX?Lx^wolF~&oPoNp4k1zYe zW`N*3N4*%fq(?Nt?Ch1=$AV_7b7;2R#E^OpD6vyp8JoBrs=c5IRx?4>xwuIm`ZPt$ zcpx9V=AyO8+P(z{IcA*G7HEY*_|m=0e0BDuDp^66+B;L{fJ%@YOqCg+0VCFUrWb94 z&*Caxbb!tP2Z-xH?)U*acp^Q;RN)xlfO`rh8VN=_dB~*PiX(KlxTLSk4gf)qQ-B9G z0aYKe0FLIFn$&KRdxMInYB8G(Pk9)j?||2m(nEo~fi)$z>|2paJhd@#vVE$+*1+9} z9{ki?l61yiZYg33n5b2WkhrM8+7K-a^#Z4up?8ae=QQuN3YbI4fHt1hX6ykqR2$fJ z07pDj+AXi7Na;x{b{rP%o&^y5eI#x7G=k_WC59+(XEC-{y$RTGUpqt=1Rj(XLkKD{ zRf}W|%Ao!9P0)EU9VlNQ`78t{APJ}3Mt5W9R2zW(pH)DBdZRt5{$V#-E(AXmeE{TD zOL8zq+9u=^0#9l$z{}P5Nmc?oP%I+=6YW%lEO$U3Bh3)|AxaU`0)(gwKxOCWPOl~w z1XW&WoWcHd05>uagUO_}Ch3-!9p;DG993bBvH`b))|<@$&giLdB(IXoZUKRUXt_JR zO)*rHz6R0&E!$Bt2j5Ef66O_t`YcsNuFR?nL{ch- zGCp-)#$1)%_tmR;SYQPs5j3iXhzMDlCEIVQhTqDSuc5(E-r|#HcW32I4#zO$6r54u z!&FPC2H20ES`T#%^pPdT#nlg!U*kEGX}uqeiWMvxW|6jX`FH9XZYRKOIa(&2y)%u&dnC8fw7vLdS` zPuUnW2xTFhI|_?+B2Z)VqNsd292FdaM|mJZ2pm;MQ*20KC#(uzwJn{q_fS{)bXs=5 z0xA%yeME@%ptmiI0kr#^(QAWjHc99?pp;7iZLpwc^Q0kUa19_wC`z+IwTP3^9^>RDgTcV5%QbC*G_q2n-Gd z4Wuf)jIXf30MK?034fLHN5HL(pU4sMdcA%FD7}_Zrk%>{0 z?ZqV1&|65gnTUoM?@B_?r2L|*A)qzF#d-rwE~&y8BA)=&@HeM)l1ZY)n8bgwsdl%) zHhL6BIFNTIqPAp}RF37|}fc=^>VRnP2+2iuAnST|(FF(q0p!*EV0fV+T^ zG^OQz7!;1y$pbUUibASo&gX*>#155M3(7H$)maP-+$K9kGO#2N;aBIH34Mq3?uKdk zifMT16+_%ZgD139+VO@VXs=+p(P>pYa4B|M8IkSnRiRE1vN@Abgd$mvcp%YqK1+h1 zwTPg_PrXnO5=^uXgwq16f&}-PWFE^fq!0l2B7?Gzv?gg;@ePql=A!U1O6;9i1BinQ z_fx4XJuER*9YWhsU=rOs(ule0Rog!FHDFu1WE`JrU4xP-Ji}`qQ2CjnbsRL99ZXXe z*y(VV+6W&!RAveGoEiJ-ox{7cYs}2J`$WO{4a<$n7+%yJVZ9#v$9%DN3!eEGb384$wAxccAxzNIs+5 zi>E@bC54N9mw-5`+10%#CY0J2Jz`hbnqRXhZIt(?R2+@96y*$YM}FZJi~-G7!ILG= z9r>h1H@?VZBe9B4=HOqHwcpYe$Uh-aAU|o08bGONkjp3hMx5MGH%=mfwAs8}-eTTF zL6K0|SS$+9QALB>&A(DbR&OZ)a(WKbZD|Uxk``eBiC>V#GPomZkly2pA(@A+0{(QY zp?y}!gWnXXGD(l+uRf4^R4&%U5F^^E7eElkC)#O&b`c;f^`m}7s9|tOE1GbHfZo7W zWC-*yp46ernYcKkkIFV$ODEZgspfztME0atVr3ML^Tju$;4;r?r&qQvI10O59-s%# ziIvKLM|wkWt{zDC6+F^lTbSx-P2CL^i=h3cs2QB?10DL(1PARz`_vaMC?ll_c|zo{ zE=)y1d~nhae6;W%J`U1Vh5q8u9 ztDeKHJ~$QGV7@`waE132P40->{`#nHb1onbJ*k`&`vQLIU8s>}-NHy16r$uEq(vaU zqm=unH8;J?d0;Q+PRO@gMTvANF)T>n8ek2;WkCDtkfBeYtoEn|8j5+X%4ux^VPyx-gdwE_*G2@^;!vbM(?ed43t%rB^) zY*Bj-3q0jvC89YTMFzSYg#eM?y&+A;a1B9mt@>GEdx1v+zXNTLQlKK3T@NAxo+G7K z=NN@0zCwo9x%R*V-i|`lOHI`WX3$R)G@BMTM;!>ExZ5-3$oA%eb^BqA_9Havf|DFw zx5RBD-xPf0Re&U(l#*_Py4W3wr6AkN!2=Ylb|o(Zss@&bj(SuVl?-iGEPS_ zXzn*mD&x7P8+%2Kd=9jkxs^!ynqMbjEEO30Qu(UKYq1g2r4K{rk(`@zu@30!a7`4v z0)kixKrxF>Jg_Z=u~AQDCmCjS5|KtOvQ)jZJ>TkoQ)f!}u}%Y8?sQV)Lg4d@4O z2ij_&R^X2;eCCM)*p*OeQsiq|7$CR{1tZ#Mt;M$kY}h1$GSX>Q_WW(ye~m`ER~vVGQLsbrEG14lMK75?lBD~^F4EG) zcF(;9yr_1Ianfn+4~+~^q!upG+|vgvJrF&QG=}nsC#?da^qrf1=9StNmNmdsBLc_g z{Ag@DW*cv5#U}A%)3E&Li-Rs+Bdr%)f_5@G#?%{6V??k)`%L=^uYZ_N?D7681o=%R z37>iax)`7!lq>=1G*!_(JRatk%?u}ZAC&`jZXLTf9`rYQL0c^>W7g6=%_iG-2`g_r z@k&=<1dYSA)LW>~6vjB~L(ovft)ccwqAs7b2?Mm^k**A`-N5#sEr^}6IfQbNf!w$ed(`Zx2qq|xNw^lPkfq2VQ}$2@k$gEFn<~* z>f7m_1~EktZpdMMMT`z9u0NVY9Df=^az57F^qNBKKXM1XDlA+U5waiyOxJwXfC9)Crh?;j$WVIey7Zvx!8 z3EgD+K-=Di^ggou_3KKvNik?o&x&n}x_vw8cK26exr>IdH&K?A%~EwGt)ZO8X$TmXqeXSFLyhS=K@GIQ-n!s3~o!?hu}$spSx^o}U1 z2K74-CyAqeL+l;pj3=n~iYf>JZp`+K(b;T`p@{j_Y+l>~4GH@L`j54SLm1?W9%Ps* zCZc()a!6luOah-sY|-}x^d+@umuz;5Y=OGdLG}|>P0MBhfU_W()`&CY^Orx0XL(HBK7d?7WZ^0T*k^I*}Lz$kn z135pkIPL`ijm`F%rz+7liH~7VM8+yaOAX%Cp{^-2nqM)2^{FSgsTU4U9V3be(oBCf zfb{d$dQl=&n~lzRs=#B$hR*z_XcikKt1*_6PuH6oJ?uP?7F3Dl--`ia_rfqv$k?1<*{oliH!U*A5^r zYOD-FFlZ7}pW%v0Atv7?kf2JDBe0>qPp^sQhnfI@vQK&dV{=Y>)BBQ1E(h~WfEEW) z%+Y9xAWZkFnVKXRA1qNfH$1-eooRLtkUryo8C$d^Yjn@WH0YLuD;XxldLv*Wc zxFg(AHxD+q6Ys?#Qska!Cvktcnjy{1ZTsnBV7X9!R13Obi5yb|+=do{dej5d`%xF2 z@L)&bRe8V}NhhcKX^AbHg;s~K{Jab=Tt1Ki9`s5H2Wpegy(?UFSWpU{VwcXhvQ)|K z)@a~qc^}PuqX-|B0d}F*qUhdAoj%o(ojkE98mv9DKA9X_8T4n(>0=Wf}GReD)O%mn1 zi2SOyc`$?%J!rGs7&#QVB%`WhgxX~oPrU!RTqlrRQMW1}Ff_>P)EVP`Z`Gl6q2F(gR}dx$0(!?Mzq^ zwA&;7AZlFN%m@G;)TOU+umS!cbNErT^eSFJz^NN@4|7v%u{|iPFQ_nLdH(=y7b$QJ z!)g4DA1#ghkN^aIuX9N1RPRzxxBDth!GQ<;BTyoS3|d-+eni!619P|nHs`-I>VX6? zpT4A{f*oqPHt@F#FV2#$_KVNVSmh9t9Qd(+5}2p@)N((+2Z zh_?0#eauY~H((OJ)BNhPr5n(|gV5C4?qS*oP!BY05=d?L0gbzbSH03eLSmP7$2&wXyw!lJtOeYDc%#S67wjtej}FbW z4uImEg!lQ^t3m<0J3*G5`Tpo@)W!dE;~Ym3-8G^(f%f4 zed#u%jv&&_#b^L9`Tqbq7tl7j9ng%SkG`OGKf96Fr6>(>?`T-)4h0fdfgp~w*VJzO z4pfdzGCQn(WEg}75IX^Q{JFwb4F@fHdEvn}2$ouLttABP%pW{U)9B;te zV2#XYwJF>PU<(Q0(wmOBHo-l{1xUG;cZumqUy#t--HakdFbtwxu_lm&aR~hT=kcMs z<)gKMYB|~p_Z|1aWIL2{4km!ScKU4OR z`=^g;sGF!|#_)Req6^*o3$i-SXca0anFNMdC$O2O9%JQ>)g3xekTBB6*i>NZJi+Q- zqKXc5#>oEZh$FbFw=h4n6P`e!xt#h?f_a*-FhLg!F&t6%1@r>7_oZgK2X!4PvvjB`$qYMnrnX$HmI}Rv8}bb$z{c+ETbCL=_oj%wmDY%=HnytN){szDwO7rW{pIuh z{ga&6J;}N6bMCn}C+B(I&+}ucjkJ5mtYm)NT5qYqN9_rqYjjscD97_jyWw$`)b71> zZL?#meTK?rMTDam^@Z_9=AI|}E3Z8FkBpP1wmS+Y25qbjzo!xdku@n~>x=DuOWV(Fv#iKOA^=86d$45*j{YfNX^g&{zfLAAr8*bTpqQT`X-~&fJ?= z4rNH#dJalMl#F353nW?hMPoYaeyoBl4{4fGH!Q8{eYckLeZOMNFr+5Y`VDu4hKe_o za;&yT)t#q-OQgQ7e!tU=WsToi8GV}ZAQBBSbou}=SM$g}uB$V4xAs=`Y=2Nk&w1RR z999{nnZ(un?s5OO&^m^E-O$KgXTVvE-3V87k=d>y^4Zfb?dzmawFgC73u_t6*QTc3 zKHt60noeqO$`&v`B-9(%XVI6XcNj3zHdEy%tX=g)=+MCog8go_HFyqdTO$A z{0q8GN58u>G2Lf{XVF*fD6AQgFs`VnoXTQ>*UvrY6-w^tDPdV#H#PNmg^18q67kXv z0pMJ6GlHrO4`i8zM12Ps4vzKH)VxW4Nw`sWnqlN0xi~eqRH+98n?Mv$Lvmx<-aAq_ zcO>bzm~#~jHiOLc={ajd0pIE-)*|jZ_{F!ySL&FIPy_YvTt)7Y-3d44W*n#*>jVTA za5W`Fep69rlh0&m2wdn+&y}5z-j+wlMrNdrPw#*5>UQ{Sk@$O`@0ZSNppSXn@HB#G zPbW>qO~-z5!`a?drt=@bm05NeiqtCB%fw@p9=OO!6PKtk0A&h<#3olZw$Pq3WNScU z!LahT*#~a%CKW#rUm?eZuuzo>9^o_B>e^BV>Iu?l?6Igl?J-rW628r`PiN-{2Jnb2 z1)?DGuKhEq@h&To=qEm3dEMbn0iY%kRf&jR6q-GRcAo_^<1&H-!CplqrvaGg5XSI~ zk={E3PtJzrH#=T~zRE)gUhaQs*yo$+W{C>IyWMyxnR-6yW@Vx`d>MAOhGw^FZU4)p zH!?uic)Z?1K=)cd74{Yl_NRS@q(0i!%>{Z*{LS3bEcAZc zvAaMDu7(z@OHa4t^f~aFJ3`1`%uqwy9)6Q9BERv_Qn-dIyDc76zOTd{k!IOTY1hJX z<(E2&ioU9vmD{(&aBUORyIFKnavigOT&?bJ;n}1JJ}H+R(i2XhXql8ZZHbXO@#y|= zGiSAAMM@>hICD7#OBO=+_SSohS~v(IZ!_vjk9DQqR$W#uM>8S0A`bw!zWC7*q*8c& zJMh+f;MHqc>$p8hX{(Y-*Yj#J79ziuVZSsrj;%AjT8{J}g;fvKq;R1VZmA}b(ofO% zQ^=ey1#4$tyrDC|DqSo}V3Sso)++A~GOJpJ^9Bk`U$pvQ@B%dbo(zeXKrnpJeAiu` z)`A3iH^-+#>)Ey*b^0sn9nv* zn`?#nx>;w}CqaKJK6$P*mYFpJhujyVr!<38ragWEYS(xRQbXn`p^;!tha^A2*S0xV zn?S<(Nx1E}zL+7_<3JdP+H?uQ&i9#g^sS5=nq~Lmz$Z$p8CxP`oIgby8uwktE$O~l zO^?aMJ>Amw$BMT8+E8YDGCHKA1Ie(r&s;(XSiLdOPU`txh$0fDe)J+i!1EDE_6YQy zKuzFtyZ7L0CNgP-0VesHdMG?meOXT5S>);?M|6ve+XI~UchCUuRT7tYp*KvPm>Wq4 zHxoXXZw!A(TkO{EOA_&9ZMN^Ja#qY~QGM5<=(a@wB-^wZd(I+Yojp4@X7-3`Es@XJ z#%Kp+yfni86{z%guIxQ$w!|&8KG*$nFRMwG?b%07BWI#p9xwIpgzocSDRAxn^t}el z&a~n`lU?cjArG09gIXT>?aCnR5BsDh^k=#A&>ierFXb&{A3xmo!#n&u(nUs+P& z0a7n`9_R0YQo@;5EfMndhZEYCaf+)<_AOIa>M!MM8hNdZE4@#O%WkM6cTT*wg?z~~C#TDCnEf=>ug*L*}kcbXE*{g+ zyvY0zgcgtQK6~O3xE}eGg+U6ZtXX4-D*%Vm7Z{IhXpRniM@|;BT(I^&Rd#yBL~jwQ z`~G51jcqNcfWcdxyv8vBqX}8gglcv~iKYq4`wa>L{i@?dSz}DF0&iY?3Li^H@^&ll z(H5s>7Jz>DMZTZG8H+bkfAeD;;yxCy!qe73>-iWC;WYJuD?V!0MLj~cLxoqnMCVHN zaJXf(8;QKumhS4(kb*N|cmP`vLwodAXDh>#C_Qd9lMi#Krf^@p_LQKs(qim017n%G zis`P!WAI-SrsWK+Ue7+B#p{b2b~r$|X0wk!sW_QB-!KwqW)IJDlX4cJAvGIgou&v2x+N zUrVk;>zW@>w1-JHqFI`@=lS4QZKQu^)r|dd-MlBDzNky%dHF4C27gOA%Z`W72{8Wm zFQwod+d8}vDh`S02Tcj^`sHR=-fWECl2h?_?&l~oC$1jaj7AcPas|_+c zLAC35J^T1))*bT$R_mDSK?)6I>Xuj8iJD+1R{cy)e(Qdi=7&Tw_0aj>x+kmYm3}+> zFMlUNN0pfKAlFYN^@b?#L`=99`DG(?M*AXiVNz!YW>!b~ObOwxBv>C0Pa8Wmz3P6V z9z37^Q3XDqa4}{r{n4mR?(@6E#i9<)_pJ!R-TP%$8;_>OF(RM+k19(E6qdwV9#$4- zGzIBSm;9RkPBXA)EL0u`>|S+6qZKL$(@F$yhJi=@(eTK$-iAk=8haD+u!e&BUAtA% z0p;#<#k}m<5JC;`bWHJ)nzzgk(ig*&%MxlK9SNt>V`bw)@<4(;&1DlwD$%_gXZ^n< zWtm49WNGQ&Ds}<|J(PI>1XKl=2*kX#g$}(Q$)^jz%XbNU_Ig|Ftj63Gwb$EY_Q~;5 zJAs2I^SV@Ict2C~t7l4&TLB*LimcwJ{~e{5TZgR@ssd}UIb0!a@&rQ%JR;#2THD6#>jFI%NWRrQc~rxKQIVU%%&wSmeC$RRIEh9%vVHVJ~kyIFvGk(%C6=IXOY$r&*uXB9eW> zoMLy#%6OKz0Zft2)Ezecbd1fm5t! z>RtcpJWA#_xvQGDAX5t)L%APKlZpr>( ze-e%GCo4Azh1nRMG7K(y&VY%`T<$GyBbJC!xz+W{r=!p)7VvUW@N?rff2?PQDrea= z!j=n4U0H3~k9}OZ8#Zf!U+G!w!8d~7^bCUB*}GDIj#qOU+Xzoll^C=7P7L8x=CYu* zw|Z}kn()rYl`|uA_ctKx+BP(#x|XwozMCYliqlO+H2n{a%igVF^_q9NVvh^>CxQs~ zwbd+5w#ae8&Aq+n%OhSxKb<%ak(pcWNd0S)3o>6q<|%pJ)o2nDc)KsxDS~>A-E4qp zfGxs;v;O#Q@M%TwfKC+qhvd>Xmd}riAY)w-DYqL*_I=;sLw$Q@S_bi5K55dkVy=qpz}FQczp+aEZvN&RivxMRicRU1G=iStN(d#)a^{ zL&bh#QWyiV#Ts|k4}BW0(xda;KwL>m%77bx(acAfX=OHZ)Bwi*%N0!eU^bqaz#6@mbr zEhVzc156+%sy8|Nfx5w5$n0riBKI|wp1_bnqc0+XB(uVJaN=(C zkg{;JY+UxFy5QVwlrR~%f4FlIq6cS#{Uh%#cspUYUJ=<<8Q%pRk%kH18u145s3ZUY&Sgw%Q5ey4;*!8 zmexz+Ob8Zi7Bq;kj2X)uTx6 z(Ad3KR%hh*ZUu_uYxpFu5D&9?ljOk`#@#X&$=J@ zrzmpyNBJzlaxO354*-U7cFb}^mp$O**J6SvFp9QILeq@GA&hcb^gTYhgKeivxt9W^v^ZHj$Br#9+#eOz|@Hq5xb>{1@sT&8O zrL#JRPqo}1)qf61?bBQ{y3nGaz=|41i}5D~LgsBqmosow$^@UQPU_~BFO&WpT-P@S zw;pL8C%jN5+oqKq6fWy*GVp;}X9Izyq(O1`4Y95n57!6wRb#y7f*BrDHIfx>Q&1-N=UIrpsSecsAei3SN}mWfP-x%~xQxB-{h= zU(LZC>%y1hoeeN7YUqf3E}B6!;FHS_NAXfub_G+3N|~*qaM9=Nq*dWDX#(K_-U6@8 zb;V0&&eB0TI3cT6%G+ELWcF_)?F^{dme!P^mpQpDBKb-B?p!oYMY(AwYME+1IJ}@n zC!%G}#O;){2#+G4wBfg7o{x4o-0@b&01k;w51h83cjjp!Nu|ndLd7|pFiEqyP>O0f z0}Cxfs584V$MYDpw*sWv@ z`b(bhI~m3Kief)ay;^@CgYHN^-K#fYAo4~``6#^;j($AlW>)9z^(R%^Q^b%+h7o=V zMcwF_=PR^yQL7Y2NS|=;ZtS{1<$^laE$C)5UWh+1ayfP?c{_S^`8fX%>gUWIZdOt#HQ7-hu%pJBjz58q{ z3ND<*0Va!$-M{6ik)Dcv5$(DcFXjxmC=$;0f}T+0lIZgOLhjR=t=|h)dnzITbIbU& z8re-~9Z6c)Fh-eTG3i)w5ZPhru=GlZXaDIRt+ufNIk&o+x%X5oACCeWDL?%%Av<49 zZWh;MUdDi1S-16cnxt+QU>sx(H+L-H?$kI_tos6WNVhy1biuPk`T}!PTvEH}{5GRW zl{q}@#6LU78Jr6#*0;U+6zhzqE>7=aJ`&jEnzd@l`e$M$vF+%ap_c%PRx7Ia9z@60 zBU~k|JQnK3soj@E<_v#2BCwCm^v^~Y0`H{*DJbCy`A!&8dcB&FU>fX;FEia#qH3@T ze^>B6VG*_>weyZg*vYd$Y!OtaZ>COY)L)f*CJ>%A;4EA)eu_MTYPDR&`dIlP@nQi# zEW>q{^9mEiPrNrI26|4!P0_i;|Q zy8l{|sRbVCrF?#OQt1Wz{Lq_Ip5{AL94Ne*JC(ga5RDRCcz8!ujK6G0dmS4d)MF52 zF13*S3|{4v65bgja`0D0_pW_X2qu(}D4OzhhHMcO9?hHYQ6lCQl~MVl8B**9Q-{tZ zR9+B1|791m)Yai?`AX-^GZf7&+K0R4DJX{LMkZOVJlTCXVnjTexKipuZ}F3F{^xSd zkk#(e`LS+o$X+A|KTjEfUQ*mrO&py8?@VFI5W*nD_+j6fc5(@A2cs*XWY8P98dD4= zEa`fB;W~yIOoJ*vlkj34eVqN!7RllkYoh3QhH$@EPwdZ0n0}n(=px+qJ-B7f4t!~3 zwvV6bQhku~_@GiHuXO>aY(yZQC>DYsZo{2c)a5QvS9d&kEtiHHqWk^*3{Dtev!OD6 z)ORl~NJEmiEqK0j%s`<|viUOt=_nH8hNP5c**HMBwG)nC$x;-5jBd4r+(67Fh}qG7 z^14%~#Wu6tUS`nw!Kb8 z7_;0?d7rC+zee{;RQ3y4h$1z=JqYs4(lAO&hXmctA`o#5o_poiE$o~-q79D?!%Cn~ zd?oDTq|RvtYo>YK+~z!#t}vISS$wu@(_K!A(i=fCWxu_=H@-w0um!h$-nuRA=4Zl? zz$YD%opNs_s}Kx4!TQeSPMq0k$O?Gk;OK$c)8ZE5cqBKfzN2}-(#-C-e7i4z^V;M- zgZ`+(#-$~^xnA|Nog(Xj z_y`UCT395laQdPk88N!26N@mvpxMd$wiJTT+9hn5{s4X)>)q`j{9+wBtZqkKp#b(8H)G5qpi!j*l;DP%;sL~5cy*f%)4RhA| zZrB~_iJgbU^P+jPnfuU(2yz)dnc4|%I{VF2Y>E#oUHAn&ZwGDguz#<6i}Bp(j?^lK zc5ga4gw_DI%s#7|{u9HDFCIyCF@O-bU_xO}Qehk#2 zzpAM%da~OpF=>hsar)iCcy4&>NDf?H+JubXnzD@=AsJvd3#;YAPTcYmW0NAuB5Vd5 zI!BwFU)H0cleJwzar-mv)XQ^H#g+3BM9a1LYY|4$!86T?o(2MgBap=P2xNla9`ntF zMR9ISHvQ~L-Ln?z9wm-Z^xatV{%>@QAC$JnXPMD6NN$r|7wXoOXQ4J@3COomQykRy z5W(E{U$R4%6Og3M1sXvlJJQu8KVeS|{o#y@WdcI?h<7QSUKUoMp0Tz+z25X-Z0qHm zQI%RS+Ah`57Gh|P!x53-C4+>Ls{k?hL{(^@T(540fmZqYUd%$fKPXfK6;kQ;wNiSb zTE(j+w7|wWiE6BH>D*L6Bo*x@c%X)P#z9kgQRJ8Y@3c*8nkV?wij*QE*3Do=*btc zy>zG+dBnZ|fA2m%7SvOkb2XYT1UX8o9bejvT3anX^_16rr#PVYd>|qJ3kXJO7`;H*jcniz#(qBIcel+R^sj?oM06XL&ia9_D4LH~5uW{Q1lRRl zRupeD405=IBS#t%rKbEzzWPZ>G8N*WwH)Y2?Fs&Xo`jmNQ41>yf=}Gdu+0F)P-3H( z3g&-sY;wnUXl5Qq0}Q3fcrEUINzbf;HmCNoxc`{oIzc>LCj5a{6oDiuX#Y%rjUejK zzUm|FPZpEPmo_=I7f&ll)3Q}Ok@&RSb3MK7vZXKloi4GNK3B6w=^ygBQRRJdO#auG zMmN@^jrLg*o#8SS{)^5SsdJ0?F$$|krP0lI^b#!*ReU>vF{6V==T1APQjk*E9cl^=VH``KI;hT7m977XQbKpVR%4BgqkTPK3g+Hh~ zqCjE!yL5mt3C)KvhQij5aJ=-M4(S1KPa`4Ra#Z zcQH%01Bq^0g7n|qv?dwYJG+jYNXhP@yMQ!6>|DSTAM=bR6PEJfU^` z*Lpl#M9C%!fq#s`&MVs;qsww7;_u>}?lW+Yi6snnr9QUidvc=`{uuU%#ccFGmT>x| zE>q3jtH`H~xTQkAiUsF)}H!E{m&bMi}h z6oOEMP<#q!N@WAk+;@&p43ZA1vwDTN%;(@qY5^`~J1a?{98A!_+nMQLW6C%?K9^OW z*AZc+Mf;Y(zV-J(!gYA{OQ{@z7l6_w7p-o$AkF)`(7?t?){45IBdK#YQS7xqV4R%< zC#L3EptPs}SWNRMf=A9sC&PU{0e(LyfxSnMdc4+!u6HYBsKD0Wuj1Y}+Xua1uMf7p zZMn)3R-(2VG7?M<&?O*F&E#4DWQuOCnmm>c?IuYTA&BYj*kVrL(5$nD;Y7e6qIwtz zYimh@>gE_UK)1qx0(CS*K=^r*Z|lWOZ_?vrJMUL$a2MO4Zi&= z?6MfWsp8>@CoI&jHFE3&9EM%lTQcs_$<b{8TMwR)IOQ<2-f#D-fL{cXu>~8MI{^wg){M2|Pk7o0O$nWo-7dNTCnFCDM^B`+ z^Dvg0KHzV0jd)~``qMHXa}N!c4BNaHu_~cPJbco^e_S#4(v=a?!F0!89+O^}-uOR8VQVe_m`m)td=d=Rus?X{6-EnnHi0wJ`HM z!GSJ3dYjn)x=yix>ur6o9^p}s?Znq4D^Du+rBLZXjpt>tbkkGLSwRyZQ>h25tAHA|Iz`cz3{7?vT3%1nW2t5i5tVrRcX9ljjP6#UT z!pp+i>lHLch<6(-CwXKI`L@og-g~u3KB5??4f>ebC;4jh(~v7+p^M~QqP}SDA$6no z*dl-g11F%?xCiVh-Ab$;x|QqGoiag~HpfDVz8@9utq5tp|D3pE)UT0{02=nX!Cg?^ z#qJHOSdwq#Hc8m!;}BHIA@MSLTWr4U>}8bFg|Tb`j+1Ocved2sDmEVt=uhyHD z)U!IyC!2GQPDKlj`UA2e^n$ubW^{`8r`Bi{Sw`l#Q$sogrAg@=n#IZG-b5K3)_UYA z>`Yb$vm`VE`N)M2Bx$At)3PN?tNRCNOE?vbOgtQ99Cnn$p3f3^L!2*W4QGU=b_Ksa zFjPIQ`SdaN2~ah1N8)_ek($_3Lt6tEXBK%@SHAzd%z1B5z5hUk`Ne<*@Ep9s#DHzR zmq>I}Ygk#x-)lNH>VJRQY(;wQ9zlN_&^XU4POfq>;#G>@ihnHyNa@tz6EW?!%=bvs zZn-XvfEohXFiBR$KpNR3y*)ay1A|==^AY=PEj;&s$tSvNIYE=X=%)+Ew%bx9Pw*71 ztGt(T%ZDG?@Wq!A`EI&L<^&}+Ut-j`|MDsp?DYp#T{sTSJOFJ2ZV$7%DByz#-Bh3Sr^N?rCaHl z@5~V^f5G;akTiSKL=pO)i|BQhK?k8yMy1EMMt?_sZ@hZAO>60ekUch(Ps3GjZH2q8 zJpFCtd;z>LT8)qV3b^mlImIDo%9+WWa6SaNW1{%#5&qH^j78xco*)R1XsVhL6^*)# z+K0UK*+s@81Ru1BK7&HzJw~ro8Q}@?+g;wD-CiOQ90e$w;e!6MMX7Dm>tr40JoGn> z>hM(Yy1SBMc#b%U-G>FaVEmfOmRLf?E$d0!LV?r9CCc!oT)ZssKuy)LO>8=`;O0$2 zCF}r2uJqN>H_6zY>Tdnsbbg3kz9JL~-jjgI3nn#2d59D0&P4DAHWwKxkvb?$5m?b=X$53Z--&ryt+Fmaf>YxbsnO!q zgRQkvru*pkXS1Ubvjye7Z&8Bu_I#P0Ahy(L%jzNzO#YvJ^`hmd&=%GW<3iLae47nqz)~1lr(_?s3(P#7is9HLbD-bR*q=@KVb9jAI z97TF5?|hNvXOSK@cV{kt#kX?XL@EUjih5`#{${ZEdCYcic_Ge(6F2vw$e+&9BoA-< zNh~gCK1>tMe1x0ORwmaQ*1a-<;}*r0uIpES3D^TqCoYoGfghO~#bkahHvt3)7M=2K z-2nYL%q9SL2x~oI*zXt_^n0XV`MTyJ9id!`DWKgwAT45s$%HH6yzZv21_=@(_v1Zd zt#JG{jq>&aeQH!!nB6F{9@i3w?doYcTO3LkT{H2Xq*04kMs~OHN4SdE3Y6jXA48QA zfrl=kiJ>D<8c-{LvpGvuBVp(e-M0;AWzz226RfBb@AN;w*&Ph*tyk@CTFxX@or4&f zx$_5{7MyGD-gdG(5m5UX@V#5nwGdf_&qk%pC&LtzhP7`~q)zZvQsY$?_qNcWd*P#0 zObRosYqK{9_DCuL_Ox!PzQ>w%3B%UdeUJ_E`H6vO-eMx-ash<)fL16bifqqF@q(uYn-8S)vTPp_{WemcN*M8y>>~#|he>KD z^j&Y6(Tt7VXXT^q;z=}j^AP*dETLhnU^*zI6nQ>VHHftblG%}hLp992gyf%NDha~A zY%JF}=}`F=5yRMLH44+RB(&)WeRxlc?0_gQY*7j_OI?1;Q0h9#jEp-@zzr%oNHfAy z1WLq-9jNw^$|O0u$B-G+V;Jz+Q$ku>dhP0L2$n~r2jw)_`%<<+EQw$4CUHyK;of)x zDOzQS#P-y6$cH2|X6uyT_JVrlXVKzU(IEV^iPB`EWiZ%~lq{G{I_nblZCflLX31ot zNDEc;TF=p-*K$twBkgSQ)-LD+QQ%mlMT3T2QOrPC#glS~QXMD^5Ek(O?Gbd2nMFXNzKssah$g};(|V3n29_0M zB*r9mkmzDI^3kKS>cy53w*o+#iyy~OZc_FSo>Edf6Sp*b!J~W4xquO3l;UQ}OspYy zxP+>PYcXtFKs&OHm59!tPJ^|+bAxy!kS9ezUP3i-SWG(`xJiKs`=hX4Ne=EkXQ}TJ zyB4_c`f|M$H`ePDXR@zqWEg}ib0>aGlv!8@TS@TeHO_xZ|?X(&_bH;%1TZ#YwhQ<7~w*%WIvrCS$BTGzm03oeIrzZ3TSx z?aNK3of3erAA+>nCpj#0xj2^uop#~OIU2^8+C_UpG$1>*`(pA;@4QFo-zqJ5%< zCs}bAZYIKBs>nFYyB0*J9NQym$T@g7bTy&#xVy#uj0J?H^86u7OtVjZUfahzD$xV) z?BZ}_y)e%0VNnbB)~s1vYJkhI7O}NqD3;yw$m9g^%zCqAJnnV;cnTB9J0&nCmSn25 zhj|~W#cuY!4WDOO{8maiFmwsc5GxsiM8B`i%6MFD=fgN?zZ=b+1 zU_uO`b4FY-HQKy5S+tbz!@I|;KJ(4DjI}yacPe%WuO_J(CUm?`1*xBjeBHM@0QZ1? zN~Hi^)+3lUvO)d0jag?+cO6vC_h->}qfOw;`BYS+^yZX4IQ;$Y>2j8-SJ7HbU}*3I z%|Ng=B}mG3R^IARAQ^AgW?M+^S@#%KW2xl*a$R=@NE!L1&ahQfLOg{4lrcCf_BRVlGm@5A_Q#a50a47`WY6S4aK7}La-N#=z1QVqq z;LDG*RA1M1?o$yEbp_ocli>eT(fL(3o2a{rW1QNho1qpnXK*ZSzT*qqyvwowrG8nYMnN`I{E+9+@dE3Q-#a%Dp^p|I%czo0Gqfk9kh0(9Ly;zTSET;bpm0PRd-$7(r=WEs|hp}>o@V* zbe4+S6#Qyc;J?CU7j6F?2G_fU|9NF|Y@dHh4OVPe_y;Ivf*RRrD%Nc&{_lA0wuR00 z^Y7Ofe3z<-s-`ur&A*gg7va^~6&wEd)oqGg0alW1y@~BJe1!Vx+TO461$=~1*o}r} z_+c%FTV1^bZv3yu_yOoKi$CRH`3LBOzq}zZ+>{KtZGQD%ltfiTKHarP%mi6%$RgD(SWH z#Qz7&eRxCgXzHorm6*zvqSDB=xgtI)lTJ|LO$lPBqU|3*O5h*BX;Ty57CyxPy6q;& zcqIY*@s}h0qRlYCDaNbvzfVC;D=@}H0q!y3D|uA^0Bb|^KP?E~Usk_Kzcv3~9oJzh z3F&qoUU)SdWDpY&ek=I$*3GmYFV+6w%pm^HWl7m7vC>aYPOr;qe8a}o%)_LI>9iz@ zCjW~e+~Kch*EK6(ngRm$^{WK3>{g8=CaL zCF!Sv>Cpks;6L}l__nmN_LRY7hco{Gk@%jQ*Pdy_hp*y?r`|XQ3cDRSTn%6K3!kgu zr2aX$q4n~{=4`fJi@Zwh5KL9}7vC90ti~1TfOPl}ewNkWF6Kg&G^tm@Sj7J8XgF5o zinM?9A0QEbtxfS#l(|p^4GXfv2UJ|)eZmf{it{-E;J7-)LphCo#rbM&7T$=*>;pdk z07M<&@YA}GI|Gp0d$0Zhf-h(5)!L@H4#5=oaV6?Xzj?5u8bBMnmU{2=1int$-i0oJ zG>*Om8ai|13MM!lm8j~v`0spzoluw}?O#*(8zV*L+YZInj}P$dR-2*E&Dyyvofqs% zw|$4*>2pu^oo+j9&PZdUA^PFpJ$8(%ZV`_P5mx_M`w#HrzdGj8 zX;1)vTpK#>AHZscmhf<#mizMt`+q^c)8gui_-mW+?#E6M7^A?>xYl*KUac*hxd*%L zKSYHiJuU`de`#Y+-rfFae+V^xrw8S~Dm&~Kb6vqR9N8eK5K$K9mY3jVwp>9h6L)y) zV=0HP-TweG&i?@TH!7|&k#)tHhfotGO$Z*Xrhc^GqqtQB-VYxDUW%OE9#w1WwN{z= z^gR|MyD9l`F{AdFaeyU#!I~qy7k{?Shaj;-TIv+xpG5xvdExIGyH>*3U-z*^f-h{& zOzZVAyzvSIKYQP9`~wKyjz!~xam0S~!ta3UY3B%MRw=D0u&pRRf41jylWRQ@|M8LK T^kPI{nZ!*l)KFIO-@^X^-VoF1 literal 377115 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

8U4TBI zcpP@aD16uqYZ3%a8tFfh%>-LCFMJKxKshAzccBXF48oKOwIl+!WC}Z7?cbbXp_wFT zn=q1VU2yyIv z#7P%nXvn&R^Jw&xAd3#Cxf@d1G(K=*6-=_a5@ar{NKJsc9ro>8ZC7UtAk+xEy(7%h zK_}I}_^zd>fM|`08#ny@@WEve%!p(!J&I)&0~s3C z0DZ#IUPr+1`tgI|%ttE?F{}BiOpO@7NV=og9gX1>dBkl?9EA%yumz11*q;23Z=LJD zCWdHPmKh}sRIp7bTBvS$_x8HKj3RI;GSdcbG$4~;dQ=)xTTwd_f2XzxN#j=zwkPu$ zfgwv++igR=ar0Z&5RnkY8kaj*l}AIk?LB8N!IuLLT{0`IsU-Rs{8k|5WovL&4?6;(i1uo!KzufxS` zJ+VKQky)|G4u zt8?iae0{r~=Nsq=BQ?u$iV7Fh!p#!hkEiNE=MxOO$l-L77t(YtfNT9fOaB18Zt$^` zthtdBt5U1_PNn4RcOTq#;1pz2*a^$T%Ov6;3$V6b+Qrd9z3;Zeka^n}mKIprCId+X zxk$#gzr;ts>4prYLq@1TcLZHiY%Eo8zidM+F~}uW*;?8_+JI0+U2k5;`*DV;5LEHY z=941&!s-h_mhWOd-uxeI3FJ!;nX$Q5g3%61CdV~I(6jN#!~FJ$m2F-(U^OV%Hm#_U zzp%PDTns79MmZE*X*!<{(h=qBCh3*M81}q6fT=Q4G@OIL3AkRkdF@a$?sCl!yT8G*y~n!*hFXHrUqZ>wz;JJ5_{N524MK zvJKcHx#0b88gb1a(kl6l5xJMmxmL+#T|vn7g+AL8+h9#q;XY*@Sm~A2k5d#ixHYgn zhu;@G&QysR$z+YWL3EGua99a@2Sx}ld zSqUrV3aw_!>Tox+z}l~|u5cseXgfpY8w zv%a4&3jl(n*p3e4f0KrF9-zpjnNJ$%06F=qBc5;Vf%7pLA@kZ|t0P%m8D6t!<;U86>MZ;#(g3fq%9e7r8g)D z(p7i8c6Jxr@4hV^FE62jz|NkPIz^J*i50b0pU>k7`bjqu8W*I034K6b{*o*FKNz#* zvTGnYX;2VI*g0BLy)f>!yH@z%`EuJfV^lTC#LNXdh|!r%FdL2z!s>?giwqMMQXyjD zN|H$+Z}@it_};z-6~z(OZZk zjAKzBb=ujrg&LD2N#ZVZmUrs1{0rsCPHL zf#2T;Wb(2J3~djZWeNx+kV@Ft_V2kj^~X&%mVxK;F6sR~G?@e_sKG_JBF!2#eC!AH z!>FSOi76U9Y%1QTy@68)X~Kh`Xp7Pz6=9L=RB- zA3ISvTNy~!(8nVUg8G!G;>}k3jxVvnnI)0)MbdVoTnZsc-0lX|eAR8=9O**Kc`SF+ zrCh9wp;fuRO`G8DwF|AVV&)7wq72SM2Lhhd>YFhx&qARc#eO>Rq6X>}xT#!`isVkRZRz(sms*P>Ed)?j@W;1Xr zNU_X~sdm*ed3I#^{;dt{GQ&*I&VRioiC33#^K>a?rDXB$h(T1Hlfb-&DCGFH_1X}C`7KYi3j7QASfb@bI;Buk_1j8VpYlz7>e!NwcjVV z1AJluq9l|LEw-g)*b+!Bx!il++mEIdZihFardKTNQb7>htsmxJ^o@z9;kzf2}cVwYmCexuEwuA(_S9x=2G;xzKrq+MG(ke~oa z3tOAm{{XfY;>EwXZ||}?x;Ce0a!VlE*MbEK+mC(li>l`Gd3ZrrRgs3KXCNI{=?8!+ z!LOVjn2j>F)Q%~g1yE6TS8tuG>-5EMs%N5S@|HAV2xSd18`|L4++O={T=7_Ap3J0C zK4DOlmNMF`Q6K3%b{F~m>b*~^gR9mQmIXaErub{-s8`al-0`qEs){O7r?Nh&o<|Is zf*z_S5)j2y8>{!L`u*`$>RF|fhe!%IP|LQ?LEU+=&nCW@&sgfC%Vl{RP$Vi5qyctn z`P%-(V!fW~4hxAScP+8gLd6Sjs2f&2CyV1KMuh%m37?WjiK25i-+L8N2%gXI|@9%X=)dk;;EAI)2Scouo(3dNXNJiE~clV`Oa{`+IVtDqznQfjya zZ}|`N+W}_eFqPEhNCeh}CjJS#=Kla(J!mvZnwmVmU7efCVnUWyG~;Uxzia;hYz`Uo zFIjmCjUi1B#MDh4{`iR&X@S!lDhg9;u_X2vTyuswcw%@4w*jiPsUvOp`TYC);E+gz zD*Pk9sXw4A6hQ^{BYCH3}-|2wYEt=2D5eml}gHkO}2izU*@K#bOW_a^GO%hP&%qY!8 zs)qjnRr%Q9KB?7Wnxf0IM;THQFh=Kv2DjjEzkE?h)aD_|BIWu@K4UamI3uB{i6)c) zzlzBe0J3{uJr}2c>9_WR4qr3l+_HF2AlZ~m$?8v8w2N1&M9Y9dBG2PxvM6j0IroKn zzgh6#Tj{u8GeWRKj=9L zIv;_0A5Dca;3WCgMf19VjW#km6Rr0&UJdb&jwl(F08xremr2TI zGtC^T1hFVs^|G2`)Ic2G-L^Yo2_nqpve~|o25wjCGJyH4;gqy-0HW4A_`mCey3bh5 zcz-I8Nz|Jyn3Q>cyTuxpUDs8x0*MvxgncGCWy?p@x}+s?Zd=KQ9YOPk`E9M2?a21W zp^B*5RKK~cEm~R$T+f!#M+!ycWnl}KQb7u%`S&%htlztDfl>0A?6m3B4ALfPyp(-L ziQ$`9BDg1g`(UY(VF&M-nBtYDj5tLl8X_*2etY&C{9qaLd3?ra!@Vym1Ir+M!|0g$ zLEP9p_ciV@BW#EhrLoO*Y@dgpEgHkp43bRot%qx+ed_MU)py?yJTzCteKW2qISD+n z!i>r3AdQBfaYpb?TcUNIvU4!_f2GZt>Jp)Z>jI($g&jhP=U^+GcR$z<{+(Z;3CCYY zpD{ZtNL-4DSGN0-EN$D9fY0RP#}_F*`!DWRNvOrioGn1CEc9{kKJ$$a!m-V)O#AZ9ED!>^=Kc zd*kL_snzncW{hzucG7gS0L-L&e0$)|o(pB;^PSjfN({iOfB2?>2FD*5Zch#wDos-~ zCG@1n{{Xe`881^+&BSe7G@)#rB#Pvn`9E)wkD4=ir_E+(mE_Xo&?kGnxBRi&e`s>X zodeE0EYY1Uqia6=cKUvp;K9|{%8C?T!uFx@_Qz}R{Av)SY4QI6Etx7@>9PP8EcW^P z<3K9HwyWPz^==L~^#Zj571ia};e4-D$!1yPSsjbn8K(n#Fbu+?TYTOaA zzW42ofIt5LOcw+x)w+x0=BxT*Q51mLjXFl;;W|Dz4ql03v-(iJHOWbTDeGzo< zS2G-@(PL$G+VuffRz6QVbB@E|?-9iwRb$ICl+dOlbg_^PlSgoFzBa4JGt1?2?I>nb zq;8-MT8TGj-@YvUKQ2)Un7u5TLg@m}di#&~$2-bPGN9*!lGkIO+GmM6UVFpy^te+o znwC7oO$Ke=s4pi#9@pQv`$PLN@k}{AEi|P9uE^R(!u15QHE?#q{P#@rGEEtAA_7d8 zwG;hD>+!Y}!wj&ZWfpBw$6zQ>4<|_$KTE>aI6OX>3&xXFeIL>?-7CkQ9-c0*o5>!X z)C)kd$Vhm_ZomaPPjSA)3{gB|;LL~Y{{S@?{t6zW)jCAdh_eyQ{$u5)0?2Pjw2%u8 zTM$QaiT?m+9ceOMAmyWLNdm*_HVM6mzvjL6`R$9W{YxvFi!qn#DHEn;h@Q{_>Ta9u z{I%V7JY$)LSv-90FU#;_$u266J(=r5eCW*P@)=i<#D)pwRgB9S*;G30MT+228`cDx z9+}tj&c`X7mo*fJE^^JCVDZUgWk=hPeIvNq@YAj2a`GpYl+8f-hzdSYSby@ZfWQyt zyWXh%`Hea^QJbkjn960+T*hiZt|5q1qi)+j;69(`I{~<(j@890WkcmUXjT6Jhw1%4 zIhV|3k>rj^85dJs0sOku3)~+``qmDMsdT1{<)sZ2%%Diy6%5O3WN};ABVq~V=|%*9FCft0;>X4|i#s}MkY<)AC>k`< ztjL5=QoGo__QANiqAZt_oY7=lgG-lO4*BU}+CFUe6dR1%#z!lz(8D%qFXEw#N3{VFYo}y@};`!hF+X<9hO)~N& zUqaX1l&?{W7Rtkv{vDMpPvUZUye^-qbu6SsRC#4@NGqsrciy-=j1u!^ghTgiVuY=CcLCS4J9d(ph$~S4WSx>w=7E=ecus(5pL{%q((AHee|$sKgX$ zU~azOucr_ctgW<6WT313O@n+6{NKjdWceuN&!LX=f;AfT0kA(ofx50{HO~giooX7w zkSk$FNUk^k0IW4j*$$32>MOp**_jii<%3EP%OwU|C4fJA+rQrxyxw|ALnA##!opbs zy}oE+uTvSE;|XRPfE6t5d)D6l_rMtl1f4<{o-v}sklTtJ{c)!oQCyhcNyS_2b>Ud! z%4U*m%YsN>UCr-SJM+E~mlDnOGc=&3*jJ1?>FY&v5o!S^ zMVWO2WP`ub#eS8F_E#W!l+sNtAj$x~TN+}g@gMWw80mz5@0jxmP`U{8gZ$q+etU6( z`etf3&l%=1qRA(fASqs&s~~N#-tg4DHBt5osc5Xo%#0S@j&obPDPd&+Wfh)>hZAjtCl3~S4P0+x8;uY z(Rv&MF3ORrf)$35WSivH$BP21oN>IY-&V{XM4xO)k;p2~b4P6CDO9!5v8~vfH&=b} zW6PvDMNuM{Leh%$8$0Sg)O(M7ZzKr=v!Hn_P#cS@J?wyMZ@wdvO%Q(Q11;X91TBlO zMekqjctm96WV!tYnIux~HPJl#jrgzWh1rQB^4?^0V@#)UpmD+X2b=l9xfY6_h%&hjs{=(oSV2h^4By3hm=<`# zf*gbI!M@$>d*ELe^^E6D%Xyh_#Q<}p3Lt<;3w7FD{7T_TaNH<^p zDZARM=x`T}yl}6Sb#~IltnLnxUx#yFQc3TOQNuTuiuCQoz&KBj2~vOo>TKI7++ zUB)!Zbu8vXD<*5GX4*+4qY^16Nu%l0{KU}Tw%F=_3YyuW#k7(-pIz}Z6S}PVpD}@H z5uwVve3E>U}>uB>r!iA}DKG)2C12=Ggj;kAG}I)Ai;e8OfeTo@PdI zMNDIog21hay}RB3l6ksxEh91&e8K)9HpkXN?m^$uEPY7B@!^g&#Stsfa>{teJqA(? zx~^m^$s%L!Ii(>vmIp; zDP%715pZu+6+54}{{T0_ca4&;!M&4v(K`NsaCPfw>ek^Z|P?}DVY1=jE8Rp1mmT2TFrF5$|8;aZ= znNQ&$_BY!Sb?%VeD>fy|jX7N5GeS7iT&L6?*SM@Kg-g_WeAZ<#s4YY@3KjG<^~Xr+ zFh$lpA=Bs0h~muV)UkRVnN<$t3IgkYt|Z?XSS|5soZ2L2l|WQCxE4=0-?!_7A;{*8 zE9Jt@z}Qq8fv;-!-}1&X*;&{t3uOE)s1L*L2XY4(utgqV=z$qxgn9!a04N6D_detO z@orxM-w{SzA=IUdDpFZu^FwGQuVHoo`(eyEEVf!C%S`&DRt4HsuoRF3F)T*auowMt zrhh$?$iwQLq-BV-2TeDy0CQJn$@am$J|~wdkjfz~Ia2H8-EF}59AAC#ErQ*nSiJX~ z&6^20SnLfUERjk_Yjy+w0IJbHQC`@l)K#!f)fEz4 zM#&ox?|!1TC<@^5`i+J+o;ik<^_Gkqk5DYOK^yJ$=Z(ALW{!e9F=*0kg5IN62S4;^ zULle*2r(vMAJzOpVMzm!LF_i)@4h_mW+GXkm88`RYH-V>Gl~L@DL&heztZuj1c5wZ zOM&IG7ZeX-2frU&dD)pX$vl!7fiz@0pOOIE>-NT=#T27VI(3jhk&P{L_v7-wPHsYbM!_8a z0DZB7?-*e-G)RStfod9oqJ8$W-moQ+2_lM6powCRFj%SYeXr@qd&H3^tFZ1z5@~$xlp^1oFum zZ3Hsv2-}hgqDl9^pzVY5^UErzj@4KOIzZT#^)Wo%ZT7}_#I!!jOcpRh>82r>RBgVi zCad4+&0(Zc2A9i0r$Q}Q(nZZGq3<~fOd zWJKw^5_eENBns`{=eF3(G(omiq(+WGr3S@DlWbdK+PK&sU_Nl$Bbh9(=35v7F7KsT ztC~BF{UdF`+OUr%JgAa5?_zyA#W4hc#CIGK_57UW=4pc}C=D>s#2Y9_b7K3E_Qq)~ zg2s6`*USxU$W?(x+KI3jU2I7Ay}r0*37I5U&}|r~*cINts5@W`yo_01X&n}=wUSjp z-B<2?j?`-hCS)rUG?e<(5VF`(!q$fRaTpYt6W5q98Fg0+K9QLA|SfHxzz*BXqg4^#mWFJ>%vU95rt_S}5?V5AT%LolpY_(>bm5P`^}Wbkhj zBA_nPN2Qp0TS(Oy0FS8^@rOXV70;59(m4dDM7*lj%A=9ojlVO6vt&%D0_qIk!&_~B zmKN4G74R#3S*OSe-7^IpH2@h|s1gaXNUPq){@;9Q`;x;GO3niS0A&WrJCk3Q_1|o0 zjBK41oX$bitgRW$Fb7Z|_7p%P@QNJQ_P`^iCSFM+2%cnO&3Z@#TVJ;NPTcn8+3K z;u&(fl$EJ83LA#1zTJ->Tq~QVvq)lhcosGF@YXo>H`kHQEDsqHC)*lhnZu!qpJz3frnGU15e+*ZQn6+y$0I8-)~wM0 z`dlfkB$}{y99Pd6=?~C6`5QE&b*EyiHw8sf(XG#M+vfr|Mo<_;z=OLF!~m_xt^Q5e z+iV;2WR}JyA7h_M)0}=7G%~we2Nq7lNdVv9zTWuEaY+R>qeumrE8Kz$ayGnNvpoga zmY>Yl03_sStZgiax3FQPvz=9Uv9LbCVT?JADzBIYopi`p zzpHX7LAq|-?Tk~6^d?dtJNd97b$3-nK}%Xv=#%bF{{W}HA}klmSq76@i)=#!!1z6@ zelR-q1!idkYphu%Ppk^xy?f#rCWL{Qf=NcvnFAAKZUEZr*!J5M2-%uUVEN+X%OV0I zD;RfSdg}L~$2HsX#BZ65LXgE6l2#{nO;@!Yx6{3k@L@)4IPUSxWGuQp0gaENeAjvd zYeZ66?@4%hh`|~SYN6zTUNtx2Oikb z3^lMhY}gbN2vtxfq-0bct+*sn2cG-jO!PBmm&!!83Uyws>cO%$?m6r*Tnfl_t4bs+ z!LIG7`hc<9-{S*jRxvB(-YFI|K4NLI)(wt!`u<-S(~cDE7coq6M-mU-426AaR2u?_ z6w8yL$( zbzYWD6hk%H+)&uneGW9F45kW+8fJXxnIu;q#9)NSW~r)%-M#qu#L{M16e#0EJp~E{ zlfK;V#`VEC$d*J_hBRGL7G?#3suVkW5qK2Q3voN65w&et+amr?bM5=Py5+)7+wjkIS&2O~| z-tnWeM2aF|8I0IhI}v8si{zh=>4ouTJjBw-8D?uz@&Q2XN7HY75e%+W%Nr??6;u{B z0jm}WvNzlOCPxB^6x%$aStUl6f)htsvqai}JMnziJ7Qy}_^cEIq1ccEFtN>$2G)1L z@s&u^Q^g*V1Cj>7gSb72J-Gn;;uX(0{vyvS7Z#^wpbo}{;Lzh@a9)}iq3nzF1PtRM#)`<=S%sC-FSuRrea-$@SDfkv zytvj>wUMGOzMVvS6UN5BECjG}84QgPX9isgCAcK|BVfQYUaB-V*z@zq#Cdjs0;XY( zx!H!L1W;NYt2h^CV?S|Wv6wISY@Vs#JoZawkr#AhoMrKB*oni>&5<10grJYm~9*Fk6_xjay#w(pe#M+~9(=$^ut0xP|z8tZU5qIvpasn$CA^283s>N3uC2C6-d`+WQRVJA@Qllki` zayEb&RYHTd#?Q9*zAL%zt(%%)@@uvmdTz9uAaAknUGdfNe+_BeigK{b_fyc)gE)*( z(?9`1w%CjB#cj6uto1IWf?|%^r7>uBAZcPOi(cIP@-RP8&$PjsDLkN}of&@@y?3f4 z{{X%eW*S0E%_6!I31MWO=BvL4?O5;O0Omj$zwzS~QU=dv7hJihNinSrOJoGI?Y(vY zb68C@k1Mc}WjdQu@4ozs6=wPRbA~yG2U4Q}slNlatMc1nM12kyv50wYbcP|8lnq4t z-E(Ih2u6d7pjjlAMkYmKtLr6>nyrs*`QNtq8%Cu^h3vE5rZfP(fgP)j`3DBdibF=J zWt+>kZC_!Xo+#dbAd~@^09~8qCOj1W7&*I-=G>$d{?TE%wNn~YG z0>?~Pl0_Y>oxT0`!LsGy1(hRejcn@tH@)8X$MnRIvclxeyp~vs*$2J+0Dnv|L?BpY zFcpn_#YoxI8}(K1&wcPfAHogg0`qK1{5QWR~qKJaK<)5=D|3W0FNyi(7z7uAPaY!1w3###=o3aLpcCJwcAUtts2o zN9)*p;B3t5iae<`F$|ilY&Z%(t>JW%w4?YDu`+sf9f1Cwuj3cdC_Y@n$Xv#Z@_r3W zXz8uF-($f2a9nwD2mb(v=OH9U3o5Sr{XK_2*8t^IWYhQj)38!ih~ECXO>NH`^N4fV z+|GGMTS*YD5=hcpZOE<#)*%e%x{vQONQ%fK2TtaXH@CH499{%vOu17U>yeg}DGY4y zX1<=>n!zwY&_xC8lK+>nJNK@-_c)ww}`+Q=HH-aY1 zWn0aZiRDcsvw!iau>Sz1FVk1PE}jSdsdYaDre7t~dS*?sac3aT=A@$*VrUWLVG~Fw z>GTR8>SAkbRN>3{F&Q&V!deUvu`5?cQ6pe>`8(e@KcaYZta!tyL({r1PtE6MYDq*f zmI!FKu1~_dDI~E1zL;KUW61{`y#XYe`nozV?RWOcC+%He$@HF?n8{=^6GgI8pYFxhfr-XqM&617 zScIWmo%?Js@(J<~Im%@-F3XjTW4RxEyh;TDxT`fo>&`dvOzGjs;K}t)w5ioIBmn7t zUQ`y`up6*YcQv>)1|su%W@-`BJUt|Ns65v>%>1Fe%*!cTbSLCi+fbp3mPzGGQtR8` zTa>1)^hGQ)=i;7NvmxS`+HtW0$E%Rly=}j2QT!>=GjsU&Ez_0<^Wk}3Gaz6{0O=rd zM|@rSq>Iz?u;${CSS08{ECCwnX#Cf1c*UE+a&#V%;+64-Q-S54Jg@GH8iK+WC!XYQ zd;1fL^}P&oXCX-9t?SHV}0mtF&_HJC{1@jrH5=m(32WASEkMJN$3` zFrsX{Q303GnoXlIY6VRm+uwWk2OT^R$Bo=jQOWR%2Sw-Lb-G(s=*aWS`-Z&8~*^0S#*aHEMdTPVl8WX9Fw)}w`^ECCrHXG#z@gD zi>V%fBm=UM$litg9x<+2Z)_=Ky|bPE*H`}l9n%I_3e<+^?pU5S=a0+s#}QO$*dy+& zZ(;fW0Jc7k{k3>_=Q>C4@zSCI3E@i)2{&Jte0=Ecj42mNfkR?fQ0Jcg@zU^QrH@9R z9jA=KOk(opO^&Tq{I~SrW2%16=Ig#W>aeF%org~8>Z}zBP|OG6$1~|&BRAH%hF_*+ z5uRDwM$2?Nx6llC4y&8#-?JY9$I|+KVPfiXsa;FE@wxT}&m#84`BGYfUsL}8g7Uti zyJK#<)w)kf>C*MBXc7X)E{w$kxFiY#x#t`TT-Q+X2U2L-Y29X<(gSQQi6ecsvM}$c zc&|0$KM&b?i*^L?>o{hj{Iy7|tItJJcOm&@h-O0p5^KKt1J z0E2Xc8I&`u4a!(KR@O7q0DkyD>(7OWucCGg8abA_YKb7$IUpLo! zYIO&PDkY97ixM965G?M(!S(=R+tik5GnqC=XrDPhl^TupZYh8KP%pjyn67xI!>iSD z*`~^rhd3bp-^kN(vonHp9(7p8WhL$|4L7ro2nz$55$FueXcE*fj`v)DTo;$=?;9Rf`BkuF{trhdqYsjT+kSIzNQ zeEfvEI|~v@*<9(}FEKpn4ofREvsEl<8%WFmB+&R4ZnpQqnI4~*&t?)FtS=;z`lF6M z7@7mW(|g3}*nMjazmJs&MM zQP1XJDKLot01y=xH$Q*^ci-EchBCh+mC=@7Tq4?r>!PLAd@(nNA1M^s*e0Jnmu4v$ zDq@$8RD&SnmimRCZgYH0;fH+T8s&Yd@<+>N|ah zXR~b&iz1Uls%A>YrbP(q<9|@#*%ZKocfV{rldDOR>pdeonaiR=HRRYR^3j${phBAG zPz3HSuY6Kw>MhhHGxbw3VfJSF=^54Y@{(MLD@3d{QLsm=aBLDP zhWN8XD0EQ{U`+};F0!EZsw1}|_p|L-L@@ddkMSWDd+*q+2xiP>B!4kiHxeVMZ~>44 zciZF&997^cB5d4FT2z8){cETd)pT!FZM{(1kG3t7^qE)8%w-U;TfJvFFlwUMlG6nmP8bY8134xw*LU0^@4NWAj*lSDG-k?q2$vRpd60%ig#Vk z=Chf-aspyyx-H6%4gUaPSBs0}_G4Hll1C$W;l204po~Qo+;IdV#D+1w&;L#uuJ@)tKd`U{#&u?Ov$)b$QW#bLz4Iw}w zgKuCGc>e&5Ht_!dg!8YIc_&R2LxgqgMeTg{IGe*GGyBJznafM1%V`FbsI7$y`;1zn zS*3x|q!AWdLlOQZR}@ViHa+{{bI8_^6PsEs-U!P@5s4X^Nj)TX5$QMI2`2wcHDpt*X{Jfp%*4;!;hOP z{{XZf6P}*sVazOXIP|Kvp+$RcM%T6xbS}G?>bY|5Y++$RyASr~j8;1DU5BXTPF6|d zFB>xosvw@c*6Lce@40UwklAu8zlYqvFDh6 zzJ6kHXutu+#B)IJN0Ic!D5$*wbm*$LP0W|`9tL>8Kg2Ykj@9?DPA7rJUUXS9%^+4% zp?}pv%@eTs!#<_dW0ECYxFwNm@Du3wQ|xRUNtWqPn9E0=eIrGyDYE36`ce4$)(Y>k z`D)pp-{E%4wpK<{t4n_n+X~<7gq=~O2@7S{TI&s<``rpVZNDcBm0w%tWEw(V}N#fGlP12CGMxHBvK&trLj8c4El${hgM6%{$%P**gWiAxo+PS~?#$?F# z2b@P9Qf6SoXvVE1k+*J7f1Gqajo}#Jd9!(^SkgK5uM6k{aeb%{`ri-pLnW5UCTk|f zAtU)HQoUC~*SE3Udwb!YzUm=7yQETjUT?%rmY4qkDUuK}r|$V>(j!}~G{>Fxzt0Og zwp;gXyfeIrw+M$Y3p0AJVjA}V`|*C*>UmCp)3LFxIF!@!b?F0R@!#o$ULf#lbr@uh zDA^WuxY0(C2qcH0y%G1J#sOuIErPN}&PZb`=0?dY5c+LK>Ny10*Nk+Z{I*xB_)9OB z$>ky$zM5=@vahph1Z}+%K28njAG7Egl{1K;(1vw>2?D?;+>BpxJ_G2zGc4(saNoQ~ zseQ>78`FO{4Bk{N6+E!$2uB3QbQAEqmnQb(v>IDNIQb05$}o=*_r3e$jXXZLPdt# z-=D7-(-msRrF%EcE!1)iZJ-7vby9)`$F&WGd*b!bQ0FI#I8K$&s;tjIDcpR4e?89_ zq30hjnUymUjXliachGX` z!55)^(Q=8J%Vjz~VobJdfizhbS(U&y_;+qL+*q;C7>A>HG^EL{WL=-l&g@M-bO9_@3{kN^z-e$1MrW9I_~8*7#pM9jJwB5yNDeSjZ}W8ZQ0q4w4mmKU;yoPlxJ(g8lMHWoJ>v8<~zDUGyI zYi9~P!q@5^!pR%=urcI^N~;l}XaGZPtP7*s&$+(XjI>P*#hq77OhD8|l6x8;SIOS* zjAZS z^XzM%d*kVWqU_RX9isD9q*V*GokO^yH~yPrD=h6YxOoMdZ5O?RsGrN;v5<<2G!YxK z2EOM101}SdUGdoB30^T7MQ`EAM!Gwd?0yAU@A!LSQBP*=B07MDg2ZWkN@($1d>yyr z?qpI3G3C&xC_rXy$EJnvu@|@L#s+y~y*Yr-OjOew0FKlu`)+aQ=}N}317P}CQkDbo z?fngH^~7k1X9UwMrWSpBX#~fp5JBt#z4`j$KvYc-wqk19{{RJ9BXPgB6^Yt62(p&- zXpC$CH^*|<$2gbG0J?{TPYl*eQ5AN60K(-G(Aq4^8x0Uzy8*?DVa@P4@4cGCEUsZ1 zT}Cz5r$AO}2*h%=#R~fqirQxL5<5om+b|mgZT2Fp-q)*z64(9~gU;nHErt7?9=eBf&h2y1Ezd?}}DiGS4!z zE`nO^PdiXhZ?GNv3_8f>G%H3x1(@kNY^WT4c)yDy88Twgc3We8auDvy5xmJATk!3; zU+?`e-={ocNTNw9FjY%xu%wg24eHMqij)(ejOxr=YN8~5HXNO|yV|d9{qW-}HXX; znW8kZ#4L73n&yho+m3&}7(mmQM1`id3;`?(Fs(e+8ZI z{m0we1!csBPeQDA-l+*1g5KbNDI5HqupA2*4-|2-#uZtLxC|J9X6)`Pnj0GLh8kW( zWs)ySQC1cd9bA%k90n)85n&*xJl2$>M$XQli+@v~-odeEmx{lfOA$>gFww3j1nDXW zQ@y?K_xTmhGnYpSt^3S{U4Gaklh1+uIu=$U{ilLqr&}Y<(koH)5y{bG_lP zWrYl+t^=J>rh)8L)Yjsv!LQd69H|P%IM4BRph&U67C$;8-nYh8Q54GvMolaMEqXTG z-zJCOd`S!wO1?wFT&gq1ipN<5?dsg`dtSo3V|E~9=mt!yW#&4{4XhdfDupEMd9Y9A zwcs4WdB|2NBvO=B9xi_&3JqY;S}_NlngI>i>kOAjO-};`^Fta(3W&P#aCPh^?A4`$y z77FuxbMK1``B{XFf@VI4)KNyVv`KA_=e7aPpc>^!!ajvsF1k+Vf_q)_?O4#D1DzH5 zx_ijU8#+dsnF#@QYXxs_lgRInf8&d)mPpK!xjKa!1G)A9fDh7%!v@ICWFk`+mmmsM zkOGM~3cx&UV#!5+{{RmHWtHbZkT2URf0lL>0ebY$?d?Z``_0Oe1j{Lk;^dx)xq=-Hal~^=Xw@#pny4d zctZtNGJ1&|ZB%zRN9}~q8=%%wp`Pio$g-7*gR+MVcM1mlj!oXcT@mwy`K+9=9V)T1 zG=!+D1XlZ9u(7}27tGFAEgFZak&%nK0vH3&)QaVQEF{jr(QAN*a2cGGrU(zm2FSYq z0Gwi+X^xIoRkK|!OuxH`BSc}RSOu9+I~F3ns2Z$$_g^9mm-q>8`+X^gdfV%PUojt?hDlReI*8eJx*h%Yuh#{G9C4IZaa%JrmeOzH#{S29 zzl;N%k))3@Om^fbw;O}7tM9g-$l;jc+Xiz+r#$&HC>eB)tZI_fh173;_rLvPG4-fi zB1~kGWFcA9YGN$WqITF3e?J%tIp!gw9C9iA0I1(`YP*q3w!@0NCd_6MJ1$I~UC=wX z(TB|)xZAcj;=vhg%_*|gn9nl;hET+@-CJtxO7VTF{{T#6^#zk$CQx(|6onPA1nete z^xG9!`iLtNOCr=Qq^_+uRYUrY`(kM`-e#bq)KmZf*lni0$)XKkzBMc~g>ozrW|J^t zgi5U>gxa0MC|lD&@9YWx0E`>vX(-Z1am-hdLr@2n;?3{y4%n|{bMg70F?h-ir~`YO zus$$mYdsirkr{QZ0;#<*{zI@F9>W*Hv;%fJ6X}iOSPK}Hi69f8mEzCS-vT_oK}g*i zPykmE8v%g5iTSQJt^KeLU#UCoB*xUL5hP@kvsdsg!9VqnW^*wW^hp{p0B&z)V|_&^ThaukZ=>GOstwo@USCO~w|#bn9RU>dB@u+Rys~73nYelJgjmBYFWi7NiXx#yB+_0t~>p&eg^oiFH>TsI971YraROME!cI~w;O$R4mQPetM#)ao?x2ECN>O4sJ5-BQSaZHz@0}t1k91j(K-GYAdM;7hW^*T zdN@TkW)Q#-7C6h0*Sik%e_y}b42O)K$3!PO;h0EeS7WFGNw5cfxa>P|g?a4EF|U@y z>yq^mUcme8HmmKwd#(BA#H z#{7Oe_!y!z&S#c%WrQm*HdufI*sX!(co+4oB+M&%;*vKk6Le=J05|8@Z@wd+tU&5v zN6;(;(%z%U+vk(M!o~y4bvU(^mPRP;qK3^wzZ>u|su&-#4MmXWlP-)|hw#{vfgIWj zvBw*2@xK_a=A`@uKz0;BZ&k5d*pBu*Es11bKH<1T2lESe7&aJM*!jd+p8y zSlkk$SyBS6jm2MYZTI@&rJy+-l2a`zhX%MLZ&VMr9Ail0F1IMXM^Yma!I*8&8~pdg znW+~`7~4T_W3_%)x4svg!w=!2voIr2(`Qh==YQ$B;}9T}m0@=+CXz){0>Nni09x!X z15G@BQx|2Vr9waj!R~k1ivIwEh$I2av5*MkIvtn4zTM8_w`^=(V+rNzmqj+34bL3> z?|rcgHd!8nN2CV+ExiWcVPDs=-v{Ngo?`y<5i09zOxv&on+M--wgg=UUr|PAzo6c9;c><1XMMrl0FJIIns(IHJCXxjJN;FG_7&LlZp zyg6|;U~ap*u-^OnerS95#M0+s>CfclCS2BJnrz7w6!r`6wF~-TR&z8bK1;ZHEI6&G z&?N8Aw)lk`<}=4LI}E&O8o3G@&1u_eI~x6PRz?2+cSxrmS(Sm20|KiZumRk5;)Qp* zz_~1ZvYwrj~`Kc#nT)OMl z4T`oh5(3yD-@Sct^tXq#77UJvm907L5;S6-Z=e4G(AX7lI&0FpEu4g9rx20rhfp9AN8$unBa9E6%`*umM@LqBl3vcE zpMZm42OE51@8I9rH(BewEj&ln%$W|1%F`E&k3MM2Qj`=*kHkwJzyLWSK{Ki$fLn<_K z%7MUN!|EpMo$HbDfbtW`na_1N@^h4q2RUyru&EzFwHMr7Z|rf5zID%uGdVcspC>j_ z80Qi)sF9h80hgOvZfI}$VHbeoY@dm`_epss%*hO%YLy#UYA4$F`-{LR{Vl&`f7GP3 z%GPVgJ}b*+B+6#GgCoN3k|o&G4I22oUHljOUp+BQZk}Ag6Rf_V2K)=HxWzBT9uVph zc$+^Qd2pF?Ib|ZfL5(xidDqJ29s-|dRGPVlsS zHs)wUDmc_N6&43$+Wv6os%Mv{czw$%i6vXmyM+W@)o((#_{Iq+T2MwgDB4g$oStTG zv(~(vlB;E*zcJWYBYlYOJ^ui|ZiAA`X3m5BQVyRk)rc0{eN7Wz80H_d$vVb&F!}ks z#L33`;zGZPH~d^!-?`?GY+f^dBa185p~!Ui2{mf;R>Nbq{{WxCyiBot_^)DQi{-@@ zzY_Gt>m3U*0cB~Fd5DZG87_(SSgQE#Sosgd9WeB+wV2Bi%Mojg0BkA$00ut1pQ&eZ zGiBnPDE8>U2KTLCv75I-e;~uaxx&Hu6MeRLbg)j7> zfb*Ses&zOcgE5_&Sfg4<*wCTgiTA+J!4ra4Q*Lj5JNx5qJWeusChkxE4cM?gT&1?o z-Qm8y`#JDmPl38FSNHy{Ia3>e8s7HYZb&42d}F5Mx{iN0(qqnb0~)ldr4+7^0Tr;m z2H=7_eB+OP%RCD5%sflhe}e=SwmYZhy+!!(&jCo1BseR(3y-ur`$ z8F;BWclR*)5sYU^-^)3VRL*9)zl!qm!Y(YFfg@r{nj{Nj^)x-N7HskfdW2~ZWRR9L z&NL%|vl<)kL=SHGvUG0)qDc_)(kRhPfO<{IMu(@q`(sJ65v}qmd7b5BZ0FcgS`jbLT zYy%x5duH2mco;R{hb)j7I&@hhnGweU@{ERCC584@1GmQbbCcm9K#08Pi%yG zkr;O4ayYMSN7b`X4CGFH!yG_1@=~!PhSy=Y`{Ls&*@kbFxW(W3{Scd{bok@zzr6J+ z+DLMtLx2Hm`mI}4L!?$35*flnEW8lfna_X1w`innwZk+DX$qa?V zD>RNsV0NzC{dwCH$(GIMbmk>?aul&Hv{t)N?Nzbgd@#%O*Ud7z#6q!VO@GZ_ZI8Y$ zog2e{{tEIWF@^k8t8Me#p5yE{=M$3co8y8Jc9F#M`4z~_(IYmVSfda*-;=ig0G2Gi z9fvUtsh7y+vhqhi<4I8IW&*(**xJV4`_>rvzoMAtB_2O5Uqb>pB#s6Ad|_uq$>zsa zg&`3YfELu}&=To^JdK#`heB2_$%=TLhs)8-$}zyX1x=gJ$-` zL31(X<&(_IMV20~G`jx)3H2(oC;v7T?rMA687Xm6ua2v4;{y z!p@>LazG-vw)Z0tjP^%2A&C&dEPI$)Kq$xYZh7s=`(Pu~Ge%jm5=)wje7FAq5hY6@ zHgunQBnsZgJOhZtxeWGA^BIvdPJvohb4CexBitb)efF*KP7#r!IdbCfXlXu8S=s^% ztcqhQpqmG44YzM^o%qB#&Yu%W3XrU!){1H+&Flv|>~N<`JpX9o?M@a9=wmcX*TAVZY$SSe#8mPUFT zliZHg&$z&uyoOy&l0pD74OPbH`F+K0_aA&e%n`Zr)=eVOb(TKWXJcQU7iOJWLK@Xe zu=JW#<6}mzj^Eb{~HW0L~6FB??{;3e77ZS#++Nt^1#G z`r;Q@AOT=CWDRY&W3e3n0Qud$v1G_}Jk0qCdfbEzoGetk5DT|q*z$S8Jnmjh%CV7y zI;lG^;Xlexu;5|%=B&q+JksGGZpJ+`D%lQ=CT2qC&D6lDAN+N>BWnbIW4`!No9fS+ zlPi<~rDT6n=mS-If!ls?lJ^5imkESocVQ7CPQqASvU_~*E+3(+%KT&{9glPP5J zLfY)zeMuio8h32V!;UvOEtZUyV>;1Bi2;QHE3Zu(q1=33AM1m%k>(?rtP!tkHcfG4 zZP=0z&N5_t!l*^^lEAhNOSRSa=jpa4$gAe_ab=~O&yk#|HA43Udz<+fQ>2VdmhTF( z<(e>KPd(Ucq6K>n)xP-a{uyZ}mNkWxmO{)!{E!D6U*~w_T{Th$SYaW`DXlw=M(o$n zUOLZ#;xlESi5-{)R$${`G=h8YWP@Adm*l^5K24(i7Dh+PDS#4)?gfLTZ)UG?Y(DAiyG|6jzUXe_sH5#$F8n63e=8Kle0Jjj z>+Avl0F->LaVB(-E!ONu2a4bWSMh>6n&x`s-t(%i0p3ul6UoU_G55PRpqyAnJp7aXt(9Nak{R1v^W(>21 z)UM})*mwKRUM#*`WL2RFAgw07Bztkc>49|0l2!Ku$#nymmGaLJ8ss-)QUj=(+mT}X zcKTtKS12+ti44}IeBG(G?WFeG`e9rd6w37@pUSR;XF6lt4aw)?&)TrXW~Ws$h|G^; zO^_P+)4>OS_P|T*4C%cE%a~^tH8fHoU5K)D?nNJS`tgmjAhfz!{MgmCASw=$4ejmU zZrB$sq{`C-ZBj{U00&mbV_Wy+>u;!+nYOaii{MBj1x7_c&n*FnR)WE6B0L@77y9R zPAvXwHypsmxn(|*#OovwYq1wy`{CZ46mExcidRK`bV!QS zx*(NXvM+sr#es5NPpHS$I*i$qlFOv(^E8U=9%dm@09%&;vz@>JNjH{bsf=?o=oOC>gUdzYQ7a=c9k@C!cc#<}Y%q;s7>^rrO#CRV9u_dm{aem`&lab4K zZ^IJ!tPIv$Kb{ZM`ZOX%3lt86%*~Rdom2==PYh1vj5g^Rvl(%4OH6c%DeQ zddTYT(RA|K-LB3|~6u zhI$W%`aGG>8RxQ*pbedm*Yd=r6Ie#no?Vk*hX57d z+i&Z9V~IvGO$CS3ts(*jwmh3K z_w9kQ0=hkOpGKmaiQUJuC?+OaH#7MKN!HD+sF z$YQtk{{SoB1G3J+r8Fa=6pe_XxWCK#;w_L8LdRE@h{yv;Zo^+AU`Vdxj@x1~fW;CC ziDI>xew{MCD##82i&Zp-+X`GDC_M)&!Tp{x){ z%CT7dwqmrjpw-ZzM}9HnWmS{H~sr!_>gEOD)F<;8D{a??qV2!x5?r(v(yil8iE}s?L;4P``0wpU4BY9(1y?vaG0&AOUnc zP+K0Zb|dGFhrQz-NTgY9%1tXWq!JqK?<> z0oYaVe>iEAVBfe8m`|vclPf`7;=?c9^@lQ5GGv%Fl`JO{YnPINgN$E2hYL7 zjILedSJby6y}y_bpn=6|syue=aETZ^VLu3I6d(*pR2z#sQR2s9J}}Z3%VniWv|P^h z<|}GrV{%1-y58UMjE_tuvA$VLkKO#$EX+3Zk8b1Kk!1W0_c$a+4Z11_=96x0D{eVz zuTI~8wgJiK0wNHliDD2nfw{J#Ioh}O2b?;9?IO(0QbrloK%qp?Ab>VI`+Q;0rVuV) zF3TY%L#Rd@%TgEsMeGOAo9=!wDoE=hvof%B05yUgxztFbzV-4iwk3`@Bhl*6D#^Q3 zM}SXrS6IZEAnP5%9S|KVWDINM@wVRIV~yCN*FvX9gw5rC?h)QYs4!UQ*D7}09e~s? zgNUaE*^G#EzRPKB1qu|qa((e3j!~IV=)~Dl!2E4@=_hLE6Ett-lBq2^l`JS4U4XH$ zJ^udq>0&a=LeSF`0V8oFg7o=Rt*5Z9h4OoL_`>P(?t!xYRD{`WDg%LJ5Y#>aKGlZP z%896&X!U3%tbp20Rd2{VcJF~Fg=@+s%#Ni}H)>ESfE-rWzS!Le*oO8dY@5o%DpN43 zH>Cq`4)zB;9leOVtWFWAYt~AJS1f>9*yMrVZO=a2;E7Xa<3cE1L4jfdoywENf_Cl4 z$g>AkDp^mMK(j)~8&UrNR@Qdg2Jw~5)Cs)uLd35k>P3x+ApxW6J+`g~;u~{~TnN+& zVk;3Eq+KBZ8(zTQ0{(V5^+li)5O|!OBX#v`Nw7FI&2m2Y@ytsk0&iI^N~yH~iW^bh zw%C)~8Rw5d#$b7f!=XiULfpTY$CF?Ix2J3T>j}DoyD#qNEY%tkRX_}~SRr=oF22VN zUS;(LC{+5SG8Q4X+%uX9{sK4w&FRhH2X`kP1=ZH@c`RyL#Yj5Eiv%3`d`gBF%> zC2MuH*#R4p-S#KqhjUnmHnGaUkf>QpQ>ZGVkg95p0rnV@P}BLW7Bp5Gm1AK`@GtRj zc<)#mNo|-6xNA{nM=C;-R!;rvfsAv8%`ujRdEY)5S}~?_9JLSTV_@IK*!Ulw0M1Vw zQb`~*(pf83Sb@EsJAe-t`C){luwspIr}C*hQTo={LDU{NA(dlvk}*of`w@HB1D}t+ z9g7{Z+<~(lK^rpfC-GPdQL9NUru5LO9ryUcywuPsT~6fcV#9*W$|zSh4U=Bm;BKRs z42)-B6G*T%0LPz$TYsC3C(ZRqG$2;X73B8R}lOVo1_g37^8nk`4t--urORhz$Ygvpw812BN5>|HdF)yCs%q1b%m zNb?S{y20yMwniqw-pJa4*q%PzV`9glMXN2HE(EJehCo4$y&m=~S-)Xp-wsnV13ZhE z^IA~lZCGz(ZTnU8_pDShWW1t4qf(Y8Fx0vTHA1 zT-_gRE>QR=cC3Rlp(SR}x<-Y*=V85Vw)NOxxFw#|l13)>LZFRY0&DP{$?v`vMVOEn z)JVfx>SH8dfkCl;*IxesTr|r|u1FO_2?%1V7QpE@qyfMdK6b@%Du>w!5+fV=6sW*z zbEb&{n!DuDvCjB&k%!63NCK_GG_VRzgTUB|1Ab5Rz#SeZk~s>*N*47ZlTAahZNKB5 z*mz=!IEqMP^|CNdH3B*N`+;ENRvb>O84I&9Lp!Xlvjh%FAb;{6+kG!?^l-B^D+Ti2 zZ6-K?CMEzqka;}tJ^8~qjrYPl{NgtrTZV_!V_ijT{I4GT zakegTt&t1!4GgfBR#7cBng>&kERGiFVy)CAd7@PSNVFV=JJ8*UEwy(WcCPq+)Fx>n zxSYz&;xr7`wcj8GQCP0^H9;%g!Ag=zn13Vx0Eq|z;$1FmgIkTr)%sy#Au(0_SAR$uzV0yVrfQNqd_YhW(2jK2p>KDzA-LM$W z)g%UU9Bt;4YN1=y1qHG=18x3?-x6fHZ<{D-BtfVZX;p@i{-RGkxgyWD4}fYGG8yR# zqe8O!SxYj$v2;eCsjfimFtb0@YCqxmMZB@80nO$@kjHqiho$~B8ZGxWn)UKT7xdzSAG4r2CEt|c=xf9f$q1~LWW>igIb6yeAxN3 zidRtaRLd-oLKsM|rkiEbdx3YcvGa}JE1T+JOY3OOyK8C#Z6K8b$JgNdVm0Vy2rfuG z!oXILZNTriG&t|S-))gt;5{USk1V;BDA|uP*te>}8>`#zjape`j7VkHs9KOE0G0(_ z)+~$qV#y~$RZ~2b7)Akt?WcXmzcu<{ZgV0;;)&LvpW&@m*RkMoen;hoEV1?q#V?d? z*2ooLFs=LVTwmre6sXDq!xhFuGun`gMys0M_~3JcWy!JzWd%b4xKKxS8-u?hju&QK z2-c*sunw#VG1CE|Vg_v4Pc^LfVTx6MGNJzb}kQloUA}f?`{|_6WcW#B_1A#lXn z`de@Tujb>QwlLC67&FUjs(`LOYwO?r@vI;*MMf^nNWFW5&cq(vU%nw!PdvI^;}U5K z)D?ggzhF7sVtlVo>KV0dF_8oU-bdVbJ0F`hUH+IZ6P7~m(WH};V3*Pj6ZhZ0z6H*8 ztkmog%Lvr|1@wWjzwN)qAqG>YO3LMDWM)AbI*SefumybB-toR#6^=8V%)KHKsJjm^`|rs3#gdGm@>nO5 zQN(4vM4R98v%lLKWuR%vGWsIX>e!Mf?mqW^zyPZ-}b zm~71=2Zt`IHU)}MAB0_9k$(4zA*)K+fO6Sr+Bi0nQq9TSf@_-g{V+~mB#~F9#O{!S zWXwnh@{h!B_PWvq)&@e+x0JewB(no!Q+t!|hG#2TMavjTGRhWEfUC~>y)ll%etv}F z`XL;WzG43WdoiR@%NPJJIcQg4Yw55D;=S>_xq*?%tf;0SiNA*st@V&7?OR>p ze}(#YQ;ViQRO=JPE_bO&*}TG_Kf}~Ul(2gWpf(nM{O`fu7|eLLt|n1(xv4U#a^~iR z82W1cZNlmztoJ9|9VhmU)mNZ&9I44nV;PLZaRJFl#TE)hS=)2I$M209F-H|)hUEKY zN(v2Qk8iUBE1SuF(DJ#l7FH~_f2KT0P|+qb9^2pX56b&iCh+G=8K2u$Ya)hR(q{T( za>^rJJB>TJ7r%Stf(F>J!O)jA;*SsJfAQH!SNFM~8HpGcgh>k(1P$z+BjADC7v7iP z$LQWS%Jp85k;vm9kjjfl@+sA7+kA!<*khlU%8V6zxYzuPi@p7V{{Z$EOFk^j9-$K~ zo?Ij(iNnwq2FHQ#TOWKP@uq90^f4lz!$;BSwed|%@Udgq8@>C?Q=6yzvC;fvAZ;{CSU2=Q^tEUmpDV4i7FWXa|; zJ|xVOmdTi*)L4Q*3_$}?zQVR2*9m`WeNIl73CU(8Mj=s3iZ%$oM#GKq*L)Gtvi&ci zMVrh)rdbA{ti`M@^`^Gt?s4;f?SH8rq1RaqnuK>?00^V7_}GkY@fyvWis=W2r^~YA$*_pH#RzSsu=h6qye%R+< zu-=p5*3Q3E>W5T`BI#x2YP~#cPT!t8_fDE_shn)A5hQUzYCT@2U0)mmMRvgXnG_`P z<5lv>3quZZcgIg~~}YQDR8c)EM*c#yYp`tM+x4>l43K&&v>lECz*c9FN7Txv!3W z@l)yjHWXEqgQ3U(B5h<}9M%5-OkBD?XE~7xl*>x!S!je77f=_t1p9sO8vLA-lz7F_ z+IVFsH3v`R=$%)qWi+oy=&})&%k0gdzNN2Fp;QmI>xaD@=X#34mjuTQM?|5{okF%d z@Ob|KH^pd<=e?UJNE;LL#@^V6sr2mERPy7? zCCbjB8Fr`lBz#`xyWx?^wLp0O72=*r`*c*Zok99`V2-Tj)HXG@ z(y%vL>WkAe=6G5;@^I!0F;Zy*5Or9uNgFX9{`i;0eKtsXz(~Y}8c4}BDT?o?f;Zd& zeXkzOMU>A*24Tv#m81d&;=@@WZQl-)S|^L+PbzYc{xP;wA=J9oYe!B3XKQUP^`TDs zRGotF#{71}$U0tE!#QZA)YDI>tjfDEBDPxGS@$RXpy|FTgCWuvC6>xSC4sIZV-)^-3{|fqgRr{e)5hHM+iY2L88ypg0FEsnFe|K^ zke#&yy>M!%d*QxLA1ZLP&ukS;ZENc1YBYXN+--q6%*1G?DkR*yeS37pC0rk)&xgl1vtP`tTNB=VVM z+01+pO&(9N8{xKKgs7o)Ib)A8m+A#Hm!cc+kn3L?5qq{F%;wHlsU~a%XM1@SR8y;d zAWM6YPyOMyRp~NIra=lKCi>sf%zFS2>M)-@l9lr)&!{Qt zZ?$2cP4K>Lx<~#?JDW_TP|!~>6Rytx08h3c=~;ZnZ>uev+fd-`vwzMvoCKnLr%2n>#YW<FwwH6B=a51lBzY84WJ(Ta(i>z0zO=|g6dg848Z;( z00bSoZQlf)1HmqYaO8Z)DU^sdk?J3c>icp30Ox!RJ?UN8I)?*~%K>*VoRY2f~zUCw568#5aU&Q7D=$=iLw9nXAGx&r1pj(RAg zc>o9)kTnY6osU0noOP~;lZ!-4muB*!)1(#x+NkZpCcxW+?}g`l6&%d5Q2I%;hFqp{ zHxLEFZLGWmGc35X;-VT%nqg#pRqe}Rr?l;5YW$%hNbk>6&`Lj5tN8I@pT z-%$V-(l#LRbT{VjoN({jk6)85mYODF1PrPVr~$sfd=2{x{c__{Ue@ht5fv}>T% zD{MEe+;;XD;h(f06hWPx^2PP}n^_wT&Hn&X{%wr@1SOf_JCa+J;_rAI<0&TJU+VN8rk(q+@JRlfE{FEM5ES$JC|(<8W`Q>Kklf!rQz zefu0yJU^G}xt9?~Gl-#5RW%W2#^d|q`+93YzNmm25&zgmm?Z1k*U_e{{SfWCu7fUP8jqlOp+`vpc>qt zsN zyZ5c@Y-M9AbeR+|Vd-;Vn%{m0f6owfmCjC&)H48;ov0E)Q)6;RAalQLGMU55VOZGe z3`V8Y2K!xez}x+?a?=?l#nFtbPMgHe!~(?G-v0myBKF($!3r}j9w9ZnG{g8{I41bB zwci-urbf~zjZ(}^SwLg4J;6M0zW&1&oS%m>;f(o=(gu!&k_xZA*t@;2f3^X%g*K5+ z=+e#AC3i>w@{WomkSGvtx&Hv1Y`HGI)PNpGlNu4LS*`ul9(elV&n|DGcz-nU$XEDp_gRSz4Kd-?d^k%T%DkzoVr6S=SpeeNHclq zWePzF5`k8th3-!V$J5&bl9hIO-XgXiUtgRW~jNT4Y0FWcg=w@AwMEUsF9z1OCl z^Gt*yGTxnz{Co@tm(2AJt|7_v?vWvuS(Vz-fz!C5#a8rjX?rGG`1U93&6kru9!^?5 zbY5Zx05npoZgo{~PQZOI2Tkf3u92CQBazcHEPigVDM%dif0Yba{6W*ReMVBP()_9N zg{4;oV^&I{2fus5M98<3Bx{!@Y^>mi+d)-5@hsPqw<Uk-1OVRV8OoADj|gow80%X_P*r(t59h{2A6d$A&saQhukA%Xz{az*X|2 z41C8V(DWcJMA0I**dLekePhNSwS4bV>YZ<^$uxZ{B;7+dB$1N_O#np+9AcI?kkAS% zf=>kFxBmd@E5|)g#Jx`^`!euMQo6H=v)O?$jbxUXgpr2ABvuAX<;Y$|8h&fUo*n(4 z_;L>e^dmNQ6?wB6zcq_CVrSXplSlv$!l8R8_p^!r0L^RM80lLW#~>`O#zxXW)CS{f z1W*=e^X>161aC5=n(1p$QU=DZz~kF>{j7ESxu8%rV^p`>2X22|@XjVwO<~fA3;?joN4Ea}C-V5hq{=l!SYrL$F<=xvo(&Ub z?{Y=$c)(>yj--D>60D=~HpgIjHhA|NZG#+CqzL4c%o|0GL7%uSSAEI(#6=}4;Uu_J9mw{ea2QzY%2f)g00;?UoB{{j_QPqy zD}cdRy@UqnlYWwT0{;N0ua&Yw1Iwwy0YSA3qgF5J@H^trb^$sWb0SYLN+_u;p@;yB zp~)QY^MEq}jYp*Skpm}6*ROB@86!s zVo1Bh*{S1+24ax06oegt410V30G;p#VoyI@CPYKH4(x25j@7XL0E{_Ax(RYiERI%L zEFl`tAeOR09mO5~JK*>;c@R|&V|`0*Bsu}B`Vs-F?nuIQ%n0I=P~L*XGc(@e#|MK~ z`EP=*BU;i3@g*M1GeJ8 zC-px#d6LX#7G_}!Ty~laK!QlV2Lp@xaf-H5L8v^jp+*`?l{QDPqgTD*-cnSSLFy@^ zL2#q_NaT^dez%ThRYBF3th=KtNAIYQKm)n3Kr}9gelXW3EKx|n<`^ha&Pv+>@W9pY z{$4BjNo7^Ikr~dCp1)WYDZN_}!TMGnW#?h9F7u#}4NQ)GE`AT>euuX>!;+{9c09|o zOHwr`YV?z9M2ex!4XTGH>xOwbWI$jPs*Cvdzk3AtvUk1goGHqMDy<`El?H}s2|7iS zv2Ff6{jUec@kU%swqa+&}L)V`WGxi@vW+u--Ye46>1QGwk?(rixqYOz({w#S|D?;)TCSewi96tGnQ zwb-BmqHJp4*!?hg*=#-^E!f6Uyuqj~NIo?UzL+)y@}UfLd7475rYg=zum%1r0{++s zDEi_uBq#s@iJ){*_P>rkPX`A_EM<(A-e#%+oQ6A9-xutARytTDBO)VcS|*W@Xtwgy zmGvrP~f8SYz|2Wok8~{ldrHyQ$0!0n%iaZg|bAg^j zkouEZ3}xMQf`E!QV}r2mc4c7JQtPH&N$Oq# zz!FkAGciO208elJv<+={)voZw{=lcQ|r zc1cjGEFr@BN+=pl><{Pw+n<~&%;zHv1Yn_AK}CH`#D6gaYzKeuh_jiHf=J7w(g8q? z6b~EnI2(7rt`z2T=7O%YG6uCO3V?VVcQ!ZMjAWEHIyTAW&c_q6Y{4&Tbdz8T2DNe9 z^1u>i)CYHIm@@3Yh^Qo41A~6%&K736gTfjd${B9$Yt%?PDZi&Zuq2X7!$36h6HLpi z+jC@ZV1fNR;S$1XgJHRjqFI$ny1Z(3lqjGw3nRuwv9Yg1wpI2H@QES5$E%NydeoG1h&FMXW5AE4{u@m;QphT^BfN}22};Lf(RUJN$yAI z#uZ8BOBf=Q`vbSr?~aBz(K`l}%!Nd#bTg8neOi?Bz24{g3^~Yu5)?v^fML!w_#v6CeQR3 zeQ2hOR$T#wN?Ws1tFgKkJ}>>gaK|eYijO0(TU9OU{{T&j2e#GiwQ+@6Dbxtgrt--2 zf;TO&02A1YAC?~Usj{+76RBxHkOQQZvs;2}jkdeO+6Ao)GTkyINAlFPM1@-;&@7$B zRo(7E`(7Dk;3F_q*YK9q>TE3=)APq*Z2Vz|OvP8`Y?3aB@BaXJpQ*cf23S}E zPm~D<(n;BB`8E1{;tZs!BVhec%^@whDhawGxVs~c)$xN}=gmjv21c7mE;R*2H~mNV zz%v%i0l4H(0-URrbQH9a=R8$AOQ?kR1ag%64%9`C{B!j8*q+z|ewy;Ik1C3hx%9D@jjqqYp@u>UeNq^aUFyDOX+L#a zcWJ{js}?jWfCHMmW2g8cbc{=xW=jguAm#m=Zszy8=NC?$(Q^58o_V2A8I?g~HAjQL zu^5LtEKCbXjE3|skU#($93D3R05`=?JAX_DB}ICEg&Yux%0o(Ie@V9_mMvt0M#AWg{tq}!n~hXRQ6mb?agn8kpUmr(@6NF|!|z?$}8X=A}(8;uZh^ zTn8aTEuJdP(fGnC&RC(PRZ7xXMJZO^`~CMg-#gTNv?aly;FZuD);_njp8MfE{ZU+& zIhe|!A;IB+8`bOv{{XK$V{|dl$i|JcF~uBCsSxu9pkGNEXr2$x_u~O(XKz}9tubSy z8VWZYQTeV<7{QhqRUr~6DuA$4YE*qmJ6~$!3p$H3Ubb&E`s|7ox3~50hb2Q2qAb@? zjb>n}so0h@dH3zN2aj`gh5Dv>2rEp*RGRz#UjG0?jhM8uF_5z@6Qfrhi6`59Nyt|S z?5IN$#8nNxH>>C078L>McN!hN3KSA|KA;Zuf;^X4%(@+mdLk^s>>c}kKRjzIGR91k zK@#b;qx`q9`S>5#9?VEXE}Y`IRnVnD?_Gz##vwq6U(i~Jt_dMY_V39Z@Jc*zqPx7H zRUuW|pXK|UYKanC2@b%qc2Vgybwu;?h(=-{!b(shyHme?$M^Zf2$^Rr%^JYPc+eYi z2Rq&Tety`7M_s^CtND=0-uScnVmb4AeKCy*sFP!oeZb$3oJABTH7E@s(oH#FScM## z?|;~PVgr8x*;~!X@@7B~sRfIjw19To>9#h`XLB>y&{jCqAX}iK`}>@0F^V|UP*m8e z3TyXvJ&kt63>Xt5n-o zr>uZG?Lx`+Jn_HA2Z2DDM5x+=mM2gmzJDxDE@D{pM-sNG^l3b|Hph{+z+YjDqQ*IF zzOd#9;#n1zBw=hdwe9}^)GsILLh%&&>0{UBy_na@%L8O08@4=poB~O|!a(ncA2TLL zD27;&yl(6e5JZmShCTGCAAha`1Zpf@T0jAJVX2vkzwly;>>_!5xkg+n%3}USC-IZp z+?|KF<$__2BZZ@43+wYFD#qVer$z6(8UXgDI0q|g!0BM+x!@D?-{4@^&lob~0e(mf zx`@*xqhM5D^55Erxx^s1spbH49;KvWbtyDBCa;me`VX9RKL>y5^TqvtCzt9yayIDM zdC8SBS(s*zJ(+<<^Qsi3jFJ=)WhCi6PpQ0zt96{q{`oX;EwCu6G{zHf3A=Uz z)ME#mm&t=s!nIAgKX2v#0D^NlsN6^SPYm>b2xRiz2g4bB!)0V;XCJ(WcaZAT8)3hv zW$ng3c>SvNyth&DUSQ<(`57350TgM{>P_r+2Iv#X(|Gzru5@U82jKkAQ0Q?y@pPV+ z8YRums#%H~b}pbUqCH!U_s7YStl8}5V>2tPv*x9Fq)?ZsoryF(w>Zc6a_1>!Zp3&{ zbCa3$myJeuq<+o1cZ>RJXOXhs_{`>3R#GJ{+Bao9-O&VA<7&rP{gh|(y+B3PdfENw zHzFg-(i*A(K>z@|dU(e<@DEAxmyNs=(Y!t4tc0T_(@b&8nDYxZW;odSN>mT!1#g?s zINuk)6m^c1`#I=S#~i>qAPDZl{e^u9*l*j6a`R&5y*K%-{{TT#l7xK-?Y30^0B+tg z$VHXTWu8DZ0LVkFxudus?SJes%Krdjz8mTOAnUR9ZlV`6nw^0`{HnZyds*0hvCsT> z;_jj1PNh3E?9ggvP|sv7pQYaXW2OGbd^^=TUx#Gtk~fsH29Z>;1R)wo1Gqny_s1Ox zVEz}y<8;}jV*Vc!`7Zwev_INMMDT)UdNxgiNFmW1BLEoL-uoR&dw2H7%^oT0zxnR3 znCf79WMV@De<$g_82ICHUO3|M&0ydpM-JZn#aks~;?wV~zW>qkhD)Jv%kl9&VwYc+xUeQ0~{UzChU6=e9nq>GJgW#Iba!Rdlwm zG+8xP2iI-;@3uZY{hM?ytJiw$Nz<9*jT{+YP0*wL_v3HNA7XfOB@aYQzC$r)e=KSP zQE~{o_}tz909f9veMNt)vr6 z`~^FKCg5}UdvAXAV*usg5WrqY;dVkotGB0$P&qtr@4q-VE0`HK^J907!vgmvYC({=p(zHo5k@sSE$cH_T2@yzrx;)+q*_c_nR$$~CecQ@N*nfy1B=@ClLmX>*+U>t2+Q1|C+7?-4Z zO+1qvibP{)DD`YeKH%MHzrHJ({{Y%nZ>U7E<#PW3#9%^_gi~@)x4+YF*m2Xkj%dOp z&H81P$VDQ7TKatVJRE4knp;N`JUobh_xJmi9~(gw*@yDd{Eaz@6dFFF4S}}C`S`^i z2`6Us&g>IW3mke+I|}~*Q9FKkvv{X9BKYSyt?F*rl34EalI>wM2g#8E^s`niH_QiQ$sbq7Dl#VGPXoWm_bg~N|{By_qV#Ah-c8B<` z@&q6;)_ZbRxFYNAg|_bRM`OlW-_?<-`x9ky;g~8EUNuTu?S4l9?b`d{wqK`Qm9F24ANUl;!D>jBHi$A83i03v++89}z_#o}M2ro?(f!<~0Q@I0b;BINq>p z1f&bg6nBNrEHwd;$1p>EBOraF9GmN~|+UzOrbYw%d+AoMSR& zicOgP&6E;`7X>XugMc>w08N5ws}OX)t&{6{UZd0@b&sbj`5AR+^)A#)EA6)X3ch`g z1(Q5_EZJ_mm7W*rx%2z3ZB%Jhb|plfqj$X>hV@u_y03GMD{ZcU`gU>R=&Kl#<;Z5F zgq1X;Z>she%~u$!X7x|dA~DRNveUamAoP@VZ${(TUH0F6GU}agJCN!b{{Rj}(sL7* z%sy@wiWVNGQA$Yc2=~ISnbN#l{{V{_IlM8NC|RassNUod2;b@sDxYSYF)kR5Gg(Z*mN@lK6hsGRQ$mLXHQk@S1Cye|IfF9-$TIS>vT7WP+<*EcTD_HJG`5Hz0eQ;bk?2k;2Y_CnpGROy-?jmEU zt7`oFnix+bOAd8B)sZ8d0H!cX$O4l~M{+NN&u@a_c|`C=C0ENhDQu+J1d29E2UqE~ z6OnO3e0&cylJ*d0`ma>ZW)%6;55#4Pt4S<-`|Y^r0Oh2QG@>4$k3EnPb&_MN-`rXL zm5UsG1In6rl3Oy(=E1oNf{7&i8#Fu6`M}cj#gW8^Eg519vnrJVZ<2Z2Z<`0(0_3kp zXUD_C7YQM3eGPK28IDJbOsHC@q=22pdjfmieXwkB25?tJLTKq)RiS2v#<$yZjr5qM zg$X1nvUa+?&5fwg{QdEnT0=%Lak^cI{d={5Z<2QBxEPJMwmul+jeRH$l!F{Oc$J*` z43X}uZIYEk? zALrbGrqpq_*A|SBRDmQ&{RKyvs)64~8vqAC6npQ6 z!PBu>bq33CgnT&1#F=AC7x*_r!e@#M!taha~f`L@ZDRBnIG< zTh&(=RB$e4DSD*LMwimer${VSe6m43f!ndXCCuetD#1Hjc`Cx)?Yddks{V82bHn+5otFLUGep@!)>wNBJ01z2;+b*zuO0AS1bGTFqK+;!AOU(>owogJo$-$+_=Ts6Fdn^bX-U1s*UvOYD!}FLEXX#UGWjfY zigi$LQ6SOy?d`rBv&onnxK+DtU5?$j70uuF#BY!a?g!x@vd|u(y$(S3{XUqHdTE@p zLh76>fQr;l^4Y((DYBb2%yiiEu%A3^9+Ya*Z)?A|8~b3Kr$op`fb7-)6164szIE~(M7Pl1r@dXo4z;W2lV{+hw>4u*>z&7L~P4STzd}HV`GYx zuO$5*8PKrJ=FQ!H741U)yZsI--AAbTol7a<+`P;oid1QbyK=|#qhsIeh_G{2WLUZA z?z!Ht;pOSk$m)@#fFe6CwFA2w7j^IL^NvlP>RBweUd;3daIr|t(Jr6?3@(SrJbd8( zuhb#P&6mjMW(9Ky>K|2`Cf4t5&5gbBRq?+`&$e$X)cSfpV6-T%bRF1#Hs|&B!C=6# zzWWOnK0nN#t>klAS=T+%%goRPFDNFP;j3=^VKm)NeD-NNpYIufkg~fP7On=H+qR$S z_b+;9TYQjQhgzb}p+c4js;VD1Skk-M zqB4J#oe50cHgwHpAdH!y)0xSLiH|c86jyLmk-o>B$F?QuzAfr~AE!w-N9$RvhEFgV z8Je0XC8|wIHv|$$eZ82RF6ljG`i4)Y=LncVnLoQUjMNpB0;Hd3t>`X3VSIPdi2G^42;m*@|WLC!klXTG`)m{cvncDlIhyLSlU&vHV`f{{S)Zg&9_hLdHv|W4I?(f(Y(x zcjFCmzF0+K=_8Hke=pmDK_le+);O|8Ht1oN4ATcWdU6J*)9P)28}Y|KTr`Nw5E8lw^eY)0+%`5O&71h63~-9GshrxLsA_iXnpwO+YPel#)x($m=@Kufxf`={qde?8Z3D^ z*;3@At&5eh={$OS*XS_wrOE=EVv39iPjOoc_aD~rQHoYXWN=7fsg_OJiJ(0ukL&cs zkEh88l3C+&2?6RoEUX6ne2;u$%^g@#E(wJZ>e>d92)@JHVn^5O z$jmV$UtehchEb8$iG_sCH&krD(0OBY*m=V4BfQd=`@K43fxQnd{4E3OB9D zJb%!>Fv<+eEZX4%fbMF@P!8sWR{g7y^ukV`GzZiQGDg9GKDJ^_5zfGFek|ecQN=`3 zGv}(Rg{4x5O_6&F8xDV5V92SFd=0WJ?-6KEmc}Ec$MFUHS*F+y-|dF^dEPYvPgWW zp^&iE_*4{QzU5E8+xrwQfh{#x~+@36N_`Q4|3PE9HSD z&{IScV_|3VtZ6Kz;ZHCogjJ5+bd$K#w{6AM-+RO@D~UX|&1+pGsA6wx1d;~e5_aar zVkstHF_tjopaD?GcI*frP;7EB(Z<^|N|A{f=Cz!cbv6_@E3vBkoCPe=f>^S$sQx0c z(!haqYW|F ztly7HfvW6pUHcJ+asq%evd0i{GYL^mN21BS_pW<`?gkKN{M^*8Ge>elfCFkQF1ETS zkEpHier{x#y6E&453QV*CcQ-ba=g~(3uPe2VP7mJtw-?C|zxQ-@kjn(&rJFy2(+-3DgC#+io_#+jqvZHH|3=M4{x}_Z2ZuAfb&X!BS*s$1&zl$3=|`=i3xg> zNfuv3vB(UOq)b8J9u0Cf1995$u4%O^sn@Q86-4wC@HX7o{=V2Zs)Uupwxd8WRVUJ> zhXnW7^Mx;~Fk8t4=pw<{jq*tLvGn5`BD6&ir*UJw81J<1!*iPHd0$8$0p_!?(T}9;WWb zSxL1_<;bE1ERra?3=0r@ zR{P(!{Nq^KM|VVlbvkNsu~N29%T#^0;O~9#yptISSsZ-91sK7~8ggR!!B=M>Ko6C*Okn=DmG z2U8Y($lA8!o&Nx!z{cdw5QdF%nclu~w|q=8QTf2iiXK1^ts5X- z;>h^kuM@@?CSDcw1>RoD)JGs6eh1Dab^xlp(Z(nW{-XZ?2-^4K37p)tiO`>@0+UHB zfGN@BMvJG@&Db5P_r-gtWR75e7cfqX2tYIl<-xVIe)x7u>zxa~Cp}CEKt5eBp`0hQh{5ZYXSA7-!r!M)2BhucY%OMPXk2@1x zw>UsxS=F>$k_2F-qb0VxC%HFQ^M2SrGcx8%=2jU1X4u}Le*4gEtB;d~*_Vw2mm~t9 z1)`T-$H#x`j)Z9{K_o2d6Xi15b0av_uU_WLnl)bB_TI5w>OE{g&XMSCR;?oKR&4%2 z{B z9gr(9-;ID3$JlqQYQcRiG;ZEi*x-$~*m5|=tJBzA`x93NE0tu6G<^?^;v#_oI08h^w>(qssH*29}Ut!<2D3(ZahDss5mfY+} z9f$Wm*p5h=B`YG3K;1zbC_g&`#v@5uW>@py_-9Bb~PQgTL0lOj!v$ zxjiTe9%X~E1mDGX{{T6}P8DNR^FRa*iQ|)hrZs6SAZJ#iK-k=O{+P-tF^@xmCE2dP zpKL-JtaDDRHI^VzC9F|C^|8UQ%K&wbHdx9ZRD|!(Yv+-*Vg+b|`Fm+MZClvlfct)j z5ar8CjAI7aQ!=ws34XUy3{`3<{1OEURf#Q+Ql|Z9bwzk||P}{v=oWzCm1o`L!>Srl-po-hu zYCZYH0yC@4D$MF>bS|6bh!yRMAYN3*mdnXH+cL3^J^5qYZNRfv&HUgD=3+;JD4Isn zhfFF!0=d7rKKLLxnn4km=#5_W6QmyJli6zip4g7Uxy{6*%zs2lK~+KE-S4*7>{fr+w}s{DPt@|=TdegNhGVHT zS$`xetRVS7lWvjvs=(A-niete*F()gkn7zysOBV=JicE&mYzq3W=V9Us#vS9saOC= zBXD@_kEj0tZr}Qr@b+V-&(S|+Jy1=V>W?%ztlUWL7GEk>y$vSjM!MC#08b|zPsNv$ zmnJ_S3i@Ss>sqegv7a_6W=be$;*SvcC&wSLj}&zti7C!JhEA21g(vdlY`~Tw6QW+~ ze9c>rQiu7#->{$kHA$M9KCR+7Rz`IsfYuOfYx?qcKbAB90Ht5puS%CsiMq~EO`3E8 zC~D9HR^LDk_s7)TZ^S(d!F@S0@VHRQEH0FwF02!6wei94c;rvZUOcCR1g&3x(_i`{ z$dmDxp@+61@n=uy-UsM!l*@!wf+MHXXHcMcJMamuvGBj`i^rMY6?L4(N({j{SX_p% zbe0|J?E4ILZ`;@H&H8}Mbk3T@GZM61k)&84pS|zz^vBI@2x2B#8QsO5Ux?W|{XY2U z{vCozdbt~EGO zCY$y&r;%C7BU2K<@85gv#y5f$cWOKJz&<%X67bOJ=@<_&D#cdVy&ALiJAEq^ z>3r^^o|`?IDXwx=NZdCh0l(iKdN`$*$ei*oq(po^S>9QjbqwZzu4cw#G=$AZKn$wsm;i>Sb!x-{6qxdVE+;9H?SlFs7iaJroqNxj})Qm1kMu!qHWBjDhBprs^{jnm3bY_5;rfP6o ze)eqg2OJJDyio>-$g*oL<%L-xr~_0!c|EJ1F)X=88FrR1&RM-Gpci|py5La%0DMNv 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˫uBx!>P>9+`WOa!PYAVcVSOUF2;P*H~ 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ÄQUY`J>f*UC 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

}_|LoxMmO3T}AcwA){USgDoW?Msh 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 DZ$slY From 71ade3b69ef55d3aed20262565186c0a4e2821f4 Mon Sep 17 00:00:00 2001 From: Martin Georgiev <3349414+Thinkorswim@users.noreply.github.com> Date: Mon, 27 Oct 2025 18:22:05 +0200 Subject: [PATCH 11/12] Address copilot complaints --- .../simface/embedding/CustomModelTest.kt | 38 +++--- .../simprints/biometrics/simface/SimFace.kt | 111 ++++++++++-------- .../biometrics/simface/SimFaceConfig.kt | 12 +- 3 files changed, 84 insertions(+), 77 deletions(-) diff --git a/src/androidTest/java/com/simprints/biometrics/simface/embedding/CustomModelTest.kt b/src/androidTest/java/com/simprints/biometrics/simface/embedding/CustomModelTest.kt index e133264..c487e7a 100644 --- a/src/androidTest/java/com/simprints/biometrics/simface/embedding/CustomModelTest.kt +++ b/src/androidTest/java/com/simprints/biometrics/simface/embedding/CustomModelTest.kt @@ -15,10 +15,10 @@ import org.junit.Test /** * This test class makes it trivially easy to run tests with new model files: - * 1. Add the new model file to the anrdroidTest/res/raw folder - * 2. Create a new test method - * 3. Provide the model file name to `openTestModelFile()` - * 4. Do the testing + * 1. Add the new model file to the anrdroidTest/res/raw folder + * 2. Create a new test method + * 3. Provide the model file name to `openTestModelFile()` + * 4. Do the testing */ class CustomModelTest { private lateinit var context: Context @@ -41,27 +41,25 @@ class CustomModelTest { fun test_processes_face_with_custom_model() = runTest { val testModelFile = context.openTestModelFile() - modelManager = MLModelManager( - SimFaceConfig( - context, - customModel = SimFaceConfig.CustomModel( - file = testModelFile, - templateVersion = "TEST_1", - ), - ), - ) + modelManager = + MLModelManager( + SimFaceConfig( + context, + customModel = + SimFaceConfig.CustomModel( + file = testModelFile, + templateVersion = "TEST_1", + ), + ), + ) embeddingProcessor = TensorFlowEmbeddingProcessor(modelManager) val bitmap: Bitmap = context.loadBitmapFromTestResources("royalty_free_good_face") val resultFloat = getFaceEmbeddingFromBitmap(bitmap) - assertThat(resultFloat) - .usingTolerance(0.1) - .containsExactly(GOOD_FACE_EMBEDDING) - .inOrder() + assertThat(resultFloat).usingTolerance(0.1).containsExactly(GOOD_FACE_EMBEDDING).inOrder() } - private fun getFaceEmbeddingFromBitmap(bitmap: Bitmap): FloatArray = embeddingProcessor - .getEmbedding(bitmap) - .let { Utils.byteArrayToFloatArray(it) } + private fun getFaceEmbeddingFromBitmap(bitmap: Bitmap): FloatArray = + embeddingProcessor.getEmbedding(bitmap).let { Utils.byteArrayToFloatArray(it) } } diff --git a/src/main/java/com/simprints/biometrics/simface/SimFace.kt b/src/main/java/com/simprints/biometrics/simface/SimFace.kt index 8b175b0..0f458ce 100644 --- a/src/main/java/com/simprints/biometrics/simface/SimFace.kt +++ b/src/main/java/com/simprints/biometrics/simface/SimFace.kt @@ -1,6 +1,7 @@ package com.simprints.biometrics.simface import android.graphics.Bitmap +import com.google.mlkit.vision.face.FaceDetection as MlKitFaceDetection import com.google.mlkit.vision.face.FaceDetector import com.google.mlkit.vision.face.FaceDetectorOptions import com.simprints.biometrics.simface.data.FaceDetection @@ -14,7 +15,6 @@ import com.simprints.biometrics.simface.matcher.MatchProcessor import com.simprints.simq.SimQ import java.util.concurrent.locks.ReentrantLock import kotlin.concurrent.withLock -import com.google.mlkit.vision.face.FaceDetection as MlKitFaceDetection class SimFace { private val initLock = ReentrantLock() @@ -28,54 +28,63 @@ class SimFace { private lateinit var faceDetectionProcessor: FaceDetectionProcessor /** Load the ML model into memory and prepare other resources for work. */ - fun initialize(config: SimFaceConfig): Unit = initLock.withLock { - try { - // Initialize the model manager with the given config - modelManager = MLModelManager(config) + fun initialize(config: SimFaceConfig): Unit = + initLock.withLock { + try { + // Initialize the model manager with the given config + modelManager = MLModelManager(config) - // Initialize SimQ quality processor with optional custom weights and parameters - qualityProcessor = SimQ( - faceWeights = config.qualityWeights ?: com.simprints.simq.QualityWeights.DEFAULT, - faceParameters = config.qualityParameters ?: com.simprints.simq.QualityParameters.DEFAULT - ) + // Initialize SimQ quality processor with optional custom weights and parameters + qualityProcessor = + when { + config.qualityWeights != null && config.qualityParameters != null -> + SimQ(config.qualityWeights, config.qualityParameters) + config.qualityWeights != null -> + SimQ(faceWeights = config.qualityWeights) + config.qualityParameters != null -> + SimQ(faceParameters = config.qualityParameters) + else -> SimQ() + } - // Initialize processors - embeddingProcessor = TensorFlowEmbeddingProcessor(modelManager) - matchProcessor = CosineDistanceMatchProcessor() + // Initialize processors + embeddingProcessor = TensorFlowEmbeddingProcessor(modelManager) + matchProcessor = CosineDistanceMatchProcessor() - // Configure and load MLKit face detection model - val realTimeOpts = - FaceDetectorOptions - .Builder() - .setContourMode(FaceDetectorOptions.CONTOUR_MODE_ALL) - .setPerformanceMode( - FaceDetectorOptions.PERFORMANCE_MODE_ACCURATE, - ).setLandmarkMode(FaceDetectorOptions.LANDMARK_MODE_ALL) - .setClassificationMode( - FaceDetectorOptions.CLASSIFICATION_MODE_ALL, - ).setMinFaceSize(0.20f) - .build() - faceDetector = MlKitFaceDetection.getClient(realTimeOpts) - faceDetectionProcessor = - MlKitFaceDetectionProcessor(faceDetector, qualityProcessor) - } catch (e: Exception) { - throw RuntimeException("Failed to initialize SimFaceFacade: ${e.message}", e) - } - } + // Configure and load MLKit face detection model + val realTimeOpts = + FaceDetectorOptions.Builder() + .setContourMode(FaceDetectorOptions.CONTOUR_MODE_ALL) + .setPerformanceMode( + FaceDetectorOptions.PERFORMANCE_MODE_ACCURATE, + ) + .setLandmarkMode(FaceDetectorOptions.LANDMARK_MODE_ALL) + .setClassificationMode( + FaceDetectorOptions.CLASSIFICATION_MODE_ALL, + ) + .setMinFaceSize(0.20f) + .build() + faceDetector = MlKitFaceDetection.getClient(realTimeOpts) + faceDetectionProcessor = + MlKitFaceDetectionProcessor(faceDetector, qualityProcessor) + } catch (e: Exception) { + throw RuntimeException("Failed to initialize SimFaceFacade: ${e.message}", e) + } + } /** Releases used resources and ML model. */ - fun release() = initLock.withLock { - try { - if (this::modelManager.isInitialized) { - modelManager.close() - } - if (this::faceDetector.isInitialized) { - faceDetector.close() + fun release() = + initLock.withLock { + try { + if (this::modelManager.isInitialized) { + modelManager.close() + } + if (this::faceDetector.isInitialized) { + faceDetector.close() + } + } catch (e: Exception) { + println("Error releasing MLModelManager: ${e.message}") + } } - } catch (e: Exception) { - println("Error releasing MLModelManager: ${e.message}") - } - } /** Returns the version of the templates generated by the underlying ML model. */ fun getTemplateVersion(): String = modelManager.templateVersion @@ -85,10 +94,10 @@ class SimFace { * metadata (quality, bounding box, landmarks, etc.) or error in a set of callbacks. */ fun detectFace( - image: Bitmap, - onSuccess: (List) -> Unit, - onFailure: (Exception) -> Unit = {}, - onCompleted: () -> Unit = {}, + image: Bitmap, + onSuccess: (List) -> Unit, + onFailure: (Exception) -> Unit = {}, + onCompleted: () -> Unit = {}, ) { if (!this::faceDetectionProcessor.isInitialized) { throw IllegalStateException("SimFace.initialize() should be called first") @@ -117,8 +126,8 @@ class SimFace { /** Compares the probe against the provided reference. */ fun verificationScore( - probe: ByteArray, - matchReference: ByteArray, + probe: ByteArray, + matchReference: ByteArray, ): Double { if (!this::matchProcessor.isInitialized) { throw IllegalStateException("SimFace.initialize() should be called first") @@ -131,8 +140,8 @@ class SimFace { * reference in a descending order. */ fun identificationScore( - probe: ByteArray, - matchReferences: List, + probe: ByteArray, + matchReferences: List, ): List> { if (!this::matchProcessor.isInitialized) { throw IllegalStateException("SimFace.initialize() should be called first") diff --git a/src/main/java/com/simprints/biometrics/simface/SimFaceConfig.kt b/src/main/java/com/simprints/biometrics/simface/SimFaceConfig.kt index d74cf31..0942df6 100644 --- a/src/main/java/com/simprints/biometrics/simface/SimFaceConfig.kt +++ b/src/main/java/com/simprints/biometrics/simface/SimFaceConfig.kt @@ -5,11 +5,11 @@ import com.simprints.simq.QualityParameters import com.simprints.simq.QualityWeights import java.io.File -data class SimFaceConfig( +data class SimFaceConfig( val applicationContext: Context, /** * Custom model file to use instead of the bundled one. If not set, the bundled model will - * be used. The custom model's inputs and outputs vectors must much the default SimFace + * be used. The custom model's inputs and outputs vectors must match the default SimFace * model. */ val customModel: CustomModel? = null, @@ -24,8 +24,8 @@ data class SimFaceConfig( */ val qualityParameters: QualityParameters? = null, ) { - data class CustomModel( - val file: File, - val templateVersion: String, - ) + data class CustomModel( + val file: File, + val templateVersion: String, + ) } From 1f183edad19154380a0172d2c4ffe257d2700e16 Mon Sep 17 00:00:00 2001 From: Martin Georgiev <3349414+Thinkorswim@users.noreply.github.com> Date: Tue, 28 Oct 2025 11:04:18 +0200 Subject: [PATCH 12/12] Add ktlint formatting --- .../com/simprints/simq/QualityWeightsTest.kt | 36 +-- .../java/com/simprints/simq/SimQTest.kt | 236 +++++++++--------- .../com/simprints/simq/QualityParameters.kt | 30 +-- .../java/com/simprints/simq/QualityWeights.kt | 10 +- simq/src/main/java/com/simprints/simq/SimQ.kt | 168 ++++++------- .../simq/analysis/AlignmentAnalysis.kt | 14 +- .../simprints/simq/analysis/BlurAnalysis.kt | 19 +- .../simq/analysis/BrightnessAnalysis.kt | 39 ++- .../simq/analysis/ContrastAnalysis.kt | 19 +- .../com/simprints/simq/utils/BitmapExt.kt | 6 +- .../com/simprints/simq/utils/ImageAnalyzer.kt | 13 +- .../simprints/simq/utils/ScoringFunctions.kt | 40 ++- .../simface/embedding/CustomModelTest.kt | 20 +- .../simprints/biometrics/simface/SimFace.kt | 117 +++++---- .../biometrics/simface/SimFaceConfig.kt | 42 ++-- .../detection/MlKitFaceDetectionProcessor.kt | 197 +++++++-------- 16 files changed, 500 insertions(+), 506 deletions(-) diff --git a/simq/src/androidTest/java/com/simprints/simq/QualityWeightsTest.kt b/simq/src/androidTest/java/com/simprints/simq/QualityWeightsTest.kt index 2d592a6..b336242 100644 --- a/simq/src/androidTest/java/com/simprints/simq/QualityWeightsTest.kt +++ b/simq/src/androidTest/java/com/simprints/simq/QualityWeightsTest.kt @@ -10,8 +10,8 @@ import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class QualityWeightsTest { private fun createTestBitmap( - width: Int = 256, - height: Int = 256, + width: Int = 256, + height: Int = 256, ): Bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888) @Test @@ -20,24 +20,24 @@ class QualityWeightsTest { // Only alignment weight val alignmentOnlySimQ = - SimQ( - faceWeights = - QualityWeights( - alignment = 1.0, - blur = 0.0, - brightness = 0.0, - contrast = 0.0, - eyeOpenness = 0.0, - ), - ) + SimQ( + faceWeights = + QualityWeights( + alignment = 1.0, + blur = 0.0, + brightness = 0.0, + contrast = 0.0, + eyeOpenness = 0.0, + ), + ) val alignmentOnly = - alignmentOnlySimQ.calculateFaceQuality( - bitmap = bitmap, - pitch = 0.0, - yaw = 0.0, - roll = 0.0, - ) + alignmentOnlySimQ.calculateFaceQuality( + bitmap = bitmap, + pitch = 0.0, + yaw = 0.0, + roll = 0.0, + ) assertThat(alignmentOnly).isEqualTo(1f) } diff --git a/simq/src/androidTest/java/com/simprints/simq/SimQTest.kt b/simq/src/androidTest/java/com/simprints/simq/SimQTest.kt index e9d5f27..6da3dd6 100644 --- a/simq/src/androidTest/java/com/simprints/simq/SimQTest.kt +++ b/simq/src/androidTest/java/com/simprints/simq/SimQTest.kt @@ -18,8 +18,8 @@ class SimQTest { } private fun createTestBitmap( - width: Int = 256, - height: Int = 256, + width: Int = 256, + height: Int = 256, ): Bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888) @Test @@ -36,20 +36,20 @@ class SimQTest { val bitmap = createTestBitmap() val perfectScore = - simQ.calculateFaceQuality( - bitmap = bitmap, - pitch = 0.0, - yaw = 0.0, - roll = 0.0, - ) + simQ.calculateFaceQuality( + bitmap = bitmap, + pitch = 0.0, + yaw = 0.0, + roll = 0.0, + ) val poorAlignmentScore = - simQ.calculateFaceQuality( - bitmap = bitmap, - pitch = 20.0, - yaw = 20.0, - roll = 20.0, - ) + simQ.calculateFaceQuality( + bitmap = bitmap, + pitch = 20.0, + yaw = 20.0, + roll = 20.0, + ) assertThat(perfectScore).isAtLeast(poorAlignmentScore) } @@ -59,12 +59,12 @@ class SimQTest { val bitmap = createTestBitmap() val quality = - simQ.calculateFaceQuality( - bitmap = bitmap, - pitch = 30.0, - yaw = 0.0, - roll = 0.0, - ) + simQ.calculateFaceQuality( + bitmap = bitmap, + pitch = 30.0, + yaw = 0.0, + roll = 0.0, + ) assertThat(quality).isLessThan(0.5f) } @@ -73,30 +73,30 @@ class SimQTest { fun calculateFaceQualityWithEyeOpennessIncludesItInCalculation() { val bitmap = createTestBitmap() val simQWithEyeWeight = - SimQ( - faceWeights = - QualityWeights( - alignment = 0.3, - blur = 0.2, - brightness = 0.2, - contrast = 0.1, - eyeOpenness = 0.2, - ), - ) + SimQ( + faceWeights = + QualityWeights( + alignment = 0.3, + blur = 0.2, + brightness = 0.2, + contrast = 0.1, + eyeOpenness = 0.2, + ), + ) val openEyesScore = - simQWithEyeWeight.calculateFaceQuality( - bitmap = bitmap, - leftEyeOpenness = 1.0, - rightEyeOpenness = 1.0, - ) + simQWithEyeWeight.calculateFaceQuality( + bitmap = bitmap, + leftEyeOpenness = 1.0, + rightEyeOpenness = 1.0, + ) val closedEyesScore = - simQWithEyeWeight.calculateFaceQuality( - bitmap = bitmap, - leftEyeOpenness = 0.0, - rightEyeOpenness = 0.0, - ) + simQWithEyeWeight.calculateFaceQuality( + bitmap = bitmap, + leftEyeOpenness = 0.0, + rightEyeOpenness = 0.0, + ) assertThat(openEyesScore).isAtLeast(closedEyesScore) } @@ -107,11 +107,11 @@ class SimQTest { val simQWithEyeWeight = SimQ(faceWeights = QualityWeights(eyeOpenness = 0.2)) val qualityNoEyes = - simQWithEyeWeight.calculateFaceQuality( - bitmap = bitmap, - leftEyeOpenness = null, - rightEyeOpenness = null, - ) + simQWithEyeWeight.calculateFaceQuality( + bitmap = bitmap, + leftEyeOpenness = null, + rightEyeOpenness = null, + ) assertThat(qualityNoEyes).isAtLeast(0.0f) assertThat(qualityNoEyes).isAtMost(1.0f) @@ -123,11 +123,11 @@ class SimQTest { val simQWithEyeWeight = SimQ(faceWeights = QualityWeights(eyeOpenness = 0.2)) val quality = - simQWithEyeWeight.calculateFaceQuality( - bitmap = bitmap, - leftEyeOpenness = 1.0, - rightEyeOpenness = null, - ) + simQWithEyeWeight.calculateFaceQuality( + bitmap = bitmap, + leftEyeOpenness = 1.0, + rightEyeOpenness = null, + ) assertThat(quality).isIn(Range.closed(0.0f, 1.0f)) } @@ -136,43 +136,43 @@ class SimQTest { fun calculateFaceQualityWithCustomWeightsAffectsResult() { val bitmap = createTestBitmap() val alignmentWeightedSimQ = - SimQ( - faceWeights = - QualityWeights( - alignment = 0.9, - blur = 0.025, - brightness = 0.025, - contrast = 0.025, - eyeOpenness = 0.025, - ), - ) + SimQ( + faceWeights = + QualityWeights( + alignment = 0.9, + blur = 0.025, + brightness = 0.025, + contrast = 0.025, + eyeOpenness = 0.025, + ), + ) val otherWeightedSimQ = - SimQ( - faceWeights = - QualityWeights( - alignment = 0.025, - blur = 0.325, - brightness = 0.325, - contrast = 0.325, - eyeOpenness = 0.0, - ), - ) + SimQ( + faceWeights = + QualityWeights( + alignment = 0.025, + blur = 0.325, + brightness = 0.325, + contrast = 0.325, + eyeOpenness = 0.0, + ), + ) val alignmentWeighted = - alignmentWeightedSimQ.calculateFaceQuality( - bitmap = bitmap, - pitch = 20.0, - yaw = 20.0, - roll = 20.0, - ) + alignmentWeightedSimQ.calculateFaceQuality( + bitmap = bitmap, + pitch = 20.0, + yaw = 20.0, + roll = 20.0, + ) val otherWeighted = - otherWeightedSimQ.calculateFaceQuality( - bitmap = bitmap, - pitch = 20.0, - yaw = 20.0, - roll = 20.0, - ) + otherWeightedSimQ.calculateFaceQuality( + bitmap = bitmap, + pitch = 20.0, + yaw = 20.0, + roll = 20.0, + ) assertThat(alignmentWeighted).isLessThan(otherWeighted) } @@ -181,37 +181,37 @@ class SimQTest { fun calculateFaceQualityWithCustomParametersAffectsThresholds() { val bitmap = createTestBitmap() val strictSimQ = - SimQ( - faceParameters = - QualityParameters( - maxAlignmentAngle = 10.0, - maxIndividualAngle = 20.0, - ), - ) + SimQ( + faceParameters = + QualityParameters( + maxAlignmentAngle = 10.0, + maxIndividualAngle = 20.0, + ), + ) val lenientSimQ = - SimQ( - faceParameters = - QualityParameters( - maxAlignmentAngle = 30.0, - maxIndividualAngle = 40.0, - ), - ) + SimQ( + faceParameters = + QualityParameters( + maxAlignmentAngle = 30.0, + maxIndividualAngle = 40.0, + ), + ) val strictQuality = - strictSimQ.calculateFaceQuality( - bitmap = bitmap, - pitch = 15.0, - yaw = 15.0, - roll = 15.0, - ) + strictSimQ.calculateFaceQuality( + bitmap = bitmap, + pitch = 15.0, + yaw = 15.0, + roll = 15.0, + ) val lenientQuality = - lenientSimQ.calculateFaceQuality( - bitmap = bitmap, - pitch = 15.0, - yaw = 15.0, - roll = 15.0, - ) + lenientSimQ.calculateFaceQuality( + bitmap = bitmap, + pitch = 15.0, + yaw = 15.0, + roll = 15.0, + ) assertThat(lenientQuality).isAtLeast(strictQuality) } @@ -253,16 +253,16 @@ class SimQTest { fun calculateFaceQualityWithZeroWeightsReturnsZeroOrHandledGracefully() { val bitmap = createTestBitmap() val zeroWeightsSimQ = - SimQ( - faceWeights = - QualityWeights( - alignment = 0.0, - blur = 0.0, - brightness = 0.0, - contrast = 0.0, - eyeOpenness = 0.0, - ), - ) + SimQ( + faceWeights = + QualityWeights( + alignment = 0.0, + blur = 0.0, + brightness = 0.0, + contrast = 0.0, + eyeOpenness = 0.0, + ), + ) val quality = zeroWeightsSimQ.calculateFaceQuality(bitmap = bitmap) diff --git a/simq/src/main/java/com/simprints/simq/QualityParameters.kt b/simq/src/main/java/com/simprints/simq/QualityParameters.kt index 76eab4e..50a6282 100644 --- a/simq/src/main/java/com/simprints/simq/QualityParameters.kt +++ b/simq/src/main/java/com/simprints/simq/QualityParameters.kt @@ -1,21 +1,21 @@ package com.simprints.simq data class QualityParameters( - // Alignment thresholds - val maxAlignmentAngle: Double = 20.0, - val maxIndividualAngle: Double = 25.0, - // Blur thresholds (Laplacian variance) - val minBlur: Double = 50_000.0, - val maxBlur: Double = 100_000.0, - // Brightness thresholds (0-255) - val minBrightness: Double = 30.0, - val optimalBrightnessLow: Double = 80.0, - val optimalBrightnessHigh: Double = 150.0, - val maxBrightness: Double = 190.0, - val brightnessSteepness: Double = 0.3, - // Contrast thresholds (std dev) - val minContrast: Double = 30.0, - val maxContrast: Double = 47.0, + // Alignment thresholds + val maxAlignmentAngle: Double = 20.0, + val maxIndividualAngle: Double = 25.0, + // Blur thresholds (Laplacian variance) + val minBlur: Double = 50_000.0, + val maxBlur: Double = 100_000.0, + // Brightness thresholds (0-255) + val minBrightness: Double = 30.0, + val optimalBrightnessLow: Double = 80.0, + val optimalBrightnessHigh: Double = 150.0, + val maxBrightness: Double = 190.0, + val brightnessSteepness: Double = 0.3, + // Contrast thresholds (std dev) + val minContrast: Double = 30.0, + val maxContrast: Double = 47.0, ) { companion object { val DEFAULT = QualityParameters() diff --git a/simq/src/main/java/com/simprints/simq/QualityWeights.kt b/simq/src/main/java/com/simprints/simq/QualityWeights.kt index 167ddb4..8db36b0 100644 --- a/simq/src/main/java/com/simprints/simq/QualityWeights.kt +++ b/simq/src/main/java/com/simprints/simq/QualityWeights.kt @@ -5,11 +5,11 @@ package com.simprints.simq * the final score. */ data class QualityWeights( - val alignment: Double = 0.28, - val blur: Double = 0.3, - val brightness: Double = 0.3, - val contrast: Double = 0.1, - val eyeOpenness: Double = 0.02, + val alignment: Double = 0.28, + val blur: Double = 0.3, + val brightness: Double = 0.3, + val contrast: Double = 0.1, + val eyeOpenness: Double = 0.02, ) { companion object { val DEFAULT = QualityWeights() diff --git a/simq/src/main/java/com/simprints/simq/SimQ.kt b/simq/src/main/java/com/simprints/simq/SimQ.kt index b50bfe0..c6e04f1 100644 --- a/simq/src/main/java/com/simprints/simq/SimQ.kt +++ b/simq/src/main/java/com/simprints/simq/SimQ.kt @@ -10,8 +10,8 @@ import com.simprints.simq.utils.centerCrop import com.simprints.simq.utils.resizeToArea class SimQ( - private val faceWeights: QualityWeights = QualityWeights.DEFAULT, - private val faceParameters: QualityParameters = QualityParameters.DEFAULT, + private val faceWeights: QualityWeights = QualityWeights.DEFAULT, + private val faceParameters: QualityParameters = QualityParameters.DEFAULT, ) { init { OpenCVLoader.init() @@ -32,95 +32,95 @@ class SimQ( * @return Quality score between 0.0 and 1.0, or 0.0 if calculation fails */ fun calculateFaceQuality( - bitmap: Bitmap, - pitch: Double = 0.0, - yaw: Double = 0.0, - roll: Double = 0.0, - leftEyeOpenness: Double? = null, - rightEyeOpenness: Double? = null, - centerCrop: Float = 0.5f, - horizontalDisplacement: Float = 0.0f, - verticalDisplacement: Float = 0.0f, - ): Float = - try { + bitmap: Bitmap, + pitch: Double = 0.0, + yaw: Double = 0.0, + roll: Double = 0.0, + leftEyeOpenness: Double? = null, + rightEyeOpenness: Double? = null, + centerCrop: Float = 0.5f, + horizontalDisplacement: Float = 0.0f, + verticalDisplacement: Float = 0.0f, + ): Float = try { + // Resize bitmap to target area (256x256 = 65536) + val resizedBitmap = bitmap.resizeToArea(65536.0) - // Resize bitmap to target area (256x256 = 65536) - val resizedBitmap = bitmap.resizeToArea(65536.0) + // Crop the bitmap + val croppedBitmap = + resizedBitmap.centerCrop( + centerCrop, + horizontalDisplacement, + verticalDisplacement, + ) - // Crop the bitmap - val croppedBitmap = - resizedBitmap.centerCrop( - centerCrop, - horizontalDisplacement, - verticalDisplacement, - ) + var totalScore = 0.0 + val totalWeight = + faceWeights.alignment + + faceWeights.blur + + faceWeights.brightness + + faceWeights.contrast + + ( + if (leftEyeOpenness != null && rightEyeOpenness != null) { + faceWeights.eyeOpenness + } else { + 0.0 + } + ) - var totalScore = 0.0 - val totalWeight = - faceWeights.alignment + - faceWeights.blur + - faceWeights.brightness + - faceWeights.contrast + - (if (leftEyeOpenness != null && rightEyeOpenness != null) { - faceWeights.eyeOpenness - } else { - 0.0 - }) + val alignmentScore = + AlignmentAnalysis.calculateScore( + pitch, + yaw, + roll, + faceParameters.maxAlignmentAngle, + faceParameters.maxIndividualAngle, + ) + totalScore += faceWeights.alignment * alignmentScore - val alignmentScore = - AlignmentAnalysis.calculateScore( - pitch, - yaw, - roll, - faceParameters.maxAlignmentAngle, - faceParameters.maxIndividualAngle, - ) - totalScore += faceWeights.alignment * alignmentScore + val blurScore = + BlurAnalysis.calculateScore( + croppedBitmap, + faceParameters.minBlur, + faceParameters.maxBlur, + ) + totalScore += faceWeights.blur * blurScore - val blurScore = - BlurAnalysis.calculateScore( - croppedBitmap, - faceParameters.minBlur, - faceParameters.maxBlur, - ) - totalScore += faceWeights.blur * blurScore + val brightnessScore = + BrightnessAnalysis.calculateScore( + croppedBitmap, + faceParameters.minBrightness, + faceParameters.optimalBrightnessLow, + faceParameters.optimalBrightnessHigh, + faceParameters.maxBrightness, + faceParameters.brightnessSteepness, + ) + totalScore += faceWeights.brightness * brightnessScore - val brightnessScore = - BrightnessAnalysis.calculateScore( - croppedBitmap, - faceParameters.minBrightness, - faceParameters.optimalBrightnessLow, - faceParameters.optimalBrightnessHigh, - faceParameters.maxBrightness, - faceParameters.brightnessSteepness, - ) - totalScore += faceWeights.brightness * brightnessScore + val contrastScore = + ContrastAnalysis.calculateScore( + croppedBitmap, + faceParameters.minContrast, + faceParameters.maxContrast, + ) + totalScore += faceWeights.contrast * contrastScore - val contrastScore = - ContrastAnalysis.calculateScore( - croppedBitmap, - faceParameters.minContrast, - faceParameters.maxContrast, - ) - totalScore += faceWeights.contrast * contrastScore + if (leftEyeOpenness != null && rightEyeOpenness != null) { + val eyeScore = (leftEyeOpenness + rightEyeOpenness) / 2.0 + totalScore += faceWeights.eyeOpenness * eyeScore + } - if (leftEyeOpenness != null && rightEyeOpenness != null) { - val eyeScore = (leftEyeOpenness + rightEyeOpenness) / 2.0 - totalScore += faceWeights.eyeOpenness * eyeScore - } + // Clean up + if (croppedBitmap != bitmap && croppedBitmap != resizedBitmap) { + croppedBitmap.recycle() + } + if (resizedBitmap != bitmap) { + resizedBitmap.recycle() + } - // Clean up - if (croppedBitmap != bitmap && croppedBitmap != resizedBitmap) { - croppedBitmap.recycle() - } - if (resizedBitmap != bitmap) { - resizedBitmap.recycle() - } - - // Normalize and clamp to 0-1 range - val finalScore = if (totalWeight > 0) totalScore / totalWeight else 0.0 - finalScore.coerceIn(0.0, 1.0).toFloat() - } catch (e: Exception) { - 0.0f - } + // Normalize and clamp to 0-1 range + val finalScore = if (totalWeight > 0) totalScore / totalWeight else 0.0 + finalScore.coerceIn(0.0, 1.0).toFloat() + } catch (e: Exception) { + 0.0f + } } diff --git a/simq/src/main/java/com/simprints/simq/analysis/AlignmentAnalysis.kt b/simq/src/main/java/com/simprints/simq/analysis/AlignmentAnalysis.kt index 76f649e..f7cc8ac 100644 --- a/simq/src/main/java/com/simprints/simq/analysis/AlignmentAnalysis.kt +++ b/simq/src/main/java/com/simprints/simq/analysis/AlignmentAnalysis.kt @@ -14,16 +14,16 @@ internal object AlignmentAnalysis { * @return Alignment score between 0.0 and 1.0 */ fun calculateScore( - pitch: Double, - yaw: Double, - roll: Double, - maxAngle: Double, - maxIndividualAngle: Double, + pitch: Double, + yaw: Double, + roll: Double, + maxAngle: Double, + maxIndividualAngle: Double, ): Double { // Reject if any angle is too extreme if (pitch.absoluteValue > maxIndividualAngle || - yaw.absoluteValue > maxIndividualAngle || - roll.absoluteValue > maxIndividualAngle + yaw.absoluteValue > maxIndividualAngle || + roll.absoluteValue > maxIndividualAngle ) { return 0.0 } diff --git a/simq/src/main/java/com/simprints/simq/analysis/BlurAnalysis.kt b/simq/src/main/java/com/simprints/simq/analysis/BlurAnalysis.kt index 08063bf..1560398 100644 --- a/simq/src/main/java/com/simprints/simq/analysis/BlurAnalysis.kt +++ b/simq/src/main/java/com/simprints/simq/analysis/BlurAnalysis.kt @@ -17,14 +17,13 @@ internal object BlurAnalysis { * @return Blur score between 0.0 and 1.0 */ fun calculateScore( - bitmap: Bitmap, - minBlur: Double, - maxBlur: Double, - ): Double = - try { - val laplacianVariance = imageAnalyzer.calculateLaplacianVariance(bitmap) - ScoringFunctions.rampScore(laplacianVariance, minBlur, maxBlur) - } catch (e: Exception) { - 1.0 // Default to good score if OpenCV not available - } + bitmap: Bitmap, + minBlur: Double, + maxBlur: Double, + ): Double = try { + val laplacianVariance = imageAnalyzer.calculateLaplacianVariance(bitmap) + ScoringFunctions.rampScore(laplacianVariance, minBlur, maxBlur) + } catch (e: Exception) { + 1.0 // Default to good score if OpenCV not available + } } diff --git a/simq/src/main/java/com/simprints/simq/analysis/BrightnessAnalysis.kt b/simq/src/main/java/com/simprints/simq/analysis/BrightnessAnalysis.kt index 7597320..429da96 100644 --- a/simq/src/main/java/com/simprints/simq/analysis/BrightnessAnalysis.kt +++ b/simq/src/main/java/com/simprints/simq/analysis/BrightnessAnalysis.kt @@ -20,24 +20,23 @@ internal object BrightnessAnalysis { * @return Brightness score between 0.0 and 1.0 */ fun calculateScore( - bitmap: Bitmap, - edgeLow: Double, - centerLow: Double, - centerHigh: Double, - edgeHigh: Double, - steepness: Double, - ): Double = - try { - val brightness = imageAnalyzer.calculateBrightness(bitmap) - ScoringFunctions.plateauScore( - brightness, - centerLow, - centerHigh, - edgeLow, - edgeHigh, - steepness - ) - } catch (e: Exception) { - 1.0 - } + bitmap: Bitmap, + edgeLow: Double, + centerLow: Double, + centerHigh: Double, + edgeHigh: Double, + steepness: Double, + ): Double = try { + val brightness = imageAnalyzer.calculateBrightness(bitmap) + ScoringFunctions.plateauScore( + brightness, + centerLow, + centerHigh, + edgeLow, + edgeHigh, + steepness, + ) + } catch (e: Exception) { + 1.0 + } } diff --git a/simq/src/main/java/com/simprints/simq/analysis/ContrastAnalysis.kt b/simq/src/main/java/com/simprints/simq/analysis/ContrastAnalysis.kt index f6aaaa0..6a1ee50 100644 --- a/simq/src/main/java/com/simprints/simq/analysis/ContrastAnalysis.kt +++ b/simq/src/main/java/com/simprints/simq/analysis/ContrastAnalysis.kt @@ -17,14 +17,13 @@ internal object ContrastAnalysis { * @return Contrast score between 0.0 and 1.0 */ fun calculateScore( - bitmap: Bitmap, - minContrast: Double, - maxContrast: Double, - ): Double = - try { - val contrast = imageAnalyzer.calculateContrast(bitmap) - ScoringFunctions.rampScore(contrast, minContrast, maxContrast) - } catch (e: Exception) { - 1.0 // Default to good score if OpenCV not available - } + bitmap: Bitmap, + minContrast: Double, + maxContrast: Double, + ): Double = try { + val contrast = imageAnalyzer.calculateContrast(bitmap) + ScoringFunctions.rampScore(contrast, minContrast, maxContrast) + } catch (e: Exception) { + 1.0 // Default to good score if OpenCV not available + } } diff --git a/simq/src/main/java/com/simprints/simq/utils/BitmapExt.kt b/simq/src/main/java/com/simprints/simq/utils/BitmapExt.kt index bdc90ba..2d318f6 100644 --- a/simq/src/main/java/com/simprints/simq/utils/BitmapExt.kt +++ b/simq/src/main/java/com/simprints/simq/utils/BitmapExt.kt @@ -13,9 +13,9 @@ import kotlin.math.sqrt * @return Cropped bitmap */ internal fun Bitmap.centerCrop( - centerCrop: Float, - horizontalDisplacement: Float = 0f, - verticalDisplacement: Float = 0f, + centerCrop: Float, + horizontalDisplacement: Float = 0f, + verticalDisplacement: Float = 0f, ): Bitmap { val hAbsDisplacement = (width * horizontalDisplacement).toInt() val vAbsDisplacement = (height * verticalDisplacement).toInt() diff --git a/simq/src/main/java/com/simprints/simq/utils/ImageAnalyzer.kt b/simq/src/main/java/com/simprints/simq/utils/ImageAnalyzer.kt index d1384fc..ab1afa1 100644 --- a/simq/src/main/java/com/simprints/simq/utils/ImageAnalyzer.kt +++ b/simq/src/main/java/com/simprints/simq/utils/ImageAnalyzer.kt @@ -1,13 +1,13 @@ package com.simprints.simq.utils import android.graphics.Bitmap -import kotlin.math.pow import org.opencv.android.Utils import org.opencv.core.Core import org.opencv.core.CvType import org.opencv.core.Mat import org.opencv.core.MatOfDouble import org.opencv.imgproc.Imgproc +import kotlin.math.pow /** * Interface for image quality analysis operations. Provides high-level methods for analyzing image @@ -30,7 +30,10 @@ interface ImageAnalyzer { * @param kernelSize Kernel size for the Laplacian operator (default: 5) * @return Laplacian variance value */ - fun calculateLaplacianVariance(bitmap: Bitmap, kernelSize: Int = 5): Double + fun calculateLaplacianVariance( + bitmap: Bitmap, + kernelSize: Int = 5, + ): Double /** * Calculates the standard deviation to measure image contrast. Higher values indicate higher @@ -43,7 +46,6 @@ interface ImageAnalyzer { } internal class OpenCVImageAnalyzer : ImageAnalyzer { - override fun calculateBrightness(bitmap: Bitmap): Double { val mat = Mat() val gray = Mat() @@ -57,7 +59,10 @@ internal class OpenCVImageAnalyzer : ImageAnalyzer { } } - override fun calculateLaplacianVariance(bitmap: Bitmap, kernelSize: Int): Double { + override fun calculateLaplacianVariance( + bitmap: Bitmap, + kernelSize: Int, + ): Double { val mat = Mat() val gray = Mat() val laplacian = Mat() diff --git a/simq/src/main/java/com/simprints/simq/utils/ScoringFunctions.kt b/simq/src/main/java/com/simprints/simq/utils/ScoringFunctions.kt index 9fa9913..6b199f6 100644 --- a/simq/src/main/java/com/simprints/simq/utils/ScoringFunctions.kt +++ b/simq/src/main/java/com/simprints/simq/utils/ScoringFunctions.kt @@ -12,15 +12,14 @@ internal object ScoringFunctions { * @return Score between 0.0 and 1.0 */ fun rampScore( - x: Double, - min: Double, - max: Double, - ): Double = - when { - x < min -> 0.0 - x > max -> 1.0 - else -> (x - min) / (max - min) - } + x: Double, + min: Double, + max: Double, + ): Double = when { + x < min -> 0.0 + x > max -> 1.0 + else -> (x - min) / (max - min) + } /** * Plateau scoring function: optimal range with smooth sigmoid falloff. @@ -34,16 +33,15 @@ internal object ScoringFunctions { * @return Score between 0.0 and 1.0 */ fun plateauScore( - x: Double, - centerLow: Double, - centerHigh: Double, - edgeLow: Double, - edgeHigh: Double, - steepness: Double, - ): Double = - when { - x in centerLow..centerHigh -> 1.0 - x < centerLow -> 1.0 / (1.0 + exp(-steepness * (x - edgeLow))) - else -> 1.0 / (1.0 + exp(steepness * (x - edgeHigh))) - }.coerceIn(0.0, 1.0) + x: Double, + centerLow: Double, + centerHigh: Double, + edgeLow: Double, + edgeHigh: Double, + steepness: Double, + ): Double = when { + x in centerLow..centerHigh -> 1.0 + x < centerLow -> 1.0 / (1.0 + exp(-steepness * (x - edgeLow))) + else -> 1.0 / (1.0 + exp(steepness * (x - edgeHigh))) + }.coerceIn(0.0, 1.0) } diff --git a/src/androidTest/java/com/simprints/biometrics/simface/embedding/CustomModelTest.kt b/src/androidTest/java/com/simprints/biometrics/simface/embedding/CustomModelTest.kt index c487e7a..b06eaf8 100644 --- a/src/androidTest/java/com/simprints/biometrics/simface/embedding/CustomModelTest.kt +++ b/src/androidTest/java/com/simprints/biometrics/simface/embedding/CustomModelTest.kt @@ -42,16 +42,16 @@ class CustomModelTest { val testModelFile = context.openTestModelFile() modelManager = - MLModelManager( - SimFaceConfig( - context, - customModel = - SimFaceConfig.CustomModel( - file = testModelFile, - templateVersion = "TEST_1", - ), + MLModelManager( + SimFaceConfig( + context, + customModel = + SimFaceConfig.CustomModel( + file = testModelFile, + templateVersion = "TEST_1", ), - ) + ), + ) embeddingProcessor = TensorFlowEmbeddingProcessor(modelManager) val bitmap: Bitmap = context.loadBitmapFromTestResources("royalty_free_good_face") @@ -61,5 +61,5 @@ class CustomModelTest { } private fun getFaceEmbeddingFromBitmap(bitmap: Bitmap): FloatArray = - embeddingProcessor.getEmbedding(bitmap).let { Utils.byteArrayToFloatArray(it) } + embeddingProcessor.getEmbedding(bitmap).let { Utils.byteArrayToFloatArray(it) } } diff --git a/src/main/java/com/simprints/biometrics/simface/SimFace.kt b/src/main/java/com/simprints/biometrics/simface/SimFace.kt index 0f458ce..5f49e51 100644 --- a/src/main/java/com/simprints/biometrics/simface/SimFace.kt +++ b/src/main/java/com/simprints/biometrics/simface/SimFace.kt @@ -1,7 +1,6 @@ package com.simprints.biometrics.simface import android.graphics.Bitmap -import com.google.mlkit.vision.face.FaceDetection as MlKitFaceDetection import com.google.mlkit.vision.face.FaceDetector import com.google.mlkit.vision.face.FaceDetectorOptions import com.simprints.biometrics.simface.data.FaceDetection @@ -15,6 +14,7 @@ import com.simprints.biometrics.simface.matcher.MatchProcessor import com.simprints.simq.SimQ import java.util.concurrent.locks.ReentrantLock import kotlin.concurrent.withLock +import com.google.mlkit.vision.face.FaceDetection as MlKitFaceDetection class SimFace { private val initLock = ReentrantLock() @@ -28,63 +28,60 @@ class SimFace { private lateinit var faceDetectionProcessor: FaceDetectionProcessor /** Load the ML model into memory and prepare other resources for work. */ - fun initialize(config: SimFaceConfig): Unit = - initLock.withLock { - try { - // Initialize the model manager with the given config - modelManager = MLModelManager(config) + fun initialize(config: SimFaceConfig): Unit = initLock.withLock { + try { + // Initialize the model manager with the given config + modelManager = MLModelManager(config) - // Initialize SimQ quality processor with optional custom weights and parameters - qualityProcessor = - when { - config.qualityWeights != null && config.qualityParameters != null -> - SimQ(config.qualityWeights, config.qualityParameters) - config.qualityWeights != null -> - SimQ(faceWeights = config.qualityWeights) - config.qualityParameters != null -> - SimQ(faceParameters = config.qualityParameters) - else -> SimQ() - } + // Initialize SimQ quality processor with optional custom weights and parameters + qualityProcessor = + when { + config.qualityWeights != null && config.qualityParameters != null -> + SimQ(config.qualityWeights, config.qualityParameters) + config.qualityWeights != null -> + SimQ(faceWeights = config.qualityWeights) + config.qualityParameters != null -> + SimQ(faceParameters = config.qualityParameters) + else -> SimQ() + } - // Initialize processors - embeddingProcessor = TensorFlowEmbeddingProcessor(modelManager) - matchProcessor = CosineDistanceMatchProcessor() + // Initialize processors + embeddingProcessor = TensorFlowEmbeddingProcessor(modelManager) + matchProcessor = CosineDistanceMatchProcessor() - // Configure and load MLKit face detection model - val realTimeOpts = - FaceDetectorOptions.Builder() - .setContourMode(FaceDetectorOptions.CONTOUR_MODE_ALL) - .setPerformanceMode( - FaceDetectorOptions.PERFORMANCE_MODE_ACCURATE, - ) - .setLandmarkMode(FaceDetectorOptions.LANDMARK_MODE_ALL) - .setClassificationMode( - FaceDetectorOptions.CLASSIFICATION_MODE_ALL, - ) - .setMinFaceSize(0.20f) - .build() - faceDetector = MlKitFaceDetection.getClient(realTimeOpts) - faceDetectionProcessor = - MlKitFaceDetectionProcessor(faceDetector, qualityProcessor) - } catch (e: Exception) { - throw RuntimeException("Failed to initialize SimFaceFacade: ${e.message}", e) - } - } + // Configure and load MLKit face detection model + val realTimeOpts = + FaceDetectorOptions + .Builder() + .setContourMode(FaceDetectorOptions.CONTOUR_MODE_ALL) + .setPerformanceMode( + FaceDetectorOptions.PERFORMANCE_MODE_ACCURATE, + ).setLandmarkMode(FaceDetectorOptions.LANDMARK_MODE_ALL) + .setClassificationMode( + FaceDetectorOptions.CLASSIFICATION_MODE_ALL, + ).setMinFaceSize(0.20f) + .build() + faceDetector = MlKitFaceDetection.getClient(realTimeOpts) + faceDetectionProcessor = + MlKitFaceDetectionProcessor(faceDetector, qualityProcessor) + } catch (e: Exception) { + throw RuntimeException("Failed to initialize SimFaceFacade: ${e.message}", e) + } + } /** Releases used resources and ML model. */ - fun release() = - initLock.withLock { - try { - if (this::modelManager.isInitialized) { - modelManager.close() - } - if (this::faceDetector.isInitialized) { - faceDetector.close() - } - } catch (e: Exception) { - println("Error releasing MLModelManager: ${e.message}") - } + fun release() = initLock.withLock { + try { + if (this::modelManager.isInitialized) { + modelManager.close() + } + if (this::faceDetector.isInitialized) { + faceDetector.close() } + } catch (e: Exception) { + println("Error releasing MLModelManager: ${e.message}") + } + } /** Returns the version of the templates generated by the underlying ML model. */ fun getTemplateVersion(): String = modelManager.templateVersion @@ -94,10 +91,10 @@ class SimFace { * metadata (quality, bounding box, landmarks, etc.) or error in a set of callbacks. */ fun detectFace( - image: Bitmap, - onSuccess: (List) -> Unit, - onFailure: (Exception) -> Unit = {}, - onCompleted: () -> Unit = {}, + image: Bitmap, + onSuccess: (List) -> Unit, + onFailure: (Exception) -> Unit = {}, + onCompleted: () -> Unit = {}, ) { if (!this::faceDetectionProcessor.isInitialized) { throw IllegalStateException("SimFace.initialize() should be called first") @@ -126,8 +123,8 @@ class SimFace { /** Compares the probe against the provided reference. */ fun verificationScore( - probe: ByteArray, - matchReference: ByteArray, + probe: ByteArray, + matchReference: ByteArray, ): Double { if (!this::matchProcessor.isInitialized) { throw IllegalStateException("SimFace.initialize() should be called first") @@ -140,8 +137,8 @@ class SimFace { * reference in a descending order. */ fun identificationScore( - probe: ByteArray, - matchReferences: List, + probe: ByteArray, + matchReferences: List, ): List> { if (!this::matchProcessor.isInitialized) { throw IllegalStateException("SimFace.initialize() should be called first") diff --git a/src/main/java/com/simprints/biometrics/simface/SimFaceConfig.kt b/src/main/java/com/simprints/biometrics/simface/SimFaceConfig.kt index 0942df6..4395849 100644 --- a/src/main/java/com/simprints/biometrics/simface/SimFaceConfig.kt +++ b/src/main/java/com/simprints/biometrics/simface/SimFaceConfig.kt @@ -6,26 +6,26 @@ import com.simprints.simq.QualityWeights import java.io.File data class SimFaceConfig( - val applicationContext: Context, - /** - * Custom model file to use instead of the bundled one. If not set, the bundled model will - * be used. The custom model's inputs and outputs vectors must match the default SimFace - * model. - */ - val customModel: CustomModel? = null, - /** - * Custom quality weights for face quality assessment. If not set, default weights will be - * used. - */ - val qualityWeights: QualityWeights? = null, - /** - * Custom quality parameters for face quality assessment. If not set, default parameters - * will be used. - */ - val qualityParameters: QualityParameters? = null, + val applicationContext: Context, + /** + * Custom model file to use instead of the bundled one. If not set, the bundled model will + * be used. The custom model's inputs and outputs vectors must match the default SimFace + * model. + */ + val customModel: CustomModel? = null, + /** + * Custom quality weights for face quality assessment. If not set, default weights will be + * used. + */ + val qualityWeights: QualityWeights? = null, + /** + * Custom quality parameters for face quality assessment. If not set, default parameters + * will be used. + */ + val qualityParameters: QualityParameters? = null, ) { - data class CustomModel( - val file: File, - val templateVersion: String, - ) + data class CustomModel( + val file: File, + val templateVersion: String, + ) } diff --git a/src/main/java/com/simprints/biometrics/simface/detection/MlKitFaceDetectionProcessor.kt b/src/main/java/com/simprints/biometrics/simface/detection/MlKitFaceDetectionProcessor.kt index 5a2d3fa..f9eacb6 100644 --- a/src/main/java/com/simprints/biometrics/simface/detection/MlKitFaceDetectionProcessor.kt +++ b/src/main/java/com/simprints/biometrics/simface/detection/MlKitFaceDetectionProcessor.kt @@ -16,42 +16,41 @@ import kotlin.coroutines.resumeWithException import kotlin.coroutines.suspendCoroutine internal class MlKitFaceDetectionProcessor( - private val faceDetector: FaceDetector, - private val qualityProcessor: SimQ, + private val faceDetector: FaceDetector, + private val qualityProcessor: SimQ, ) : FaceDetectionProcessor { override fun detectFace( - image: Bitmap, - onSuccess: (List) -> Unit, - onFailure: (Exception) -> Unit, - onCompleted: () -> Unit, + image: Bitmap, + onSuccess: (List) -> Unit, + onFailure: (Exception) -> Unit, + onCompleted: () -> Unit, ) { val inputImage = InputImage.fromBitmap(image, 0) faceDetector - .process(inputImage) - .addOnSuccessListener { faces -> - val faceDetections = mutableListOf() - faces?.forEach { face -> - val faceDetection = - FaceDetection( - sourceWidth = image.width, - sourceHeight = image.height, - absoluteBoundingBox = - face.boundingBox.clampToBounds( - image.width, - image.height, - ), - yaw = face.headEulerAngleY, - roll = face.headEulerAngleZ, - landmarks = buildLandmarks(face), - quality = calculateFaceQuality(face, image), - ) - faceDetections.add(faceDetection) - } - onSuccess(faceDetections) + .process(inputImage) + .addOnSuccessListener { faces -> + val faceDetections = mutableListOf() + faces?.forEach { face -> + val faceDetection = + FaceDetection( + sourceWidth = image.width, + sourceHeight = image.height, + absoluteBoundingBox = + face.boundingBox.clampToBounds( + image.width, + image.height, + ), + yaw = face.headEulerAngleY, + roll = face.headEulerAngleZ, + landmarks = buildLandmarks(face), + quality = calculateFaceQuality(face, image), + ) + faceDetections.add(faceDetection) } - .addOnFailureListener { exception -> onFailure(exception) } - .addOnCompleteListener { onCompleted() } + onSuccess(faceDetections) + }.addOnFailureListener { exception -> onFailure(exception) } + .addOnCompleteListener { onCompleted() } } override suspend fun detectFaceBlocking(image: Bitmap): List { @@ -59,98 +58,96 @@ internal class MlKitFaceDetectionProcessor( return suspendCoroutine { continuation -> faceDetector - .process(inputImage) - .addOnSuccessListener { faces -> - val faceDetections = mutableListOf() - faces?.forEach { face -> - val faceDetection = - FaceDetection( - sourceWidth = image.width, - sourceHeight = image.height, - absoluteBoundingBox = - face.boundingBox.clampToBounds( - image.width, - image.height, - ), - yaw = face.headEulerAngleY, - roll = face.headEulerAngleZ, - quality = calculateFaceQuality(face, image), - landmarks = buildLandmarks(face), - ) - faceDetections.add(faceDetection) - } - continuation.resume(faceDetections) - } - .addOnFailureListener { exception -> - continuation.resumeWithException(exception) + .process(inputImage) + .addOnSuccessListener { faces -> + val faceDetections = mutableListOf() + faces?.forEach { face -> + val faceDetection = + FaceDetection( + sourceWidth = image.width, + sourceHeight = image.height, + absoluteBoundingBox = + face.boundingBox.clampToBounds( + image.width, + image.height, + ), + yaw = face.headEulerAngleY, + roll = face.headEulerAngleZ, + quality = calculateFaceQuality(face, image), + landmarks = buildLandmarks(face), + ) + faceDetections.add(faceDetection) } + continuation.resume(faceDetections) + }.addOnFailureListener { exception -> + continuation.resumeWithException(exception) + } } } private fun calculateFaceQuality( - face: Face, - image: Bitmap, - ): Float = - try { - val boundingBox = face.boundingBox.clampToBounds(image.width, image.height) - val faceBitmap = - Bitmap.createBitmap( - image, - boundingBox.left, - boundingBox.top, - boundingBox.width(), - boundingBox.height(), - ) + face: Face, + image: Bitmap, + ): Float = try { + val boundingBox = face.boundingBox.clampToBounds(image.width, image.height) + val faceBitmap = + Bitmap.createBitmap( + image, + boundingBox.left, + boundingBox.top, + boundingBox.width(), + boundingBox.height(), + ) - val qualityScore = - qualityProcessor.calculateFaceQuality( - bitmap = faceBitmap, - pitch = face.headEulerAngleX.toDouble(), - yaw = face.headEulerAngleY.toDouble(), - roll = face.headEulerAngleZ.toDouble(), - leftEyeOpenness = face.leftEyeOpenProbability?.toDouble(), - rightEyeOpenness = face.rightEyeOpenProbability?.toDouble(), - ) + val qualityScore = + qualityProcessor.calculateFaceQuality( + bitmap = faceBitmap, + pitch = face.headEulerAngleX.toDouble(), + yaw = face.headEulerAngleY.toDouble(), + roll = face.headEulerAngleZ.toDouble(), + leftEyeOpenness = face.leftEyeOpenProbability?.toDouble(), + rightEyeOpenness = face.rightEyeOpenProbability?.toDouble(), + ) - faceBitmap.recycle() + faceBitmap.recycle() - qualityScore - } catch (e: Exception) { - 0.0f - } + qualityScore + } catch (e: Exception) { + 0.0f + } private fun buildLandmarks(face: Face): FacialLandmarks? { val leftEye = - face.getLandmark(FaceLandmark.LEFT_EYE)?.position - ?: face.getContour(FaceContour.LEFT_EYE)?.points?.getOrNull(4) - ?: return null + face.getLandmark(FaceLandmark.LEFT_EYE)?.position + ?: face.getContour(FaceContour.LEFT_EYE)?.points?.getOrNull(4) + ?: return null val rightEye = - face.getLandmark(FaceLandmark.RIGHT_EYE)?.position - ?: face.getContour(FaceContour.RIGHT_EYE)?.points?.getOrNull(4) - ?: return null + face.getLandmark(FaceLandmark.RIGHT_EYE)?.position + ?: face.getContour(FaceContour.RIGHT_EYE)?.points?.getOrNull(4) + ?: return null val nose = - face.getLandmark(FaceLandmark.NOSE_BASE)?.position - ?: face.getContour(FaceContour.NOSE_BRIDGE)?.points?.lastOrNull() - ?: return null + face.getLandmark(FaceLandmark.NOSE_BASE)?.position + ?: face.getContour(FaceContour.NOSE_BRIDGE)?.points?.lastOrNull() + ?: return null val mouthLeft = - face.getLandmark(FaceLandmark.MOUTH_LEFT)?.position - ?: face.getContour(FaceContour.LOWER_LIP_BOTTOM)?.points?.lastOrNull() - ?: return null + face.getLandmark(FaceLandmark.MOUTH_LEFT)?.position + ?: face.getContour(FaceContour.LOWER_LIP_BOTTOM)?.points?.lastOrNull() + ?: return null val mouthRight = - face.getLandmark(FaceLandmark.MOUTH_RIGHT)?.position - ?: face.getContour(FaceContour.LOWER_LIP_BOTTOM)?.points?.firstOrNull() - ?: return null + face.getLandmark(FaceLandmark.MOUTH_RIGHT)?.position + ?: face.getContour(FaceContour.LOWER_LIP_BOTTOM)?.points?.firstOrNull() + ?: return null return FacialLandmarks( - Point2D(leftEye.x, leftEye.y), - Point2D(rightEye.x, rightEye.y), - Point2D(nose.x, nose.y), - Point2D(mouthLeft.x, mouthLeft.y), - Point2D(mouthRight.x, mouthRight.y), + Point2D(leftEye.x, leftEye.y), + Point2D(rightEye.x, rightEye.y), + Point2D(nose.x, nose.y), + Point2D(mouthLeft.x, mouthLeft.y), + Point2D(mouthRight.x, mouthRight.y), ) } }