From 9b475a307393eb67d5b68e2fb85c206bb0d773a2 Mon Sep 17 00:00:00 2001
From: Watermelon02 <1446157077@qq.com>
Date: Tue, 26 Jul 2022 15:51:59 +0800
Subject: [PATCH] =?UTF-8?q?[+]=E6=89=93=E5=8C=85=20[+]=E8=A7=86=E5=9B=BE?=
=?UTF-8?q?=E7=BE=8E=E5=8C=96=E7=94=A8=E6=88=B7=E7=95=8C=E9=9D=A2=EF=BC=8C?=
=?UTF-8?q?=E4=BD=86=E6=98=AF=E6=9D=A5=E4=B8=8D=E5=8F=8A=E5=81=9A=E5=AE=8C?=
=?UTF-8?q?=E4=BA=86?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 30 +++++
app/build.gradle | 4 +-
.../tobe/ui/fragment/UserFragment.kt | 1 +
.../tobe/view/piechart/PieChartArc1.kt | 106 ++++++++++++++++++
.../tobe/view/piechart/PieChartArc2.kt | 102 +++++++++++++++++
.../tobe/view/piechart/PieChartArc3.kt | 88 +++++++++++++++
.../tobe/view/piechart/PieChartView.kt | 19 ++++
.../tobe/view/piechart/PieChartViewGroup.kt | 71 ++++++++++++
app/src/main/res/layout/fragment_user.xml | 23 ++--
"pic/\351\241\265\351\235\242 1 (2).png" | Bin 16323 -> 0 bytes
10 files changed, 436 insertions(+), 8 deletions(-)
create mode 100644 app/src/main/java/watermelon/tobe/view/piechart/PieChartArc1.kt
create mode 100644 app/src/main/java/watermelon/tobe/view/piechart/PieChartArc2.kt
create mode 100644 app/src/main/java/watermelon/tobe/view/piechart/PieChartArc3.kt
create mode 100644 app/src/main/java/watermelon/tobe/view/piechart/PieChartView.kt
create mode 100644 app/src/main/java/watermelon/tobe/view/piechart/PieChartViewGroup.kt
delete mode 100644 "pic/\351\241\265\351\235\242 1 (2).png"
diff --git a/README.md b/README.md
index 16351f8..683f01d 100644
--- a/README.md
+++ b/README.md
@@ -114,6 +114,36 @@ fun queryTodoList(status: Int = -1, date: String, priority: Int = 0, index: Int
因为需要满足在`添加\删除`Todo后,Service能及时更改数据,所以需要通过`Binder`实现通信。这里通过`AIDL`然后重写`Stub`的方式完成(总不能要我手写吧)
+> Activity
+
+```kotlin
+//绑定启动TodoManagerService
+private fun bindTodoManagerService() {
+ val todoManagerServiceConnection = object : ServiceConnection {
+ override fun onServiceConnected(name: ComponentName, service: IBinder) {
+ BaseApp.todoManagerBinder = TodoManager.Stub.asInterface(service)
+ }
+
+ override fun onServiceDisconnected(name: ComponentName?) {}
+ }
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ bindService(Intent(this@DateActivity, TodoManagerService::class.java),
+ todoManagerServiceConnection,
+ Context.BIND_AUTO_CREATE)
+ }
+
+}
+```
+
+> Service
+
+```kotlin
+override fun onBind(intent: Intent?): IBinder {
+ iBinder.queryTodoList()
+ return iBinder
+}
+```
+
## 不足
在自定义View方面还不够熟练,浪费了很多时间,而且最后的组件间耦合度比较高。对于Flow的使用不够熟练,有许多暗病.
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index d1a6939..c2c2d7a 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -16,7 +16,9 @@ android {
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
-
+ lintOptions {
+ abortOnError false
+ }
buildTypes {
release {
minifyEnabled false
diff --git a/app/src/main/java/watermelon/tobe/ui/fragment/UserFragment.kt b/app/src/main/java/watermelon/tobe/ui/fragment/UserFragment.kt
index 2733cc9..0a7da91 100644
--- a/app/src/main/java/watermelon/tobe/ui/fragment/UserFragment.kt
+++ b/app/src/main/java/watermelon/tobe/ui/fragment/UserFragment.kt
@@ -37,6 +37,7 @@ class UserFragment : DialogFragment() {
Editable.Factory.getInstance().newEditable(viewModel.user.value?.data?.publicName)
binding.fragmentUserTodoAccountEdit.text =
Editable.Factory.getInstance().newEditable(viewModel.user.value?.data?.username)
+ binding.fragmentUserAccountPieChart.start()
return AlertDialog.Builder(requireContext()).setView(binding.root).create()
}
diff --git a/app/src/main/java/watermelon/tobe/view/piechart/PieChartArc1.kt b/app/src/main/java/watermelon/tobe/view/piechart/PieChartArc1.kt
new file mode 100644
index 0000000..4a533c7
--- /dev/null
+++ b/app/src/main/java/watermelon/tobe/view/piechart/PieChartArc1.kt
@@ -0,0 +1,106 @@
+package watermelon.tobe.view.piechart
+
+import android.animation.ValueAnimator
+import android.annotation.SuppressLint
+import android.content.Context
+import android.graphics.*
+import android.graphics.drawable.shapes.ArcShape
+import android.os.Build
+import android.util.AttributeSet
+import android.util.Log
+import android.view.MotionEvent
+import android.view.View
+import androidx.core.graphics.alpha
+
+/**
+ * description : TODO:类的作用
+ * author : Watermelon02
+ * email : 1446157077@qq.com
+ * date : 2022/7/26 14:38
+ */
+class PieChartArc1(context: Context?, attrs: AttributeSet?) : PieChartView(context, attrs) {
+ private var redAlpha1 = 0
+ private var redAlpha2 = 0
+ private var redColor1 = Color.WHITE
+ private var redColor2 = Color.WHITE
+ private val outOfDatePaint = Paint().apply {
+ color = PieChartViewGroup.RED
+ style = Paint.Style.FILL
+ }
+ private var redAnimator1 = ValueAnimator.ofFloat(1f, 0.25f).apply {
+ duration = 9000
+ repeatMode = ValueAnimator.REVERSE
+ repeatCount = ValueAnimator.INFINITE
+ }
+ private var redAnimator2: ValueAnimator = ValueAnimator.ofFloat(1f, 4f).apply {
+ duration = 4000
+ repeatMode = ValueAnimator.REVERSE
+ repeatCount = ValueAnimator.INFINITE
+ }
+ private val circlePaint = Paint().apply {
+ color = Color.WHITE
+ style = Paint.Style.FILL
+ }
+
+ override fun onTouchEvent(event: MotionEvent?): Boolean {
+ Log.d("testTag", "(PieChartView.kt:17) -> 1")
+ return super.onTouchEvent(event)
+ }
+
+ @SuppressLint("DrawAllocation")
+ override fun onDraw(canvas: Canvas) {
+ super.onDraw(canvas)
+ val radius = width / 2f
+ outOfDatePaint.shader = LinearGradient(
+ 0f,
+ 0f,
+ width.toFloat(),
+ height.toFloat(),
+ arrayOf(redColor1, redColor2).toIntArray(),
+ null,
+ Shader.TileMode.REPEAT
+ )
+ canvas.drawArc(0f,
+ 0f,
+ width.toFloat(),
+ width.toFloat(),
+ 0f,
+ 120f,
+ true,
+ outOfDatePaint)
+ canvas.drawCircle(width / 2f, height / 2f, radius - 15, circlePaint)
+
+ }
+
+ override fun start() {
+ redAnimator1.removeAllUpdateListeners()
+ redAnimator2.removeAllUpdateListeners()
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ redAlpha1 = (PieChartViewGroup.RED.alpha * 0.8).toInt()
+ redAlpha2 = (PieChartViewGroup.RED.alpha * 0.2).toInt()
+ }
+ redAnimator2.addUpdateListener {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ this.redColor2 = Color.argb(
+ (redAlpha2 * (it.animatedValue as Float)).toInt(),
+ Color.red(PieChartViewGroup.RED),
+ Color.green(PieChartViewGroup.RED),
+ Color.blue(PieChartViewGroup.RED)
+ )
+ }
+ }
+ redAnimator1.addUpdateListener {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ this.redColor1 = Color.argb(
+ (redAlpha1 * (it.animatedValue as Float)).toInt(),
+ Color.red(PieChartViewGroup.RED),
+ Color.green(PieChartViewGroup.RED),
+ Color.blue(PieChartViewGroup.RED)
+ )
+ invalidate()
+ }
+ }
+ redAnimator1.start()
+ redAnimator2.start()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/watermelon/tobe/view/piechart/PieChartArc2.kt b/app/src/main/java/watermelon/tobe/view/piechart/PieChartArc2.kt
new file mode 100644
index 0000000..f5a1bea
--- /dev/null
+++ b/app/src/main/java/watermelon/tobe/view/piechart/PieChartArc2.kt
@@ -0,0 +1,102 @@
+package watermelon.tobe.view.piechart
+
+import android.animation.ValueAnimator
+import android.annotation.SuppressLint
+import android.content.Context
+import android.graphics.*
+import android.os.Build
+import android.util.AttributeSet
+import android.util.Log
+import android.view.MotionEvent
+import android.view.View
+import androidx.core.graphics.alpha
+
+/**
+ * description : TODO:类的作用
+ * author : Watermelon02
+ * email : 1446157077@qq.com
+ * date : 2022/7/26 14:38
+ */
+class PieChartArc2(context: Context?, attrs: AttributeSet?) : PieChartView(context, attrs) {
+ private var blueAlpha1 = 0
+ private var blueAlpha2 = 0
+ private var blueColor1 = Color.WHITE
+ private var blueColor2 = Color.WHITE
+ private val circlePaint = Paint().apply {
+ color = Color.WHITE
+ style = Paint.Style.FILL
+ }
+ private val notFinishedPaint = Paint().apply {
+ color = Color.GREEN
+ style = Paint.Style.FILL
+ }
+ private var blueAnimator1 = ValueAnimator.ofFloat(1f, 0.2f).apply {
+ duration = 5000
+ repeatMode = ValueAnimator.REVERSE
+ repeatCount = ValueAnimator.INFINITE
+ }
+ private var blueAnimator2: ValueAnimator = ValueAnimator.ofFloat(1f, 5f).apply {
+ duration = 3000
+ repeatMode = ValueAnimator.REVERSE
+ repeatCount = ValueAnimator.INFINITE
+ }
+
+ override fun onTouchEvent(event: MotionEvent?): Boolean {
+ Log.d("testTag", "(PieChartView.kt:17) -> 2")
+ return super.onTouchEvent(event)
+ }
+
+ @SuppressLint("DrawAllocation")
+ override fun onDraw(canvas: Canvas) {
+ super.onDraw(canvas)
+ val radius = width / 2f
+ notFinishedPaint.shader = LinearGradient(
+ 0f,
+ 0f,
+ width.toFloat(),
+ height.toFloat(),
+ arrayOf(blueColor1, blueColor2).toIntArray(),
+ null,
+ Shader.TileMode.REPEAT
+ )
+ canvas.drawArc(0f,
+ 0f,
+ width.toFloat(),
+ width.toFloat(),
+ 120f,
+ 120f,
+ true,
+ notFinishedPaint)
+ canvas.drawCircle(width / 2f, height / 2f, radius - 15, circlePaint)
+
+ }
+
+ override fun start() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ blueAlpha1 = (Color.BLUE.alpha * 0.8).toInt()
+ blueAlpha2 = (Color.BLUE.alpha * 0.2).toInt()
+ }
+ blueAnimator1.addUpdateListener {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ this.blueColor1 = Color.argb(
+ (blueAlpha1 * (it.animatedValue as Float)).toInt(),
+ Color.red(PieChartViewGroup.YELLOW),
+ Color.green(PieChartViewGroup.YELLOW),
+ Color.blue(PieChartViewGroup.YELLOW)
+ )
+ }
+ }
+ blueAnimator2.addUpdateListener {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ this.blueColor2 = Color.argb(
+ (blueAlpha2 * (it.animatedValue as Float)).toInt(),
+ Color.red(PieChartViewGroup.YELLOW),
+ Color.green(PieChartViewGroup.YELLOW),
+ Color.blue(PieChartViewGroup.YELLOW)
+ )
+ }
+ }
+ blueAnimator1.start()
+ blueAnimator2.start()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/watermelon/tobe/view/piechart/PieChartArc3.kt b/app/src/main/java/watermelon/tobe/view/piechart/PieChartArc3.kt
new file mode 100644
index 0000000..7549e4b
--- /dev/null
+++ b/app/src/main/java/watermelon/tobe/view/piechart/PieChartArc3.kt
@@ -0,0 +1,88 @@
+package watermelon.tobe.view.piechart
+
+import android.animation.ValueAnimator
+import android.annotation.SuppressLint
+import android.content.Context
+import android.graphics.*
+import android.os.Build
+import android.util.AttributeSet
+import android.view.View
+import androidx.core.graphics.alpha
+
+/**
+ * description : TODO:类的作用
+ * author : Watermelon02
+ * email : 1446157077@qq.com
+ * date : 2022/7/26 14:38
+ */
+class PieChartArc3(context: Context?, attrs: AttributeSet?) : PieChartView(context, attrs) {
+ private var yellowAlpha1 = 0
+ private var yellowAlpha2 = 0
+ private var yellowColor1 = Color.WHITE
+ private var yellowColor2 = Color.WHITE
+ private val finishPaint = Paint().apply {
+ color = Color.BLUE
+ style = Paint.Style.FILL
+ }
+ private val circlePaint = Paint().apply {
+ color = Color.WHITE
+ style = Paint.Style.FILL
+ }
+ private var yellowAnimator1 = ValueAnimator.ofFloat(1f, 0.2f).apply {
+ duration = 6000
+ repeatMode = ValueAnimator.REVERSE
+ repeatCount = ValueAnimator.INFINITE
+ }
+ private var yellowAnimator2: ValueAnimator = ValueAnimator.ofFloat(1f, 5f).apply {
+ duration = 8000
+ repeatMode = ValueAnimator.REVERSE
+ repeatCount = ValueAnimator.INFINITE
+ }
+
+ @SuppressLint("DrawAllocation")
+ override fun onDraw(canvas: Canvas) {
+ super.onDraw(canvas)
+ val radius = width / 2f
+ finishPaint.shader = LinearGradient(
+ 0f,
+ 0f,
+ width.toFloat(),
+ height.toFloat(),
+ arrayOf(yellowColor1, yellowColor2).toIntArray(),
+ null,
+ Shader.TileMode.REPEAT
+ )
+ canvas.drawArc(0f, 0f, width.toFloat(), width.toFloat(), 240f, 120f, true, finishPaint)
+ canvas.drawCircle(width / 2f, height / 2f, radius - 15, circlePaint)
+
+ }
+
+ override fun start() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ yellowAlpha1 = (Color.GREEN.alpha * 0.8).toInt()
+ yellowAlpha2 = (Color.GREEN.alpha * 0.2).toInt()
+ yellowAnimator1.addUpdateListener {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ this.yellowColor1 = Color.argb(
+ (yellowAlpha1 * (it.animatedValue as Float)).toInt(),
+ Color.red(Color.parseColor("#FFFFFF")),
+ Color.green(PieChartViewGroup.GREEN),
+ Color.blue(PieChartViewGroup.GREEN)
+ )
+ }
+ }
+ yellowAnimator2.addUpdateListener {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ this.yellowColor2 = Color.argb(
+ (yellowAlpha2 * (it.animatedValue as Float)).toInt(),
+ Color.red(PieChartViewGroup.GREEN),
+ Color.green(PieChartViewGroup.GREEN),
+ Color.blue(PieChartViewGroup.GREEN)
+ )
+ }
+ }
+ yellowAnimator1.start()
+ yellowAnimator2.start()
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/watermelon/tobe/view/piechart/PieChartView.kt b/app/src/main/java/watermelon/tobe/view/piechart/PieChartView.kt
new file mode 100644
index 0000000..b91062d
--- /dev/null
+++ b/app/src/main/java/watermelon/tobe/view/piechart/PieChartView.kt
@@ -0,0 +1,19 @@
+package watermelon.tobe.view.piechart
+
+import android.content.Context
+import android.util.AttributeSet
+import android.util.Log
+import android.view.MotionEvent
+import android.view.View
+
+/**
+ * description : TODO:类的作用
+ * author : Watermelon02
+ * email : 1446157077@qq.com
+ * date : 2022/7/26 14:58
+ */
+abstract class PieChartView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
+ val pieChartViewGroup by lazy { parent as PieChartViewGroup }
+
+ abstract fun start()
+}
\ No newline at end of file
diff --git a/app/src/main/java/watermelon/tobe/view/piechart/PieChartViewGroup.kt b/app/src/main/java/watermelon/tobe/view/piechart/PieChartViewGroup.kt
new file mode 100644
index 0000000..23bd9dc
--- /dev/null
+++ b/app/src/main/java/watermelon/tobe/view/piechart/PieChartViewGroup.kt
@@ -0,0 +1,71 @@
+package watermelon.tobe.view.piechart
+
+import android.animation.ValueAnimator
+import android.annotation.SuppressLint
+import android.content.Context
+import android.graphics.Canvas
+import android.graphics.Color
+import android.graphics.Paint
+import android.util.AttributeSet
+import android.view.MotionEvent
+import android.widget.FrameLayout
+
+/**
+ * description : 统计完成和未完成Todo的饼状图
+ * author : Watermelon02
+ * email : 1446157077@qq.com
+ * date : 2022/7/26 09:41
+ */
+class PieChartViewGroup(context: Context, attrs: AttributeSet?) :
+ FrameLayout(context, attrs) {
+ companion object {
+ val RED = Color.parseColor("#FE4365")
+ val YELLOW = Color.parseColor("#F9CDAD")
+ val GREEN = Color.parseColor("#83AF9B")
+ }
+ private val textPaint = Paint().apply {
+ color = Color.BLACK
+ style = Paint.Style.FILL
+ textSize = 20f
+ }
+ private var touchState = TouchState.NULL
+ private var centerText = "TEST"
+
+ override fun onTouchEvent(event: MotionEvent?): Boolean {
+ when (event?.action) {
+ MotionEvent.ACTION_DOWN -> {
+
+ }
+ }
+ return super.onTouchEvent(event)
+ }
+
+ @SuppressLint("DrawAllocation")
+ override fun onDraw(canvas: Canvas) {
+ super.onDraw(canvas)
+ val radius = width / 2f
+ //空心圆
+ canvas.drawText(centerText,
+ width / 2f - textPaint.measureText(centerText) / 2,
+ height / 2f + textPaint.textSize / 2,
+ textPaint)
+ }
+
+ fun start() {
+ for (i in 0..2){
+ if (getChildAt(i) is PieChartView) (getChildAt(i) as PieChartView).start()
+ val animator = ValueAnimator.ofFloat(0f,360f)
+ animator.addUpdateListener {
+ rotation = it.animatedValue as Float
+ }
+ animator.repeatMode = ValueAnimator.RESTART
+ animator.repeatCount = ValueAnimator.INFINITE
+ animator.duration = 18000
+ animator.start()
+ }
+ }
+
+ enum class TouchState {
+ FINISHED, NOT_FINISHED, OUT_OF_DATE, NULL
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_user.xml b/app/src/main/res/layout/fragment_user.xml
index f664bdc..404cbc1 100644
--- a/app/src/main/res/layout/fragment_user.xml
+++ b/app/src/main/res/layout/fragment_user.xml
@@ -11,15 +11,24 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="20dp">
-
+ >
+
+
+
+
+ app:layout_constraintTop_toBottomOf="@id/fragment_user_account_pie_chart" />
sDh4-Q3M4Bkgf>oC@>Ba6lqbwN=I5~L1qL+KtV;N1RIVZ
zeFz<*h%_N6V$e_p4ALQlUcR-%`}NlFuf58>?zM9LH`BwS
zYoym8ghY=XIrKY1#A^8e%_>3o#^ctHe(=u<&x1$*SOxzDta1oPXfrx`=)fPo34?8c
z<}&9WE)6NS{d4OFGjEl=ypg3mXXoa{tAy2C9;Gx-$**pGlWqUQ!M2#FC$)D)8d^BV
zMf#o$Jc?fA1TQ|X_xVDvfB*jdlsvqPnmCpFZIA5|(RuFt?g)E$>twShw`{nxC(|G(
zgTp$b7(+m)MWe%K1RgoIO@b*OU{il|af}9ElUWOY2hyI*OwWWe-
zyf2-1kelWgdZ1tK?3|dXt#fwJB7?ifHZvHZ5l;%`VMIhkWZ8Qi=|~k>G1Ujh$45uA
zvh5_0SWP)^c+6~38!;X#DJ#Rs*`LcN-@iWr7v?0=@bIu+?-ZgM^0=YDAx3fF%y@6p
z*Xg{brltV=XRtid+$I3x>8XoTmJ$oInp?P5@#u&kRrE(#Fd;53&MLC|d_~t@{MS+-
zfh@n;0Zk`!tWv~zQ$p0hEw>1r#2b&RD=Upy_B~&}g51U~_8C7uN+iwxbCQsh~J+OB1k=ZLTRBVig
z%}Q1WCagx@e;Ei;fBA#dTz4!xDk{pu!{Y-_5@p4%P(d#rG1qEIiWJEakar9o1xM_o
z``WDVZ(;OlD@-aHDAuFL6hwhL_!m0C^Dh+w{Dr7q(_(ATM+Qwiz{~pR)mE2VX43RDV}QTkZFs-jnG(F;XjK9u;|HuBdT%etpBJFo
zfKbUM@CH9$-#*Gs32||8r9J_wIE)!3G<{cdW_#-zgTY+U8ls4xmWyzFdgQ#*jw%nX
z=o;^cJ!+9gV%Z~x={gvH03J?s$s3;i*I|)~pbr9o6I6`yZhKH5BY&dYtE!2}=)yuYijI!<3kVnl$#e>}o)rc6u@>AIx^-wX5g~&gK`#+H3TKMY
zw*TDtA0m>YQN?lybv_XcJrMIWHC1-griE^fnW^dGSoV`APyQg?ZN79DoN4fUfDH>=
zdhpz-Cbf$XcQ~_CG6qCV#0~6LIiTdJ+MIcIbZYAF>y5zwn6H;-|8R1BbKlOt(uuGCpk`9lM39vW5$VbA2=Z@oRLc^+SLc|KnOQ8?-Ff{h
zuSD!yQHCmw37>RDqSJMFh5EtuuAe*=?X0aGvQOcU9?eI0Bf}Q#p7A9$wf2Hqt(&G!
z0rw4iV*XnNcxW&cE?8!-$7kLt{=E#O{!V{;T$A@ayYJ3kr@$x-wS3Q8LDP5A7z;|@XH0Onch-~Yz=$qCkzQKHd_
zRgP3qFfE3-s9-4A_?qrbV_J9Q<>gfqO?7vz=}ZLU8`S`VhL9k)M1NvSGf!f24oY=y
zf*ZGbn0w2Liaf?X$*rwLBjCb28Fw8Yq^0fN{np<}O&a@xsi~<4_2+D&iH%mUHnES~
z?uQLbX0hB~dlYW`Bq1Ro6=_^pTzt%iWfQ%kQ5z3wbklrSS^3w{N1?w{Q|A}wM&Nk}
zyFT5&Fm~hn;X@yFWTLAe{yjLp!%}f0o?95-pbmYUKVo?gBIU7-5k@;=uOBO+hVBGs
z$rKH%u(q`YAdqqR(erB+X9PoE)zL3g4RIthD=oXTI_R0g4eS6lWxuiWT^n`~g=(y7
zP*xZm3@g*Fa^HvriL}V2EonX%lidbh$^V>=9A|))`64xS;6%#_qZ3#W>OOzAWIaJn
zclUfkSvw)l_Vzl$%UDmccEXmIlh$ykH5jb)qiIEN1u{=BJ0qbyf|AqH~)df!&z
z#_R4k)Y9(a-DoiU{e?SlbneGp!yU*S(_+F%yAxu@$&)7m3oMPw*0>Z1PKF#SLdhI>
z?;D{~i}jUtGMW$=yDy?oAm`-g|J$A!@h}SuVp89h^V*+DOis`FTr8cEc-3musQUH3
z4dvEPzu0bT-BF?dZvVxpI>ppy;Ac$SxTM37Q*atCTrVTScKl1O(m?aBclG4#PB
zwLDHueY5WkN1)LRbdBCKGrxWGIY?~Gw-xY>GQ88NCQjMz_j`^kdxK10LCwaUcwFcF
zyiVw=G9U3PaIAJo;=!7edYc#xodEgy8cVJk5aV}a{B
zBOBTq{2Y=mm)R2;JIBt-w=?1DSlKLM?98%R|EXI?rExn*N9Nl~y?}RMGZ)nQDI%Q+
z!+ML^Rr%Tf-Kb}5;5Q*I;CG@s>(&%w5)W(
zfKPn<>n1#v`gTANM#~epy^?)%jY9ECYfGpbGy<_75l{(CSZ0qEk)ez141-5c4%9
zl?Da$;^FaMY;0@**vZPCUkqVlcq97cy#gPc%5IbJCeVy9XydyLg4ieW-mDuU0c&9E
zBWki@>2iiuZ@b-DTakZX!2khr3g0tj#rNuZ_4O?7J=4(fhOO6L(K2aLvxycMT#KLD
zD=DIaVQ8rQ1-81E&G|y>b9twqWelj9aEGbVB7%@okVwz?83?<9Z4REVu(TA=8#x;E
zz*p#e^xP9?wvL|OIe4(p8lqO@d=WG4T}0*AUVEbxB_;d6&R-5bWhAJM;j@gT?yxPJ
z4t@#%;&hkycV^D%bij1Bj|;)&BqaFu{3Z^%etbtPD8l5QAPkKhN^4@T#{=xu;U#&e
zy>v|hC4S@j!KXIoov)6!pVeV-;KL&${$m`0mOufiY97yvwKd@3(&EU{Fy+toqO!8~
z{xz)`yX!vmy9+^VN@=>7x%5)qB(}x@+(is1E|=^1sKm(VgoBRUd96fm-8ET4a8@ND
z&D}#^{@S~En?rJZRAPg(p89hZw?o9SQVK&(r6%pA`}V+vhdc7~^R*@3cKD0+a=Bc-
z9W}J?zVQ>BT<+(W11G4PPF~SPXrc|D^`D_`!NIhpx$-6UjAoFtR^o8mQcBr)fCqUU
zymbC*b2pR3@>-nkjxN%xjGbx=S3y|QBF>&r}BUI*wgdAvN$MTwvMa#yHiDRs;c00rBY
zN(oTLxz^S*kdJ>mU@9#JLoo-z-_@Ns(IdXuACRg$Q&UcGAVYVsynNm=*4eex{2
zGb98~X|@%R)Yiy!nkX&b+j>hs#hGnwXZIZEM4v6WGdlQi_IW>K+AoiQu*BLr_z#4ZQ53qlY
z17vyr&n`-HZtFAFsEpde!ff5SL$i>;Sl9AaZ;behTYY)_n#A&*v8xna00s@4f*;S#
z`Nt)tKT@p2;7gJr27YPuhCxty%0-n#(_%UM%yf(0Y!<7>Q`%P?q!&DPkfPgA?NW6%
z+bxYJEgO&84Z+InN^S*}_j>&Ng#x+zOe(?nxqK
zUXMG|T6tpA57i?aPZ{6cF!A*bDZdolPm?ie;v=)SrVu`dDJ#f_!REsaf--wOF7gTt
zEpB&I!S*a*dohsX@>XeA_Pgiz7kTghq76V7d|1|2(5-Dhuj%-)ZM7@sC%w)+Ftrf#Q(gW#hlR88JhtTl!S>g?1&~;hM1$+p^mGevRRE`}
z>(Rhk@2gDDe-D2#pq18~I9XQ!nlMP|zZKt
z>$O|$F!`5rA0rbkkl1TrmEe{xz!=R7wtI>E`GxB59hVT5We<1JegOxu5
zCgd<`@q>kv#S4y${%grQckZ-_W+<=fvGe30ye(=d7$$4$L=rcBVMkO)3N}JSG2Kjb
z8|^Q`e%iAvuVaPEzXS-04u~MQ>t8}+C~q)2b2q1|RYfdI3eUx{{>l!|S{xtw=4}08
z<@^l;!OqUrJ^AjjUiyH#ACJZi@4;*W?1Gc_GbqY-8&~_gIkb6yzj$oas~BSZvq}5a
z)%@Nw&uU!<$0g^0B%&(>bWPue?PYvVy`pUEt&X>x{maU5-tqeoP8GI}LUwXxaXJ!@
z@7lc!y_tEF58zmRKrZ|7lJ~GQ;%n?nrP45k0daO(M}squVTDbHdwpb|9NyP_VO!f|
zfBw2^hShZH8p!iUPTYHzTdnIxp?m>5s+hdgnGR?ArvHQg^;{P~B~1OGFsu}WmbD<~
zvnyvxSDemw@(h-b8zr~`a^DyvGVJBP#pBlFGC1vD)CLiNHTfx@{4z>s2vnx}qzX6&jEa1OFcQB0MPiB6XKtc@XbrPw+nJ
z$dcPx2fV3hV4Nfgk#%EzJ=`r{S}azr(FcipczJD)(x^7_XA}i&htPT-=aX3{ty_6!
zO!s%+ATYhO06`(|J2>zHGQl40t*u{_L-gKR?g`VczTCliqz5jQQSN5R`nD`tYisK(
zy1(Ky&9!{t+X+)zva=OCEkqm#Amx|FfjDRG2$~y8ZfLh4-CdgJ=u3$R+C=BXIb{m!
z^}CgAB`~BPrmU@@UDzwxqrWs`#!vMEigI&vandTpyT+i;Sg+LU$EY-UWMf3-ffd##
zm&KQ3t>o$NU+fdj0=QXNR5X4+&Fm9B-9S(e)04^o`ygub<4LWpjEEpk|2%_(%Oy0z
zC5&!ILD(YTNyzYGK*muN1|`J%w!oaeTANp8X>K0!DZO
z%Lwlkz$RZE`i+w9K%DpY?*e?Qy{`6kfi`z0V1)jS*oI@IU|RF8h|1UApZEB0ss)x2
zP=n7FfZNMl$WJ%5&+;T&)`LrQRZBEo>2a8kOB;N3Ol??z7cr+dcw3J|a#WLc)RZj>
zNVBi&&GB)4h>DNFnq_`5iJb{hiqVFw8k96<8y|$1%}>81E7hq0*#HzaSm&?q(Wi6;
z)xnw=+NX?$Hoa~Y+4KtM;DdP-k2+U>~#dJ&*#zqGZtgG^-;Ffx#wR>Q+Ts+j;N
zFP0;U)jFtr2lNn)0TlJK)4i07MeyxwCv`s4K^WWzqLa@$o$i!(ZO;Yvrzp|RCOkA5
za6dLW$t;$Ot84D*ba<-86Q))tt32SN25M=Ki2~UQHs)l|q{gRK2>vzu1ed?6zM|!I
zM#8COVWE_{n|v9Mx^-8nMOIst>I{K2>j2myX0rE@m5=XOC*eu3!W2jaa3y;ljUK?D
z$eQs97SfUhBwc*GO#bPLhy6tjcr(kX<@5>wr^CY;Fazfw=lJ4cZL72pQ|v{y!P9;Y
zzR!UM1_B+YnAmMxhp8pzMvdG55GVqwu5(?wMH;Zg`=dq5J6rcP3c=R&9&oEiM-sFJ
zXR(EDY|&by&w*PKaEt!N&tZC}s~jN^a0B^R!r^P>p2L!TG9WywKUiLT!i}f}F&5zc
zH+Tjk3Hr;7fmVDpf>)NIZ-jla4+!E4S&tUsAojsiRy$gJ;x?RM)H{wRM|r;{VEA=a
z2ClH}zD6f?&roHd?#W4YP}qTeCsS90&N
zUL|B}^1<_6%#Ch8;B~CF%J{5il^SAbAMpzsl(Nd0QNUM@E2Yrntv#%lb@wiH-on~w
z&a}!H!G`tMrbc@Do@U0Y+)8OQ*?L8*zM{eqw$9Jz!{i<^Ilu|NmelkGMGyn~fXuCd
zPbV7H<_uD{QIazT;#3C^9HOQIcr~yF94@1)Y@!Vh^NTcI-TN6>TV(Hp0YEl16OaV{
zmYpGfbLb<|2XxqJ0O`)azyNSZKq*qTeN4K{Plf5`#Cc&jAt4t%8fR?mJ$*p8neGfC
zgUlOfuL%rAZRs{09UbQ(;ntC}I??V9xrTbYqaKZIDmrQmEA|D|u~l;Yv9|cd#fQhA
zH$jml<1nFRKirxQV?Dy%F5aA$}h9kVLHGT4I7A8aMg!)Ht%$4
zLYzqqK%CT6I9DJzJx0^&Kvsp;-^RxF)%AXuyhxRUAjPmyjH`nWguiWm*Lw|D1L@A4
znAjFhpgl*^ydplbcH4_
z>(BCN-BWXx{Y8siOhT4Cs83dIQnz>ZsVh3G(OhyL1?pF*58Lnm`}$V8Q@a#G@-Da+
z;6H`7|CAU(S^sav)uU0grEh(GeZ83-OE8dX!=ev~`{z5ew*{{phmMXqA@KOWLm{98
z0vMyr*QI?#8w^LEI5QJ^)FU7u0ZM*=P|E{l;c4$S&&_dQWZC8EoArY`q0s>9&OhHc
zC=1VK#o3M|1i5r=TUuH(4zotveLb}ee{W{nQO=uZ#jWgS$@?z)pNGB#)Z&w=tvOS(
z=Tqj%JGhU8R#H|!n{gaADtv>BJ-5EVC2AQS^30HGuQ
zx$z&7{EtwEqaLk1gxKndrjQ7B0N0v{8Pl02T4w4lqcP6hKVV79!9ZVtInq_Ome8%0
zVj-=1?#u@3gNRoVOvlMmZv7agcW_Vy`bOQRK}^QhSf_$#TB|E5
zqOQA32wGs4Gpyy5lxDmag#l1(JeJnn|9tI2iB=$#A77El%@5=OBm$g*S7r>@mHkXa
zFm)ogL~B9I7kHwvF?Ul_Q|u2?Q?(LqWkAl3WB100&~^b)1_hjuf0y4~H$B?U8PB_Z
z(6+T#(m_+!TW1puP)NDaJ`@0z5wbGmjgU*h2kKbxV&K~Wxv;aR7yv8-^du^g6Hox;
z5y&wBI>j~jF2fdyprQLfC)1cvPbbf*AsXZvZf;5Tg{i5K9jDdm=36VN#@D~xNF4nR
zD-lZLClF;$uk`fwmssaDa&2H^P2WEbH6f=+OuCh}U)7b1hPt|oQK2CK6RpHDr|Uvg
zXG|T`I;s1w?j7@0ypw-KlGykQ1pN-^a(G~h>nMc<1=YAr_q0?4aM^?7%OILc#F^1f
z;O-#Lz%_rU-f?2}5Af?3UIYnL`rC3P1t2!S=Q9H%*Y<3TnD1CxplJ#wYrF)AE~AsV
zLwRF_wT;dG_<4dwB%yCN!2eM(W?B*^LuyUobXY9bS4pZZ&dN+7yT@6N-w0$;P<0V^
zRYLsw{3l3BJv=?Tt;c16@(-Astl!g&CLXH7GX!A%p-ltuvQ6{{tK83uu{BR2LF$ad
z?-w$8-o#J3jFnBEo4boJ8UUYV5g;Y>9vFeMXzl3mfljj$++QUMRhbPn!O%=+(Yy?9
z)i0<#ke%OC56iQ``Dkd8Ji+Vl+t#c+)haZo2qKh$)X2lfhsBe$VyQ(!YLwLkClzoN
zfG597kOtYtn|;d-YdfJ?K>vRFr>5@{RmmN=uH7jgbpm9Xh3OOCAmP+TDZW&p3RluA(9|
z7X*ZL%<7X`y{T~yzSM@xO)Yr_wu&2*{6!e;@b<yvh#vJ-E4|!|$6_go
z@pNN+dK1);6SOw)Q)ag#AoMGLGYLi3O3N$;qQlCO{y)NT;RMDGoD2U(V{R69Kw@B0
zRIxl~HuUiECMG`eR-r5s9Ea9N4(SW-;iCb~g_asQ=^bd)5~dv$4=l5hL70R=i?3#2
z4g6%D=dPX0kte!^^M~LBMF2S^;xX|2^0ykGV7TXlS`L;fy9?wrA1PdfH2;9tO~>PO
zg@Cl&v7?=UUXIUU!I3E!q1Q)Q-tOaJT*P0CsIc`iF#NLjb|d@mNJJO`t!EtUjHo7X
zrU9wTjW^PfG25W?4@?A_|8%7EyJM7)*j=z8r{kZBW6PuKj48MKFL7$EPP27<|+&_My|@G#}3DZg^%1g$dr_4R$q
zwA$>!i7k{je{Nl8Ve6mi)PG)t->;K9CkP?ud;2xQqiHT&v732?D|a@a-J
zS=G5>bgOVpxO`|;)w{u^;d-^mP|??`UMU822PLXqlol!ZQHxnA`=T&*1I6e=nyS*^m
zn<6OjJIiZuYR)$x;7ai?222pODgCpP;EduJvpPo+Xrz8AYiQIP%M4!Fotk>1#^I|s
zg_;EV>vjOh9sg(y75*O3f_iU||8R-IjcRUdvm-xEciZAoB=MkjHx*KI6q5O{m229wl
zW^QWgS*^sBBm$bpjacXZSZ@R{;-e~}uEV!u73;nN`|_e0HJXEFHUMcr8J0wt5MW4w
zr4x6v~aq3cs5XkkS!&Hx0Vo
zprdaqll##eQH8-Lk8bK7(}d?7Ebmd)Ah(sK(Dmh7P+T1G{mQN=0@(nRJD{S=E!>Qz
zSNYtGb~c~=EQyG$aYK`SHhbt#6(oYYMam5nh>RgT-#YlJRS9IW(^tH=`O=1}?tMI2
z)G2}|Vo*w>f|uqx-m97P|BM(yaJFy*>k@WL;j2E6ctX86F*g;i_;uo5skQA4mrjay;IN<9ltFW(kH3s|mKaaja4
zuEXCC>c+6?Cb}!pG``G8z9_xZ8VFT*e?d$|*AL~3v(R)!jl$C!{Un8oaCzYFCb6*T
z`I+3%Vw7wTtKSA?GaY^X=lIN{V9ST-Z0C}alBf6@2d6)6?d)O1hv6J
zHfO^dXnKLa>JpJ4a6JY>Y9{Ld`S3)LByM@%lx>>{ojjmB+@~Hjrl^9Rf>tEkdlx7AY$X~9z+SYfb79eZ_je(mZDhj&y<#MTHuNc+yiMpV
z!ZZHCrknmFNZk$FYdqtUD@Yvxvu-@Y9#ZG6K$164^b-(cD$iM_xJ{`x=eX`);?-Q8
zaUC;VB2^wvqtQLS-gvW*^@;WF!NKy-S2L~?{aE3rx}1->X!u?cLA!L+o_Wp4wf6CYyGQar!gEx
zA0gk;rvfNGzAr!$;0Ke1#KH`L;-|b#=0iF+T$Z2s)4=qy9_@J&V*IuLsW3IxWJhdn
zNzmWUY-ptdRp}n{z2=zzeQ2nDAnC`S>pmQ9MnpIX&ClD#c4^5)k4;W)gw500>Ey-4
zg&-Q`HF^I5S+XR|oEYP13G3~+3Vy`b&(Gc8{SZEa*JQs*$>jl1Ec%1AVSuLvy4Sz|
zD2T19`+a&Dm>ldWSppmxxJ6MtF&iV(iVY6bGa!fwW6OJE`Q;0HcsHM}@Q^lK3X`Hf
z!r%XDd2e5$sX6nA@#g1XOuw6<&NZ-zQq`WR_gXJSkP=REv`2Q@RODfQx(*cx;CKXO
zc8UP;>&DB=vw!%_Y=d`%m$ZNse}xm_2BuFgN(WEz_ly>=LY9Re#oXbj#GrRE_(#w^
z><=1`8J4y2e05Ti_MT!gnLkN&UV~Gh0PXv6U5wN?tyDOPM(b{RZU&vUf|0+ABdWPm
zKKtW3$*eXP3D6c00T9py<>k@uFRV8@aVUxNfhZ*MnErEadikTa`hzwXH0o*;<<7{r))!g{i7ig{
zE7mE^a#yM#!(J#tl%8ParB$sxvEB&WwOcGcFCQH_`%>Ggy1HZ7F^GZ(x?;hmpI~{t
zWDRJ_ioM{7yuHv9ERH01bWqWigH3AgI&xrbzW)9ZZ7!Ur{fBfyMHs)qu1x`BKfd@-
zeBtIo&`7^q6`0U9sJgi2q+E3QmiJ4bd*sOh{9WzkB$Rv@YERteJuw7H*eufZNGJXS
zi!p>vB_D=Atg(NPE3_zB0}p_l4Wg}gTSMg_b9_H)+zuu~={X%@y}pv9CxnWCZZ>Jd_QwV
zaiui%5jJSzi?d$PP(EXgjzH8h5PwQh&NdJvV+=e&g*?m+H;QOwDAqZQY-`AQ2Yy2Y
z_pwIBAK!6Qzk>uzg^bjo>Y3Qbk2G<_!p2ttu}QHm#s$Kt_HBaX3hb3W-A&5}TnVnD
zKoeizb+kM$P$+ydhtT-}UUlUUR>l`^XK|E(TPnqBa};rOm0Ego*&lVb;sK5DBb3%X
z^_KUHa5zScO6;xfE7|G>K{{$~hNuyEH~VZ#DDz58u0ov(XlubL{HhPVX;mW-tnlgM
zTuJL`-O1>VUcdI4a3QKWo+e!HFOHLXgbvf3iKw~Q;jM)V8W%=6T5be>AHUBM3zho)
z%9rAbOaP}N>JS&)T$c*?IF4}t>Ze{A7i(?ac;SrSHTA##I-nVShv!@$C`*(L6N0PdKTd
zqlH(Yb@7E_-6^HG+Z@0CpEY_HKKIl({0OggDHiPPheMh-8X-X2y17~5MMulG5KIQW
zwI7KvNU-7Q5C}p5nxMRTkhfvABg(+Nu|BK1T>z`3Ts&K9dl&-fPJ-JLm?vO6Kc0!*
z?7#n5;cTJx+q2o>0E6S}-;x|r18(67CXqIDkF}`2-4y3&2|M=rX}xXp0nTeu-<^
z-%;h!q_#SafXmO+c#HK$K(bk_7yjBcy)ZNmh^oE49eh>G$kcnaNUI#eG!%6VMm89&
z1)GAIe0(JM&KOJR;*~@996JKa0stJa>F?F*UEeDv5UzoiHLf1HJ(mY{a>>ZWrGfs%
z#l^5C(RmV}C1)>5{k_l79!07^Lc=))k
z^K5&!6t%117~oNaitz6`kO3SnLgCnAq0j_?1)$*z{eUePNO5pF
z@XVqAJoNvGAi^b|!4IztbJ|=04Oa%0M}rQ5$^wi#bO?GbjP5x?tJPUGY0y-_itCgG
zsrW~DZf8uI-ki&YHsx+#ouH|y(l8G;9RoE$THrvz%cwj!bYeXVGJ;SDvz-Sg=K@R0
z%8YGTJC|;Dk4eVY?@*670V4#y!+5J*2Xb3oc81U?0AE6Gt6zF{KDWOp3bM}ZQ*Rtp
z_OqEQ(IWijimGarZUF#Xd6HWmF!Lj5x}2Px(xepHdkAMjs2{jxh&AzzJc8Cio5>f|MoH_{Fl?4=Dk}YSu*tD)d{NK|a`q?yn@wSqS0JRJY^J>aPEk6YSLO9csLXF43
z)J#VwC+|^S`*``upevXGU3X<>mvdY`!5|J?qvin#*UTVRuQO_N#Dg1qR}GD;qdpZ_
z*-i|kb_SgM@39DB+um7NJTQFn0{_by!Iji?J$_05=k)sz7MF;kBAoQDhEla|S8>t*
zx`qZNbF=9TC08O<2|%0M)yE22e!D%BI5=Eg2XB#ZK}YU+(x}kCw-{TqjrXU1-`5?e
z54Sk%l#Vn`T=M~(Kjb7>hVaqRN#dN_dz2-O4IjBefa6Z4SS@iI&u|JRsDT^;YUpCA;pWT>b4B_zUMeL
zI@=_+!O7-@w4gq73G^YFg@z&raWLsvv>D3VRU9HmFJ5H+{YwNN8n`
z6ZpXec7Nk>LF4aeGx!NcB{+NNSb!gx0U!r@CA(w9zPzJq%=acFn`_tl`1st0M8^1u
lWTY|hH8HW-1oGdD#Hk