diff --git a/MyOpenCv/.gitignore b/MyOpenCv/.gitignore
new file mode 100644
index 0000000..aa724b7
--- /dev/null
+++ b/MyOpenCv/.gitignore
@@ -0,0 +1,15 @@
+*.iml
+.gradle
+/local.properties
+/.idea/caches
+/.idea/libraries
+/.idea/modules.xml
+/.idea/workspace.xml
+/.idea/navEditor.xml
+/.idea/assetWizardSettings.xml
+.DS_Store
+/build
+/captures
+.externalNativeBuild
+.cxx
+local.properties
diff --git a/MyOpenCv/app/.gitignore b/MyOpenCv/app/.gitignore
new file mode 100644
index 0000000..42afabf
--- /dev/null
+++ b/MyOpenCv/app/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/MyOpenCv/app/build.gradle.kts b/MyOpenCv/app/build.gradle.kts
new file mode 100644
index 0000000..1484ed2
--- /dev/null
+++ b/MyOpenCv/app/build.gradle.kts
@@ -0,0 +1,88 @@
+plugins {
+ alias(libs.plugins.android.application)
+ alias(libs.plugins.kotlin.android)
+ kotlin("plugin.serialization") version "2.1.0"
+}
+
+android {
+ namespace = "com.example.myopencv"
+ compileSdk = 34
+
+ defaultConfig {
+ applicationId = "com.example.myopencv"
+ minSdk = 24
+ targetSdk = 34
+ versionCode = 1
+ versionName = "1.0"
+
+ testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+ vectorDrawables {
+ useSupportLibrary = true
+ }
+ }
+
+ buildTypes {
+ release {
+ isMinifyEnabled = false
+ proguardFiles(
+ getDefaultProguardFile("proguard-android-optimize.txt"),
+ "proguard-rules.pro"
+ )
+ }
+ }
+ compileOptions {
+ sourceCompatibility = JavaVersion.VERSION_17
+ targetCompatibility = JavaVersion.VERSION_17
+ }
+ kotlinOptions {
+ jvmTarget = "17"
+ }
+ buildFeatures {
+ compose = true
+ }
+ composeOptions {
+ kotlinCompilerExtensionVersion = "1.5.1"
+ }
+ packaging {
+ resources {
+ excludes += "/META-INF/{AL2.0,LGPL2.1}"
+ }
+ }
+}
+
+dependencies {
+
+ implementation(libs.androidx.core.ktx)
+ implementation(libs.androidx.lifecycle.runtime.ktx)
+ implementation(libs.androidx.activity.compose)
+ implementation(platform(libs.androidx.compose.bom))
+ implementation(libs.androidx.ui)
+ implementation(libs.androidx.ui.graphics)
+ implementation(libs.androidx.ui.tooling.preview)
+ implementation(libs.androidx.material3)
+ implementation(project(":opencv"))
+ testImplementation(libs.junit)
+ androidTestImplementation(libs.androidx.junit)
+ androidTestImplementation(libs.androidx.espresso.core)
+ androidTestImplementation(platform(libs.androidx.compose.bom))
+ androidTestImplementation(libs.androidx.ui.test.junit4)
+ debugImplementation(libs.androidx.ui.tooling)
+ debugImplementation(libs.androidx.ui.test.manifest)
+}
+
+dependencies {
+
+ // Camerax implementation
+ //def cameraxVersion = "1.3.1"
+ implementation (libs.camera.core)
+ implementation (libs.androidx.camera.camera.camera22)
+ implementation (libs.androidx.camera.camera.view)
+ implementation (libs.camera.lifecycle)
+ // Camerax implementation
+}
+
+
+dependencies {
+ implementation(libs.core.ktx)
+ implementation(libs.kotlinx.serialization.json)
+}
\ No newline at end of file
diff --git a/MyOpenCv/app/proguard-rules.pro b/MyOpenCv/app/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/MyOpenCv/app/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/MyOpenCv/app/src/androidTest/java/com/example/myopencv/ExampleInstrumentedTest.kt b/MyOpenCv/app/src/androidTest/java/com/example/myopencv/ExampleInstrumentedTest.kt
new file mode 100644
index 0000000..2a3bcd9
--- /dev/null
+++ b/MyOpenCv/app/src/androidTest/java/com/example/myopencv/ExampleInstrumentedTest.kt
@@ -0,0 +1,84 @@
+package com.example.myopencv
+
+import android.content.Context
+import android.graphics.BitmapFactory
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.ext.junit.runners.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+import org.opencv.android.Utils
+import org.opencv.core.CvType
+import org.opencv.core.Mat
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+ @Test
+ fun useAppContext() {
+ // Context of the app under test.
+ val appContext = InstrumentationRegistry.getInstrumentation().targetContext
+ assertEquals("com.example.myopencv", appContext.packageName)
+ }
+
+
+ @Test
+ fun testLoadBitmapFromResource() {
+ //照片选取 计算后的xReal=-127.2813 yReal=94.4458
+ //测点区域 x=97,y=1054,w=569,z=425
+ // 质心 x=-284.0299 , y=210.900
+ val imageResourceId =R.drawable.zp_127_245___210_90
+ val options = BitmapFactory.Options()
+ options.inScaled = false
+
+
+ // 获取应用程序上下文
+ val context: Context = ApplicationProvider.getApplicationContext()
+ val rawBitmap = BitmapFactory.decodeResource(context.resources, imageResourceId,options)
+ val rawMat = Mat(rawBitmap.width, rawBitmap.height, CvType.CV_8UC3)
+ Utils.bitmapToMat(rawBitmap, rawMat)
+ //灰度
+ val garyMat =imageHandler.mat2gary(rawMat)
+ val garyBitmap = imageHandler.mat2bitMap(garyMat)
+
+ //二值化
+ val thresholdValue=128.0
+ val binaryBitmap=imageHandler.binaryBitMap(thresholdValue,garyMat)
+
+
+ //图像截取 取值实际配置的区域参数
+ var x=97
+ var y=1054
+ var w=569
+ var h=425
+
+ val subMat=imageHandler.cropMat(rawMat,x,y,w,h)
+ val subBitMat= imageHandler.mat2bitMap(subMat)
+
+ val subGary=imageHandler.mat2gary(subMat)
+ val binaryThreshold=30.0
+ val subBinary=imageHandler.binaryMat(binaryThreshold,subGary)
+ val center=imageHandler.calcMoments(subBinary)
+ println("center数据= $center")
+ }
+}
+
+
+class ConfigLoadTest {
+ @Test
+ fun useAppContext() {
+ // Context of the app under test.
+// val appContext = InstrumentationRegistry.getInstrumentation().targetContext
+// val info=UserInfo(2017,"lucas","249324454@qq.com","male")
+// SharedPrefs.saveUserToPreferences(appContext,info)
+// val infoRead=SharedPrefs.loadUserFromPreferences(appContext)
+// assertEquals(info, infoRead)
+ }
+}
\ No newline at end of file
diff --git a/MyOpenCv/app/src/main/AndroidManifest.xml b/MyOpenCv/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..641839a
--- /dev/null
+++ b/MyOpenCv/app/src/main/AndroidManifest.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MyOpenCv/app/src/main/java/com/example/myopencv/MainActivity.kt b/MyOpenCv/app/src/main/java/com/example/myopencv/MainActivity.kt
new file mode 100644
index 0000000..f354bab
--- /dev/null
+++ b/MyOpenCv/app/src/main/java/com/example/myopencv/MainActivity.kt
@@ -0,0 +1,311 @@
+package com.example.myopencv
+
+import ImageHandler
+import android.Manifest
+import android.content.ComponentName
+import android.content.Context
+import android.content.Intent
+import android.content.ServiceConnection
+import android.content.pm.PackageManager
+import android.graphics.BitmapFactory
+import android.os.Bundle
+import android.os.IBinder
+import android.util.Log
+import android.widget.Toast
+import androidx.activity.ComponentActivity
+import androidx.activity.compose.setContent
+import androidx.activity.enableEdgeToEdge
+import androidx.activity.result.contract.ActivityResultContracts
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.wrapContentSize
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.material3.Button
+import androidx.compose.material3.HorizontalDivider
+import androidx.compose.material3.Scaffold
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableIntStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.asImageBitmap
+import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import androidx.core.content.ContextCompat
+import com.example.myopencv.ui.theme.MyOpenCvTheme
+import org.opencv.android.OpenCVLoader
+import org.opencv.android.Utils
+import org.opencv.core.CvType
+import org.opencv.core.Mat
+import org.opencv.core.Scalar
+import org.opencv.imgproc.Imgproc
+
+
+val imageHandler = ImageHandler()
+lateinit var myTcpSvc: MyTcpServer
+lateinit var myUdpSvc: UdpServer
+val deflectometer= Deflectometer()
+
+class MainActivity : ComponentActivity() {
+
+ private var binderTcp: MyTcpServer.LocalBinder? = null
+ private var binderUdp: UdpServer.LocalBinder? = null
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ enableEdgeToEdge()
+ val configContent=fileUtils.readerFile(this,"settings.json")
+ deflectometer.defaultSet(configContent)
+ val isOk=OpenCVLoader.initLocal()
+ if (isOk){
+ Toast.makeText(this,"opencv加载成功",Toast.LENGTH_SHORT).show()
+ }else{
+ Toast.makeText(this,
+ "opencv加载失败,退出",
+ Toast.LENGTH_SHORT).show()
+ finish()
+ }
+
+ applyForPermission()
+
+ val serviceIntentTcp = Intent(this, MyTcpServer::class.java)
+ bindService(serviceIntentTcp, serviceConnectionTcp, Context.BIND_AUTO_CREATE)
+
+ val serviceIntentUdp = Intent(this, UdpServer::class.java)
+ bindService(serviceIntentUdp, serviceConnectionUdp, Context.BIND_AUTO_CREATE)
+
+
+ when (PackageManager.PERMISSION_GRANTED) {
+ ContextCompat.checkSelfPermission(
+ this,
+ Manifest.permission.CAMERA
+ ) -> {
+ setCameraPreview()
+ }
+ }
+ }
+
+ private val serviceConnectionTcp = object : ServiceConnection {
+ override fun onServiceConnected(className: ComponentName, iBService: IBinder) {
+ //绑定到服务,可以获取服务中的Binder实例
+ binderTcp = iBService as MyTcpServer.LocalBinder
+ myTcpSvc = binderTcp!!.getService()
+ }
+
+ override fun onServiceDisconnected(arg0: ComponentName) {
+ binderTcp = null
+ }
+ }
+
+ private val serviceConnectionUdp = object : ServiceConnection {
+ override fun onServiceConnected(className: ComponentName, iBService: IBinder) {
+ //绑定到服务,可以获取服务中的Binder实例
+ binderUdp = iBService as UdpServer.LocalBinder
+ myUdpSvc = binderUdp!!.getService()
+ }
+
+ override fun onServiceDisconnected(arg0: ComponentName) {
+ binderUdp = null
+ }
+ }
+
+
+ private val cameraPermissionRequest =
+ registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
+ if (isGranted) {
+ setCameraPreview()
+ Log.i("权限","同意授予")
+ } else {
+ // Camera permission denied
+ Log.i("权限","拒绝授予")
+ }
+
+ }
+ private fun setImageHandler() {
+ setContent {
+ MyOpenCvTheme {
+ Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
+ Greeting(
+ name = "Android,来了",
+ modifier = Modifier.padding(innerPadding)
+ )
+ }
+ }
+ }
+ }
+
+ private fun setCameraPreview() {
+ setContent {
+ CameraPreviewScreen()
+ }
+ }
+
+
+ private fun applyForPermission(){
+ if (ContextCompat.checkSelfPermission(
+ this, Manifest.permission.WRITE_EXTERNAL_STORAGE
+ )!=PackageManager.PERMISSION_GRANTED ) {
+ cameraPermissionRequest.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
+ Log.i("权限", "请求外部存储")
+ }
+ if (ContextCompat.checkSelfPermission(
+ this, Manifest.permission.CAMERA
+ )!= PackageManager.PERMISSION_GRANTED ) {
+ cameraPermissionRequest.launch(Manifest.permission.CAMERA)
+ Log.i("权限", "请求相机")
+ }
+ }
+}
+
+
+@Composable
+fun Greeting(name: String, modifier: Modifier = Modifier) {
+
+ //照片选取
+ var result by remember { mutableIntStateOf(2) }
+ val imageResource = when (result) {
+ 1 -> R.drawable.zp_1
+ else -> R.drawable.yu_5
+ }
+ val options = BitmapFactory.Options()
+ options.inScaled = false
+ val rawBitmap = BitmapFactory.decodeResource(LocalContext.current.resources, imageResource,options)
+ val rawMat =Mat(rawBitmap.width, rawBitmap.height, CvType.CV_8UC3)
+ Utils.bitmapToMat(rawBitmap, rawMat)
+ //灰度
+ val garyMat =imageHandler.mat2gary(rawMat)
+ val garyBitmap = imageHandler.mat2bitMap(garyMat)
+
+ //二值化
+ val thresholdValue=128.0
+ val binaryBitmap=imageHandler.binaryBitMap(thresholdValue,garyMat)
+
+
+ //图像截取 取值实际配置的区域参数
+ var x=600
+ var y=600
+ var w=252
+ var h=186
+ if (result==2 ||result==6){
+ x=97
+ y=1054
+ w=569
+ h=425
+ }
+
+ //用外包方式的计算质心
+ val viewRect=android.graphics.Rect(x,y,x+w-1,y+h-1)
+ val wbc=imageHandler.getBinImageCentroid(rawBitmap,30,viewRect)
+ //
+
+ val subMat=imageHandler.cropMat(rawMat,x,y,w,h)
+ val subBitMat= imageHandler.mat2bitMap(subMat)
+
+ val subGary=imageHandler.mat2gary(subMat)
+ val binaryThreshold=30.0
+ val subBinary=imageHandler.binaryMat(binaryThreshold,subGary)
+ val center=imageHandler.calcMoments(subBinary)
+ //测试
+// val deflectometer= Deflectometer()
+// val cp= CentroidPoint(center.x,center.y)
+// val centroidDataArray= CentroidData("", arrayOf(cp))
+// val r=deflectometer.dataProcess(centroidDataArray)
+// println("挠度数据= $r")
+ //测试
+
+ // 在原图像上标记质心
+ Imgproc.circle(subMat, center, 5, Scalar(0.0, 0.0, 255.0), 2)
+ val centerBitMap=imageHandler.mat2bitMap(subMat)
+ LazyColumn(
+ modifier = Modifier
+ .fillMaxSize()
+ .wrapContentSize(),
+ horizontalAlignment = Alignment.CenterHorizontally
+ ) {
+ item {
+
+ Image(
+ painter = painterResource(imageResource),
+ contentDescription = result.toString(),
+ Modifier.size(300.dp),
+ contentScale = ContentScale.Fit
+ )
+
+ Image(
+ bitmap = garyBitmap.asImageBitmap(),
+ contentDescription = "灰度",
+ Modifier.size(300.dp),
+ contentScale = ContentScale.Fit
+ )
+
+ Button(onClick = {
+ result = (1..7).random()
+
+ }) {
+ Text("灰化效果")
+ }
+ }
+
+
+ item {
+ HorizontalDivider(color = Color(0.1f, 0.8f, 0.9f, 1.0f))
+ Image(
+ bitmap = binaryBitmap.asImageBitmap(),
+ contentDescription = "二值化",
+ Modifier.size(300.dp),
+ contentScale = ContentScale.Fit
+ )
+ }
+
+ item {
+ Image(
+ bitmap = subBitMat.asImageBitmap(),
+ contentDescription = "区域截取",
+ Modifier.size(300.dp),
+ contentScale = ContentScale.Fit
+ )
+ }
+
+ item {
+ Image(
+ bitmap = imageHandler.mat2bitMap(subGary).asImageBitmap(),
+ contentDescription = "区域灰度",
+ Modifier.size(300.dp),
+ contentScale = ContentScale.Fit
+ )
+ }
+
+ item {
+ Image(
+ bitmap = centerBitMap.asImageBitmap(),
+ contentDescription = "质心标记",
+ Modifier.size(300.dp),
+ contentScale = ContentScale.Fit
+ )
+ }
+
+ item {
+ Text("底部,没有了")
+ }
+ }
+
+
+}
+
+
+@Preview(showBackground = true)
+@Composable
+fun GreetingPreview() {
+ MyOpenCvTheme {
+ //Greeting("Android")
+ }
+}
diff --git a/MyOpenCv/app/src/main/java/com/example/myopencv/UdpServer.kt b/MyOpenCv/app/src/main/java/com/example/myopencv/UdpServer.kt
new file mode 100644
index 0000000..0c29fb8
--- /dev/null
+++ b/MyOpenCv/app/src/main/java/com/example/myopencv/UdpServer.kt
@@ -0,0 +1,77 @@
+package com.example.myopencv
+import android.app.Service
+import android.content.Intent
+import android.os.Binder
+import android.os.IBinder
+import android.util.Log
+import java.net.DatagramPacket
+import java.net.DatagramSocket
+import java.net.InetAddress
+
+
+
+class UdpServer:Service(){
+ // 内部Binder类
+ inner class LocalBinder : Binder() {
+ // 返回TcpService的实例
+ fun getService(): UdpServer = this@UdpServer
+ }
+ private val binder = LocalBinder()
+ override fun onBind(intent: Intent?): IBinder {
+ println("==onBind")
+ return binder
+ }
+ override fun onCreate() {
+ super.onCreate()
+ Thread(runnable).start()
+ println("启动 udp runnable")
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ Log.d("data","-> onDestroy")
+ }
+
+ private var runnable= kotlinx.coroutines.Runnable {
+ udpWork()
+ }
+ private fun udpWork(){
+ val serverSocket= DatagramSocket(2230)
+ println(serverSocket.localSocketAddress)
+ println(serverSocket.localAddress)
+ while (true) {
+ val buffer = ByteArray(102)
+ val packet = DatagramPacket(buffer, buffer.size)
+
+ serverSocket.receive(packet)
+
+ val remoteAddress = packet.address
+ val remotePort = packet.port
+ val recvMsg = String(packet.data, 0, packet.length)
+ // 创建应答数据
+ val responseMsg=decodeCmd(recvMsg,this)
+ val response = responseMsg.toByteArray()
+
+ // 发送应答
+ val responsePacket = DatagramPacket(response, response.size, remoteAddress, remotePort)
+ serverSocket.send(responsePacket)
+ println("收到${remoteAddress}:${remotePort}搜索设备命令${recvMsg}")
+ println("应答搜索${responseMsg}")
+ }
+ }
+
+ private fun sendData(msg:String,ip:String){
+ val socket = DatagramSocket()
+ val address = InetAddress.getByName(ip)
+ val port = 2230
+
+ val data = msg.toByteArray()
+ val packet = DatagramPacket(data, data.size, address, port)
+ socket.send(packet)
+ socket.close()
+ println("发送完毕")
+ }
+
+}
+
+
diff --git a/MyOpenCv/app/src/main/java/com/example/myopencv/camera.kt b/MyOpenCv/app/src/main/java/com/example/myopencv/camera.kt
new file mode 100644
index 0000000..9bab8a7
--- /dev/null
+++ b/MyOpenCv/app/src/main/java/com/example/myopencv/camera.kt
@@ -0,0 +1,262 @@
+package com.example.myopencv
+
+import ImageHandler
+import android.content.ContentValues
+import android.content.Context
+import android.graphics.Bitmap
+import android.graphics.BitmapFactory
+import android.graphics.Rect
+import android.icu.text.SimpleDateFormat
+import android.os.Build
+import android.provider.MediaStore
+import android.util.Log
+import androidx.camera.core.CameraSelector
+import androidx.camera.core.ImageAnalysis
+import androidx.camera.core.ImageCapture
+import androidx.camera.core.ImageCaptureException
+import androidx.camera.core.ImageProxy
+import androidx.camera.core.Preview
+import androidx.camera.core.resolutionselector.ResolutionSelector
+import androidx.camera.core.resolutionselector.ResolutionStrategy
+import androidx.camera.lifecycle.ProcessCameraProvider
+import androidx.camera.view.PreviewView
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.safeDrawingPadding
+import androidx.compose.foundation.layout.size
+import androidx.compose.material3.Button
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.mutableDoubleStateOf
+import androidx.compose.runtime.mutableLongStateOf
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.asImageBitmap
+import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.platform.LocalLifecycleOwner
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import androidx.compose.ui.viewinterop.AndroidView
+import androidx.core.content.ContextCompat
+import com.example.myopencv.models.CentroidData
+import com.example.myopencv.models.UData
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.runBlocking
+import kotlinx.serialization.encodeToString
+import kotlinx.serialization.json.Json
+import java.util.Locale
+import java.util.concurrent.Executors
+import kotlin.coroutines.resume
+import kotlin.coroutines.suspendCoroutine
+
+@Composable
+fun CameraPreviewScreen() {
+ val imageHandler = ImageHandler()
+ val cameraExecutor=Executors.newSingleThreadExecutor()
+ val lensFacing = CameraSelector.LENS_FACING_BACK
+ val lifecycleOwner = LocalLifecycleOwner.current
+ val context = LocalContext.current
+// val previewView = remember {
+// PreviewView(context)
+// }
+ val cameraxSelector = CameraSelector.Builder().requireLensFacing(lensFacing).build()
+// val imageCapture = remember {
+// ImageCapture.Builder().build()
+// }
+
+
+ val timeStampState= remember { mutableLongStateOf(0) }
+ val xView= remember { mutableDoubleStateOf(0.0) }
+ val yView= remember { mutableDoubleStateOf(0.0) }
+ //var centroidObj by remember { mutableStateOf(0.0) }
+// val rawMat = Mat(2112, 1568, CvType.CV_8UC3)
+// val options = BitmapFactory.Options()
+// options.inScaled = false
+ val rawBitmap = BitmapFactory.decodeResource(LocalContext.current.resources, R.drawable.yu_5)
+
+ val yuMap= remember { mutableStateOf(rawBitmap) }
+
+ //val preview = Preview.Builder().build()
+ val imageAnalyzer = ImageAnalysis.Builder()
+ .setResolutionSelector(
+ ResolutionSelector.Builder().
+ setResolutionStrategy(ResolutionStrategy.HIGHEST_AVAILABLE_STRATEGY)
+ //.setAspectRatioStrategy(AspectRatioStrategy.RATIO_16_9_FALLBACK_AUTO_STRATEGY)
+ .build()
+ )
+ .build()
+ .also {
+ it.setAnalyzer(cameraExecutor, GdndAnalyzer { img ->
+ val imageBitMapRaw=img.toBitmap()
+ //缓存bitmap 用于图像上传
+ val rotation = img.imageInfo.rotationDegrees //180
+ //println("角度信息: $rotation")
+
+ val imageBitMap=imageHandler.rotateBitmap(imageBitMapRaw, rotation.toFloat())
+ val grayBitMap=imageHandler.bitMap2Gray(imageBitMap)
+ yuMap.value=imageBitMap
+ timeStampState.longValue=System.currentTimeMillis()
+ val timeStr=timeNow2string()
+ val centroidDataArray= CentroidData(timeStr, mutableListOf())
+ val threshold=deflectometer.readThreshold()
+
+ deflectometer.readSensor().forEach{ s ->
+ val x=s.x.toInt()
+ val y=s.y.toInt()
+ val w=s.w.toInt()
+ val h=s.h.toInt()
+ //cv计算
+ //val p=imageHandler.img2Moments(img,threshold,x,y,w,h)
+
+ //外包计算方式
+ val viewRect= Rect(x,y,x+w-1,y+h-1)
+ val p=imageHandler.getBinImageCentroid(imageBitMap,threshold,viewRect)
+ //Log.d("传感器[${s.pos}] ${s.des}", "计算图像[w=${img.width},h=${img.height}]质心${p}")
+ centroidDataArray.centroids.add(p)
+ }
+
+ myTcpSvc.cacheImage(grayBitMap)
+ val mResult=deflectometer.dataProcess(centroidDataArray)
+// val uploadData=result2uData(mResult)
+// val uploadDataJson=Json.encodeToString(uploadData)
+// myTcpSvc.send2All(uploadDataJson)
+
+// //preview显示首个测点数据
+// if (mResult.sensorsData.size>0){
+// xView.doubleValue=mResult.sensorsData[0].xReal
+// yView.doubleValue=mResult.sensorsData[0].yReal
+// }
+
+ 0.0
+ })
+ }
+
+ LaunchedEffect(lensFacing) {
+ val cameraProvider = context.getCameraProvider()
+ cameraProvider.unbindAll()
+ cameraProvider.bindToLifecycle(lifecycleOwner, cameraxSelector, imageAnalyzer)
+ //注意实际运行的时候 注释preview
+ //preview.setSurfaceProvider(previewView.surfaceProvider)
+ }
+
+
+ Box(contentAlignment = Alignment.BottomCenter, modifier = Modifier.fillMaxSize()) {
+ //AndroidView({ previewView }, modifier = Modifier.fillMaxSize())
+ Column(
+ modifier = Modifier
+ .padding(horizontal = 20.dp)
+ .safeDrawingPadding(),
+ horizontalAlignment = Alignment.CenterHorizontally,
+
+ ) {
+
+ Text(
+ text = time2string(timeStampState.longValue),
+ color = Color.Green,
+ fontSize = 30.sp
+ )
+ Text(
+ text = "xReal= ${String.format(Locale.CHINA,"%.5f", xView.doubleValue)}\nyReal= ${String.format(Locale.CHINA,"%.5f", yView.doubleValue)}",
+ color = Color.Green,
+ fontSize = 30.sp
+ )
+ Image(
+ bitmap = yuMap.value.asImageBitmap(),
+ contentDescription = "图像区域截取",
+ Modifier.size(500.dp),
+ contentScale = ContentScale.Fit
+ )
+ Button(
+ onClick = {
+ //captureImage(imageCapture, context)
+ }
+ ) {
+ Text(text = "抓拍")
+ }
+
+ Spacer(Modifier.size(60.dp))
+ }
+ }
+}
+
+
+
+private fun captureImage(imageCapture: ImageCapture, context: Context) {
+ val tName= timeNow2string()
+ val dirName="光电"
+ val name = "${dirName}_${tName}.jpeg"
+ val contentValues = ContentValues().apply {
+ put(MediaStore.MediaColumns.DISPLAY_NAME, name)
+ put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
+ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
+ put(MediaStore.Images.Media.RELATIVE_PATH, "光电抓拍拍")
+ }
+ }
+ val outputOptions = ImageCapture.OutputFileOptions
+ .Builder(
+ context.contentResolver,
+ MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
+ contentValues
+ )
+ .build()
+ imageCapture.takePicture(
+ outputOptions,
+ ContextCompat.getMainExecutor(context),
+ object : ImageCapture.OnImageSavedCallback {
+ override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
+ Log.i("照片存储","Successes")
+ }
+
+ override fun onError(exception: ImageCaptureException) {
+ Log.i("照片存储","Failed $exception")
+ }
+
+ })
+}
+
+private suspend fun Context.getCameraProvider(): ProcessCameraProvider =
+ suspendCoroutine { continuation ->
+ ProcessCameraProvider.getInstance(this).also { cameraProvider ->
+ cameraProvider.addListener({
+ continuation.resume(cameraProvider.get())
+ }, ContextCompat.getMainExecutor(this))
+ }
+ }
+
+
+fun timeNow2string() :String{
+ val sf = SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS",Locale.CHINA)
+ return sf.format(System.currentTimeMillis())
+}
+
+private fun time2string(timeStamp:Long) :String{
+ val sf = SimpleDateFormat("yyyyMMdd_HHmmss.SSS",Locale.CHINA)
+ return sf.format(timeStamp)
+}
+
+
+
+private class GdndAnalyzer(private val listener: imageListener) : ImageAnalysis.Analyzer {
+
+ override fun analyze(image: ImageProxy) {
+
+ //图像处理
+ //Log.i("图像处理","处理图片帧")
+ listener(image)
+ image.close()
+ }
+}
+
+
+typealias imageListener = (img: ImageProxy) -> Double
+
diff --git a/MyOpenCv/app/src/main/java/com/example/myopencv/configLoad.kt b/MyOpenCv/app/src/main/java/com/example/myopencv/configLoad.kt
new file mode 100644
index 0000000..effd39a
--- /dev/null
+++ b/MyOpenCv/app/src/main/java/com/example/myopencv/configLoad.kt
@@ -0,0 +1,90 @@
+package com.example.myopencv
+
+import android.content.Context
+import android.content.SharedPreferences
+import com.example.myopencv.models.UserInfo
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.json.Json
+import kotlinx.serialization.encodeToString
+
+
+
+object SharedPrefs {
+ private const val TOKEN_PREF = "TOKEN_PREF"
+ private const val TOKEN_KEY = "TOKEN_KEY"
+
+ private fun getPreferences(context: Context): SharedPreferences {
+ return context.getSharedPreferences(TOKEN_PREF, Context.MODE_PRIVATE)
+ }
+
+ // 存储单个值
+ // 调用 : SharedPrefs.setToken(this@MyActivity, "123456")
+ fun setToken(context: Context, token: String) {
+ val editor = getPreferences(context).edit()
+ editor.putString(TOKEN_KEY, token)
+ editor.apply()
+ }
+
+ // 获取单个值
+ // 调用 : token = SharedPrefs.getToken(this@MyActivity)
+ fun getToken(context: Context?): String? {
+ return context?.let { getPreferences(it).getString(TOKEN_KEY, null) }
+ }
+
+ // 移除单个值
+ // 调用SharedPrefs.removeToken(this@MyActivity)
+ fun removeToken(context: Context?) {
+ context?.let { getPreferences(it).edit().remove(TOKEN_KEY).apply() }
+ }
+
+ // 存储userInfo对象
+ // 调用 : SharedPrefs.saveUserToPreferences(this@MyActivity, jsonElement)
+ fun saveUserToPreferences(context: Context, userinfo: UserInfo) {
+ val json = Json.encodeToString(userinfo)
+ val sharedPreferences = context.getSharedPreferences("UserPrefs", Context.MODE_PRIVATE)
+ val editor = sharedPreferences.edit()
+ editor.putString("userinfo", json)
+ editor.apply()
+ }
+
+ // 获取userInfo对象缓存
+ // 调用 : userInfo = SharedPrefs.loadUserFromPreferences(this@MyActivity) userId = userInfo .id
+ fun loadUserFromPreferences(context: Context): UserInfo {
+ val sharedPreferences = context.getSharedPreferences("UserPrefs", Context.MODE_PRIVATE)
+ val json = sharedPreferences.getString("userinfo", "")
+ val userInfo = Json.decodeFromString(json?:"")
+ return userInfo
+ }
+
+ // 更新userInfo对象某个字段
+ // 调用 : SharedPrefs.setUserInfo(this@MyActivity, "username", "alic")
+ fun setUserInfo(context: Context, editName: String, editValue: String) {
+ val sharedPreferences = context.getSharedPreferences("UserPrefs", Context.MODE_PRIVATE)
+ val json = sharedPreferences.getString("userinfo", "")
+ val myObject1 = Json.decodeFromString(json?:"")
+
+ val editor = sharedPreferences.edit()
+ if (editName == "username") {
+ myObject1.username = editValue
+ }else if (editName == "email") {
+ myObject1.email = editValue
+ }else if (editName == "sex") {
+ myObject1.sex = editValue
+ }
+
+ val myObject2 = Json.encodeToString(myObject1)
+ editor.putString("userinfo", myObject2)
+ println("更新后的个人信息 : $myObject2")
+ editor.apply()
+ }
+
+ // 清除所有缓存
+ // 调用 : SharedPrefs.clearAllData(this@MyActivity)
+ fun clearAllData(context: Context) {
+ val preferences = context.getSharedPreferences("UserPrefs", Context.MODE_PRIVATE)
+ val editor = preferences.edit()
+ removeToken(context)
+ editor.clear()
+ editor.apply()
+ }
+}
diff --git a/MyOpenCv/app/src/main/java/com/example/myopencv/dataProcess.kt b/MyOpenCv/app/src/main/java/com/example/myopencv/dataProcess.kt
new file mode 100644
index 0000000..1b54caf
--- /dev/null
+++ b/MyOpenCv/app/src/main/java/com/example/myopencv/dataProcess.kt
@@ -0,0 +1,277 @@
+package com.example.myopencv
+
+import com.example.myopencv.models.CentroidData
+import com.example.myopencv.models.SensorData
+import com.example.myopencv.models.ManSetting2
+import com.example.myopencv.models.Sensor
+import kotlinx.serialization.*
+
+
+@Serializable
+data class MResult(
+ var sensorsData: MutableList,
+ var timestamp:String
+)
+
+class Deflectometer {
+ var imageSendEnabled=true
+ var isClearZero=false
+ private var m_settings = ManSetting2()
+
+
+ var m_result = MResult(mutableListOf(),"")
+
+ fun dataProcess(data: CentroidData) :MResult {
+ // 从设置中获取零点计数,并确保其至少为1
+ var zeroCount = m_settings.baseParam.zeroCount
+ zeroCount = if (zeroCount <= 0) 1 else zeroCount
+ // 获取是否清除零点的标志
+ // 获取无效数据计数
+ val invalidDataCount = m_settings.baseParam.invalidDataCount
+ // 获取传感器数组
+ val t_sensors = m_settings.sensors
+
+ // 获取结果中的传感器数组
+ val sensorDataList = m_result.sensorsData
+ // 获取数据的时间戳
+ val timestamp = data.timestampStr
+ // 获取质心数组
+ val centroids = data.centroids
+
+ // 遍历质心数组
+ for (i in centroids.indices) {
+ val centroid = centroids[i]
+ val xCur = centroid.x
+ val yCur = centroid.y
+ if (i < sensorDataList.size && i < t_sensors.size) {
+ val sensorData = sensorDataList[i]
+ val t_sensor = t_sensors[i]
+ var invalidCount = sensorData.invalidCount
+ // 如果当前质心为(0,0)
+ if (xCur == 0.0 && yCur == 0.0) {
+ if (invalidCount < invalidDataCount) {
+ invalidCount++
+ }
+ } else {
+ if (invalidCount > 0) {
+ invalidCount--
+ } else {
+ sensorData.xCur = xCur
+ sensorData.yCur = yCur
+ var xAvg = sensorData.xAvg
+ var yAvg = sensorData.yAvg
+ // 计算平均值
+ xAvg = if (xAvg == 0.0) xCur else (xAvg * (zeroCount - 1) + xCur) / (zeroCount*1.0)
+ yAvg = if (yAvg == 0.0) yCur else (yAvg * (zeroCount - 1) + yCur) / (zeroCount*1.0)
+ sensorData.xAvg = xAvg
+ sensorData.yAvg = yAvg
+
+ // 如果需要清除零点
+ if (isClearZero) {
+ sensorData.xZero = xAvg
+ sensorData.yZero = yAvg
+ t_sensor.xZero = xAvg
+ t_sensor.yZero = yAvg
+ }
+
+ val xZero = sensorData.xZero
+ val yZero = sensorData.yZero
+ val xTemp = xCur - xZero
+ val yTemp = yCur - yZero
+ sensorData.xTemp = xTemp
+ sensorData.yTemp = yTemp
+ }
+ }
+ sensorData.invalidCount = invalidCount
+ sensorDataList[i] = sensorData
+ t_sensors[i] = t_sensor
+ }
+ }
+
+ m_settings.sensors=t_sensors
+ // 重置清除零点
+ if (isClearZero) {
+ isClearZero = false
+ }
+
+ var xBase = 0.0
+ var yBase = 0.0
+ // 查找基准传感器
+ for (i in sensorDataList.indices) {
+ val sensor = sensorDataList[i]
+ if (sensor.sensor.tar == "y") {
+ xBase = sensor.xTemp
+ yBase = sensor.yTemp
+ break
+ }
+ }
+
+ // 获取结果计数
+ var resultCount = m_settings.baseParam.resultCount
+ resultCount = if (resultCount <= 0) 1 else resultCount
+ // 遍历传感器数组进行计算
+ for (i in sensorDataList.indices) {
+ val sensor = sensorDataList[i]
+ val invalidCount = sensor.invalidCount
+ if (invalidCount > 0) {
+ if (invalidCount >= invalidDataCount) {
+ sensor.xReal = Double.NaN
+ sensor.yReal = Double.NaN
+ }
+ } else {
+ val arg = sensor.sensor.arg.toDouble()
+ val xTemp = sensor.xTemp
+ val yTemp = sensor.yTemp
+ val xReal = sensor.xReal
+ val yReal = sensor.yReal
+
+ // 计算实际值
+ val xVal = (xTemp - xBase) * arg
+ val yVal = (yTemp - yBase) * arg
+ val xAvg = if (sensor.xReal.isNaN()) xVal else ((resultCount - 1) * xReal + xVal) / resultCount
+ val yAvg = if (sensor.yReal.isNaN()) yVal else ((resultCount - 1) * yReal + yVal) / resultCount
+ sensor.xReal = xAvg
+ sensor.yReal = yAvg
+ }
+ sensorDataList[i] = sensor
+ }
+ m_result.sensorsData = sensorDataList
+ m_result.timestamp = timestamp
+ return m_result
+ }
+
+ fun readResult():MResult{
+ return m_result
+ }
+
+ fun defaultSet(configStr:String){
+ m_settings = ManSetting2(
+ sensors = mutableListOf()
+ )
+ if (configStr!="") {
+ m_settings = json.decodeFromString(configStr)
+ }else {
+ m_settings.sensors.add(
+ Sensor(
+ arg = "0.448",
+ des = "default",
+ pos = "1",
+ tar = "n",
+ x = "97",
+ y = "1054",
+ h = "425",
+ w = "569",
+ xZero = 0.0,
+ yZero = 0.0
+ )
+ )
+ }
+
+
+ defaultSensorsData()
+ }
+
+ private fun defaultSensorsData(){
+ m_result.sensorsData= mutableListOf()
+ m_settings.sensors.forEach {
+ val sd = SensorData(sensor = it)
+ sd.xZero=it.xZero
+ sd.yZero=it.yZero
+ m_result.sensorsData.add(sd)
+ }
+ }
+
+ fun readSensor():List{
+ return m_settings.sensors
+ }
+ fun updateSensor(sensorList: MutableList):ManSetting2{
+ //纪录之前Zero
+ for(i in 0 until sensorList.size){
+ m_settings.sensors.forEach {
+ if(it.pos==sensorList[i].pos){
+ sensorList[i].xZero=it.xZero
+ sensorList[i].yZero=it.yZero
+ }
+ }
+ }
+ m_settings.sensors=sensorList
+ defaultSensorsData()
+ return m_settings
+ }
+
+ fun updateThreshold(t:Int):ManSetting2{
+ m_settings.baseParam.threshold=t
+ return m_settings
+ }
+ fun readThreshold():Int{
+ return m_settings.baseParam.threshold
+ }
+
+ fun updateInvalidDataCount(t:Int):ManSetting2{
+ m_settings.baseParam.invalidDataCount=t
+ return m_settings
+ }
+ fun readInvalidDataCount():Int{
+ return m_settings.baseParam.invalidDataCount
+ }
+
+ fun updateImageSendTime(t:Int):ManSetting2{
+ m_settings.baseParam.imageSendTime=t
+ return m_settings
+ }
+ fun readImageSendTime():Int{
+ return m_settings.baseParam.imageSendTime
+ }
+
+ fun updateZeroCount(t:Int):ManSetting2{
+ m_settings.baseParam.zeroCount=t
+ return m_settings
+ }
+ fun readZeroCount():Int{
+ return m_settings.baseParam.zeroCount
+ }
+
+ fun updateResultCount(t:Int):ManSetting2{
+ m_settings.baseParam.resultCount=t
+ return m_settings
+ }
+ fun readResultCount():Int{
+ return m_settings.baseParam.resultCount
+ }
+
+ fun updateDataFps(t:Int):ManSetting2{
+ var interval=t
+ if (interval<=0){
+ interval=1
+ }
+ m_settings.baseParam.dataFPS=interval
+ return m_settings
+ }
+ fun readDataFps():Int{
+ return m_settings.baseParam.dataFPS
+ }
+
+ fun updateVideoFps(t:Int):ManSetting2{
+ m_settings.baseParam.videoFPS=t
+ return m_settings
+ }
+ fun readVideoFps():Int{
+ return m_settings.baseParam.videoFPS
+ }
+ fun updateClearZero(set: Boolean):ManSetting2 {
+ isClearZero=set
+
+ //更新配置
+ for (i in 0 until m_settings.sensors.size) {
+ val pos=m_settings.sensors[i].pos
+ m_result.sensorsData.forEach {
+ if (it.sensor.pos==pos){
+ m_settings.sensors[i].xZero=it.xAvg
+ m_settings.sensors[i].yZero=it.yAvg
+ }
+ }
+ }
+ return m_settings
+ }
+
+}
\ No newline at end of file
diff --git a/MyOpenCv/app/src/main/java/com/example/myopencv/dataTrans.kt b/MyOpenCv/app/src/main/java/com/example/myopencv/dataTrans.kt
new file mode 100644
index 0000000..654963a
--- /dev/null
+++ b/MyOpenCv/app/src/main/java/com/example/myopencv/dataTrans.kt
@@ -0,0 +1,286 @@
+package com.example.myopencv
+
+import android.content.Context
+import com.example.myopencv.models.UData
+import com.example.myopencv.models.USensor
+import com.example.myopencv.models.URealValue
+import java.io.ByteArrayOutputStream
+import android.graphics.Bitmap
+import android.util.Base64
+import com.example.myopencv.models.Command
+import com.example.myopencv.models.ManSetting2
+import com.example.myopencv.models.Sensor
+import kotlinx.serialization.encodeToString
+import kotlinx.serialization.json.Json
+import kotlinx.serialization.json.JsonArray
+import kotlinx.serialization.json.JsonNull
+import kotlinx.serialization.json.JsonObject
+import kotlinx.serialization.json.boolean
+import kotlinx.serialization.json.int
+import kotlinx.serialization.json.jsonArray
+import kotlinx.serialization.json.jsonObject
+import kotlinx.serialization.json.jsonPrimitive
+
+fun result2uData(r:MResult):UData{
+
+ val uValue=URealValue(
+ timestamp = r.timestamp,
+ sensors = mutableListOf()
+ )
+ r.sensorsData.forEach {
+ uValue.sensors.add(
+ USensor(
+ arg = it.sensor.arg,
+ des = it.sensor.des,
+ pos = it.sensor.pos,
+ tar = it.sensor.tar,
+ xReal = if (it.xReal.isNaN()) null else it.xReal,
+ yReal = if (it.yReal.isNaN()) null else it.yReal,
+ )
+ )
+
+
+ }
+
+ return UData(
+ command = "result",
+ type = "reply",
+ values = uValue
+ )
+
+}
+
+
+
+
+fun bitmapToBase64(bitmap: Bitmap): String {
+ // 创建一个ByteArrayOutputStream
+ val byteArrayOutputStream = ByteArrayOutputStream()
+
+ // 将Bitmap压缩为PNG格式并写入到ByteArrayOutputStream
+ bitmap.compress(Bitmap.CompressFormat.JPEG, 90, byteArrayOutputStream)
+
+ // 将压缩后的数据转换为字节数组
+ val bytes = byteArrayOutputStream.toByteArray()
+
+ // 使用Base64进行编码
+ // 这里的 Base64.NO_WRAP 参数表示不将编码结果分割为多行
+ val base64Image = Base64.encodeToString(bytes,Base64.NO_WRAP)
+
+ // 关闭ByteArrayOutputStream
+ byteArrayOutputStream.close()
+
+ // 返回Base64编码的字符串
+ return base64Image
+}
+
+
+
+fun decodeCmd(cmdStr:String,ctx:Context):String{
+ val command = json.decodeFromString(cmdStr)
+
+
+ var reply=""
+
+ when(command.command) {
+ "sensors" -> {
+ when (command.type) {
+ //传感器信息获取
+ "get" -> {
+ val s=Json.encodeToString(deflectometer.readSensor())
+ val replyCommand=Command(
+ command = command.command,
+ type = command.type,
+ values = Json.parseToJsonElement(s)
+ )
+ reply = Json.encodeToString(replyCommand)
+ }
+
+ "set" -> {
+ val sensorSetStr = command.values.jsonArray.toString()
+ val sensors = json.decodeFromString>(sensorSetStr)
+ val mSet = deflectometer.updateSensor(sensors)
+ val mSetStr=json.encodeToString(mSet)
+ fileUtils.saveFile(ctx,"settings.json",mSetStr)
+ reply = """{"command":"sensors","type":"set","values":"ok"}"""
+ }
+ }
+ }
+
+ "imageSendEnabled" ->{
+ when (command.type) {
+ //信息获取
+ "set" -> {
+ val imageSendEnabled = command.values.jsonPrimitive.boolean
+ deflectometer.imageSendEnabled=imageSendEnabled
+ reply = """{"command":"imageSendEnabled","type":"set","values":"ok"}"""
+ }
+ }
+ }
+
+ "isClearZero" ->{
+ when (command.type) {
+ //信息获取
+ "set" -> {
+ val isClearZero=command.values.jsonPrimitive.boolean
+ val mSet=deflectometer.updateClearZero(isClearZero)
+ val mSetStr=json.encodeToString(mSet)
+ fileUtils.saveFile(ctx,"settings.json",mSetStr)
+ reply = """{"command":"isClearZero","type":"set","values":"ok"}"""
+ }
+ }
+ }
+
+ "threshold" ->{
+ when (command.type) {
+ "set" -> {
+ val threshold=command.values.jsonPrimitive.int
+ val mSet=deflectometer.updateThreshold(threshold)
+ val mSetStr=json.encodeToString(mSet)
+ fileUtils.saveFile(ctx,"settings.json",mSetStr)
+ reply = """{"command":"isClearZero","type":"set","values":"ok"}"""
+ }
+ "get" -> {
+ val t=deflectometer.readThreshold()
+ reply = """{"command":"threshold","type":"get","values":${t}}"""
+ }
+ }
+ }
+
+ "invalidDataCount" ->{
+ when (command.type) {
+ "set" -> {
+ val invalidDataCount=command.values.jsonPrimitive.int
+ val mSet=deflectometer.updateInvalidDataCount(invalidDataCount)
+ val mSetStr=json.encodeToString(mSet)
+ fileUtils.saveFile(ctx,"settings.json",mSetStr)
+ reply = """{"command":"invalidDataCount","type":"set","values":"ok"}"""
+ }
+ "get" -> {
+ val t=deflectometer.readInvalidDataCount()
+ reply = """{"command":"invalidDataCount","type":"get","values":${t}}"""
+ }
+ }
+ }
+
+ "imageSendTime" ->{
+ when (command.type) {
+ "set" -> {
+ val imageSendTime=command.values.jsonPrimitive.int
+ val mSet=deflectometer.updateImageSendTime(imageSendTime)
+ val mSetStr=json.encodeToString(mSet)
+ fileUtils.saveFile(ctx,"settings.json",mSetStr)
+ reply = """{"command":"imageSendTime","type":"set","values":"ok"}"""
+ }
+ "get" -> {
+ val t=deflectometer.readImageSendTime()
+ reply = """{"command":"imageSendTime","type":"get","values":${t}}"""
+ }
+ }
+ }
+
+ "zeroCount" ->{
+ when (command.type) {
+ "set" -> {
+ val imageSendTime=command.values.jsonPrimitive.int
+ val mSet=deflectometer.updateZeroCount(imageSendTime)
+ val mSetStr=json.encodeToString(mSet)
+ fileUtils.saveFile(ctx,"settings.json",mSetStr)
+ reply = """{"command":"zeroCount","type":"set","values":"ok"}"""
+ }
+ "get" -> {
+ val t=deflectometer.readZeroCount()
+ reply = """{"command":"zeroCount","type":"get","values":${t}}"""
+ }
+ }
+ }
+
+ "resultCount" ->{
+ when (command.type) {
+ "set" -> {
+ val resultCount=command.values.jsonPrimitive.int
+ val mSet=deflectometer.updateResultCount(resultCount)
+ val mSetStr=json.encodeToString(mSet)
+ fileUtils.saveFile(ctx,"settings.json",mSetStr)
+ reply = """{"command":"resultCount","type":"set","values":"ok"}"""
+ }
+ "get" -> {
+ val t=deflectometer.readResultCount()
+ reply = """{"command":"resultCount","type":"get","values":${t}}"""
+ }
+ }
+ }
+
+ "dataFps" ->{
+ when (command.type) {
+ "set" -> {
+ val dataFps=command.values.jsonPrimitive.int
+ val mSet=deflectometer.updateDataFps(dataFps)
+ val mSetStr=json.encodeToString(mSet)
+ fileUtils.saveFile(ctx,"settings.json",mSetStr)
+ reply = """{"command":"dataFps","type":"set","values":"ok"}"""
+ }
+ "get" -> {
+ val t=deflectometer.readDataFps()
+ reply = """{"command":"dataFps","type":"get","values":${t}}"""
+ }
+ }
+ }
+
+ "videoFps" ->{
+ when (command.type) {
+ "set" -> {
+ val videoFps=command.values.jsonPrimitive.int
+ val mSet=deflectometer.updateVideoFps(videoFps)
+ val mSetStr=json.encodeToString(mSet)
+ fileUtils.saveFile(ctx,"settings.json",mSetStr)
+ reply = """{"command":"videoFps","type":"set","values":"ok"}"""
+ }
+ "get" -> {
+ val t=deflectometer.readVideoFps()
+ reply = """{"command":"videoFps","type":"get","values":${t}}"""
+ }
+ }
+ }
+
+ "name" ->{
+ when (command.type) {
+ "get" -> {
+ val ip= getIP4Address()
+ reply = """{"command":"name","type":"reply","values":"$ip"}"""
+ }
+ }
+ }
+ }
+
+
+ return reply
+}
+
+
+fun testParseValue(cmdStr:String){
+ val command = json.decodeFromString(cmdStr)
+
+ // 检查values字段的类型并处理
+ when (command.values) {
+ is JsonArray -> {
+ // 处理数组
+ command.values.jsonArray.forEach { element ->
+ val pointsStr=element.toString()
+ println(pointsStr)
+ }
+ }
+ is JsonObject -> {
+ // 处理对象
+ command.values.jsonObject.keys.forEach { key ->
+ println("Key: $key, Value: ${command.values.jsonObject[key]}")
+ }
+ }
+ is JsonNull -> {
+ println("null")
+ }
+ else ->{
+ println("其他类型")
+ }
+ }
+}
\ No newline at end of file
diff --git a/MyOpenCv/app/src/main/java/com/example/myopencv/fileUtils.kt b/MyOpenCv/app/src/main/java/com/example/myopencv/fileUtils.kt
new file mode 100644
index 0000000..7ecf020
--- /dev/null
+++ b/MyOpenCv/app/src/main/java/com/example/myopencv/fileUtils.kt
@@ -0,0 +1,43 @@
+package com.example.myopencv
+
+import android.content.Context
+import android.util.Log
+import java.io.BufferedReader
+import java.io.BufferedWriter
+import java.io.InputStreamReader
+import java.io.OutputStreamWriter
+
+object fileUtils {
+ /*保存文件*/
+ fun saveFile(context: Context, fileName: String, cont: String) {
+ try {
+ //第一个参数是文件名
+ //第二个参数是文件的操作模式(相同文件MODE_PRIVATE覆盖,MODE_APPEND追加内容)
+ val output = context.openFileOutput(fileName, Context.MODE_PRIVATE)
+ val writer = BufferedWriter(OutputStreamWriter(output))
+ writer.use {
+ it.write(cont)
+ }
+ } catch (e: Exception) {
+ Log.e("配置settings.json", "存储异常 ${e.message}")
+ }
+ }
+
+ /*读取文件*/
+ fun readerFile(context: Context, fileName: String): String {
+ val content = StringBuffer()
+ try {
+ val input = context.openFileInput(fileName)
+ val reader = BufferedReader(InputStreamReader(input))
+ reader.use {
+ reader.forEachLine {
+ content.append(it)
+ }
+ }
+ } catch (e: Exception) {
+ Log.i("配置settings.json", "读取异常 ${e.message}")
+ }
+ return content.toString()
+ }
+}
+
diff --git a/MyOpenCv/app/src/main/java/com/example/myopencv/models/centroidData.kt b/MyOpenCv/app/src/main/java/com/example/myopencv/models/centroidData.kt
new file mode 100644
index 0000000..4969c5f
--- /dev/null
+++ b/MyOpenCv/app/src/main/java/com/example/myopencv/models/centroidData.kt
@@ -0,0 +1,19 @@
+package com.example.myopencv.models
+
+import kotlinx.serialization.Serializable
+
+
+@Serializable
+data class CentroidPoint(
+ val x: Double,
+ val y: Double
+)
+
+@Serializable
+data class CentroidData(
+ val timestampStr: String,
+ val centroids: MutableList
+)
+
+
+
diff --git a/MyOpenCv/app/src/main/java/com/example/myopencv/models/command.kt b/MyOpenCv/app/src/main/java/com/example/myopencv/models/command.kt
new file mode 100644
index 0000000..7b159e8
--- /dev/null
+++ b/MyOpenCv/app/src/main/java/com/example/myopencv/models/command.kt
@@ -0,0 +1,15 @@
+package com.example.myopencv.models
+
+import kotlinx.serialization.*
+import kotlinx.serialization.descriptors.*
+import kotlinx.serialization.encoding.*
+import kotlinx.serialization.json.Json
+import kotlinx.serialization.json.JsonElement
+
+@Serializable
+data class Command(
+ val command: String,
+ val type: String,
+
+ val values: JsonElement= Json.parseToJsonElement("0")
+)
diff --git a/MyOpenCv/app/src/main/java/com/example/myopencv/models/mSetting.kt b/MyOpenCv/app/src/main/java/com/example/myopencv/models/mSetting.kt
new file mode 100644
index 0000000..cac6be3
--- /dev/null
+++ b/MyOpenCv/app/src/main/java/com/example/myopencv/models/mSetting.kt
@@ -0,0 +1,39 @@
+package com.example.myopencv.models
+
+import kotlinx.serialization.Serializable
+
+
+@Serializable
+data class ManSetting (
+ var dataFPS: Int=1,
+ var imageSendEnabled: Boolean=false,
+ var imageSendTime: Int=1000,
+ var invalidDataCount: Int=1,
+ var isClearZero: Boolean=false,
+ var resultCount: Int=10,
+ var sensors: MutableList =mutableListOf(),
+ var threshold: Int=128,
+ var videoFPS: Int=10,
+ var watchValues: String="pos, des, arg, tar, xReal, yReal",
+ var zeroCount: Int=30
+)
+
+@Serializable
+data class ManSetting2 (
+ var baseParam:BaseParam=BaseParam(),
+ var sensors: MutableList =mutableListOf()
+)
+
+@Serializable
+data class BaseParam (
+ var dataFPS: Int=1,
+ var imageSendEnabled: Boolean=false,
+ var imageSendTime: Int=1000,
+ var invalidDataCount: Int=1,
+ var isClearZero: Boolean=false,
+ var resultCount: Int=10,
+ var threshold: Int=128,
+ var videoFPS: Int=10,
+ var zeroCount: Int=1,
+ private var watchValues: String="pos, des, arg, tar, xReal, yReal",
+)
diff --git a/MyOpenCv/app/src/main/java/com/example/myopencv/models/sensor.kt b/MyOpenCv/app/src/main/java/com/example/myopencv/models/sensor.kt
new file mode 100644
index 0000000..960bbd0
--- /dev/null
+++ b/MyOpenCv/app/src/main/java/com/example/myopencv/models/sensor.kt
@@ -0,0 +1,17 @@
+package com.example.myopencv.models
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class Sensor (
+ var arg: String,
+ var des: String,
+ var pos: String,
+ var tar: String,
+ var x: String,
+ var y: String,
+ var h: String,
+ var w: String,
+ var xZero: Double = 0.0,
+ var yZero: Double = 0.0,
+)
\ No newline at end of file
diff --git a/MyOpenCv/app/src/main/java/com/example/myopencv/models/sensorData.kt b/MyOpenCv/app/src/main/java/com/example/myopencv/models/sensorData.kt
new file mode 100644
index 0000000..2e38aaa
--- /dev/null
+++ b/MyOpenCv/app/src/main/java/com/example/myopencv/models/sensorData.kt
@@ -0,0 +1,19 @@
+package com.example.myopencv.models
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class SensorData(
+ var xCur: Double = 0.0,
+ var yCur: Double = 0.0,
+ var xAvg: Double = 0.0,
+ var yAvg: Double = 0.0,
+ var xZero: Double = 0.0,
+ var yZero: Double = 0.0,
+ var xTemp: Double = 0.0,
+ var yTemp: Double = 0.0,
+ var xReal: Double = Double.NaN,
+ var yReal: Double = Double.NaN,
+ var sensor: Sensor,
+ var invalidCount: Int = 0,
+)
\ No newline at end of file
diff --git a/MyOpenCv/app/src/main/java/com/example/myopencv/models/uploadData.kt b/MyOpenCv/app/src/main/java/com/example/myopencv/models/uploadData.kt
new file mode 100644
index 0000000..229bd25
--- /dev/null
+++ b/MyOpenCv/app/src/main/java/com/example/myopencv/models/uploadData.kt
@@ -0,0 +1,40 @@
+package com.example.myopencv.models
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class USensor (
+ var arg: String,
+ var des: String,
+ var pos: String,
+ var tar: String,
+ var xReal: Double?,
+ var yReal: Double?,
+)
+
+@Serializable
+data class URealValue(
+ val sensors: MutableList,
+ val timestamp: String
+)
+
+@Serializable
+data class UData(
+ val command: String,
+ val type: String,
+ val values: URealValue
+)
+
+
+@Serializable
+data class UImage(
+ val command: String,
+ val type: String,
+ val values: ImageInfo
+)
+
+@Serializable
+data class ImageInfo(
+ val image: String,
+ val timestamp: String
+)
diff --git a/MyOpenCv/app/src/main/java/com/example/myopencv/models/userInfo.kt b/MyOpenCv/app/src/main/java/com/example/myopencv/models/userInfo.kt
new file mode 100644
index 0000000..448a5c7
--- /dev/null
+++ b/MyOpenCv/app/src/main/java/com/example/myopencv/models/userInfo.kt
@@ -0,0 +1,12 @@
+package com.example.myopencv.models
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class UserInfo(
+ val id: Int,
+ var username: String,
+ var email: String,
+ var sex: String,
+)
+
diff --git a/MyOpenCv/app/src/main/java/com/example/myopencv/tcpServer.kt b/MyOpenCv/app/src/main/java/com/example/myopencv/tcpServer.kt
new file mode 100644
index 0000000..c6b460c
--- /dev/null
+++ b/MyOpenCv/app/src/main/java/com/example/myopencv/tcpServer.kt
@@ -0,0 +1,224 @@
+package com.example.myopencv
+
+import android.app.Service
+import android.content.Intent
+import android.graphics.Bitmap
+import android.os.Binder
+import android.os.IBinder
+import android.util.Log
+import com.example.myopencv.models.ImageInfo
+import com.example.myopencv.models.UData
+import com.example.myopencv.models.UImage
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+import kotlinx.serialization.encodeToString
+import kotlinx.serialization.json.Json
+import java.io.BufferedReader
+import java.io.BufferedWriter
+import java.io.InputStreamReader
+import java.io.OutputStreamWriter
+import java.io.PrintWriter
+import java.net.NetworkInterface
+import java.net.ServerSocket
+import java.net.Socket
+import java.util.regex.Pattern
+import kotlin.math.log
+
+
+class MyTcpServer:Service(){
+ private val coroutineScope = CoroutineScope(Dispatchers.IO)
+ // 内部Binder类
+ inner class LocalBinder : Binder() {
+ // 返回TcpService的实例
+ fun getService(): MyTcpServer = this@MyTcpServer
+ }
+ private val binder = LocalBinder()
+ override fun onBind(intent: Intent?): IBinder {
+ println("==onBind")
+ return binder
+ }
+ override fun onCreate() {
+ super.onCreate()
+ val ip= getIP4Address()
+ println(ip)
+ Thread(runnable).start()
+
+ dataTask()
+ imageTask()
+ heartTask()
+ }
+ override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
+ Log.d("data","-> onStartCommand")
+ return super.onStartCommand(intent, flags, startId)
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ serverAllowed = false
+ Log.d("data","-> onDestroy")
+ }
+
+ private var clientMaps= mutableMapOf()
+ private var serverAllowed=true
+ private var runnable= kotlinx.coroutines.Runnable {
+ val serverSocket=ServerSocket(9999)
+ while (true) {
+ val accept: Socket = serverSocket.accept()
+ val acceptId=accept.remoteSocketAddress.toString()
+ clientMaps[acceptId] = accept
+ Thread { response(accept) }.start()
+ }
+ }
+
+ private fun response(accept: Socket) {
+ val acceptId=accept.remoteSocketAddress.toString()
+ //从客户端接收的信息
+ val bufferedReaderIn: BufferedReader = BufferedReader(InputStreamReader(accept.getInputStream()))
+ //发送信息给客户端
+ val out: PrintWriter = PrintWriter(BufferedWriter(OutputStreamWriter(accept.getOutputStream())),true)
+ try {
+
+ while (serverAllowed){
+ //0xOA换行为一次读取
+ val msg = bufferedReaderIn.readLine()
+ Log.i("tcp", "收到客户端[${accept.remoteSocketAddress}]的信息: $msg")
+
+ if (msg.length<=1){
+ continue
+ }
+ val reply = decodeCmd(msg,this)
+ if (reply.isNotEmpty()){
+ send2All(reply)
+ }
+
+ }
+
+ }catch (e:Exception){
+ println("异常:${e.message}")
+ println("异常-离线:$acceptId")
+ }finally {
+ println("关闭服务:$acceptId")
+ bufferedReaderIn.close()
+ out.close()
+ accept.close()
+ clientMaps.remove(acceptId)
+ println("剩余客户端数量:${clientMaps.size}")
+ }
+
+ }
+
+
+ private fun send2All(msg:String){
+ val nMsg=msg+"\n"
+ clientMaps.forEach{
+ try {
+ val out: PrintWriter = PrintWriter(
+ BufferedWriter(OutputStreamWriter(it.value.getOutputStream()))
+ ,true)
+ out.println(nMsg);
+ }catch (e:Exception){
+ Log.i("数据上报","发送异常:${e.message}")
+ }
+
+ }
+ }
+
+ private fun sendData2All(r: MResult) {
+ //多次发送 更新时间戳
+ r.timestamp=timeNow2string()
+ val uploadData = result2uData(r)
+ if (uploadData.values.sensors.size==0){
+ return
+ }
+ val uploadDataJson = Json.encodeToString(uploadData)
+ send2All(uploadDataJson)
+ }
+
+ private fun sendImage2All(){
+
+ imageBitmapList.forEach {
+ val base64=bitmapToBase64(it)
+ val imgInfo= ImageInfo(base64,timeNow2string())
+ val uploadImage=UImage("image","reply",imgInfo)
+ val imageBase64= Json.encodeToString(uploadImage)
+ send2All(imageBase64)
+ }
+
+ }
+ //缓存图像
+ private var imageBitmapList= mutableListOf()
+ fun cacheImage(bitmap: Bitmap) {
+ if (imageBitmapList.size>0){
+ imageBitmapList[0]=bitmap
+ }else{
+ imageBitmapList.add(bitmap)
+ }
+ }
+
+
+ private fun imageTask(){
+ coroutineScope.launch {
+ while (true) {
+ delay(deflectometer.readImageSendTime().toLong())
+ if(deflectometer.imageSendEnabled) {
+ sendImage2All()
+ }
+ }
+ }
+ }
+
+ private fun dataTask(){
+ coroutineScope.launch {
+ while (true) {
+ val interval=deflectometer.readDataFps().toLong()
+ delay(1000/interval)
+ sendData2All(deflectometer.readResult())
+ }
+ }
+ }
+
+ private fun heartTask(){
+ coroutineScope.launch {
+ while (true) {
+ delay(10000L)
+ val heart="""{"command":"heartbeat","type":"reply","values":0}"""
+ send2All(heart)
+ }
+ }
+ }
+
+
+
+}
+
+fun getIP4Address(): String? {
+ try {
+ val en = NetworkInterface.getNetworkInterfaces()
+ while (en.hasMoreElements()) {
+ val intf = en.nextElement()
+ val enumIpAddr = intf.inetAddresses
+ while (enumIpAddr.hasMoreElements()) {
+ val inetAddress = enumIpAddr.nextElement()
+ if (!inetAddress.isLoopbackAddress && isIPv4(inetAddress.hostAddress)) {
+ return inetAddress.hostAddress
+ }
+ }
+ }
+ } catch (ex: java.net.SocketException) {
+ ex.printStackTrace()
+ }
+ return null
+}
+fun isIPv4(ip: String?): Boolean {
+ val pattern = Pattern.compile("^(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)$")
+ return pattern.matcher(ip?:"").matches()
+}
+
+val json = Json { ignoreUnknownKeys = true } // 允许JSON中存在未知键
+
+
+
+
diff --git a/MyOpenCv/app/src/main/java/com/example/myopencv/ui/theme/Color.kt b/MyOpenCv/app/src/main/java/com/example/myopencv/ui/theme/Color.kt
new file mode 100644
index 0000000..a2bf41e
--- /dev/null
+++ b/MyOpenCv/app/src/main/java/com/example/myopencv/ui/theme/Color.kt
@@ -0,0 +1,11 @@
+package com.example.myopencv.ui.theme
+
+import androidx.compose.ui.graphics.Color
+
+val Purple80 = Color(0xFFD0BCFF)
+val PurpleGrey80 = Color(0xFFCCC2DC)
+val Pink80 = Color(0xFFEFB8C8)
+
+val Purple40 = Color(0xFF6650a4)
+val PurpleGrey40 = Color(0xFF625b71)
+val Pink40 = Color(0xFF7D5260)
\ No newline at end of file
diff --git a/MyOpenCv/app/src/main/java/com/example/myopencv/ui/theme/Theme.kt b/MyOpenCv/app/src/main/java/com/example/myopencv/ui/theme/Theme.kt
new file mode 100644
index 0000000..c434a90
--- /dev/null
+++ b/MyOpenCv/app/src/main/java/com/example/myopencv/ui/theme/Theme.kt
@@ -0,0 +1,58 @@
+package com.example.myopencv.ui.theme
+
+import android.app.Activity
+import android.os.Build
+import androidx.compose.foundation.isSystemInDarkTheme
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.darkColorScheme
+import androidx.compose.material3.dynamicDarkColorScheme
+import androidx.compose.material3.dynamicLightColorScheme
+import androidx.compose.material3.lightColorScheme
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.platform.LocalContext
+
+private val DarkColorScheme = darkColorScheme(
+ primary = Purple80,
+ secondary = PurpleGrey80,
+ tertiary = Pink80
+)
+
+private val LightColorScheme = lightColorScheme(
+ primary = Purple40,
+ secondary = PurpleGrey40,
+ tertiary = Pink40
+
+ /* Other default colors to override
+ background = Color(0xFFFFFBFE),
+ surface = Color(0xFFFFFBFE),
+ onPrimary = Color.White,
+ onSecondary = Color.White,
+ onTertiary = Color.White,
+ onBackground = Color(0xFF1C1B1F),
+ onSurface = Color(0xFF1C1B1F),
+ */
+)
+
+@Composable
+fun MyOpenCvTheme(
+ darkTheme: Boolean = isSystemInDarkTheme(),
+ // Dynamic color is available on Android 12+
+ dynamicColor: Boolean = true,
+ content: @Composable () -> Unit
+) {
+ val colorScheme = when {
+ dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
+ val context = LocalContext.current
+ if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
+ }
+
+ darkTheme -> DarkColorScheme
+ else -> LightColorScheme
+ }
+
+ MaterialTheme(
+ colorScheme = colorScheme,
+ typography = Typography,
+ content = content
+ )
+}
\ No newline at end of file
diff --git a/MyOpenCv/app/src/main/java/com/example/myopencv/ui/theme/Type.kt b/MyOpenCv/app/src/main/java/com/example/myopencv/ui/theme/Type.kt
new file mode 100644
index 0000000..2119875
--- /dev/null
+++ b/MyOpenCv/app/src/main/java/com/example/myopencv/ui/theme/Type.kt
@@ -0,0 +1,34 @@
+package com.example.myopencv.ui.theme
+
+import androidx.compose.material3.Typography
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.font.FontFamily
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.sp
+
+// Set of Material typography styles to start with
+val Typography = Typography(
+ bodyLarge = TextStyle(
+ fontFamily = FontFamily.Default,
+ fontWeight = FontWeight.Normal,
+ fontSize = 16.sp,
+ lineHeight = 24.sp,
+ letterSpacing = 0.5.sp
+ )
+ /* Other default text styles to override
+ titleLarge = TextStyle(
+ fontFamily = FontFamily.Default,
+ fontWeight = FontWeight.Normal,
+ fontSize = 22.sp,
+ lineHeight = 28.sp,
+ letterSpacing = 0.sp
+ ),
+ labelSmall = TextStyle(
+ fontFamily = FontFamily.Default,
+ fontWeight = FontWeight.Medium,
+ fontSize = 11.sp,
+ lineHeight = 16.sp,
+ letterSpacing = 0.5.sp
+ )
+ */
+)
\ No newline at end of file
diff --git a/MyOpenCv/app/src/main/java/imageHandler.kt b/MyOpenCv/app/src/main/java/imageHandler.kt
new file mode 100644
index 0000000..c33afc0
--- /dev/null
+++ b/MyOpenCv/app/src/main/java/imageHandler.kt
@@ -0,0 +1,181 @@
+import android.graphics.Bitmap
+import android.graphics.Color
+import android.graphics.Matrix
+import androidx.camera.core.ImageProxy
+import com.example.myopencv.imageHandler
+import com.example.myopencv.models.CentroidPoint
+import org.opencv.android.Utils
+import org.opencv.core.CvType
+import org.opencv.core.Mat
+import org.opencv.core.Point
+import org.opencv.core.Rect
+import org.opencv.core.Scalar
+import org.opencv.imgproc.Imgproc
+
+class ImageHandler {
+
+
+ fun mat2bitMap(mat: Mat): Bitmap {
+ val bitmap = Bitmap.createBitmap(mat.width(), mat.height(), Bitmap.Config.RGB_565)
+ Utils.matToBitmap(mat, bitmap)
+ return bitmap
+ }
+
+
+ fun mat2gary(mat: Mat): Mat {
+ //灰度
+ val garyMat = Mat(mat.width(), mat.height(), CvType.CV_8UC3)
+ Imgproc.cvtColor(mat, garyMat, Imgproc.COLOR_RGB2GRAY)
+
+ return garyMat
+ }
+
+ //图片二值化
+ fun binaryMat(thresholdValue: Double, mat: Mat): Mat {
+ // 设置二值化的最大值
+ val maxValue = 255.0
+ val binaryMat = Mat(mat.width(), mat.height(), CvType.CV_8UC3)
+ // 进行二值化操作
+ Imgproc.threshold(mat, binaryMat, thresholdValue, maxValue, Imgproc.THRESH_BINARY)
+ return binaryMat
+ }
+
+ fun binaryBitMap(thresholdValue: Double, mat: Mat): Bitmap {
+ // 设置二值化的最大值
+ val binaryMat = binaryMat(thresholdValue, mat)
+ val bitmap = mat2bitMap(binaryMat)
+ return bitmap
+ }
+
+ //图片加文字
+ fun tagText2mat(content: String, mat: Mat): Bitmap {
+ val point1 = Point(100.0, 100.0)
+ val point2 = Point(300.0, 300.0)
+ val color = Scalar(0.0, 0.0, 255.0)
+ Imgproc.line(mat, point1, point2, color, 5)
+ Imgproc.putText(mat, content, point1, 1, 10.0, color, 5)
+ val bitmap = Bitmap.createBitmap(mat.width(), mat.height(), Bitmap.Config.RGB_565)
+ Utils.matToBitmap(mat, bitmap)
+ return bitmap
+ }
+
+ //裁剪图片指定区域
+ fun cropMat(mat: Mat,x: Int, y: Int, width: Int, height: Int): Mat {
+ val subMat: Mat = Mat(mat, Rect(x, y, width, height))
+
+ return subMat
+ }
+
+ //裁剪图片指定区域 并生成点位图
+ fun cropMat2bitMap(x: Int, y: Int, width: Int, height: Int, mat: Mat): Bitmap {
+ val subMat: Mat = Mat(mat, Rect(x, y, width, height))
+ val bitmap = Bitmap.createBitmap(subMat.width(), subMat.height(), Bitmap.Config.RGB_565)
+ Utils.matToBitmap(subMat, bitmap)
+ return bitmap
+ }
+
+ //计算质量心
+ fun calcMoments(binary: Mat): Point {
+ var center = Point(0.0, 0.0)
+ val moments = Imgproc.moments(binary)
+ val area = moments.m00
+ // 如果面积为0,则质心不存在
+ if (area != 0.0) {
+ val cx = moments.m10 / area
+ val cy = moments.m01 / area
+ center = Point(cx.toDouble(), cy.toDouble())
+
+ //println("质心: (${center.x}, ${center.y})")
+
+ } else {
+ println("质心不存在")
+ }
+ return center
+ }
+
+ fun rotateBitmap(original: Bitmap, degrees: Float): Bitmap {
+ // 创建一个新的Bitmap对象,具有与原始Bitmap相同的配置
+ val rotated = Bitmap.createBitmap(
+ original, 0, 0, original.width, original.height, null, false
+ )
+
+ // 创建Matrix对象
+ val matrix = Matrix()
+
+ // 设置旋转角度和旋转中心
+ matrix.postRotate(degrees, (original.width/2).toFloat(), (original.height/2).toFloat())
+ // 创建一个新的Canvas对象,并使用Matrix进行变换
+ val canvas = android.graphics.Canvas(rotated)
+ canvas.drawBitmap(original, matrix, null)
+
+ // 返回旋转后的Bitmap
+ return rotated
+ }
+
+ fun img2Moments(image: ImageProxy,threshold: Int,x: Int,y: Int,w: Int,h: Int):CentroidPoint{
+ val bitImg=image.toBitmap()
+ val rawMat=Mat(bitImg.width, bitImg.height, CvType.CV_8UC3)
+ Utils.bitmapToMat(bitImg,rawMat)
+ val subMat= imageHandler.cropMat(rawMat,x,y,w,h)
+ //灰度
+ val garyMat =imageHandler.mat2gary(subMat)
+
+ //二值化
+ val binaryMat=imageHandler.binaryMat(threshold.toDouble(),garyMat)
+ val center=imageHandler.calcMoments(binaryMat)
+ return CentroidPoint(center.x,center.y)
+ }
+
+ fun bitMap2Gray(bitImg: Bitmap):Bitmap{
+ val rawMat=Mat(bitImg.width, bitImg.height, CvType.CV_8UC3)
+ Utils.bitmapToMat(bitImg,rawMat)
+ //灰度
+ val garyMat =imageHandler.mat2gary(rawMat)
+ Utils.matToBitmap(garyMat,bitImg)
+ return bitImg
+ }
+
+ //外包的计算方法
+ fun getBinImageCentroid(image: Bitmap, threshold: Int, viewport: android.graphics.Rect): CentroidPoint {
+ val rect = android.graphics.Rect(0, 0, image.width, image.height)
+ val left = Math.max(viewport.left, rect.left)
+ val right = Math.min(viewport.right, rect.right)
+ val top = Math.max(viewport.top, rect.top)
+ val bottom = Math.min(viewport.bottom, rect.bottom)
+
+ var sumA = 0L
+ var sumX = 0L
+ var sumY = 0L
+ for (y in top until bottom) {
+ for (x in left until right) {
+ val pixel = image.getPixel(x, y)
+ val r = Color.red(pixel)
+ val g = Color.green(pixel)
+ val b = Color.blue(pixel)
+ val gary = qGary(r, g, b)
+ if (gary >= threshold) {
+ val v=255
+ sumA += v
+ sumX += v * (x - left)
+ sumY += v * (y - top)
+ }
+
+ }
+ }
+ val cp = if (sumA == 0L)
+ CentroidPoint(0.0,0.0)
+ else {
+ CentroidPoint(-1.0 * sumX / sumA, 1.0 * sumY / sumA)
+ }
+
+ return cp
+ }
+
+
+ fun qGary(r :Int,g :Int ,b :Int):Int{
+ return (r*11+g*16+b*5)/32
+ }
+}
+
+
+
diff --git a/MyOpenCv/app/src/main/res/drawable/ic_launcher_background.xml b/MyOpenCv/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..07d5da9
--- /dev/null
+++ b/MyOpenCv/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/MyOpenCv/app/src/main/res/drawable/ic_launcher_foreground.xml b/MyOpenCv/app/src/main/res/drawable/ic_launcher_foreground.xml
new file mode 100644
index 0000000..2b068d1
--- /dev/null
+++ b/MyOpenCv/app/src/main/res/drawable/ic_launcher_foreground.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MyOpenCv/app/src/main/res/drawable/xml_4.jpg b/MyOpenCv/app/src/main/res/drawable/xml_4.jpg
new file mode 100644
index 0000000..0b85fc8
Binary files /dev/null and b/MyOpenCv/app/src/main/res/drawable/xml_4.jpg differ
diff --git a/MyOpenCv/app/src/main/res/drawable/yu_5.jpg b/MyOpenCv/app/src/main/res/drawable/yu_5.jpg
new file mode 100644
index 0000000..aea42a0
Binary files /dev/null and b/MyOpenCv/app/src/main/res/drawable/yu_5.jpg differ
diff --git a/MyOpenCv/app/src/main/res/drawable/zp_1.png b/MyOpenCv/app/src/main/res/drawable/zp_1.png
new file mode 100644
index 0000000..e06cdb3
Binary files /dev/null and b/MyOpenCv/app/src/main/res/drawable/zp_1.png differ
diff --git a/MyOpenCv/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/MyOpenCv/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..6f3b755
--- /dev/null
+++ b/MyOpenCv/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MyOpenCv/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/MyOpenCv/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..6f3b755
--- /dev/null
+++ b/MyOpenCv/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MyOpenCv/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/MyOpenCv/app/src/main/res/mipmap-hdpi/ic_launcher.webp
new file mode 100644
index 0000000..c209e78
Binary files /dev/null and b/MyOpenCv/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ
diff --git a/MyOpenCv/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/MyOpenCv/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
new file mode 100644
index 0000000..b2dfe3d
Binary files /dev/null and b/MyOpenCv/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ
diff --git a/MyOpenCv/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/MyOpenCv/app/src/main/res/mipmap-mdpi/ic_launcher.webp
new file mode 100644
index 0000000..4f0f1d6
Binary files /dev/null and b/MyOpenCv/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ
diff --git a/MyOpenCv/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/MyOpenCv/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
new file mode 100644
index 0000000..62b611d
Binary files /dev/null and b/MyOpenCv/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ
diff --git a/MyOpenCv/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/MyOpenCv/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
new file mode 100644
index 0000000..948a307
Binary files /dev/null and b/MyOpenCv/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ
diff --git a/MyOpenCv/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/MyOpenCv/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
new file mode 100644
index 0000000..1b9a695
Binary files /dev/null and b/MyOpenCv/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ
diff --git a/MyOpenCv/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/MyOpenCv/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
new file mode 100644
index 0000000..28d4b77
Binary files /dev/null and b/MyOpenCv/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ
diff --git a/MyOpenCv/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/MyOpenCv/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
new file mode 100644
index 0000000..9287f50
Binary files /dev/null and b/MyOpenCv/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ
diff --git a/MyOpenCv/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/MyOpenCv/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
new file mode 100644
index 0000000..aa7d642
Binary files /dev/null and b/MyOpenCv/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ
diff --git a/MyOpenCv/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/MyOpenCv/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
new file mode 100644
index 0000000..9126ae3
Binary files /dev/null and b/MyOpenCv/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ
diff --git a/MyOpenCv/app/src/main/res/values/colors.xml b/MyOpenCv/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..f8c6127
--- /dev/null
+++ b/MyOpenCv/app/src/main/res/values/colors.xml
@@ -0,0 +1,10 @@
+
+
+ #FFBB86FC
+ #FF6200EE
+ #FF3700B3
+ #FF03DAC5
+ #FF018786
+ #FF000000
+ #FFFFFFFF
+
\ No newline at end of file
diff --git a/MyOpenCv/app/src/main/res/values/strings.xml b/MyOpenCv/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..8643136
--- /dev/null
+++ b/MyOpenCv/app/src/main/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+ MyOpenCv
+ raw centroid
+
\ No newline at end of file
diff --git a/MyOpenCv/app/src/main/res/values/themes.xml b/MyOpenCv/app/src/main/res/values/themes.xml
new file mode 100644
index 0000000..449b754
--- /dev/null
+++ b/MyOpenCv/app/src/main/res/values/themes.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/MyOpenCv/app/src/main/res/xml/backup_rules.xml b/MyOpenCv/app/src/main/res/xml/backup_rules.xml
new file mode 100644
index 0000000..fa0f996
--- /dev/null
+++ b/MyOpenCv/app/src/main/res/xml/backup_rules.xml
@@ -0,0 +1,13 @@
+
+
+
+
\ No newline at end of file
diff --git a/MyOpenCv/app/src/main/res/xml/data_extraction_rules.xml b/MyOpenCv/app/src/main/res/xml/data_extraction_rules.xml
new file mode 100644
index 0000000..9ee9997
--- /dev/null
+++ b/MyOpenCv/app/src/main/res/xml/data_extraction_rules.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MyOpenCv/app/src/main/res/图片.txt b/MyOpenCv/app/src/main/res/图片.txt
new file mode 100644
index 0000000..0199034
--- /dev/null
+++ b/MyOpenCv/app/src/main/res/图片.txt
@@ -0,0 +1,137 @@
+
+[2024-12-05 22:27:49.278]# RECV ASCII>
+{"command":"result","type":"reply","values":{"sensors":[{"arg":"0.448","des":"","pos":"1","tar":"n","xAvg":-389.81056662629834,"xCur":-390.0168741113125,"xReal":-174.7275,"xTemp":-390.0168741113125,"yAvg":216.29202587154657,"yCur":216.33073662504296,"yReal":96.9161,"yTemp":216.33073662504296}],"timestamp":"2013-01-26 23:48:10.575"}}
+
+
+
+[2024-12-05 22:27:49.328]# RECV ASCII>
+{"command":"result","type":"reply","values":{"sensors":[{"arg":"0.448","des":"","pos":"1","tar":"n","xAvg":-389.81056662629834,"xCur":-390.0168741113125,"xReal":-174.7275,"xTemp":-390.0168741113125,"yAvg":216.29202587154657,"yCur":216.33073662504296,"yReal":96.9161,"yTemp":216.33073662504296}],"timestamp":"2013-01-26 23:48:10.625"}}
+
+
+
+[2024-12-05 22:27:49.378]# RECV ASCII>
+{"command":"result","type":"reply","values":{"sensors":[{"arg":"0.448","des":"","pos":"1","tar":"n","xAvg":-389.8118084324824,"xCur":-389.84782081182004,"xReal":-174.6518,"xTemp":-389.84782081182004,"yAvg":216.29220710562203,"yCur":216.29746289381092,"yReal":96.9012,"yTemp":216.29746289381092}],"timestamp":"2013-01-26 23:48:10.675"}}
+
+
+
+[2024-12-05 22:27:49.427]# RECV ASCII>
+{"command":"result","type":"reply","values":{"sensors":[{"arg":"0.448","des":"","pos":"1","tar":"n","xAvg":-389.8118084324824,"xCur":-389.84782081182004,"xReal":-174.6518,"xTemp":-389.84782081182004,"yAvg":216.29220710562203,"yCur":216.29746289381092,"yReal":96.9012,"yTemp":216.29746289381092}],"timestamp":"2013-01-26 23:48:10.725"}}
+
+
+
+[2024-12-05 22:27:49.477]# RECV ASCII>
+{"command":"result","type":"reply","values":{"sensors":[{"arg":"0.448","des":"","pos":"1","tar":"n","xAvg":-389.8094530184802,"xCur":-389.7411460124188,"xReal":-174.604,"xTemp":-389.7411460124188,"yAvg":216.29465648197694,"yCur":216.36568839627031,"yReal":96.9318,"yTemp":216.36568839627031}],"timestamp":"2013-01-26 23:48:10.775"}}
+
+
+
+[2024-12-05 22:27:49.527]# RECV ASCII>
+{"command":"result","type":"reply","values":{"sensors":[{"arg":"0.448","des":"","pos":"1","tar":"n","xAvg":-389.8094530184802,"xCur":-389.7411460124188,"xReal":-174.604,"xTemp":-389.7411460124188,"yAvg":216.29465648197694,"yCur":216.36568839627031,"yReal":96.9318,"yTemp":216.36568839627031}],"timestamp":"2013-01-26 23:48:10.825"}}
+
+
+
+[2024-12-05 22:27:49.577]# RECV ASCII>
+{"command":"result","type":"reply","values":{"sensors":[{"arg":"0.448","des":"","pos":"1","tar":"n","xAvg":-389.8094530184802,"xCur":-389.7411460124188,"xReal":-174.604,"xTemp":-389.7411460124188,"yAvg":216.29465648197694,"yCur":216.36568839627031,"yReal":96.9318,"yTemp":216.36568839627031}],"timestamp":"2013-01-26 23:48:10.875"}}
+
+
+
+[2024-12-05 22:27:49.627]# RECV ASCII>
+{"command":"result","type":"reply","values":{"sensors":[{"arg":"0.448","des":"","pos":"1","tar":"n","xAvg":-389.80837651055305,"xCur":-389.7771577806646,"xReal":-174.6201,"xTemp":-389.7771577806646,"yAvg":216.2928601589806,"yCur":216.24076679208707,"yReal":96.8758,"yTemp":216.24076679208707}],"timestamp":"2013-01-26 23:48:10.925"}}
+
+
+
+[2024-12-05 22:27:49.678]# RECV ASCII>
+{"command":"result","type":"reply","values":{"sensors":[{"arg":"0.448","des":"","pos":"1","tar":"n","xAvg":-389.80837651055305,"xCur":-389.7771577806646,"xReal":-174.6201,"xTemp":-389.7771577806646,"yAvg":216.2928601589806,"yCur":216.24076679208707,"yReal":96.8758,"yTemp":216.24076679208707}],"timestamp":"2013-01-26 23:48:10.975"}}
+
+
+
+[2024-12-05 22:27:49.728]# RECV ASCII>
+{"command":"result","type":"reply","values":{"sensors":[{"arg":"0.448","des":"","pos":"1","tar":"n","xAvg":-389.8090465640172,"xCur":-389.8284781144781,"xReal":-174.6431,"xTemp":-389.8284781144781,"yAvg":216.2972694219192,"yCur":216.42513804713803,"yReal":96.9584,"yTemp":216.42513804713803}],"timestamp":"2013-01-26 23:48:11.026"}}
+
+
+
+[2024-12-05 22:27:49.776]# RECV ASCII>
+{"command":"result","type":"reply","values":{"sensors":[{"arg":"0.448","des":"","pos":"1","tar":"n","xAvg":-389.8090465640172,"xCur":-389.8284781144781,"xReal":-174.6431,"xTemp":-389.8284781144781,"yAvg":216.2972694219192,"yCur":216.42513804713803,"yReal":96.9584,"yTemp":216.42513804713803}],"timestamp":"2013-01-26 23:48:11.075"}}
+
+
+
+[2024-12-05 22:27:49.827]# RECV ASCII>
+{"command":"result","type":"reply","values":{"sensors":[{"arg":"0.448","des":"","pos":"1","tar":"n","xAvg":-389.8090465640172,"xCur":-389.8284781144781,"xReal":-174.6431,"xTemp":-389.8284781144781,"yAvg":216.2972694219192,"yCur":216.42513804713803,"yReal":96.9584,"yTemp":216.42513804713803}],"timestamp":"2013-01-26 23:48:11.125"}}
+
+
+
+[2024-12-05 22:27:49.876]# RECV ASCII>
+{"command":"result","type":"reply","values":{"sensors":[{"arg":"0.448","des":"","pos":"1","tar":"n","xAvg":-389.8090465640172,"xCur":-389.8284781144781,"xReal":-174.6431,"xTemp":-389.8284781144781,"yAvg":216.2972694219192,"yCur":216.42513804713803,"yReal":96.9584,"yTemp":216.42513804713803}],"timestamp":"2013-01-26 23:48:11.175"}}
+
+
+
+[2024-12-05 22:27:49.928]# RECV ASCII>
+{"command":"result","type":"reply","values":{"sensors":[{"arg":"0.448","des":"","pos":"1","tar":"n","xAvg":-389.8090465640172,"xCur":-389.8284781144781,"xReal":-174.6431,"xTemp":-389.8284781144781,"yAvg":216.2972694219192,"yCur":216.42513804713803,"yReal":96.9584,"yTemp":216.42513804713803}],"timestamp":"2013-01-26 23:48:11.225"}}
+
+
+
+[2024-12-05 22:27:49.980]# RECV ASCII>
+{"command":"image","type":"reply","values":{"image":"/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAYgCEADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD5/ooooAKKKKACiiigAooooAKM0UUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFAC0lFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRS0lABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUtJRmgAooooAKKKKACiiigAooooAKKU0lABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUALRSUUDuLikoooEFFFFABRRRQAtJRRQAUUUUAGaKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigApRSUUALRSUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFLSUUALiikpaBhRRRQAlFFFAgooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACijFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFAC4pKWigYlFFFAhc0lFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFLSUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAuKSlpKBhRRS0CEpaKKACkpaSgAooooAKKUUlABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABS0lFABRRRQAUZoooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKXNJQAUUUuKAEopcUlA7BRRRQIKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKADNFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFAC0lFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUALSUtJQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKXFACUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKM0UUAGaKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAUUlFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUWAKKKKdgCiiilYAooxRinYAooxS4osAlFLijFFgEopaMU7AJRS4oxSsAlFLiiiwCUUtGKLAJRRiiiwBRRRSsAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUuKMU7AJRTgKMU0h2G4pcU7FGKLBYbijFOxRinYLDcUYp1LinYLDcUYpcUuKLDsNxRinYoxRYLDcUYp2KMU7CsNxS4pcUYosOwlGKXFFFgsJikxTqKLBYbijFOoxRYVhuKMU6iiwWG4oxTqKVgsNxSYp2KKLBYbRS0UrCsJikp2KKVgG0UuKKLAJRS0YpWASiiilYAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKXFLinYBuKXFLilxVWHYTFGKdijFFh2ExRinYop2HYbilxS0U7BYTFFLiiiwCUYpcUtOwxMUUtGKdgEopcUYosAlLijFLiiwCUlOxRimFhKMUtFILDcUYp1FAWG0Yp1JinYAxSU6jFKwWG4pMU7FFOwrDcUYp1FFgsNxRTsUmKLCsJRS0YpWASkxS4opWAbijFOopWFYbikxT6TFFgsNop2KTFKwrCUmKdikpNAJRS0YpWASiiilYAooopAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRS4pQKdgEpcUuKXFUkVYQUuKUCnYqkikhuKXFLiinYdhMUYpaKdgsJiilxRSsFhKKWinYLCYpaKWiwCYopaSmAUUUUAFFLRTCwlLRRQAUUUUDCiiigQlLRSUALikpaKAEopaKAEooopgFFLRSATFGKKKBCYoxS0UBYTFJinYoxQKw2jFLijFKwWG4op2KMUWCw2jFLilxSsFhtJTsUUWENxSYp2KKVhWGYop2KDU2FYZRS0UrAJRS4pKloAooopAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFKBQAlOAoApwqrDSEAp2KMUtWkXYMUYpcUuKqw7CUUuKMUDsLSYpaKY7CYopaKAEooxRQIKKWigBKKMUUAFFFFMBKKWm0hMM0bqSgCp1FdjqXNJRVDFzRmm0UBcdRRS4pjEoopaLAJRRRiiwBRS0UwEopcUYoCwUlLRRYBKMUtFFgExRiloosKwlJS0UWASiloosAUmKXFGKAsJiilxS4oCw3FJin0mKLCsNxSU/FJilYLDaTFOxRilYTQzFGKdiilYQw02nkU0iokiRKWkxS1KQCYopaKLAJRRiilYAooopAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUoFOAp2HYQCnYoAp2KpIpIQClxS4oq7FWClxRRimNIWlpBS0yhKKKKYBRRRSAKKKKBBmkoooAKKXFFABSUUtOwhKKXFGKLDEpKfikIosJobS0uKSiwbCUtGKdRYEMIoAp+KMUWCwgopaXFVYY2lxS4oxRYLCYoxS4oosOwmKMUuKMUWCwlFLS4p2AbRilxS4osFhuKMU7FJRYBMUlOopCsNopaMU7AJRilxS4pBYbRS0lAgpaBQaBiUYpN1LmlcWgUlLS0wG0Yp1JQFhuKTFPxSYpCsNxTStPxSYpcpLQzbRin4pMVLiKw3FJin4pMUrBYbikp+KQik0TYZRTsUmKjlASilxSUrAFFFFIAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKMUAFOAoApwFVYaQmKUClAp2KpItIQClxSilqkXYSlFFLiqCwlJTqMUrDEooxS0wDNJRRQAUUYooEFFFLRYBKKWinYdhKKWiiwCYpcUUuKYWEpaMUuKdgEpAOadSUBYDSYpaWhjG4oxTs0GiwWEopcUUwCiijFMBMUtGKWiwCUUYpcUWEJRS4oxQMSilxRQAlFLijFFgEoooosAUUUYoEJS4oooATFFLRRYBtGKdSYpWAKaadSEZosJkZpM08rSbalpkNMAafTQKUU0NC0UtJTKCkpaKAEpMUtFIQmKTFPpKAsMxRinYoxUtE2GYpMU/FJilYVhuKTFOxRik0KwzFIRTyKTFS0JoZRTsUmKhoQlFFFTYAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiinYpgIBSgUoFOAqkikhAKcBSgUuKtItIKKXFLinYpITFLRRTGFFJRmgBaM0ZozQAUUUU0AlLiiigBKXFFLQFhKKKUUDCiloqrAJRilxS4p2CwlFLijFOwWEpcUuKXFFh2G0Yp2KMU7BYbijFOxRiiwWG4pKfRiiwWG4oxTsUYosOw3FGKfikxTsFhKKWikFhKMUtGKYWEopcUYosAlFLRQFhKKWkoEJRS0UAJRS4oxRYQlFFFKwCUUtFACUUtJQIKKKKACkxS0UAJijFLRSsAUlLSUAFGKKKQhMUUtFFgEpKdSUAJRS0UgExSYp1GKLCsMxSU/FIRSFYbSYp2KMUrE2GEUmKfikxUuImhmKSnkU0ioaJaG0UtJUNAFFFFIAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACilxTgKdhpCAU4CgCnAVaRSQgFOxSgUtUkWkIKWgU6qKsJiilooGJQaKKBCUtFLQMSilpM0wCiiigQYpaBS4pjEop2KSnYLDMUopaAKVhWHDpSgUmKWqLDFFFLVAJilopQKLDsJS0uKWqsOw3FLilop2HYTFFLRiiwWExSYp+KTFFgsJijFOxRiiwWG0mKdijFFhWG4op2KTFFgsJijFLijFFgExRinUUWCw2jFOoosFhtGKXFFKwrDcUUpoosAlFIaTNJsQ7FJSg0tAWG0lOxSUCsJSU+m0WFYSilpKQgopaKBiUUtJRYQUUUUAJRS0UgEopcUlAgooopAFFFFAxKKWigQlFLRSAbikxT6SgLDKSnEUYpWJsNxSYp1JipsKwwikxUmKbik0S0MpKfikxWbRI2ilIpKloAooopAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFBoAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKAClFAFOApoaQgFPApAKeBVpFpBilxSgUuKtItISlopaZQlLRSUwCjNIaKVxC0CgUtMYUUUUWAKQ07FBFOwWEFLSYpQKYABTsUoFKBTsWkNxRinYoxVWHYbijFOxS4osHKNxRT8UmKdgsMoAp22lFFhWEApwFFLiqRSQYopaKChKMUtFVYBKWiikAYpKWlphYbRS0UCsGKSloxQFhKMUuKKAsJRS0UWCwlFLRQAlJilooEJRilooAbiilpDSERmm5qRhURXms5IydxwNPFMUVIBREqIUYpaKuxQmKTFOxSUWCw00lOxQRSJaG0UuKMUWCwhpKcRTTSaEwpabTqlAFJS0lMAooooEFFFFIBKMUtFACUUtJSAKMUCloASilpKAEpMU6igVhmKKdSYpCsNpMU7FJUisNxSEU+kIpWJaIyKSpMU0ioaJsMop2KbUNCCiiipAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKUCgCnAUDSACnAUAU4CrijRIAKXFLilFaJFJAKKWiqKsFFFFAwoNFIaGIbSiilAqbCFxS4oxS4q0irCUmaU0lDAcKXFItSAVSRS1GYpQtPxRVWK5RMUoFLilxTsVYbRilophYSlopadgsJijFLRTsA2lxS4oxSsKwgFLS0U7FWEpaXFFOwCYopaKdgEoxS0UWASiloosAlGKWiiwCUYpaKADFJilop2ASilooASjFLRQISjFLSGlYYYpMUtFMVhuKCKdSUrCIyKTbUhFJipcSHEYFp2KdijFCiOwlFLRTsA2kpxpppMTEzRRS0gEpaWkxRYQU0in0hFDQWI8UU40lQ0TYWiiimMSkp1JilYTG0tFFIQUUUUAFFFFACUtFFABRRRQAlFLSUgCiiloAbSYp2KSlYVhuKSn4pCKVhWGYpKdRSaJsMIppFSEU0iocSWhlJT8U0ioaJEoooqbAFFFFIAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAopaSgAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACgUYpwFNIaACnigCnAVaRaQAU4CgCnVaRokFIadTKY2OBpaZTxTQIKSlopjExS4paSgYbaXFApRQkCQYpaWlxV2KSGkU3bUmKXFPlDlGquKdilAp2KpItIaaSlNJQxDgaWminU0UhMUUtGKdgG0tFFFgFooxS07AJS0lFABRRRQMKWiimIKKKKYC0UUlAwooooEFFFFABRRSigBKQ0tNLUm7A2GaXNMzSg1KZNx9FJmirKuLRRRQAlLRRQAlFFFAgpKWigQlFLikoAKKKKAEppFPxSYpNCaG4opaKmwhKWkpaEAlFKKDTsA3FJinUVNhWG4oxTqKLBYaRSU/FJikKw3FJTsUlFhWEpMU6kpCEopaKQCUUUUhBRRRQAUlFFIAopaKAA00mnGmkUMTGk0ZoNIBUk3HUmKUUUDG4pMU8im4pCaGkU0inmkxUtXJaGU2nkUhqGiBtFFFQAUUUUgCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigApRSYpwFNDACnYoApwFUkWkAFPFIBTsVqkWkLRigU6mWhMUhFOzRQNoaBTqKMU7CsJS4pcUuKaRVhMUlPxRiqsFhtKBS4pcUWGkGKcKTFOAqkWkGKXFGKXFVYqwlLS4oqkOw00YpxFJiiwrCAUuKWihIdhKDRRQxCUCilxRYAoxRRTsAlFLSGkIKKKDQAUUmaBzQA6iiiqAKKKKACiiigYUUUUCClpKKAA1Gwp5pppMmQwCnCinAVKQkgpaMUVdigpaKKBhRRRQAlFLSUCCiiigQUUUUDEpaKKBBSUtBoAaaaTTjTSKlksQU6kpaSBC0UUYqrDExRinYpKAsJSU6kpMQlFLSUrAJRS0UhWG0YpcUYpCsNopSKMUCsNopcUmKmwrCUUtFACUUtJSAKKKKBBSGlpDSYDcUuKQ0oOaQgop1JTHYSkxTqSkJobikIp1IRU2JaGYppFSYpCKlolojxSU8immoaJaG0UtJUNCCiiikAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABS0mKcBTsNABTgKUCnAVSRaQAU4CgCnYq0aJCYpaWlqirCUtFFUMSloxS0WGgxSgUYpcVSHYKXFGKWqRVhKXFLijFMdhMU4UUoFA0gxRilxS4qkirABS4oFLVDsJRRRTASlooosAlFFFMQUUUUgCiiimAUlLRikISkpaKGITFBpaDRYBuKUUUtCAKWikpjA0hoNNJqXoS2OBp1RCnChMEx9FFFUUJRRijFAgpCKdSUwaG4opDSc1DJuPzTs0wUopoaYtFFFMYUUUUAFFFFACUtFJQIKKKKLAFFFFABSGnU00MGGKQilopCEAoxS0U7CsFFLSUDCiiigAxSUtFIBtFLRSEJSU6koEJSU6kqRCUUtFAWG0UtJSEJRilopBYbRS4pKQgpDS0UCEFBFLRSAjIoFPIpMVNibCU6kxS00MSilpKAEoxS4pKVgExTSKfSUmTYYRTSKfikIqWiGiKkp5FNxWUkQJRS4pMVNgCiiikAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUooAUU8CkAp4FUjSKACnYpQKWtEjVIKWjFLiqKSEpaKWmOwmKKWlxTSASlApQKXFUUkFLijFLimkUgpcUYpQKuw0gAop1IaaRQ3FOFGKWiwJC0UlFMdx1JSA07NMYlFFFMQUlLRQAlFLRQAUlLSUCCiiimAUUUUAFGKKKQCUUtFAhKMUtFMLBRRRQAhpjDNSU0ik0JojGaeKUClxSSEkFFLiirGFFFFIYUlLRQAyjFOxRiixNhMUtFLQMKSlopgJRRRQAUUUUAFJS0UgEpcUUUwCiiigApKWigQdqbS0UgCilpKACiiigApKWkoEFFFFIAoopKACiiikITFGKWigLCYpDTqTFKwWExRS0UrCsNxRilopWAbSU40mKLEiUlOxSYpWFYSijFFIQlFLSUgCiiigAooooAKSlopANxQaWkpMVhKQ06kIpWJGEU0ipCKaRUtEtDMUhpxpprNogbRTsU2pYgoooqQCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAUU4U0CngU0ikhwFPApop4rRI1ihQKdikFOq0aJBRRRVDCijFKKYwpcUopQKaKSDFKBRilxVWKSDFKBS4pRVJFWExS0YpaY7CUYpaKoBMUtLRRYY003NOpDUtEsBzS0gp1NAgoooqhhRRRTuAUUUUAFJS0UAJS4oooEJRS0UAJRS0lABRRRQIKKKKYBRRRQMKMUtFAWExRS0UCCkpaSgAooooAKKKKAEpaKSgQtFFFAwooooASlxRRQAmKWiigBKKWigBKKKKBBRRRQAUUUGgAooooAKSlpKQhaSiimAUUUUgCiiigQlFFFACUUtJSEFLSYpaBiUUtJQAUlLRSEJRS0lKwCUlOpKBCUmKdRUisNxSU6m0hCUlOxSUhWCkpaSgQUUUUgCiiikAUlLRQAlJS4pKQrCUhFOpKTJsMIppFSEU0ioaJaI6SnkU3FQ0QIaSnU2pEFFFFSAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRS0lABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABS4pKcBQNCgU8CkAp4FWkaRQoFOApOlOFapGiQU4Ugp1NFoKKKWmMSnAUAUuKpFJBTqQCnVaRSQAUoFFLVWKQAUtGKKdigoxS0UxhRRRTEFFFFACYpMU6kpWBoAKWkpaYIKSlpKACijFFAgooooAKKKKYBRRRTAKKKKQhKKWigBKKKKACiilpgFFFFACUtFFABRRS0wEooooATFFLRQIKSlooASilopAJRS0YoASjFLRTASig0lIBaKSjNAhaKKSgYtJRRTELRSUUgClpKKACiikJoC4tFIDS0BcKSlooEFJS4ooASiiikAUUUUAFFFFAhKKWikAlFFFABRRRQAlFLRQFhtFLSYpWEJRS0UgEptOoxSE0Mop2KSpsSxKSlopWENopaKQhKKKKACiiikMKSnUlFhMbRS0lIQhFIRS0lSJjTTTTyKaRUtGbQw0hpTTTWbIYUUUCpAKKKKQBRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAKKcKaKkApoqKFAp4pAKeK1ijZIUUoFAp1XY0SCiilqirBilAopwFOw7ABS4oFLVItIKWgU6qSKSEpRRS4qirBRS0lUFgoopaAEoopaAEopaSkAUUUUxBRRRQAUUUlAC0lLRTAKSlooEJRS0GmAlFFFABRRRQAUUUUAFJS0UCCiiigAopcUUwEooxS0AJRS0UAJRmg0lJgLRTc07NCYIKKKKYBSUUUhC0UlLTAKKKKYwpKWkpCEoxS0UWEFFFFIYlFFFMQUtFFIAooopgFMbrT6YaTExKcDxTacKSEhaKKKZQUUUUAJRRRSEJRS0UCCiiigAooooGJRS0lIAooopiFpKKWgYlJS0UhCUlOpKVhCUUtJSASkpaSlYTEpDTqKTRI2kp2KSkAlJTqbUkhRRS0DEpaKKBCUlOpKQWG0YpaKkVhpppFPpDSJaISKbUpFMIrOSM2hmKWnYpCKkVhKSloxSaEJRRRUgFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFADhUiimKKlUVUUawQ4CnCkFPArVI2SACnYoFLWhaQmKUUtGKdirBThQBS4qkikgpcUUtUirBilopcVSKsFLRRTsMKKKWmAmKMUtFAWEopaSgBM0tFJQIWkpaSmAUUUUgCiiimIKKKKQBRRRTAKKWkpgFJS0UCEoNLRQAlFLRTEJRilooGJS0UUAFJS0UCEpaKKACkpaKACoz1qSmGlITEpwpuKdSQkLRQKDVFCZoJpMUpWlqIQU6kHFLQCCil7UlMYUUUUxBiiiikAlJS0UWEJS0lLigAooooAKSlpO9AC00inUYosDGU6jFLSsJISloooKCkoooEFFLSUAFFFFIBKKWimKwlFFFIAoopaAEooooASilooASiiikAUUUUCEopaKAsNxSYp1JU2EJSU6koEJSU7FJUisNNFLRSsIbSU6mmpYmFLTTSilcQtFFFMYlJTqaakTQmKQinUlIVhpppp5ppFIhoaRTTTzTTUNEsbRRRUMkbiilpKliCiiikAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFACgU4CkFPFUkUkKoqQCmqKkFaJG8UKBTgKQU4VokaJCgUuKBTsVaRpYTFLRinAU7DSExS4paBVFJC4ooopooWlpKXFUNC0UYpcUxiUtFFMApKWkoAKKKKBBSGlpKAEpaMUUCCkpaKACiiigAxSUtFMQlFFFAC0UlFAC0UUUAFJRRQAlLRRigVgooopgFFFFABRRRQAUUlLQAUUlFMQtNNOpMUmDEpaMUtIApKWimAlBooosITFLS0UDENFLSUwCiiigAoooNACZopKQmpuTcfSUgbNOpjEopaSmAUUUUgCiiigAoooosIKKKKQxKKKWmISiiikAUUUUAFFFFABSYpaKAEpaKKACkpaSkAtFJS0AJSYpaKBCUUtJSAKKKMUAFJilooEJSYp1JSEJSGnYpKVgG0UtJikKwmKaRT6SpYmiMilpxFJipsRYQUtFFAwpKWkoEJSU6kqRDaSnUlIQ3FIadTTUslobSYp1IahkNDaQ0tFSISkpcUhpNCCiiipAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAopaSgAooooAWkpaSgAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKXFFKKBoUCpFFNUVIBVpGsUOApwpAKeK1SNkgAp4FIKcK0SNEgAp1IKcKqxaDFFLilxVWKSEpQKMUtOwwooopgKKWkpaopBS0UUDCiiimAUlLRQIMUlLSUAFFFFABRRRQISilooATFFLRTEJRRRQAlLRSZoELRRRQAUUUUDCjFFFACUUtFFhCUUppKYBRRRRYQUUUUAFFFFABSUtFABRRRQAUlLSUCCloooASiiimAUtFFABSUtJQAUtJRSAWkNLSGmDGGmEmpKQioaM3cRadQBS4ppFIKKUUUxiUUtFMAoopKQBRRRQIKKKKBhSUtFAhKKU0lABRRRSAKKKKACiiigAooooAKKKKACiiikAU00tFAhKKWikAUUUUAJRRRQAUUUUgDFIRS0UCsNpKcaSkISkNKaKmwhtJSmkqWSFJS0UgEooNFAhKQ06kpCY2ilpKQhDTSKfSGpYmhmKQinUmKlkWGUlPIppqGiWhKQ0tIaloQlFFFIQUUUUgCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAUCnAUgp4ppFpDlFPApqipBWsUbRFFPApop4FaJGsUKBTgKBSirSNEKBS4oxRVFpC0tFFUMKKKKYxaKBS00FgpRQKKZSCilpKYBRRRQAUUUUCEpaKKACkpaKYCUYopaAEopaKAEooooEFJS0lAhKKDTDmk9CWx2aXNMBpc0kxXH5opgNOBqkykxaKKKYwpM0E03NJslsdmimg0uaEFxaTNFJmhsQ6iminUIdwoooqgCiiigAooopAFJS0lAgooooAKWkpaEAlLRRTAKSlpKACgUUUWEFLRRTGJikxTqKTCwlFFFAgooooAKKKKACkpaKAEopcUlIAooooAKKKKQCZpaSlpiCiikpAFFFFABRRRQAUUUUAFFFFABRRRQAlFLRSASiilpAFJRQaAEpc02ikK46kozS0AJRS0lACUlONNNBLCkpaKlgNNJTjSUmSxtFFJUCFpKWigBKSlopCEpKWikIbRS0lJoQ00lONJUMTQ2m4pxpKlohjcUlOIpKlktDTRS0mKQhKKMUUhBRRRSAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAxRS0UAJRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABS0lKKAHCngU0CpFFWjWKHKKkApop4rVG8UKBTxTQKeK0SNUhaUUClxVotC0UUoqkUFLRRTGFFJmloAKWilpjQUUUtNDCiiimMKSiimIKKWkoAKKKKACiiigQUUUUAFFFFABRRSUAFFFLQIYaYTUpFRkc0miJDO9JnFOIpMZrOxAoNPBqMLinCrQ0ySijNFWWI1RGpDTcVLRDEWn0gFOxQkNDcUmKfSYp2BoBS0AUuKaGkJRRRRcBc0lJS5oC4UUUUwCiiigQlFBpDSAKAaaTQDU3JuSZopop1WirhRiiimAmKWiigApKWigBKKWkpAFFFFABSUtFAgoNFFACUtFJQAtFFFABRRSUgCilxSUAGKMUtJQISilopAJRRRQAUUUUAFFFFABRRRSAKKKKYBRRRSAKSg0UAFIaU0hpMQmaQHmnUlTYQuKUUlLTGFFFFMYlJTqSkISilxSUhCGm040lJiY2jFKRSVDRNhKKWikIbRS0lIApKWigQ3FFLSUhWEpMUppDUsTGmkNONNqSGIabTjSGpaJEpKU0lSJiGkpaKlkiUUUUgCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACnCmjrTxTSGhwqRRTFFSgVpE3ihwFPApBTwK1RukKBTgKAKcK0SNEgFLRS1RYYopaKodgooooGGKKKKBC0uKQGnCmikJS0tFUhiUUUUAFJS0UwEooooEFFFFABRRRQIKKKSgBaKKQ0AFLSZpaYhKWkpaAA0wjmn0hFJoHqMK8UzFTU3FJohxGU4ClxQKLAkLRRS1RQ3FGKWigVhAMUtFFMAooopAFBopDQDGk0maCabUNkXHZpRSCnAVS1AKWjFFOxQUUUUAFNNOpMUCaG0gFOxSgUrE2EpcUtFUVYKKKKYBRRRQAlFLSUABooooEFFFFABRRRSAKKKKACiiigApM0tJQAtJS4opAFFFFMApDRSmkAlJS0UCEooopAFFFFABRRRQAUUUUAFFFFAAaSlpKQhaSlpBQMKMUtFAWGkUYp1FKwWEooNFAgopKWkAUUUlAwoNLSUCExSGnUlSxDaSnUlIVhpFFLSUmiRKKWkqRCGkp1JikAlIaWikISkNOpKQmMNIafimkVLJaG0lKaSpsQxDTacaSpaEJSU7FJUksbRSmkpMQUUUUgCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKMUUUAFFFFAC0lLSUAFFFFABRRRQAUtJRQAtJRRQAUUUUAFFFFAC0lFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUtAAKkWmCpAKpFxQ5RUgpqipAK0SOiKHCnimqKeK1RtFDhTgKQU4VojRIKWiirKFpKWkosMKUUlKKYARTc080wikxMAakFRdDUgoiOLHUUgpa0LEopaSkIKKKKAEopaKYhKKKKAFpKKKACiiigQlFLTTQxMKWm04GkmJBS0UVQxKKWkoAKTFLmigBKKWigQUlLSUAFFLSUCCiiimAUUUUAFIaWgigGR4oAp2KUCp5SbCBad0ooqloUgpKWigBKKKKYgooopAFFFFACUtFFAgooopgFFB4puaQXHUlANLQAlGKKKACiiigQUUUUAFFFFABRRRQAlFLRQAUUUUAFFFJQAUUUUCEzS5pKSpAWijNFAC9qSijFMBaSlooASiiigAooopAFFFFABSUtJSAWkzQaTNSwbDNO60zNLQK4pooopjCkpaDSAKKKSgAxRS0negQUhp1JSBjaKWikITFIaWkpCY3FFLSGpZIlFIaKkQUYpaSgBKKWkNJiG0hooJqGSIabijNGam5AlIaWg0mIbRQaKlokSkNLQaliG0UUUhBRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAZooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigApRSUooAcKkUUwVItXFGsR4qQUxakArZI6IocBUgFNApwrRI2SHClFAFLWiRogpaBRVDCiiigYlKKBS0wFxxTMc0+kI5pg0MIp60YpQKVhJBS0UUyxKWiimISilooASiiigQlLRRQAlFLSUAFFFFAgpp4p1NNDExM0UhFAqdiR4paSiqKFpKKWmAlFFFAAaSnUlAhKWkpaACkpaKYCUUtJSAKKKKAClpKKYgooooAM0lBozSEFLSUUBcKKKKYBRRRQAUUUUIAooooAKKKUUwGtTM09qjINRJkSHA06mJT6IjQtJS0lUMKKKKACiiigAooooEFFFFABRRRQAUUUUAFFFFACUUtIaAGmk5p1JUsloBS0AUtCGFFFFMANJS0UAJS0UlABRRRSAKKKKACiiikAhptPppFJoTQ3FOFGKWkkJIKKKKYwooooGFJS0UhCUtFFAwooooATFBpaSpAbRS4opEjaQinUhpMTQwiinYpMVJNhKKXFGKQWG0hpaSkJjSKYRUuKaRSaIaGYpKcRSYqCGhtFLSUhMTFJTjSVLENopaSkSNNFKaSpEFFFFIAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiigUALSigUopopIcBUiimrUgrRG0UPAqQUxaeK2RvEeKcKQCnAVojZIUU6gCiqRaCilxSVQxaSiigBaKKUUxi0YoFFMYmKXFFLTEJRSmkoGFFFFIApKWimISiiigQUUUUAFFJRQAtJQKKYBSYp1FIVhlGKdRRYVgxSUtJTAKWkopALRRSVQAaSlNGaQhKWkpaACiiigApKKKYgooooAKKKKQBiiiimAGkxS0lIQUUUUAFFFFABRRRQAUUUUwCiiigAooooARqbT6TFJq5LQgFLiloosNIKSlopgFFFFACUUUUAFFFFAgpaSigYUUUUCCiiigAopaSgYUUUUCDFJilopAJRS0lABRRRTEFFFJSAWg0UUAJRRRSAKKKKQBRRRQAUUUUNgFFFFIApKWigBKKKKACiiikMDRRRQIKKKKAEpaKKQCGkpxptJoTCkNLRSENpKWikxDaKU0lSISkp1NNITEpDSmipJG0008000mSxppKWkqCBKSlxRSFYSkNKaKliG4pCKcaSlYTG0UpFJUkhRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAppKWkoAKKKWgBKMUtFACUUtJQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUooAUU4U0U4U0WkSLUiimLUi1rE3gh4FSAU0U8CtonRFDgKfSClrVGqFooFLTKCiiimAUUUUDClFFLimAUUUUxi0ZoNJQAUUUUAFBoopgFJS0UxCUUUUgCiiigApKWimISlpKWgQlFFFABRRRTEFJS0lIAooooAWiiimAhoxQaKQCUtFFArBRRSUwClpKKQC0lFFMQUlLRQAUZoopAFJilooASiiigQUUUUwCiiikAUUUUwCiiigAooooAKKKKBBRSUtABRSUtABRRRQAUlLTaLgxaKSloEFFFFACUtFFABRRSUXAXNFJRU3AKWkpaYBRRRTAKKKSkAUUtI3SmAwmgNzTCaQVk2Z8xNS0wGn1Sdy0JRS0UxiUUUUCCiiikAUUUUWAKKKKQBRRRRcApKWigYlFFFIQUUUUDCiiigQUUUUhhSUtLigVhtJTiKSkwsNpKdikNSS0NNJTqTFIliUhpaDSENptOpKlksSmmnGkNSxMZSU6kNSyBKSlpKliYUlLRSENpKdSUiWJTadSVLE0JRRRSEFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUoooGFFFJQAGiiigQtJRRQAUUUUAFGKKWgBKKKKACiiigAooooAKKKKACiiigAooooAKKKKAClpKWgAxS0lLQUKKeKYKetUkVEkWpFpgFSqK2ijogh4qQUxakFbJHRFDgKWkFOxWiNEFFFFMoKKKKBBRRS0DCloxRiqGKKKKKBhSUtFMQlFLSUAFFFFIAooopiEopaSgAooooAKSlpKYgooopCCiiimAUUUlAC0UUUWAKKKKYgoopO9AC0lLRSAKSiimDCkpaM0hCUUZooEFFFJTAWikpaACiikpAFLRRQAlFLSUCCiiigAooop2AKKKKQBRRRTAKKKKACiikoAWikozQK4tFFFABRRRQAhpuacaYaliYuaWminUkIWiigVRQUUUUxBSUtIaTASlopKLCFpRSUtA0FFFFABRSUUALSGig0ARkUwDFSEUmKzaM2hBUlNAp1NFIWiiiqKEooopCCiiigAooooAKKSlpAFFFFAwooooAKKKSkAUUtJQAUUUUAFFFFIQUZopKBhnNJQTSZqSbi0UUUAJSGnU2kyWJSUtJU2ENopTSVLJEpKWkpMkaaSnGmmpaJY00lONJUkiUUUVIhKQ06kNJgNopaDUskaaSlNJSJCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAoopaACiikoGFFFFAgooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKWkooAWiiigYtLTc0ooGhwp6imCpFq4mkUSLUqio1FTLW8Togh4p4poFSAVtFHTFBS0tJVlhRiil7UAIaKKKAFopKUUwHUUClpjAUGikNABSUtFMGJRRRQAUUUUWEFFFFABSUtJQDCiiimIKKKKQBSUtJQAUYpaTNABRRRTJCilpKBhRRS0wEopaSgQUmaDTaTE2OopAaWgANNNOzTWoYmJSg0ylFTcm4+ikFLVFBRRRQAUUlLQAUUUlMBaSlopAJiilooASiiimIKKKKACiiigAopKM0riFppp1IRTYMbTqSlqUIKWkpaoYUUUlAAabT6TFJoVhopcUtFFrBYKKKKBiUtFFMQUUUUgCiiigBKKKWgBKKKKACilpKACiiikAUmKWkoEFLSUtFhhRRRTEFJS4pDUsYUU3NKDSuIWiiimMKKWkoAKKWkoAKKKKQBRRRQAUUUUgEopaSgQUUYopDCmmnGkxQxMbilpcUuKVhWG4pcUuKSkOwlJSmkoEJSU6mmpJY00lKaaahshi0lJRU3EBppp1NIpMljTSU40lSQJRRSUgCkNLRSENpKWjFSIaaSnGmmkSwooopCCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAWkoooAKKKKAFpKWkoAKKKKACiiigBaKSigdwooooEFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFAC0lFFABS0lFAC0opKUUWKTHipFqNalWtIo1iSLUy1EoqVRW8VY6YEi08U1RT1FbI6EFLS0hqigopKKACiijFABThSClxTAKWkpaoYClpBS0WGJSUtJQIKKWimAlFGKKQgoopKYC0lFFArhRRRQAUUUUgEooooELSUUUwCilpKACiiigApaSimAUUUUCEamU40lSyWC06kApaENBTTTqTFAMbSgUuKKLCsGKKKKdgDNGaSikAuaKQUtMBKWiigAooooAKKKSmAtJRiloASiiikIKKKKaAaaKDSVLJHClpopaYxcUUUUxhRRRQAUUUUCEopaSgApaSlpAFFFJTAKKWkpAFFFFABRRSUCCiiigAopKWkIKKKSgYtFJS0AJRRS9qAEpaSloAKKKKACmk040w0mJjc04U3FOFR1JQ4UtJS1aLCkpaKdgEpaKKQCUUUUAFFFFIAooooASlooqQCiiigBKWkopiFopKKQxaQ0tIaAEpKWkqSRKQ07FIaQmRGmmpSKaRUNGbQyilxRipsISkNOpKTExhpDTjTalkMSiikzUsQUUUUCEooNJUtCCmmnGmmpExKKKKRIUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFAC0lFFABRRRQAUUUUAFFLikoAKKKWgBKKMUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFLSUUAFFFFABRRRQAUtJRQAtKKSnCixSHrUq1GoqVa0ibwJVqUVGoqUV0xOqCHiniminCtUbIdTTTqbVIoAKDQKQ9aQgpaSlpgKKXNJS0xhRS0U0NBRRRQAlGKKKYCUtFFIQUUUUAJRRRQAlFLRQKwlFLSUAwooooEFFFFACGiiimIKKKKAFpKKWiwCUUUtMBKKKKBCEUYpaKQBSUtJQAUUUUAFJS0lAgooNJQAGjFFLQIKKKKACiiigAooopgFFFFABQaKDQAlFFLQISiiigBDRS0UhWEopaQ0wDNLTaWlcBaKKSmAtFFFIApKWkpgLRSUUALRSGlpAJRS0YoASilpKACiiigQlGaDSYpAFFJS0kIKKKWmMTFLRRQAlFFLQAlLSUtABRRRQAlJSk00mpYmGKcBTc0oNISHdqSlzTSaq4wzS5phalBqbhcfSUUtUMTFLRRQAUhpaSgAooopAFFFFIAooooAKSlpppMQZoFJilFSAtLSUtUMaaTFOpDSYhKQ0tJUiENNp9JSsSNIptPNNIqWiWJTTTjSGpJGmm04001LIYhpKWkqWSFJS0lSAUlLSUMQGmmloNSJjKKU0lSQFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUALRRSUDFopKKAuLRRRQAUlFFAgFFFFABRS0lABRRRQAUUUUAFFFFABRRRQAYooooAKKKKACiiigApaSigApaSloAKcKaBTxTKiSLUq1EoqVa1idECZalFQrUq1vE6oMkFOFNFPFbI2QUhp1NNMYUUlFAgpaKKAFpaKKZQtFFFABRRSZpgFFFFMQUUUUAFFJRQAtIaKKACkpaSgQtJS0UAJRRRQIKKKKAEpaKKACkoxRTEFFFFABS03NKDSuAtJS0lMGFFFFAgpKWikAlFFFABRRRQIQ0maWkxSYmApaKKYwooooAKKWigBKKKKYgooooAKSlpKAClpKM0gCiiloASiiimIKQ0tJikDExS0CloEgooopjCiiigApKWkoELRRSUgCijFLTAKKSikAUUUUAFFFFACUZpaTFAhKKMUtIQUUUUDCkopaACiiikAUUUUwENLRRQA003NONIVqGS7jM0oNG2lAqbMSuOpDTgKTFVYoZinLRilApJCSFpaKKsoKKKKBhSUppKQgooooAKKKKQBRRRQAUlOpCKGFhKXFFGaQBRS0lMYUhpaDSENxSUtBqRDaSnGm0mSIaQ0tIalksbSGnUlSyRpppp1NNQyGNooNJUkBRSZpaACkpaQ0gEpKWkqSWNNJTjTalkBRRRSAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKADFLRRQAlLSUUwCiiikAUUUUAFFFFABilpKM0DA0UUUCFopKKB3CiiigQUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUtJS0AKKeKYKeKaLiSLUoqJalFbROiI9alU1EoqZBitoo6IEqinimilFbG6FNNpTSUxhSUUtAgpaSlFAxaUUlKKoYUUUU0MWmmlpKTQgooopiCiiigYlFLijFIQlFFFABRRRmgQUUUUwCkoooEFFFFABRRRQAUUUUwCkNLSGkAzNG6kYc00Dmo1MrkoNLTRSirRdxaKKKYBRR2pKQBRRRQIKKKKYwIpKdSUhBRRRQAUUUUAFJS0UAFJRRQAUUUtMQlFFFIApKWigBKKKKBBRRRQAUtFJQMKKKKBBRRRQAUUUUAFFFFABRRSUCFopKKACiiigAooooAWkoooAKSlooASkpaBSEJS0YooAKKKWgYlFFLQISiiigAooooAQijFLS0rBYZilFFFLYB1IRSZpc00wDFFLRQOwlFFFABRRRQAUlLSUgClpKKQgoopaBiUUUYoEFBooNAxuaQmgmmZrNshskBpc1GKeKExpjqKSirGFIaWkNSAlJTqQ0hDTSGnGmmpaJY00lOpKkhjD1pDTjTTUshjTTacaSoIYlFFFIQUhpaDQA2kp1NqSRKbTjTaglhRRRQIKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAUUlLSUALSUtBoGJRRS0CEooooAKKKKACiiigApaSigAooooAKKKKACiiigApaSigBaSiigAooooAKKKWgBRTxTBTxVIuJKtSrUS1MtaxOmCJFFSoKYoqUV0RR1RQ4DFOxTacK1NRDSGlNIaACiiigApaKKYC0UUopjCilxRTASkpaSgAoooxSAKKKKEAUUUUxBSUUuKAEooooEJS0Ud6ACkpaKAEopaSgQUUUUAFFFFMAoIoooAZikxTyKQCpsRYAKWlAoNMqwlFFFMQUYpKKQBRRRQAtFFFACUUUUAFFFBpgFFJRSELRRRQAlFBopgFFLRQAlFFFIQUUUUAJRRRQIKKKKAFpKKKBhRRRQIKKKKACiiigAooooAKSlooEJRRRQAUUUUgCilpKYBRRRQAUUUUAFJS0UAJQKU0lIQtFFFAwooooASiiigQUUUUAFFFFAxpFJyDT6TrUtE2EHNLQBS0JWGFLSUtMYUlFFABRRSUALRRRSASilpKBBRRRQAUtJS0DCkNLRSYEZFJipMUm2psTYaBTgKcBRTsNITFFLSUDEpDRSVLJCilpKQCGkNOpppEtDTSU402pJY000080w1LIYlNNOpprNkMSiilxSEJRS0UANpKU0lSyWNNNp5ppqWQxKKKKQgooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAXFJRRQAUUUtABSUUtABSUtJQAUUUUAFFFFABS0lFAC0UUlAwopcUlAgooooAKKKKACiiigAopaSgAooooAKMUUUAFLRRQMUU9etMp61SLiTLUy1CtTLW8UdMCZakFRLUoreJ1RHClpBTqs0EpKWm0xC0UUUhgKdSClqkMBS0UCmgCilopjEpKXFFABSUtJQIKKKWgBKKKKBBRRRQMSilpKBBRRRQIKKKKACkpaSgQUUtJQAUUUUAFFLSUwCiiiiwBRSUtIQUlLSUAFFFFACUUtFFhCUUUUALRSUtABQaKDTAbRRRUtiFopMUtMYUUUUCEopaSgAooooAKQ0tNNBLClFNzQKVxJjqKBS0ygpKWkoAKKKWmAlFFFIQUUUUAFGKKKACiikoELSUUtACUUUUgCiiigAopaKYCUUuaSgApKKKQC0UUUwCiikpALRRRQAlFLRQAlLRRQAmKWiikAYzSYpaKYaCUmaUmoyahsTdh4pc1Gp5p9CYJi0UClqhiUUUUAJS0UUhBRRRQMTFLRRQAUUUtACUUtJQMKKKWkAlFFFABSYpaKLAJikNOpKTENxRinUhqRWG0UtJSExhpDTjTTUshjTTTTjTTUMzYw0lONIahkMbS0UlSSGaWkpaAGmkpTSVLAQ0004001LIYlFFFIkKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACilooHYSlpMUtABRRRQAUlLSUALRSUUAFFFGKBC0lFGKACiiigBaSlpKACiiigAooooAKKMUUAFFFFABRRRQAUUYpaAAUUUtA0KKeopgqRaaNIkq1MoqJamWuiJ1QJBUgpgp4reJ0IcKdSClqyxKSlNJTGFFFLSABS0lLTQ0FLSUtUhi0UUUwCkpcYpDRcQUUUUxiUUtJSsIKKKKBBRRRQMSlopKBC0lLSUAFFFFMQlLRSUhBRS0UAJRS0UwCkpaSkAUUUUAFFFFMApKWigTEooopMAooooAKKKKYgooooAKKKKAG4pcUtFKwBSUtJTAKDRRSASloozQISiiikAU006kIoJY3FAFLilAoSFYKKKKYxaKKKBhRRRQAmKWkooAKKKKACjNFFAgpKWigBKWikoEFFFFIApaSigBaSlpKYwoopKQgopKUUhC0UUUxhSUUuKBCUtFFAwooooAKKKKACiiikAUhpaKAGmmEVIRSYqWiWrjVFPFAFLTSGkFFFFMoKSlooASilpKBBiilooASilxRSAKKSloGFFFFACUUtFIBKKWkoAM0UUUAFFL2pKQCGkxS0UhCUlLQaQhhppp5phqWQxpphp5phrNmbG0hpTTagzYUUlFS2IWiikoASg0UGkyRppDSmmmoZLEooopEhRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAtJS5ooGFFFFABRRRQAUUlFAgooooAWikpaLDuFFJRQIWkoooAKKKKACiiigApaSigBaSiigAooooAKWkooAKWkooAWlptKKBocKkWoxUi04mkSZamWoFqda6InVAlFPFMWpBXRFHTEcKWkFOqixppKDSUCFpabS0DTFpaSnCqQwoopaYwpaSlpgJSUtFACUUuKKYWEpKWigQlFFLSASiiimAUUUUCCkpaKAEooooEFFFFACUuaKKQBRRRQAUlLSUxBRRRSQBRRRTAKMUUUAJRS0UCEopaKAsJRRRQIKKWkpDCiiigQUUUUwCiiigBKKKKQBRRRQAlFFFIQUUlFAgzRRRQAUtFFMAooooAKKKKAEopaSgAopaTvQwCiiigQUUUUAFFFFACUUtJSAWiiimAUUUlIApKWjFAhDQKKWgQUUUUDCiiigAooooAKKKKBhRRRQAlLRRSEFLSUUxi4ooooASijFFIAopaSgAooooAKKWkoAKKKKACiiikAUUUUAFFFFABRSUtABQaKSkAUUUUAFLRRSGNoNLSUiRKKXFJigQ00004001DJYw0ynmmGs2ZMbSUppDWbM2JSUtFKwhKKWigBDSUtJSYhppppxppqCGJRRRSJCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigBaSlpBQAUUtGKB2EooxRQIKKMUUAFFFFABRRRQAUUUUAFFLSUAFFFLQAlLSUUAFFFFABRRRQAUUUUAFFLSUAFGKKWgBMUtFFAxwqRajFSLVxNIkyVMtQpU61tE66ZItSCoxUgroidERwpaBQassaaTNKaSkxMKWkpaYCilFIKWmikLQKKWmhhRRS1QxKKKTNIQtFFGKYCUUUtACUUUUgCkpaKYhKKKKBBSUtFACUUtFAhKKKWkMSiiii4gooopgFFFFAgoooxQFgooooASilpKACiiigAoopDQAUUZpaBBRmg0lIAooopgFFFFAgoopKQBRRRQAUlLRQIKSlooASiiilYQUmKWigAooopgFFFFABRRRQAlLRRQAUUlFABRRRTEFJTqSkFhKM0tJikAtFFFMAooopAFFFFACGkzS0YoFYSlpKWgAopaKBiUUUUAFFLSUgCiiimAUUUUgCilxSUAFFFFABRmiloAKSlooAKSlooASiiigBaKSjFABRRRQAUUUUAFFFFIApKWigAooooASlopKQC0lFLQAUUUGkMSiiigQlFLSUhDTTDTzTDUsiQw0w080w1kzJjTSU4001DIYlFBopEhRSUtIBppKcaShkjTTTTjTTUMhiUUUVIgooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAWikooC4tFJS0DCkpcUmKBC5ozSUYoAKKXFJigBaKKSgApaSigBaSlpDQAUUUUAFFFFABRRRQAUUUUALRRSUDCiiigQUUYpcUAGaUUlLTQ0KKkWmCnrVI1iTLUy1CtTLW8DpgSrUgqNakFbo6YjxS02lq7GghptONJQIAKKKDQAopRTRThTQIWlpBS1VixaUUlFMBD1ppOKc1RsKlkvQcDTs5qNadmhAmOpO9FLVDCkpaTFABRRRTsISiiikAUUUUCCiikoAWiiigAooopAFJS0lABRS0mKAClpKWmISiiigBKWiiiwgxSUtFACUUUUAFFFFAhKKKKACilpKACiiigAooopAJRS0lAgooooAKKWkoASilooEJRRRSAKKKKACiiimIKKKKACiijNAwooooADSUtNxSExc0UUUxBRRS0DEooooAKKWigBKKWigBtFKaSkIBS0gpaACkpaKAEopaKAEpaKKQCUUtJigApaTFFMBaSilpAJRRRQAUtAooAKKKKBhRRRQAlGKKXFACUtFFABSUtFIAooooASilpKACiiigQUUUUDCiiikIKKDRQOwUUUUAJS0UUgDFJS0lAMaaYaeaaahkMiNNNPNMNZsxkNNNNKaSsmZsSiiikiWFJS0GgBDSUtJSENNNNONIahkMbRRRSJCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigBaKM0UDCiiigAooooAKDSUUCCloooGFFFFABSUtJTELRiiigBKKWikAlLRSUALSUUUAFFFFABS0lFAC0lLmkoAKXNJRQAU4UlKKBocKkWoxT1qkaxJlqZKgWp1rogdMCQVIKiU1KDW6Z0RJByKKaKdVGiEooxRimAUmKM0tMAxSikpwpoaFpaQUtMoKM0lFAXA0win5pKNyWMApwpcUuKEgsJS0UGmMQmkzSE0malsm5JSUgNLmqTGFJTqSmFhKKKKQBRRRQIKKKKACiiigAooooAKKKKACiikoAKKKKBBQRS0UAJRS0lACGkzSmkoJFopKWgAooooGFFFFAgpKWigApKWkpAFFFFABRRQaLiCkNFFABRSUUhBRRS0AFJRRRcAooopgFFFFAgooooAKKKKACkpaKADFFGaKQBRRRQAUUUUwEopaMUBYKKKDQAhpMUtFIQUUUUDDFFLSUAFFFFAgooxRSAKKKKBhRRRQAUUUlAgopaKACiiigAooooGLSUUUAFGaWkoAKKKKACiiigAooopAFJS0UAJS0UUAFJRRQAUUUUAFFFFIAooooAKKKKQBSGloNAMYaaaeaYalkMYajNPNMNZSMZDTTTTjTTWTZmxKSlopEhQaKDQAlJS0hqRDTTTTjTTUtkMSiiikSFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABiloooGFFFFABRRQaAEooooEFFFGKACilooAKSlooGFFFGaYgooopDCkoooEFFFFABRRS0AJRS0lABRQKKAClpKWgApRSUCgaHinrUYqRapGsSVamWoVqZa6IHRAkWnimCpBzWyOiI9adTRTq0Rqhe1MJp56VHmhgwpwpmacKEJDhS00U6qRSFFOPIpopaooaTimljTsZNBUUmiXcFHFLikHSlpjQtFFFAxKQ06kNAmRkUmDTzSYpNENAKUUAU6nYpBSUtJQMKSlopiDFJilopAJRS0lAgooooAKKKKYBRRRQKwUUUUhhRRRTEFJS0UgEooooAQ03FPNJQSxBS0UtAwpDS00mkwClpuaAaLiuOooopjCkpaSgQUUUUAFFFFIQlFFFABSUUtIQlFLSUAFFFFAC0lFFABRRRQAUUUUxBRRRQMKSlooEJiilooASloooASloooABS0lFAwooooAKMUUUCExSiiikFgpKWigApKWkoAKKKKQBRRRTEFFFFIYUUUUAFFFBoAKKSlzRcAooooAKKWigApKWkoAKWkpaBiUUtJQIKKKKACiiigAooopAFFFFABSUtFABSUUUgCiikoAUUtNpaAFptOpKGA00w080w1myGRtTDTzTDWTMZDD1pDTjTTWbM2JSijFFBIYpKWkpDEpDS0hpEjTTTTjTTUMhiUUUUiQooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKWiigYUUUUAFFFFACUUuKTFAhaKKKBhSUtFACUUYoxQIKKKKAFpKMUUAFLSUUALikpaSgBaKKSgYUUUtAgoNJRQMWikpaAClpKWgaHCnLTBUgpxNESLUymoVqZa3ibwJRUi1EtSrW8TpiPFKKSlFaI1QHpUfOakPSm0MTQ0dakHSm04dKECFpabThVlIWlpBS0yxCKAKWlxTFYQCilNJQAUUUUDCiiigQmKTFOpKBWCiiimAUlFFABRS0UCEooopAJRS4ooASloooAKSlpKYhaKKKQCUtJRTADRRmikAUUUUAFJS0UxCUYpaKAG0tFFILCUw1JTSKTJaIzmnLSkUBalIlJi0tGKKssKSlNJSELSUtJTAKSlopAJSUtJSYgooooEFFJS0gCiilpgJS4pKWgApKWkoAKKKKACiiimAUUUUgCilopgJRS0lABRRRQAUUUUAFLSUUAFFFFABRRRSYgooooAKSiloASloooASlxSUtABRRRQAlFFFIAoNGaDQA2lFFKKQgopcUlMYtJmiikAuaKSlpoYUlFLQISilooGJRS0lAC0UUUAFJS0lABSGlpDSYhKM0UVIhc0lJilFIAzRQaKYBS4oFLTGFIaWkNAMaaYaeaYahkMjamGnmmGsZGMhpptONNqDNhRRRUiCkpaQ0AxKSlNNpMgQ0004001DJYlFFFIkKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKAFooooGFFFFAwooooEFFFFABRSUtMQUUUUhhRSUtAXCiiimAUlLSUgCiiloEJRRRQAtFJRQAtJS0UDEopaSgQClpKWgaClpKKBjhT1pgp4qkXElWpVqJalWtYnRAlWpFqJTUgreLOmJJSikFKK1RohaTFLS0x2G4paWm96YC0tJS0xjhS00UtNFC0uaZSg0wuOpKWkoGFFFFFhAKKKKAEooooEFFFFMYUUUUCCiiigApKWkoEFFFFABRiilpAJRRRTAKKKKAEoNLSGhiG0uaSipJHUUlLTuUFFFFMQUlLSUhhS0UUCCkIpaKLANxS0uaSgLB3ooooASiiigQUlLSUgCiiigQlFFFIQlFLSUCDFFLiigLBSUtFMBMUtFFABRRRQMKKMUUCCjFFLQMKSlpKYBRRRSAKSloouIKSlooASlpKXFABSUtFABRRRQAlFLSUAFFFFAgxRRRSGFFJS0AFFFLQAlFFFAAabTyajNJiYtGabnmnCkhJhilozRTGLQelFFMY00lOpKmwhRS0UUxhRRRQAUUUhNAC0U3NOBoC4UUUtACUlLRQAUhpaDSCw2jFLiiiwrCYpMU6ik0FhtKBS0UBYMUtJS0xoDTTSmkNJgxpphpxphrNmUhhphpxpprJmUhpptKaSoM2FFFLSEJSGlpDSBiUhpaQ1LJYw02nGm1BmwooooEFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFAC0UUlFh3FopKWgLhRSZpaLCuFFJRQAClpKWgYUUlLQIKKTNFAC0UUUDCikooEFGaWkoAKKKKAFopKKACiiigBaSiinYApaSigBaKSlpDFFSLTBT1NUkaRJFqVaiWpVraJvEkWpVqIVIprZHREkFOpopa0RqmLS0lLVFIWkoopgFKKSlFNAhRTu1Npc0yxDQKKAKBDqO1LiinYaEooooGFFFFAhKKWkoAKKKKYgooooAKKKDQFgpKKKBC0lGaXNACUUUUAFFFFABRRRQAUhpaDQA3FGKWilYmwYooopjCkJpTTDSYmOzS4pmacDSBMWiiimMKKKKAEooooEFFFFACUUUUhBRRSUAGaKSkPFBNx2KKQGigAzRRRQIKKKKBid6UUYooELSUUUDCilooAKSiloASiiigAoopaACkpaSmAUUYpaVgEpDS0UxCUtFGKQBRRRQAUlLRQAUUUUAJRRRQAUUUUrCAUtJS0DEpaKKACkpaSgGIabmnE02pfkSwxTsUgFOpgkG2k6UuaKBhmjFFFMYYooooAKWkpaAEopaKBiUxjzTz0qM9alkyDNOFM708VKEhwpaQUtWWFJS0lABSUtFAhKKWkoAXFJS0lIAopaKACilpKBiUhpaaaTExDUbU81GazkZSGGmU402smYsQ0lKaSoICiiikAGmmlpDSYmJTTTqaalkMYaSlNJUszCiiikAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUALRRSUx3FopKKBC0UUUhhSUtFABRSUtACUUtIaACiiloEJRS0UDEooooEFFLSUAFLSUUAFFFFABRRRQAUUUUAFFFFAC0UgpaYxRTxTBThQi4kq1KtQrUq1rFm8SVakFRrTxW8TeJKKdTBThWqNkLThSCiqKFoopaYxKUUlKDQMWlpM0oqhoMUoopRTGFFLSUDsJRS0UwEoopaQCUUUUxCUUtFABSUtFABRRRQA00UGiglhRRS0AFBoooGJRRS0CEopaM0AJS0lLQMSilpKBBSUtJQIDUZ61JTcUmiWhop9IFpwFJIEgFFLSVRQUYoooAKDRQaBCUUUYpAFJRS0CEopaQ0AxhBpvepaaRUtEtCgcUUUUDCiiimAlLRRigQUUYooATFKKSloAKKKKYBRRRSAKSlpKAClpKWgApKWjFABRRRTASloooAKKSlpAFFFFAWEpaKKAEopaSgAooooAKSlooEIKWikpALRSUtABSGlpKGDGkUDiloxU2FYM0tFFMYUtFFMBKWiikMKSlopgFFApaBiUhpaSkJiGmEU/FGKViWhoFPAoApcU0hpBRRRQMKKKKACkpaSgBaTFFLSASiiigAopaKACkpaQ0AJTTTqaaTJYw0xqeTUZrJmUhhptONNrJmTENJS0lQQBooooAQ02nGmmkyWJTTSmkNSyGNNJSmkqWQFFFFIAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAWkpaKB2EopaKAEpaKKYgooopDCiiimAUlLRQISlxRRSHYKKKKAEopaKBCUUUUAFFFFAAKKWjFACUUtFA7BSUtFACUUUtAgooooGLThTaUU0UiValWoVqVa1ibRZKtPFRg08GtonRFkop4qIU8VombRY+lFNFOFWi0LRRmlqigFIaWmmmxC5pwqMGpBSTGtR1LSUtUXYWkopaoYYptOpKLCEooooAKKKKBBRRRQAUUUUAFFFFACUUtJQKwUUUUAFFLSUwCiiigApKKWgQlLSUtIYUlLSUAFFFIaGJhmim5oBpXJuOpaSimMKKKKQBRRRQAUlLSUCCloooASjvRRQAlLRRQISjFLSUgsFFLSUwsJRS0UCEpcUUUAFJRRSAKKKWgBKKKKACiiimISilxRSASiiigApaSloAKKKKBhRS0lMAooooAKKKWgBKKKKQBSUtFAhKKKKACiiigAooooAKKKKQBmiilpgJRRRSAKKKKACiiigAooopAFFFFMApaSloASiiigAxRRRSAWkzS0lMYUUUUAFFFFABRRRSEFFFFABRRRSGFFFFABSUtIaAENMJpxphqWZsYaYakao2rKRlIYaSlNIayZkxtFFFSSFFFJQIDTTTjTTUsTGmmmnGm1DIY2ilNJSICiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAWlpKSgdxaKSloAKKKKLAFFFFABRRRQAZooooAKKKKADNGaMUUAFFFFABSUtFACUUUUCDNLSUooAKM0UlAxaKKSgVxc0lFFABS0lLTGKKcKbSigpEi09TUYqQVcTWLJRTxUa08GtkbxZKKeKjFPFaI2ix9KKQUtao0Q4GikFLVIpMWmmnCkIoGxoFSLTcU4U0hRHClptLVFoWikpaZQUUopDQISlpKWgApKKKACiiigAooopiCiiigApKWigAoopKQBRS0lMQUUUUgCiiimAUUuKQ0AFJRmlpCEprU+mNQ9hSIyaVeaQilUVnYzV7jxS0gFOq0aISiilp2ASiiigApKDRSEGaKSloAKKKKACiiigAooooAKSiikIKKKKACiiigApKWinYQUUUUAJRRS0WASiilxQAlFLSUrAFFGKWmAlFFLQAlFLRRYAooooAKSlooASiiigApaKKAEooopAFFFFAhKKKKAFoopKBhRQKWgBKWkxRSAKKWkoEFFFGKACijFLiiwCUUUmaAFoopaBhRRSUAFLSUtAgpKKKBi0UUUgEpaKKLAGaSg000MVx1FIDS0hphRRRTsAUUUUWAKKMUUgCkpaaaBMQ0w040w1DIY01GaeaYayZixp6000402s2ZMSiiipEFIaWkoEJSGlpppEsaaaacaaazZDEooopEhRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUALSUtFAwooooAWkozRmgAopKKYhaKKKTGgooooAKKKKADNJS0UWASjFLRQAUUZooASilpKBBRRRigBaKSigAooooAKWiigYUUmaKYhc0tJSigaHg1IKiFSLVI1iyQGpBUYqQVtFm8SQGnioxTwa1RsmPFOFNFOzWiNULTqbSiqRSFpaSlplIWiikqgHUtIKWmUFLSUUxi0UUUwCiiigApKWkpALRSUUALSUUUCCig0UwCiiiiwBSUtFACUUUUCClopKBhS0daKACmHrTzTCaTYmFKKjJyaeOlStWSmOpjU4UGqYMjxTgKKWkhJC0UlFMYUtJRQAUUUUgENJTqSkJiClpMU6gEJS0UUxhSUtJQIKKKKACiikpCCiiimAUUUUAFFFFABRS0lABRRS0ANpaKKBBSUtFIYlLRRTEFJS0UAFFFFABRRRQAUUUUAFFFFABSUtFIYlFLRTEJRRRSASig0UCFpKWigYlLRRQAUUUUAJRS0UAFFFFABRRRQAhpKWkxSZLFFLSCjFFhi0UUUDCiiigAooooASlopKQBRSZoJoEBNNp1JSEwFOFIBS4oGgoooxTGFLRRQAUlLSUAIaQ0pppqWSxDTDSk001DM2xpphpxphrJmUhDTTS0lZszYUUlLSASkNKaQ0XJY2kNOppqWSxhpKU02szNhRRRQIKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigBaKKSmAUtFFIYYopaSgAooopiEpaKDQAUUlGaAFopKBSAWiiigYUUlFAhaM0lFABS4pKXNABmikooAWikopgLSd6KKQC0UlGaAFooopgFOFNpQaLlIcKeKZSg1SZaJlqQVEpqQVqmbxJBTxUYp4rVM2Q8U4GmCnirTNEOpwNMpRVlodmnUlFUUh1FJmimMUU4U2lplIdRSUoqhhRS0UxiUUtJikIKKKKYBRRRQAUlLSUAFFLSUCFpKWkoGFFFFAgooooAKKSigBaKKKAEJppFOopbktEe3mn44o70oFCQkgFIadTcUymJilxRilpWFYSiiigApKKMUCCiiiiwBRiiigAooooAKKSlpAFJS0lAgoopKBBRRRSAKKKKACiiloASilopgFFFLTGJRRRSASloopiEpaKSgApaSloASilpKACiiigQUUUUhhRRRQIKKKKBhRRSZoELRSUUgFooooASkp1JQAUUUUALSUtFAxKKWkoEFFFFABRS0lABRS0UANop1JQFgxRS0lABRS0UDEoopaQCUUUUAFIaWg0CExRiiikIKMUtFAwAooopgFFFFIAooozQAlIaWkNIQlNNONNNSyWNNMNONNNQzNjTTDSmmms2ZNiUlLSVmyAoopKAuFJRSGpZNxDTTSk001DJbGmkpTSVJmwooooEFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUtFVYAooopXAKKKKGMKKKSkAtJS0UAJRilooCwlLRRQAUUUUAFJRRRYQUUtJQAUYoooAWikooADRRS0AFJS0lABRRS0AJiilooAKKKKYxRThTacKaKRKtSLUKmpVNaRN4slFOFRinitUbRZIKUU0U4VojRMeKWminVaNEOpaaKWrRSHUUgpaooWlFJQKBi0ZoNNzQ2Fx4NPFQg808GmmNMd3oopKpFXCiiigQUUUUgCkNKKRqAG5ozTSaTdSuZ3JM0tNBpRTuUmLRRS0FCUUtJTAKKKKBBRijFFABSYpaKAEpaQ0UCFpKKKACilpKACkoooEFFFFIAooooAKSlpKBBRRRQAUUUUgEpaKSgApKWigQlFLSUCEpaKUUAJS0UUDsFLRRQAlLSUtMBKKWigBKKWkoEFFFFACYpaKKACkpaKADFJS0UAJRS0lABRRS0AJRRRSAKKKKAEopaSgQUUUtABSUtFIYUUUUwCiiikAUlLRTEJS0UUhhRRRTAKKKKACiiikAUlLSGgQZoBpM0makVx9FJS00UFJS0lABRRRQAUUUUAFFFFAhaSiigYUUUYpAFJS0lJgFIaKQ0iRDTDTiaYalkNiGmmnGmGoZmxppppxNMNZtmTCiikzUkhSGlpKQmIaaacabUsljTTTTjTTUNmbEpKWkqSQooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigBaKWkpjCiilpAgpKWkoBiGilopiCiikpDFpTSCg0AFFFFMQUUUUhiUUtFAgoopKYBRS0UgEopaSgAoopaYBiiiigAopKWgAooooGFFFFK4C04U0cUoNUNMeKkBqIGnqauLNEyZTUgqFTUgrVM6IskFOFMFOBrRM1Q8UuaaKWrTLTHA08VGDTxTTLTHUtJS1oihaWkFLVIoQ00in4ppFSxNCDinimhTTulNDWg4UtIDS1aLEopaKAEooooEFI1LSGgTRGVpMVJijFTYnlEFOFAWlp2KSCiiimMKKKKAEoopaBBSUtJQAUUUUgEoooxQISlpKWmAtJRRQAUlLiikAmKXFFFBIlFLikoGFFFFMAooopCCkpSKTFABRRiigBKKWiiwhKKKKQBRS0lAC0lLijFMAopaSgYUUUUxBRRRQAUUUUgCkpaSgBcUUUUwCkpaSgQUUUUgCkpaKAEopaTFABRRRQAZopKWkIKKKKBhiilooASlpM0UAFLRRQAlFLRQAlFFLQAYooooGFFFFIAooooAKSlpKACkNLQaBDcUmMU6lxSJsJS0YoosUFFFFACUUuKSgAooooAKKKKAFooooAKQmlNMzSYmxaKbmlzU3C4GmmlpDQyWxppppTSVm2ZsaaYacaaaiTIYw0lKaSs2ZMKTFLSUCA0lBpDUsQhpppxNMNSyGIaaaXNNNQQ2FFFFIkKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAWjNFFCGFLTaWnYLi0maWkxSBhSUUUCCiiigBaKKKBiUtBpKBC0UUUAFFJRQMWkoooBiiikpaAEooooEFFFFABS5pKKACiiigApaSloAKKSloGFKKSlFUCHCnLTBThTRoiYGpBUINSg1qjaLJBThTBTxWiNoscKWkFFWaXFqRTUYFOFVEaJKXNNFLWhohwpwpgp1UikOpppwppoY2Aem5yaXbSAc0rMV2PFOFNFOFWi0OpKUUlMoKWkooEFJS0UAGKMUUUAFFFFAmJRS4pKAuFFLSUAJS0lLQISilooAKSlpDQAlFFFAgxRRRQAUUtJQAUUpFJQAUUUuKTEGaTvRiigdgooxSUxBRRRSAM0UUYoEFJS0lABRS0UAJS4oooCwlFFLQAUUUUAFFFGKADFFFFACUUUYpgFFBooEFFFGKACiiigAooooAKKKKADFJThSGkIKSiiiwBSUtFACUUtFIAooooAKWkpcUwExRS4opDEoxRS0AJRRRQAUUtFACUUuKSgQUUYooGFJS0UAFFJRSEFFFFABS0UUAFFGKKYwpKWmmkxC5pOtKBRUgGKKWkpjCiiigQUUtJQMDTCKeaaaTJY3FFLikqSbCUhpTTTUtiY00hpTTSahkMQ0w040w1DMmxDSUUVDIYlFFJSEFJRSGpbJYhphpxphqWyGIaSiioMwooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAWiiihDCiikpgLmiiigAooooEIaKXNJSAWikFOoGIaSlpKBBRRS0AFFFFIYlFLSUxBRRRQAUtJRQAtFJRQMWkoooEFLSUUAFGaKKAFopKWgdwpRSUUwHU4UylBplJkoqRTUKmpQauLNoslBp4qIGng1sjaLJAaUU0U6rNEx2aXNNFKDVItMeKdUYp4qy0x1LTaWrTKHikNFLVFCZoxRRQAop4plKDQmUh1LSUZqhi0YoBozTBiUtFFACUUppKQBRRRTELSUUUgsFJS4ooCwYpMUtJQKwYopaXtQA00lLSUAFJS0UgENFLSYpiFo70UUDFNNNKaaaBBmnA1HmlBqbiTH4opM0tUMBSU4CkPWkAYoxQKdQxDcUHpSmkxSCw2ilxRimISilooGJQKKWmDCilxSVIkFJTiOKSmgExRS0lMBaSlooASlpKKAA0lKRSCgQUtFBpWAKSilpjEopaUCgTExRSmkxSASijFLimAlFFFABigilopANpaKKACijFLQAlLSUUWELRSUtAxKKWkoGFFLikoEFFFFMAopaCKkYlJS0UAJRS4pKQgpKWigAooooAKKKUUAJRTqSgY2gmg0mKCWFKBQKWlYEFFFFAwooooAKSlpKLgBpKKQ0riA00mgmkqWQ2FNNGaaahktiGmmnGmGs2ZsQ0w9KUmm1DZkwooooEFNNKaSoYriU0mlJphNSyGwNMNKTSZqDNsSiiikSFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFADqSikp6ALRRmihK4BRRRTsO4UUUVLBCUUpooCwUUUUABooooAKKKKADNJRRQIWkpaSgAooooAKKKKACg0UtAAKKKSgAooooAKKKKACgUUtABRRRQMWikpaY0PFSA1EKkFVE0iyVTTxUSmpAa2RvFjxTxTAacK0TNEOpabSiruWmOFPBqOnA1SZSZJSimZpQao0TH5ozTc0ZqrjuPzSE0maTNFx3FzTlNMpymhMEx+aTNJTSadxtj84pQ1RbqUGhMSkTZozTBSiqKuOzRSZxS5p3GFFJmigYtFJSii4gooNJmkFxaKSlpibEooPWlHShgGKQilzRSuIbRRmimAUUUtK4CYooJpKLgLTTTs000XBjDSiloFTYgdinYpMUGqRSFFIaBS07jAUtIKM1IhabmlJptNALmlIplOzxQwA0lBNFAgozS4pDRcAzQKSlouK4pNNpaAKLjFpKXFFFxXCkoJoBoGJiinGm5ouFwzRSUtMApKWii4rgKKSjNAC0UmaKAHUU3NGaAHUlGaWi4XDFFGaKVxDTSijFFF0MDSUUUBcM0tFFK4XDFLSZpM0xC4opM0oNIAoopDRcdxaDRmkzQMWiikJwKdxC0VHup4Oam4rgaKDSZqhi0lFFIApabS0AFAoopALRSZoJoGLmikFBoFcTvRS0UgsFFFLRcBKKKKBhRRSZoAWkNJmkzSJuLTSaM0hqWxNiE0hNFIalshiE000pppqGyGBphpSabmobM2xDSUtNJqGQwopM0mc0rk3A0maWmmlcliGmGnGmGokyGJRRSVBAUUUUCCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigD/2Q==","timestamp":"2013-01-26 23:48:10.929"}}
+
+{"command":"result","type":"reply","values":{"sensors":[{"arg":"0.448","des":"","pos":"1","tar":"n","xAvg":-389.8090465640172,"xCur":-389.8284781144781,"xReal":-174.6431,"xTemp":-389.8284781144781,"yAvg":216.2972694219192,"yCur":216.42513804713803,"yReal":96.9584,"yTemp":216.42513804713803}],"timestamp":"2013-01-26 23:48:11.277"}}
+
+
+
+[2024-12-05 22:27:50.030]# RECV ASCII>
+{"command":"result","type":"reply","values":{"sensors":[{"arg":"0.448","des":"","pos":"1","tar":"n","xAvg":-389.8064779454367,"xCur":-389.7319880066031,"xReal":-174.5999,"xTemp":-389.7319880066031,"yAvg":216.29694055999957,"yCur":216.28740356432976,"yReal":96.8967,"yTemp":216.28740356432976}],"timestamp":"2013-01-26 23:48:11.328"}}
+
+
+
+[2024-12-05 22:27:50.078]# RECV ASCII>
+{"command":"result","type":"reply","values":{"sensors":[{"arg":"0.448","des":"","pos":"1","tar":"n","xAvg":-389.8064779454367,"xCur":-389.7319880066031,"xReal":-174.5999,"xTemp":-389.7319880066031,"yAvg":216.29694055999957,"yCur":216.28740356432976,"yReal":96.8967,"yTemp":216.28740356432976}],"timestamp":"2013-01-26 23:48:11.375"}}
+
+
+
+[2024-12-05 22:27:50.127]# RECV ASCII>
+{"command":"result","type":"reply","values":{"sensors":[{"arg":"0.448","des":"","pos":"1","tar":"n","xAvg":-389.8051369446735,"xCur":-389.7662479225402,"xReal":-174.6152,"xTemp":-389.7662479225402,"yAvg":216.29437134855138,"yCur":216.21986421655373,"yReal":96.8664,"yTemp":216.21986421655373}],"timestamp":"2013-01-26 23:48:11.425"}}
+
+
+
+[2024-12-05 22:27:50.177]# RECV ASCII>
+{"command":"result","type":"reply","values":{"sensors":[{"arg":"0.448","des":"","pos":"1","tar":"n","xAvg":-389.8051369446735,"xCur":-389.7662479225402,"xReal":-174.6152,"xTemp":-389.7662479225402,"yAvg":216.29437134855138,"yCur":216.21986421655373,"yReal":96.8664,"yTemp":216.21986421655373}],"timestamp":"2013-01-26 23:48:11.476"}}
+
+
+
+[2024-12-05 22:27:50.229]# RECV ASCII>
+{"command":"result","type":"reply","values":{"sensors":[{"arg":"0.448","des":"","pos":"1","tar":"n","xAvg":-389.8051369446735,"xCur":-389.7662479225402,"xReal":-174.6152,"xTemp":-389.7662479225402,"yAvg":216.29437134855138,"yCur":216.21986421655373,"yReal":96.8664,"yTemp":216.21986421655373}],"timestamp":"2013-01-26 23:48:11.527"}}
+
+
+
+[2024-12-05 22:27:50.277]# RECV ASCII>
+{"command":"result","type":"reply","values":{"sensors":[{"arg":"0.448","des":"","pos":"1","tar":"n","xAvg":-389.8051369446735,"xCur":-389.7662479225402,"xReal":-174.6152,"xTemp":-389.7662479225402,"yAvg":216.29437134855138,"yCur":216.21986421655373,"yReal":96.8664,"yTemp":216.21986421655373}],"timestamp":"2013-01-26 23:48:11.575"}}
+
+
+
+[2024-12-05 22:27:50.327]# RECV ASCII>
+{"command":"result","type":"reply","values":{"sensors":[{"arg":"0.448","des":"","pos":"1","tar":"n","xAvg":-389.8051369446735,"xCur":-389.7662479225402,"xReal":-174.6152,"xTemp":-389.7662479225402,"yAvg":216.29437134855138,"yCur":216.21986421655373,"yReal":96.8664,"yTemp":216.21986421655373}],"timestamp":"2013-01-26 23:48:11.625"}}
+
+
+
+[2024-12-05 22:27:50.377]# RECV ASCII>
+{"command":"result","type":"reply","values":{"sensors":[{"arg":"0.448","des":"","pos":"1","tar":"n","xAvg":-389.8040744740049,"xCur":-389.7732628246152,"xReal":-174.6184,"xTemp":-389.7732628246152,"yAvg":216.2914982407032,"yCur":216.20817811310587,"yReal":96.8612,"yTemp":216.20817811310587}],"timestamp":"2013-01-26 23:48:11.675"}}
+
+
+
+[2024-12-05 22:27:50.427]# RECV ASCII>
+{"command":"result","type":"reply","values":{"sensors":[{"arg":"0.448","des":"","pos":"1","tar":"n","xAvg":-389.8019684632462,"xCur":-389.7408941512433,"xReal":-174.6039,"xTemp":-389.7408941512433,"yAvg":216.29163619952334,"yCur":216.29563700530724,"yReal":96.9004,"yTemp":216.29563700530724}],"timestamp":"2013-01-26 23:48:11.725"}}
+
+
+
+[2024-12-05 22:27:50.478]# RECV ASCII>
+{"command":"result","type":"reply","values":{"sensors":[{"arg":"0.448","des":"","pos":"1","tar":"n","xAvg":-389.8019684632462,"xCur":-389.7408941512433,"xReal":-174.6039,"xTemp":-389.7408941512433,"yAvg":216.29163619952334,"yCur":216.29563700530724,"yReal":96.9004,"yTemp":216.29563700530724}],"timestamp":"2013-01-26 23:48:11.775"}}
+
+
+
+[2024-12-05 22:27:50.529]# RECV ASCII>
+{"command":"result","type":"reply","values":{"sensors":[{"arg":"0.448","des":"","pos":"1","tar":"n","xAvg":-389.8019684632462,"xCur":-389.7408941512433,"xReal":-174.6039,"xTemp":-389.7408941512433,"yAvg":216.29163619952334,"yCur":216.29563700530724,"yReal":96.9004,"yTemp":216.29563700530724}],"timestamp":"2013-01-26 23:48:11.826"}}
+
+
+
+[2024-12-05 22:27:50.576]# RECV ASCII>
+{"command":"result","type":"reply","values":{"sensors":[{"arg":"0.448","des":"","pos":"1","tar":"n","xAvg":-389.8019684632462,"xCur":-389.7408941512433,"xReal":-174.6039,"xTemp":-389.7408941512433,"yAvg":216.29163619952334,"yCur":216.29563700530724,"yReal":96.9004,"yTemp":216.29563700530724}],"timestamp":"2013-01-26 23:48:11.875"}}
+
+
diff --git a/MyOpenCv/app/src/test/java/com/example/myopencv/ExampleUnitTest.kt b/MyOpenCv/app/src/test/java/com/example/myopencv/ExampleUnitTest.kt
new file mode 100644
index 0000000..2620244
--- /dev/null
+++ b/MyOpenCv/app/src/test/java/com/example/myopencv/ExampleUnitTest.kt
@@ -0,0 +1,122 @@
+package com.example.myopencv
+
+
+import androidx.test.core.app.ActivityScenario.launch
+import com.example.myopencv.models.CentroidData
+import com.example.myopencv.models.CentroidPoint
+import com.example.myopencv.models.Command
+import com.example.myopencv.models.ManSetting
+import com.example.myopencv.models.Sensor
+import com.example.myopencv.models.SensorData
+import kotlinx.coroutines.*
+import kotlinx.serialization.json.Json
+import kotlinx.serialization.json.JsonArray
+import kotlinx.serialization.json.JsonNull
+import kotlinx.serialization.json.JsonObject
+import kotlinx.serialization.json.JsonPrimitive
+import kotlinx.serialization.json.jsonArray
+import kotlinx.serialization.json.jsonObject
+import org.junit.Test
+import org.junit.Assert.*
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+class ExampleUnitTest {
+ @Test
+ fun addition_isCorrect() {
+ assertEquals(4, 2 + 2)
+ }
+ //@Test
+// fun calc_CentroidPoint() {
+// val cp2 = CentroidPoint(-284.11025502125176, 210.8166722226852)
+// val centroidDataArray2 = CentroidData("", mutableListOf(cp2))
+// val deflectometer = Deflectometer()
+// deflectometer.updateSensor( mutableListOf(
+// Sensor(
+// arg = "0.448",
+// des = "",
+// pos = "1",
+// tar = "n",
+// x = "97",
+// y = "1054",
+// h = "425",
+// w = "569",
+// xZero = 0.0,
+// yZero = 0.0
+// )
+// )
+// )
+// deflectometer.readSensor().forEach {
+// val sd = SensorData(sensor = it)
+// deflectometer.m_result.sensorsData.add(sd)
+// }
+//
+// //设置上次数据的avg
+// deflectometer.m_result.sensorsData[0].xAvg=-284.03910070884103
+// deflectometer.m_result.sensorsData[0].yAvg= 210.88589473100282
+//
+// val r2 = deflectometer.dataProcess(centroidDataArray2)
+// assertEquals(r2.sensorsData[0].yReal,94.4458,0.0001)
+// assertEquals(r2.sensorsData[0].xReal,-127.2813,0.0001)
+// }
+
+ @Test
+ fun parseCommand(){
+
+ val json = Json { ignoreUnknownKeys = true } // 允许JSON中存在未知键
+ //报文处理
+
+ val payLoad="""{"command":"sensors","type":"set","values":[{"arg":"0.448","des":"","h":"425","pos":"1","tar":"n","w":"569","x":"97","y":"1054"}]}
+"""
+ //val payLoad2="""{"command":"sensors","type":"set","values":0} """
+ // decodeCmd(payLoad)
+ }
+
+ @Test
+ fun testLaunch(){
+ println("开始")
+ val r= runAsync()
+ println("结束")
+ Thread.sleep(2000) // 让当前线程暂停2秒
+ }
+
+ private fun run() {
+ val result= runBlocking {
+ val lr=launch {
+ doWorld()
+ println("Hello")
+ "123"
+ }
+ println("lr=${lr}")
+ "234"
+ }
+ println("r=${result}")
+ }
+
+ private fun runAsync() {
+ val result=runBlocking {
+ val lr=async {
+ doWorld()
+ "123"
+ }
+ delay(1100L)
+ println("Hello")
+ println("lr=${lr.await()}")
+ "234"
+ }
+
+ println("r=${result}")
+ }
+
+ private suspend fun doWorld(){
+ delay(1000L)
+ println("world")
+ }
+
+
+}
+
+
diff --git a/MyOpenCv/build.gradle.kts b/MyOpenCv/build.gradle.kts
new file mode 100644
index 0000000..922f551
--- /dev/null
+++ b/MyOpenCv/build.gradle.kts
@@ -0,0 +1,5 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+plugins {
+ alias(libs.plugins.android.application) apply false
+ alias(libs.plugins.kotlin.android) apply false
+}
\ No newline at end of file
diff --git a/MyOpenCv/gradle.properties b/MyOpenCv/gradle.properties
new file mode 100644
index 0000000..20e2a01
--- /dev/null
+++ b/MyOpenCv/gradle.properties
@@ -0,0 +1,23 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. For more details, visit
+# https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app's APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Kotlin code style for this project: "official" or "obsolete":
+kotlin.code.style=official
+# Enables namespacing of each library's R class so that its R class includes only the
+# resources declared in the library itself and none from the library's dependencies,
+# thereby reducing the size of the R class for that library
+android.nonTransitiveRClass=true
\ No newline at end of file
diff --git a/MyOpenCv/gradle/libs.versions.toml b/MyOpenCv/gradle/libs.versions.toml
new file mode 100644
index 0000000..cdbca42
--- /dev/null
+++ b/MyOpenCv/gradle/libs.versions.toml
@@ -0,0 +1,40 @@
+[versions]
+agp = "8.6.0"
+cameraCoreVersion = "1.3.1"
+kotlin = "1.9.0"
+coreKtx = "1.10.1"
+junit = "4.13.2"
+junitVersion = "1.1.5"
+espressoCore = "3.5.1"
+kotlinxSerializationJson = "1.6.3"
+lifecycleRuntimeKtx = "2.6.1"
+activityCompose = "1.8.0"
+composeBom = "2024.04.01"
+coreKtxVersion = "1.6.1"
+
+[libraries]
+androidx-camera-camera-view = { module = "androidx.camera:camera-view", version.ref = "cameraCoreVersion" }
+androidx-camera-camera-camera22 = { module = "androidx.camera:camera-camera2", version.ref = "cameraCoreVersion" }
+androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
+camera-core = { module = "androidx.camera:camera-core", version.ref = "cameraCoreVersion" }
+camera-lifecycle = { module = "androidx.camera:camera-lifecycle", version.ref = "cameraCoreVersion" }
+junit = { group = "junit", name = "junit", version.ref = "junit" }
+androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
+androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
+androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" }
+androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" }
+androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
+androidx-ui = { group = "androidx.compose.ui", name = "ui" }
+androidx-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" }
+androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
+androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
+androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
+androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
+androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
+kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" }
+core-ktx = { group = "androidx.test", name = "core-ktx", version.ref = "coreKtxVersion" }
+
+[plugins]
+android-application = { id = "com.android.application", version.ref = "agp" }
+kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
+
diff --git a/MyOpenCv/gradle/wrapper/gradle-wrapper.properties b/MyOpenCv/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..26f0e12
--- /dev/null
+++ b/MyOpenCv/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Sat Nov 16 20:08:14 CST 2024
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/MyOpenCv/gradlew b/MyOpenCv/gradlew
new file mode 100644
index 0000000..4f906e0
--- /dev/null
+++ b/MyOpenCv/gradlew
@@ -0,0 +1,185 @@
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=`expr $i + 1`
+ done
+ case $i in
+ 0) set -- ;;
+ 1) set -- "$args0" ;;
+ 2) set -- "$args0" "$args1" ;;
+ 3) set -- "$args0" "$args1" "$args2" ;;
+ 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=`save "$@"`
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+exec "$JAVACMD" "$@"
diff --git a/MyOpenCv/gradlew.bat b/MyOpenCv/gradlew.bat
new file mode 100644
index 0000000..107acd3
--- /dev/null
+++ b/MyOpenCv/gradlew.bat
@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/MyOpenCv/opencv/build.gradle b/MyOpenCv/opencv/build.gradle
new file mode 100644
index 0000000..315ae62
--- /dev/null
+++ b/MyOpenCv/opencv/build.gradle
@@ -0,0 +1,193 @@
+// This file is part of OpenCV project.
+// It is subject to the license terms in the LICENSE file found in the top-level directory
+// of this distribution and at http://opencv.org/license.html.
+
+//
+// Notes about integration OpenCV into existed Android Studio application project are below (application 'app' module should exist).
+//
+// This file is located in /sdk directory (near 'etc', 'java', 'native' subdirectories)
+//
+// Add module into Android Studio application project:
+//
+// - Android Studio way:
+// (will copy almost all OpenCV Android SDK into your project, ~200Mb)
+//
+// Import module: Menu -> "File" -> "New" -> "Module" -> "Import Gradle project":
+// Source directory: select this "sdk" directory
+// Module name: ":opencv"
+//
+// - or attach library module from OpenCV Android SDK
+// (without copying into application project directory, allow to share the same module between projects)
+//
+// Edit "settings.gradle" and add these lines:
+//
+// def opencvsdk=''
+// // You can put declaration above into gradle.properties file instead (including file in HOME directory),
+// // but without 'def' and apostrophe symbols ('): opencvsdk=
+// include ':opencv'
+// project(':opencv').projectDir = new File(opencvsdk + '/sdk')
+//
+//
+//
+// Add dependency into application module:
+//
+// - Android Studio way:
+// "Open Module Settings" (F4) -> "Dependencies" tab
+//
+// - or add "project(':opencv')" dependency into app/build.gradle:
+//
+// dependencies {
+// implementation fileTree(dir: 'libs', include: ['*.jar'])
+// ...
+// implementation project(':opencv')
+// }
+//
+//
+//
+// Load OpenCV native library before using:
+//
+// - avoid using of "OpenCVLoader.initAsync()" approach - it is deprecated
+// It may load library with different version (from OpenCV Android Manager, which is installed separatelly on device)
+//
+// - use "System.loadLibrary("opencv_java4")" or "OpenCVLoader.initDebug()"
+// TODO: Add accurate API to load OpenCV native library
+//
+//
+//
+// Native C++ support (necessary to use OpenCV in native code of application only):
+//
+// - Use find_package() in app/CMakeLists.txt:
+//
+// find_package(OpenCV 4.10 REQUIRED java)
+// ...
+// target_link_libraries(native-lib ${OpenCV_LIBRARIES})
+//
+// - Add "OpenCV_DIR" and enable C++ exceptions/RTTI support via app/build.gradle
+// Documentation about CMake options: https://developer.android.com/ndk/guides/cmake.html
+//
+// defaultConfig {
+// ...
+// externalNativeBuild {
+// cmake {
+// cppFlags "-std=c++11 -frtti -fexceptions"
+// arguments "-DOpenCV_DIR=" + opencvsdk + "/sdk/native/jni" // , "-DANDROID_ARM_NEON=TRUE"
+// }
+// }
+// }
+//
+// - (optional) Limit/filter ABIs to build ('android' scope of 'app/build.gradle'):
+// Useful information: https://developer.android.com/studio/build/gradle-tips.html (Configure separate APKs per ABI)
+//
+// splits {
+// abi {
+// enable true
+// universalApk false
+// reset()
+// include 'armeabi-v7a' // , 'x86', 'x86_64', 'arm64-v8a'
+// }
+// }
+//
+
+apply plugin: 'com.android.library'
+apply plugin: 'maven-publish'
+apply plugin: 'kotlin-android'
+
+def openCVersionName = "4.10.0"
+def openCVersionCode = ((4 * 100 + 10) * 100 + 0) * 10 + 0
+
+println "OpenCV: " +openCVersionName + " " + project.buildscript.sourceFile
+
+android {
+ namespace 'org.opencv'
+ compileSdkVersion 31
+
+ defaultConfig {
+ minSdkVersion 21
+ targetSdkVersion 31
+
+ versionCode openCVersionCode
+ versionName openCVersionName
+
+ externalNativeBuild {
+ cmake {
+ arguments "-DANDROID_STL=c++_shared"
+ targets "opencv_jni_shared"
+ }
+ }
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_17
+ targetCompatibility JavaVersion.VERSION_17
+ }
+
+ buildTypes {
+ debug {
+ packagingOptions {
+ doNotStrip '**/*.so' // controlled by OpenCV CMake scripts
+ }
+ }
+ release {
+ packagingOptions {
+ doNotStrip '**/*.so' // controlled by OpenCV CMake scripts
+ }
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
+ }
+ }
+
+ buildFeatures {
+ prefabPublishing true
+ buildConfig true
+ }
+ prefab {
+ opencv_jni_shared {
+ headers "native/jni/include"
+ }
+ }
+
+ sourceSets {
+ main {
+ jniLibs.srcDirs = ['native/libs']
+ java.srcDirs = ['java/src']
+ res.srcDirs = ['java/res']
+ manifest.srcFile 'java/AndroidManifest.xml'
+ }
+ }
+
+ publishing {
+ singleVariant('release') {
+ withSourcesJar()
+ withJavadocJar()
+ }
+ }
+
+ externalNativeBuild {
+ cmake {
+ path (project.projectDir.toString() + '/libcxx_helper/CMakeLists.txt')
+ }
+ }
+}
+
+publishing {
+ publications {
+ release(MavenPublication) {
+ groupId = 'org.opencv'
+ artifactId = 'opencv'
+ version = '4.10.0'
+
+ afterEvaluate {
+ from components.release
+ }
+ }
+ }
+ repositories {
+ maven {
+ name = 'myrepo'
+ url = "${project.buildDir}/repo"
+ }
+ }
+}
+
+dependencies {
+}
diff --git a/MyOpenCv/settings.gradle b/MyOpenCv/settings.gradle
new file mode 100644
index 0000000..8cb6916
--- /dev/null
+++ b/MyOpenCv/settings.gradle
@@ -0,0 +1,24 @@
+pluginManagement {
+ repositories {
+ google {
+ content {
+ includeGroupByRegex("com\\.android.*")
+ includeGroupByRegex("com\\.google.*")
+ includeGroupByRegex("androidx.*")
+ }
+ }
+ mavenCentral()
+ gradlePluginPortal()
+ }
+}
+dependencyResolutionManagement {
+ repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+rootProject.name = "MyOpenCv"
+include(":app")
+include(":opencv")