From 7ed66b827fc9672f51a4f49a679639f4b5193fbe Mon Sep 17 00:00:00 2001 From: tom5079 Date: Sat, 12 Sep 2020 09:48:30 +0900 Subject: [PATCH 1/5] Implemented eye recognition TODO: Move pages according to eye blinking --- app/build.gradle | 1 + app/src/main/AndroidManifest.xml | 11 +- .../xyz/quaver/pupil/ui/ReaderActivity.kt | 80 ++++++++++--- .../main/java/xyz/quaver/pupil/util/camera.kt | 113 ++++++++++++++++++ app/src/main/res/drawable/dot.xml | 30 +++++ app/src/main/res/drawable/eye.xml | 8 ++ app/src/main/res/drawable/eye_closed.xml | 44 +++++++ app/src/main/res/drawable/eye_off.xml | 8 ++ app/src/main/res/drawable/icon.xml | 30 +++++ app/src/main/res/drawable/icon_red.xml | 30 +++++ app/src/main/res/layout/activity_reader.xml | 12 ++ app/src/main/res/layout/reader_eye_card.xml | 67 +++++++++++ 12 files changed, 416 insertions(+), 18 deletions(-) create mode 100644 app/src/main/java/xyz/quaver/pupil/util/camera.kt create mode 100644 app/src/main/res/drawable/dot.xml create mode 100644 app/src/main/res/drawable/eye.xml create mode 100644 app/src/main/res/drawable/eye_closed.xml create mode 100644 app/src/main/res/drawable/eye_off.xml create mode 100644 app/src/main/res/drawable/icon.xml create mode 100644 app/src/main/res/drawable/icon_red.xml create mode 100644 app/src/main/res/layout/reader_eye_card.xml diff --git a/app/build.gradle b/app/build.gradle index a880fd7e..641cfab9 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -78,6 +78,7 @@ dependencies { implementation 'com.google.firebase:firebase-crashlytics:17.2.1' implementation 'com.google.firebase:firebase-perf:19.0.8' implementation 'com.google.android.gms:play-services-oss-licenses:17.0.0' + implementation 'com.google.android.gms:play-services-mlkit-face-detection:16.1.1' implementation 'com.github.arimorty:floatingsearchview:2.1.1' implementation 'com.github.clans:fab:1.6.4' //implementation 'com.quiph.ui:recyclerviewfastscroller:0.2.1' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 47df453c..d96312dc 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -6,10 +6,13 @@ - - + + + + + + + { + eyes.apply { + visibility = View.VISIBLE + TranslateAnimation(0F, 0F, -100F, 0F).apply { + duration = 500 + fillAfter = false + interpolator = OvershootInterpolator() + }.let { startAnimation(it) } + } + testCamera(context) { faces -> + eyes.dot.let { + it.visibility = View.VISIBLE + Timer().schedule(50) { + runOnUiThread { + it.visibility = View.GONE + } + } } + + if (faces.size != 1) + ResourcesCompat.getDrawable(resources, R.drawable.eye_off, context.theme).let { + eyes.left_eye.setImageDrawable(it) + eyes.right_eye.setImageDrawable(it) + + return@testCamera + } + + val left = ResourcesCompat.getDrawable(resources, + if (faces[0].rightEyeOpenProbability?.let { it > 0.4 } == true) R.drawable.eye else R.drawable.eye_closed, + context.theme) + val right = ResourcesCompat.getDrawable(resources, + if (faces[0].leftEyeOpenProbability?.let { it > 0.4 } == true) R.drawable.eye else R.drawable.eye_closed, + context.theme) + + eyes.left_eye.setImageDrawable(left) + eyes.right_eye.setImageDrawable(right) } } - setImageResource(R.drawable.clock_end) - } else { - autoTimer?.cancel() - autoTimer = null - setImageResource(R.drawable.clock_start) + else -> { + eyes.apply { + TranslateAnimation(0F, 0F, 0F, -100F).apply { + duration = 500 + fillAfter = false + interpolator = AnticipateInterpolator() + setAnimationListener(object: Animation.AnimationListener { + override fun onAnimationStart(p0: Animation?) {} + override fun onAnimationRepeat(p0: Animation?) {} + + override fun onAnimationEnd(p0: Animation?) { + eyes.visibility = View.GONE + } + }) + }.let { startAnimation(it) } + } + closeCamera() + } } } } diff --git a/app/src/main/java/xyz/quaver/pupil/util/camera.kt b/app/src/main/java/xyz/quaver/pupil/util/camera.kt new file mode 100644 index 00000000..f783a9e4 --- /dev/null +++ b/app/src/main/java/xyz/quaver/pupil/util/camera.kt @@ -0,0 +1,113 @@ +/* + * Pupil, Hitomi.la viewer for Android + * Copyright (C) 2020 tom5079 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +@file:Suppress("DEPRECATION") + +package xyz.quaver.pupil.util + +import android.content.Context +import android.content.pm.PackageManager +import android.graphics.ImageFormat +import android.hardware.Camera +import android.view.Surface +import android.view.WindowManager +import com.google.android.gms.tasks.Task +import com.google.mlkit.vision.common.InputImage +import com.google.mlkit.vision.face.Face +import com.google.mlkit.vision.face.FaceDetection +import com.google.mlkit.vision.face.FaceDetectorOptions + +/** Check if this device has a camera */ +private fun Context.checkCameraHardware() = + this.packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA) + +private fun openFrontCamera() : Pair { + var camera: Camera? = null + var cameraID: Int = -1 + + val cameraInfo = Camera.CameraInfo() + + for (i in 0 until Camera.getNumberOfCameras()) { + Camera.getCameraInfo(i, cameraInfo) + if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) + runCatching { Camera.open(i) }.getOrNull()?.let { camera = it; cameraID = i } + + if (camera != null) break + } + + return Pair(camera, cameraID) +} + +val orientations = mapOf( + Surface.ROTATION_0 to 0, + Surface.ROTATION_90 to 90, + Surface.ROTATION_180 to 180, + Surface.ROTATION_270 to 270, +) + +private fun getRotation(context: Context, cameraID: Int): Int { + val cameraRotation = Camera.CameraInfo().also { Camera.getCameraInfo(cameraID, it) }.orientation + val rotation = orientations[(context.getSystemService(Context.WINDOW_SERVICE) as WindowManager).defaultDisplay.rotation] ?: error("") + + return (cameraRotation + rotation) % 360 +} + +var camera: Camera? = null +private val detector = FaceDetection.getClient( + FaceDetectorOptions.Builder() + .setClassificationMode(FaceDetectorOptions.CLASSIFICATION_MODE_ALL) + .build() +) +private var process: Task>? = null + +fun testCamera(context: Context, callback: (List) -> Unit) { + if (camera != null) closeCamera() + + val cameraID = openFrontCamera().let { (cam, cameraID) -> + cam ?: return + camera = cam + cameraID + } + + with (camera!!) { + parameters = parameters.apply { + setPreviewSize(640, 480) + previewFormat = ImageFormat.NV21 + flashMode = Camera.Parameters.FLASH_MODE_OFF + } + setPreviewCallback { bytes, camera -> + if (process?.isComplete == false) + return@setPreviewCallback + + val rotation = getRotation(context, cameraID) + + val image = InputImage.fromByteArray(bytes, 640, 480, rotation, InputImage.IMAGE_FORMAT_NV21) + process = detector.process(image) + .addOnSuccessListener(callback) + } + + startPreview() + } +} + +fun closeCamera() { + camera?.setPreviewCallback(null) + camera?.stopPreview() + camera?.release() + camera = null +} \ No newline at end of file diff --git a/app/src/main/res/drawable/dot.xml b/app/src/main/res/drawable/dot.xml new file mode 100644 index 00000000..f75e450c --- /dev/null +++ b/app/src/main/res/drawable/dot.xml @@ -0,0 +1,30 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/eye.xml b/app/src/main/res/drawable/eye.xml new file mode 100644 index 00000000..c5853f1e --- /dev/null +++ b/app/src/main/res/drawable/eye.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/eye_closed.xml b/app/src/main/res/drawable/eye_closed.xml new file mode 100644 index 00000000..cb8e83fd --- /dev/null +++ b/app/src/main/res/drawable/eye_closed.xml @@ -0,0 +1,44 @@ + + + + + + + + + diff --git a/app/src/main/res/drawable/eye_off.xml b/app/src/main/res/drawable/eye_off.xml new file mode 100644 index 00000000..2f1a1e82 --- /dev/null +++ b/app/src/main/res/drawable/eye_off.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/icon.xml b/app/src/main/res/drawable/icon.xml new file mode 100644 index 00000000..8bca8ba9 --- /dev/null +++ b/app/src/main/res/drawable/icon.xml @@ -0,0 +1,30 @@ + + + + + + diff --git a/app/src/main/res/drawable/icon_red.xml b/app/src/main/res/drawable/icon_red.xml new file mode 100644 index 00000000..00fdcd21 --- /dev/null +++ b/app/src/main/res/drawable/icon_red.xml @@ -0,0 +1,30 @@ + + + + + + diff --git a/app/src/main/res/layout/activity_reader.xml b/app/src/main/res/layout/activity_reader.xml index 2b9de763..f2b3fb7e 100644 --- a/app/src/main/res/layout/activity_reader.xml +++ b/app/src/main/res/layout/activity_reader.xml @@ -45,6 +45,14 @@ + + @@ -87,6 +96,7 @@ android:id="@+id/reader_fab_retry" android:layout_width="wrap_content" android:layout_height="wrap_content" + app:srcCompat="@drawable/refresh" app:fab_label="@string/reader_fab_retry" app:fab_size="mini"/> @@ -94,6 +104,7 @@ android:id="@+id/reader_fab_auto" android:layout_width="wrap_content" android:layout_height="wrap_content" + app:srcCompat="@drawable/clock_start" app:fab_label="@string/reader_fab_auto" app:fab_size="mini"/> @@ -101,6 +112,7 @@ android:id="@+id/reader_fab_fullscreen" android:layout_width="wrap_content" android:layout_height="wrap_content" + app:srcCompat="@drawable/ic_fullscreen" app:fab_label="@string/reader_fab_fullscreen" app:fab_size="mini"/> diff --git a/app/src/main/res/layout/reader_eye_card.xml b/app/src/main/res/layout/reader_eye_card.xml new file mode 100644 index 00000000..b199a922 --- /dev/null +++ b/app/src/main/res/layout/reader_eye_card.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + \ No newline at end of file From 0f8c68b22e90f3fc0eba343e0342559690f81702 Mon Sep 17 00:00:00 2001 From: tom5079 Date: Sun, 13 Sep 2020 21:42:02 +0900 Subject: [PATCH 2/5] Fixed to work on old Androids --- app/build.gradle | 1 + .../quaver/pupil/ui/dialog/DownloadLocationDialogFragment.kt | 2 +- app/src/main/res/layout/item_galleryblock.xml | 3 ++- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 700b5b08..9c121c79 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -95,6 +95,7 @@ dependencies { transitive = false } implementation 'com.tbuonomo.andrui:viewpagerdotsindicator:4.1.2' + implementation 'com.gu:option:1.3' implementation 'net.rdrei.android.dirchooser:library:3.2@aar' implementation 'com.github.chrisbanes:PhotoView:2.3.0' implementation 'com.andrognito.patternlockview:patternlockview:1.0.0' diff --git a/app/src/main/java/xyz/quaver/pupil/ui/dialog/DownloadLocationDialogFragment.kt b/app/src/main/java/xyz/quaver/pupil/ui/dialog/DownloadLocationDialogFragment.kt index c235eac3..042854e2 100644 --- a/app/src/main/java/xyz/quaver/pupil/ui/dialog/DownloadLocationDialogFragment.kt +++ b/app/src/main/java/xyz/quaver/pupil/ui/dialog/DownloadLocationDialogFragment.kt @@ -186,7 +186,7 @@ class DownloadLocationDialogFragment : DialogFragment() { if (key == null) entries[key]!!.location_available.text = downloadFolder } else - Preferences["download_folder"] = File(directory).canonicalPath + Preferences["download_folder"] = File(directory).toURI().toString() } } else -> super.onActivityResult(requestCode, resultCode, data) diff --git a/app/src/main/res/layout/item_galleryblock.xml b/app/src/main/res/layout/item_galleryblock.xml index 7d6a9f4f..efab2973 100644 --- a/app/src/main/res/layout/item_galleryblock.xml +++ b/app/src/main/res/layout/item_galleryblock.xml @@ -100,7 +100,8 @@ android:contentDescription="@string/galleryblock_thumbnail_description" android:adjustViewBounds="true" app:layout_constraintLeft_toLeftOf="parent" - app:layout_constraintTop_toBottomOf="@id/galleryblock_progressbar"/> + app:layout_constraintTop_toBottomOf="@id/galleryblock_progressbar" + app:layout_constraintBottom_toBottomOf="@id/barrier"/> Date: Mon, 14 Sep 2020 22:34:51 +0900 Subject: [PATCH 3/5] Bug fix --- app/build.gradle | 2 +- app/libs/recyclerviewfastscroller-release.aar | Bin 52026 -> 53588 bytes app/release/output-metadata.json | 2 +- .../pupil/adapters/GalleryBlockAdapter.kt | 19 +- .../quaver/pupil/services/DownloadService.kt | 14 + .../quaver/pupil/ui/dialog/GalleryDialog.kt | 4 +- .../xyz/quaver/pupil/ui/dialog/ProxyDialog.kt | 3 +- .../xyz/quaver/pupil/util/download/Cache.kt | 297 ------------- .../pupil/util/download/DownloadWorker.kt | 389 ------------------ .../quaver/pupil/util/download/Metadata.kt | 46 --- app/src/main/res/layout/item_galleryblock.xml | 50 ++- 11 files changed, 61 insertions(+), 765 deletions(-) delete mode 100644 app/src/main/java/xyz/quaver/pupil/util/download/Cache.kt delete mode 100644 app/src/main/java/xyz/quaver/pupil/util/download/DownloadWorker.kt delete mode 100644 app/src/main/java/xyz/quaver/pupil/util/download/Metadata.kt diff --git a/app/build.gradle b/app/build.gradle index 9c121c79..1a65c84b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -21,7 +21,7 @@ android { minSdkVersion 16 targetSdkVersion 30 versionCode 59 - versionName "5.0.2" + versionName "5.0.2-hotfix1" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true } diff --git a/app/libs/recyclerviewfastscroller-release.aar b/app/libs/recyclerviewfastscroller-release.aar index 9b1211278602d9d2de9bc8e517165ac4652e01fb..d0f8ce00ac5a31a44b329e9b8d0907c80dc2dd15 100644 GIT binary patch delta 50981 zcmV)6K*+zkmIKtH0~k=9ktB2&6rhn>Zqp z{773l2noE`kEY&{*^hrXQk~p+Grt}C;kJMF1HP0m#w50++>!1G6~7(^QjTR;p?rzD z>DwOd;Jdyi;ob$r4M=?CT@>!7r?S}1w`8iuW-vz@0>2&0=W-LsvmaifnByFSd~CWp zhPkK1E?OTZ>OW|1{d2G_9!N{7`MPam89waGFcIOZ^<~{Hf7uI_{;nb^AVQO0=!{Lmc#8zEvRrFSRb@4h!X8vq?W_JL>_I(+*GvJ znr%ZyyDB3!a6eFyvi?H4-MmKg+_fwOWr8f;^s~%09o2om+3Lwk{L#$& zYc?HDe%u$bb((8Q{f@Qfl1vrd7)yp)e5E6GSK@C&JH=<4RL5z5?hgwY6Y835%VRtL z$B~RLpPcbm^U1d#>AL(oUELigES*jzTQZKMMyLDQH~H4h1jf$eNUQIp3~l-HZ9p2o z##T(?;irCV{zcowmKKrhsUA!FlbQ)lpu)S?YQn^_!fZsZx*S_RMcA3(P z6{o>r{KVi=yp!@);6TpJIMF_tNZWK&P^hS2owx06$%7|LXf zdkjn)=My7;TyJMvV?*M%PMA_$>?}ZkAlK6$!{@H1vN+p=88S8g3E9zQ)`a4yWnZ>Z*W6IeW|uR4fi^`Z z&c?U0rYm-BQ1VF&>&6yoIR5Oe?C9HBZ4KF>*-!<4ezWhJN^@g*x@&hwh zr?9OU5yAs~-w<5*Qm>a4zl-tN_K@a#4z3i>R0hdmr&OCV$$3Cu%F)(49wf4)a*#q| z9IMv{bS+yS60vf9P{iV;{nWcpycYbS{KW?!){qBMPREge&CD7PWTsT)opB4`lSZmU?Q8&{gGiSMBYwHSnh8!~JWII>`o4=MUa) z5h-+L|Jpw`vn|&HcmaGy8B2s=1127#z>IWcHenmQ_}s;kJkCv)#(gGs!?PrhF*tZO zP=?^Z9>9M#KCxB)!%$X^G9HBT2R{y`thIE1B>R7YQQ>Rff8wh(w*TgxnMUS6z)LgJ zJUZM2Au5L&z%Nzn^$U-L%J78F+7oks!yCC{hNtk#P$Y2utK|QKGX;0 zGPLmf{`q>kMiu~&B4#Fp10sn$b;sMpCcm(bn&`Mf42fxI5Tg;E(pA0O27^4Y*5W9C zG^M4>D|hWajTN?PoWQ61aqJI{3Zf}9DasAia7Brzx9PZn@y-^UPRhZ*Gec8nq#ec6 z(Ego{LDrReGS)E19ZWn_5We@%Xg3{)p&#dm=VqW*+IO<0TEJ3(6Z3xEH65ZHc^axx zcoJ48?oA84^9*Tids7Y*lAuUzR=t;hIyi_F)>aDUfzZ)iJ8nV`*i}3xP*o3hVr*O1 zgz{~-?_{C|zym5TempWrEihCx&{j;eG;7u0VhqX4{$oVm{Yy_*>vmn-32ojt)z8k+ zT{HLuKsHdB;;GJDqaM44%uGwUbG*9pDUy|zg5~Doah%&7@QCKTYdUYj2P<-a%Sv{% zm6nDWOp1k#g2*J&U7k#H@G)j?p!^5BhV z5EysDo838N_B)5UH)R?yUGRMQv{NWq}{e{cEu9F1NzvW7Wpn7 zz?XgJqAIIBDfTqI;I?Bw7T~8CscJ83T^r`p%{@7d4{?m}7Ym=1hG_wRGlC*VXfZ7N zMe8Lt21C%APU2$$qXU|HK2F8%SdMi%()*sQS++_6McdVj_Z2Yktw`P)Vq2={yY?ko zR01=p(5!NzS@We)aU5Glh$D*5+++0vVc9zotXFL$mtzl9*n4R&?}PhZ9}I*-1^F6t zhy|)G2d|Y3J4l`eocU0HB|i&h33(BG{p3w%c6nh=fda!~0>W)$LD2T->alO?Uvwmo zq!^oFpaPn~u-aZUSU3kH{Krlxwj!P(_<})vxa8D)!`Y2Y>1nD&4Dm?z3AD80nvS_l zGD~w4IyrsS4?lo39;1#(TF4KWijJVql7tPp!*M{-S>`(v{`lI3lqd%+ zNZ40kq9qm+W<(1~&O1FzZkwm)Y~!&4?P-bQ|3lg@L;v$5RnjsTGR*VT8 z`ZoKbE1$v~DQZ0SB(We#65E>v(I&z?<^(RLM6QZAOT;sOb^0X2uvCd@++KvOo$!hd zHRm0rf8|jADy(pzAbu`4jPq=4b>I}?q8I0FDGhvmsr8fOxgRo^!c3*$bU9l%?4?ej zsICZcVeg>e@wJ*;E71A~p*G_D7pzF;19GpT4MX)YC`x+c1SxGbC)k~TA=B)YJK+l)MzZDmGe7)5h{A^TGCRH;sE0sCHKPP3jC|3XqVSOgX(!;f z;J95xT6fJxu!fh`gOy^Rkgb4*bA@ms)fi&%cfAmWDUk=`o|4RsB8Q@n+F zov7C|j^^4-#IJ|(!i-@D*gS?r9PXR?Wjr^8CGwen%QvJ9BzGr@H*WP{vlPPUsSLR6 zIFb)CHB)$7$7ZByA)6KHGUdMFI~v8m5DXJm_NHQ}wXoS9%GF`yV3`6;W8^7l7Tv`( zEziOy4Ke^qo3ldM3jZ?OHW*}Rp?|K!;l8?nCl{*0Jh8gHn^G^Gs$MFE2o7?4>_<&5 z02G^lX6H*fP|-Xde5sQWJ)tG?6~thL04xCR({KI-##jAPtU^_^u;U z9H=%J%Wh}C?6Uc9RZqkaq{5LG_hPX(XS@0-dAcxfc49X>HCqoH%br`T{gKY8d(sYn zY;^ph_H0RKc;4plYzq-nQRW1Zq6MLA*nzNYo=DqQ`T@BlriX>O{n-FR1RujHl^DWO zd!?wFv0^F{kwpV6oq@thGa0d52wqbPs3P%!G3{Ys4`su)K#qq_Uz-IfbXqNoj$QVV z@Tz=UHL1Bdbb<@z66?a}R=zc}ShTo*y7Cd(TvtxK*@7H8;igCeER<*!5+I_hi~tOd zmVW7ws+SmT3dG-B0@2QriFD*w%_IZV#ob{2c1x$`G{(G#DDS?tUtGd%XRinLA_}Fm zV#kMi3}}I5P$hE*Zi)#mK%!;Rl?%JE&Aj!-L~HJ8P&7yo1x|!W94$O84(1ns`Q_r+ z?Q$`&b~)X-wgH-eUR?&zBAPBW!DevLp=OY~ zP)6qGt4zXbjT0&=uA0m>a3NF&d;hy6Jno>05h7zk8o(;b!QcbjT$fW9akdQ1?!+2#EuDbQX-5{Qp24tmKAp>Y%TSKO zEkjwyGf$!4m+gl}8ij$keRTx89V!ukwSBjfCVm8}!vd|~Vq;C9qQ7;2O+=Sv{7`FB zc_~>WS3|8$vr0Bu$%SQ=5zCr8t;(_fNnWH+8ieJb2mBfgzMR)}c^J|Oo|uh@ z?!rjL`TS!#nl31hn++M&bfj(y4h#&3L}y_ssbRw)f$1?46jQ}!rB;$V*Q0RhiZ>!` zBG`t_nPY6?G~N6W>>zG`vW`y*5(;ztwjphuZcFfu05*5OdFPwE8E9X&+c*-7P6|Vl zItAi8QpbmdjpYn>QFR=rc)rVl1nJg;9Yf-sE1)z4?a}vlt)fB|q z2b;X$)J#PfW?H_MlP-d$w)Ft#Pi5G3793tSPH7;@&WDor6cz&RQlv|YIlDdPory86 zx~66)ou;YTG;K3~zo^*sw&AC{3b^>f4;LaUSm&w0RWdL=%k(_g$;gXjY@(@R(B4>knOB|7X)+nZlz zfM?4k^!j6eX@on^NNqkE`>sC_tM!rB6OY`2*Z^{$I6!{Of!xa;%F!x7E~He0yS-*a z>gx$?Ti~C@y|eI?U0*CSY{-N$83xuR`kh2HVY&X7e^BU8Be7?fw;7MrCz<5%;*v6# zMtAXVO(7!!E^syfcJA(`PmSwb#ozqj@Qcb;BWC zeHTc7{$p?x;l@GZDR*yd%G&Hx^?byhIs;QA2n9Z4X>8P+Awx^zuJ^F$*l=1)B(YT? z@_ZUAXR46#)NI$tDM^oH2BCkl8;N%ATpi6Ehq5wdYZ^!eyP{;frTI^ry0J9w8x+rfp}3Kh`s2CW*rT3Sv%prYQy65fXCq*U zgtcZy7X+(x*DRWO3>qC6#mHlN+5VVuPl|-GyBTZbs#^ij_LUs14C%*?J3{LMc46oo z!os@DJEl=62odS@J2L@h$t3)}wjVq&v2yRhwUQm9ggL%H8`Iw0m_yBNN_Ze{_x##_ z-#Dg$IB+QZFGfl~IBJsl({1&loQmedhEB;wQD)me*`Kq3XKV=3ey5GQ7O7w zBKSgH)&=&HxUBv5IHsTTOoOl!gU4rl0O>qB4FZ*E3n*6 ze;Kt=Aeyt&4r>5s9Qu}BzU%dRFaFs=C+M!NSLL%x$j9eT&#zHhPJuePA4tuwjT7jU zmxcOhsQtN6anrsPKgZRAVHe`Sg-NsABvG|T%`S71Qv;t{i~CH}|+?4hpjB{@J)d_iTBS?8KBuE#hkltjGK8gDsvPhr#1;1Gw^J8+!jMK_u zn=wC{dPn9$eF5c^D&QHJpMXip=+3+pC7p88``_t%t0@HiyD}#e3+D?q**QGs)3dvR zF-~gM2Yvy_DV&pk%FAyJuGCK|%Rk+CIbvL>?}p^dos+{!BIM2Gq?T}U%kKs}i`Ul% zHv0a8CSuu~{8lGSwg$6UzF}9~SXX%DXZHFWUePQ1$LmhvFEfhusj!ps$e-T+f{9IJ z@xV^xoWg{3*mEo%xVtB@Eu}!K?0yqYYW5zdX7VW3YZ+sI%$tXQfWep1#OISDMm36D z^hyTjRu6kmgP&H8cUcr9@D*7G&AV1(_=INF*8=cQHG5|-3m$nz2l-=9I{(;2DUs%I z@$Q$@;~eMnjsZ$)a|??Z#3wF2E-krbb$nL)>csR`HdtA0Z7@SE{^xp?Kc*BZEbs^{ zFH?X2d%?kf0@i7@c3`1;T%_gcz(RRmrRC|s!g>0p3>^P1tqu+>P=~iCNZQ+^YB;E@ zEaO$qk+QdLLth`~9)7~UgETx+xxdxTYdj%o zS8>V6K8F6-?{@eKC(eQz91<(5ud?MTF^L$`*bewJY`kSOA)kKo6t~66P~SE)Ly05Q z+mlsuBv8Rxp+FwfxR>38@BIF?bg+0e= zBy*Z3$kE*bTl~?%{NHqmlW>-?l3i&Mhke~ zmNOi_@UFyM0J^SHuq1zE1daI@W0YW}z^@Rkivfz|cbSskWomwj!u@@2<%_2WUudMz z;tKLWL^j0cbr8Ezl_P^8s?zwGMH)P+E%~jfzZ*fXxw$;pr}?ro;AiZvjWc$+nIKkw zR0bK@9SE^Ct$tVTGW(8`eHKIplL?I-|B}nMLt%3G|6#=%=JN4A+L}$_%B-jiSm8pvsM%$_<;!jhM;|mdc8gIw?dd64aCuxs#IxrqKS1 z0Ik0wHY+bI>$HfhoM5b1g;Sj#NtG3UM0Ha9RA%VZiBVHo0aGW%N@a#gy(&WL)xlAJ zSzOfXLZbefXsFi*LY+5oQgDmtDYmqluXNF?EDhlgW0a&kyy?SNX)$1azUKeb2 zQk>Oa5MpIzA^2alvn1IB+OOIrNXe`()U=A&dKk^P`XGZ99k$tlX0MDfdrf$MS&}Cw zGpH=x-*ZYRnV0kO74g1A(AlM6`+@mkY8mdWa0o?uT$&SP5oj;0p+fOlev-Gj{Agcn zR)pqn=K#kOUFD^H?US1z>CN+AIO9FDUhlWVFxwuIlrWq8K)#HCoKwR0vLp9S3BAKP z>5}0`Cdc?>hWF$~_GAb3WXJP=v%=9HM3)Nq-MNSVwanUmsU(ny{~iL6(Y znbPceu{bA&;iS?|Dm7nZGN%QEn>sn@ROXV&e!R_v58vBU_mlY_$q5piMi z_PKE`=}hD4cE|tzKb*vW?qOb<{l6gnZ~sRBIs5PB1D;(G2kNu)1iJD*)9LBBIc&s7qZzT-Hby-mkL%{7UA z=V!8O5f|tee%;@DFQMik8Q%upEGvI!$`3oN{Jpq*PGRNmzCB@oEw%D@+n$#5jSV!~ z2s}{pY~}ATxQOt2`eRrojg`O404y41%q z>MK5Le}_m6=tq%%p}${5ZvKw3vwG)Ow?Ya)>8{RK=jWRXzq;etqU`Firz>85iDt1I zOIV4V`En&7B+25(V zq~TRXAKV^2iXb0O113z!vfnZ7_Rz`Cs8yvf$!>4riGnEp~2q+{&*YVhw3$ z)O5|iz5maRKOe|&|vIR-5Yj8u9mT*qcp~}7m?)d46mcu)w@o{Z{03qw-6FA zc4h)=MkyD6VzW{yi}zQ5lRsCL{CRP%{j3$>{pIrWjoY>1B2{<89o2J5=UsN|!ikyG z)LsEo;Y2#SfA(WpliTCS?FmOdQgiy%%tl6z^dx5VRE`ZimNTRyUa9%;4`X1O$Cm?J z1T7NrUiR{NjSS#WCQJ8twNMhhsWC0&qduzd#$Ydh@#amr{M;-*->1LYQot)-5Xoda z_J_}Px)38-uurM+4o{X~B%8VaES5QDlgq^|+a@rrjMe+7u6Nj~ylJf5mUH10CiIol zMlN^;gwqH(j@c`L_mz$o^|o*9+0OsA()*&?mfv9?gU?O%^9}-Wysv5_AA>K9p<}NN zcFQM!_657;&98`>3f^BR{eQJpKi{4&fb{}U)5iG)GFP}IIz#J2KeI0&oj`>}ySEtw zJhmG5wrGI(9k(G9n0%$~DEkEFV?VeSMSwS(2NAErVqgq*+J*l!-XOb1zLyCK2`3)s z9xRT#@)xtt!T1P@h{e z#50xZI-~rYUd9W${wasFZN_PaqsZU`f9xsulkjcDg<{)x)G$3X?F-_qLeYPM1qx<= z!2_9L(_=y$SPro*^%`<oQHG#+RWj9aDrcfIfTXK=htHviM6UxzrO#D)-A9AIcd(>Zjq)rB}o2!O<*j*JFLk_AN-TSd3p z7heLi8V=jhEesqp`p|V_AxSQ2Q0-V3(o_5?PuX7%MVjin&i1VNM0s?yJTSzx;9xzevl21Bw5}n zNm9&R176FEBx#XM7{G#;ATHL{gCNG_WpRD;da|oV1UDuy3-^Y(d*wHrFJjWN5JgEb zFWE@Co+geQt3BNDSw@!`6(yopH5 zMh1r)q=={}(pLgI&`*ZaeiIQFjeMNPvNgC7aZ%j+9(T3%%*bj*M`q;y9gMMS7i6 z?nkmE<49_`7j_lt`dU+ezE_bB7g0u9bm>*3vjyW%s^yys@R6Rbg&8eFb;aT%(&_Tc zs4UP}HUO;Jgn#5JA_qjA_|Q8jA_HB6miXw`L^g8Ut z^R4jZowed3aHH{n&d%OOBm>Fgf$h*QIYeXyau7>@c|FSFZA4gFEplBn zRzy5nGk#r=A_CHSWbti8R6IO>GW1rWh!71B>!OYOcM<7fcn}}ZHC$`Hi-?aw;qhYcBEmDsGX=se5|Np~ z7S8t(IT@F8dV&ytk&RJ?@(XxG98CD4Sl&k@!Q^qVeIM!nNgW0db&K@)#5Z>ZIMUtx z>)nuIIRW2CI^9Rq4w$}=2!Z(Sw|>A$R5~IKf+)N-=Mh<$m^mZC5jimT4w+I~4$7>~ zBVu8(Md%piMZ^NO3MaCRx3IuDCO2bsiBRldfM*rfxo2 zokyg}pU0!fARAFZ7r)EwV?Po;Mul57=2w-xu{;=_)tGA)KGXfV+qTrm8E@K>YJyeFr7FA~>M+VG z=0UXx;#L-a%8ST}&I1?OLX3zAC$djMahv0={7-1am>1RMH67zc1VrPpDODC1kqn0> zN{fgHr^&lBWLXjUut=h$h;VSy*Itb4wHs=pE)LLQQhSPW`w zZWlU#@0;pp2Ns_jYyNSGG|4;yvM^Zy%Kg~$mGE)i_oF)a5+~fy8GUj($pijKn5jt3 zbh3MKdMiYNd+D$P0v^siRaE89?KuyeUx)36Z7*>6r8L3ig$lO3yij`Wa*4*gyinnq zmpoiEw^QKP608h``}@Pe3d1Fx;D#Uh`^F)E|G-c2co_3s(e)hp73dm;RK>23D)(c=6(yP_qRB5Y)=C*`U#l_fQ8=<_~c0+_1e|LH_g#L#!aB(z| zs}y_Gdf|U}2CNtQ4`@(>7RtEd$?gw-dq6AHp@VauFa*Q&qY3a(-?7R_TUP zO^D~!GN#t=k|sd6xW$MTk*?QmvtzeXoJ_shH*L)owmr52naBgd_5ce|s3ApL8$X*C zpgnV^`|;omIfNun?%PAo4^=yRamIm^({UtlLjm*E!IlecJ7?q}R5(;Ac2}lWryt*~mZ$EB@Mar4-hE02@}`4R`Mi@;q{+i)8v*We&b};3O_8NKSGq21 zq~Q#jcH)J5kC#2$Z(LQl4HwQpZsC6OX&P`P^3NG51w%AbX^F6245(F2mY<7%0XZP6 zGG8<#L|;JK2ePN4fM`pXLpn%*a3gqKWaHj(;)3AQNjI<*>gnRc)(^iU*Nqv|L>tl0&qL*UqOaM5P zO0TW=9iS9*Tgy8@c9V*2Sh=X$v8No2F%%qg%7J&s0~xhua<&5;M&I4EP4&}_tag#s zFmv4h4nu6hMEi>2=whcP-9(TOYKI`lujAfV$SNT?T7jXv_&F9qkFbp_rZT#ipx+_raUl$y}dzc%uQlURvkRQnPXx@_L{lCF@bex*1-Wxcn!{z zn7?m5_NGHXBWy82W~>3uYmQF@-sWK_D=<(oLFQ-EkDEL7*+JKTwnWXJO5IAZdV7WU zIcC1F&s6iZC&|lWqGBD^8B1{m!(0KcWB!8 zTBb*;YN>+iXWy>iJ9Bh z03P^a)U#+*b&SDQ266gG#Z1v{)!?Da6@gi{ts!D$qhwoS7-YV1x+}YKNA;II1sYI( zwTHaF$esob=roj_xV$MS5fkj4ejNJ)yC5Mf-TF6-|MJrfu|ZkaOD?FOe<}H%X_HJV zCpQ)m!1fA5!jEwYdbMPP#iIa2(r%LIjQxobueWnV_6;JN#ZF5CU!v zL|s9efbNDPze>aIJ_LLyfBje-VK|mwNC-<+yL)s{e>gNVL)jx(L)Bzk9^0917k>hj zJ#IDZu4lQ~gH%JnVhh$!^@o>Rp0P7BHFS$lMjGOuP=77m<_z@BKh-NZqfA5b*jRwE zcX0-k1Ld$lXHe7qU>xUk#*6{pfzO#r&iDRVUhEp^o+ox3fK|bbdy+S8s};f3;<4H+ z{-(FfrpDWiXFP~2vTYZqc9&-WO>H`A*dar~!r3bbr|oS#wJipB8(zY+>tf%yZDZe4 z_W$CNLVu@_v}+0dG|xqZenR}}!2maQ*`S{qyIwHB^g3{(7YW9jKX7ZHSriNKb~gW( zzFsfee9m2Mr%yUssm9e)-?m#oV9! z3dhTJcgL)jkut27Qf+@cBh_p|DF=}^Y`zTpXKsXxg;*%T`o_xpUZAJSFh30 zV13P055E%Oe|8&t7}LJ2`)3iMo zB!(=J^h#>hw+!=p9r1jYjcNhvH z`{IK;=Co8}_s-W}bfwFk>7P8G*ib-rB+J)5%l9R)dzE~hwXn3+6@t?i8O}DO#HjB^ zIJ=NG!oJ(e*EKqxPYTXt#cU?f}7kckPMX7%+CEs4p_9Y8|>`!Rnh;&)M27`$&3)@f`&nc<>qv+jPMtKXK+r{}D{(%|v1s~?)##->{aqC+x zGH;E(=8{1udfkWQhZ}3;es&L|l@=eG_`gs~0|W{H00;;G002P%rr_O=lWQ+8e;Z?j zBt7)r%V2k5E2(j8rh>Rg7FSAaW9VTkHy|kJXl$5zxa4vD z3j3kyJO(=wXHoFLEe4aKH9eeiURtGCpU5N2>PsEH!o{gXtf~jAMwD7mJDjM8g2;2m z*~vuuQ_qyHmTn_*W}V_(bWPNJe_NM4L{rkw|2L25OLHT4atmTuHFv1HF!7p=yUWL% zx8cpW_uu@3IG5I2mk;8K>#~YU;kQ_00671 z000XB003ibVRLh3b1rIOa;*AOaAt4R^^L~7W4n`%ZKGq`w(WF`JGO1xf3|Jg>DcD} zzqOxlSH0iqv)9?0vud5J@w>*DS4{Gq%?zDgoQ<9AZT@>_Q2L*S+J6nP{~F5w)1WuDF?4nw z_J%c3Szf+vf01KO+$ZBje+AS0V+4at9`Hv+M3eLnNdTzr>ZRLlS3POMZ^q|l`Wk z-><=0Ur>-4mngHk%Ly87bA7cPlA`{D|7*WFT;7}pua6DC+$(di(P(e{A-I~H|Q6N#^bC>4OeK* z_rdhkbY$CIZ_H0;LzKHZdy4L>OPZ|kkM>7qx)JBs9&IJUehCM+ksAO1^N(Tm~< z3rE0cpsJ}kHQ{Pn(tUpAbioOV^hOOew~Oogp1B5HZvV{me_(1q*4iE+ds`|(&luE8 zegBuuzDp|0ZZQ)7pwv)Qf2n5A$-(k_C7Mtr;!>z^oc2S1N zJBN;-9KPyMnsbF)N66hkR!vDZrD9yJVqA@FrU;i}C2DzFMLDzj-`-;LP`TFDJIrNe zd5>6hNuG0Jf1b0dte%oA;R^aiVc4oxYUCMrce-ui<7aWPr(rnwD4SL@CTTO~xiNBs zhU38i3fBInMq{-GgCPBArcTVDdHFiCo`CHcME8~r)!;t}@0^^aLY>?&UNuTW@yZOi z;U`j6j=H@?o#q-$BMug(q)gje-edUGbhF9S!z`Q+1waD>jcjg z%D=O$UNaH}ENEv@tFuLzNYR0>oZ!;UW*_PAnv~s*uwa|IFnlzYN#+-gD4sFI+BO2v zo3pY5{NlNtO@DIjg=Sf-|6Tl}tDeJ3XT@4NX~%ybKvnPgO=NAhM2FM0Qv6Q0fc5*z zvoV(@fBM0*JKr^H$6|mk-SOL|$6ue*qdKT+`O1OqTv|Kw(KMpfd0`{vOt$*ilO@{O z?K$ug9@_oHP@2Dm^@5HJan;F3w0+PuU}u9{Pd~bQ!;C@YHi##zCFE=4sd&x4xTj*d zu(qENi^N^elcXnv)Z6;8dCflC7v-Q+Lw{GRfBb_^dg%My)=d~+Xs{>sl>f3*@aE4H zsOdb^NxWqmxF^N)^+IR8yF#rEL81MC9^Q1k9EW&^9Vz-8KJtf4j zf76%hpl1r|#T4%4n4P;z=j_(0c#uXR)cBFccCS|C)yU`8>fS+}Y&~=`y64*J(RHJ4wHXE9ihu;!Z7Oe*>pW_UVAIG>Ai5>PM z&%8v%@6NPDJ#id>HgU|aO#hPU^mj~+9w|X5E;7`%Z4Kw&fnj2#xC}iZ89nlOfBm5l zpP3M!oe-a(LRnC05-`_95>=7g1FpC|6M;XQ54&(}K!4IeZ;??5KT3t1m4IWQpYSh# zub*gJZSQQE;VRW3=1!Dx(@L-xD8HNQhpMgH#!z%0w;|_jB;1>kR(aLx@ zoTe^b@_F;Kc_cM~HDR^2JZr?(pD4R(1*(l}-hxa?l-_3P3M-<8@p~cPe-?k3(*h;r z5u+P9eihfk
v9`)2USQgqx)|QN7omW^2N9EI#C0sg~mjd$Ow!8P~K&72yCZMcn z!xoi{*f5UQ3XWI{Sg`M(XgT_&VY0Ysx9rl@j4ce?1dha8M%6ZcDWQvn3P&c(f%)QI zoEwZ0iEaHJ%!fj6y|e?kf08gCS(s4PxuTo^zKYPvUK1qpSWx4(p=P7IIW-2XSrZ;% zeMsjpMEJxojr)4MgG4@HM3B)nYi_P0?d&feTp@4^19pZ3VjPCB5R4BY2h*)Epg3$5 zO*+CULzfEQ|?zTE(z`km&X!XSnEVe?U<|4nCIjA|+=0 z@iNeEnorv-+t=GAPbvr4{mR5XhKKa3kF0=shA7+&Rk*|zr7_YHthB#~VBF|CBM5m` zOC!Y_KpAwKGsMnfDSM+t>j)@O*Ua)2=LG(aCdsO@+}**tT@@wixuX1_Z7T0$KO$n% zKm*c_hpKt`9*6JAf4lW86XrgY7*Os-VqZ6`V+m=KHBye2JTqFQzn;O0fb(t2Iws1} z53C3A=D338ujP}^%S@?EM@Y0WAcx!4DrW%D;NR4=Hs^@We|1mg;q(w+?$(f(&ZAXg zy$KP3HqpD7G}dOnn zwCAxj;&d}fe+@t(+FGXx)tQH6_0qK)a{KXEnV27aM+NuaYXQjBbBf&Y$XEhORdN7T zTJRlOg?7>DON0~NpwCSSP)AOGXW%Cs`Oux zzvfs!Ian^Nb9Tr?QP)H&(Rw<7_I~GCBjUYxF{uUZV_A1j;wybjC2qQQ&r zk^+`>3m0^@2n2jgBr?A7>wJ?d`Xx3+f8O~D zoLVi!3Yh0NXO8``I9UQ!Fl78X`16*M^W5=@GD~HqWo*Cx&9RGeE~qv#A#Wq!K?*aM zr&d|QifhM_T^`HNy!=Cq>?CgZ;(GXJF$epNKNhHu=uBUIjR?$O;u0(_VEM)fDaLrp z|K4Fw@)2)cS6~89EpCp+{e<$(e+2Ih+0B1O!xY@kzJ=B~8blGeYP7ngh_ieB{izvb zzK?ToUrXbM%Ymq=JgPdoqzz8 z>Y~*Z;$7kd_Y&buQ1{eNG0b%r0!j%S{@4}9^Q_$Cr~Dzn47{Ve`#n4VJ?8k zCB@U_NG-=%(htu#65UQTNEz5boV;x*Ln$(4$k3RMJE?YHB!|%QM<62LxXl1Q=sY$7 zojd)+tbHoLFU*ujsu_0?L8_3o4f>i~3X;Apw117bK$l|hE{d$k7`7a56LT26sVI+| zZ)8COmc}(GFv~=#_)cR#^3^jw*~+=E za?XG4zpso~v9`fqlYUJ#sUO=!XB(E?%X}c3Tic|}@7qkN)7lL*f0!Bi)s5=cSM)Sj zJN}JK%nn+tx4mn4il)25%>>VMUTe3h;hWIJ&9u+sMZy_TWP4{*Ghcfa+7NpD(EjiO z!_~F{6zr^>Nf6QmNo7W_JTUoONyo#QY2xza(h(n8v!a%_onvR&8UHOh@xW3UW?m6_ zUX7~Y#Hm%!m+Q^4f8jcr_WgaNV}F@cbu;L=f6L|uDrpXBE!&}GD!o0vF|W6rLv>Je zp-U6E33gJRFrwBk!l6B`wh8}+AN?1BxVHaIEWKQi@HmpZAPQJ*j5V*)i%o`Lo>;^{ zjKNBcMmQ5+Vdzg_=Ml7z@A4RIszMODW+Nb@TUal*B1&@2fBu}Kw9HE;DLT5?IKti_ zJLH4p`A7^BCBou5VeqYN@lSd_{Tb(Av#MXYj4?|{DQGmh)mOL(N~pZPnskhD)9liV zjI0T_Gl>+>EEUJni&t@F4MS`&`E(7{DIdc}RD(`695O(6Ixl!2w#cFg{8$$gAvJg) z-?D-#BBpK%fB)45_x16$uhblIYq+LZbmY)%wT^%@J*F|E_$@6PSH}uw9}3|;sx@=# z(o;>i1lXdCs(-i?-~b}a5izMviW!HGDmQPvDA?M;B`8Hrk4#N{-W%Ie8 z8+WT*oN0nRF@KrOGltcIUSJmwy(4o7JL4TS%PCY57|wBSG++NOG-NF)1o~2Z02&HB z>_muKL)&}S?1Qv*98GI>;EV{Re!g91Nu4fHda=!lmvj1N)Z)H zC&eRB2xLAe$w{1JOzc>3bE$yG(D{3odGkkcW_>e-C_9>~p3ru#n)=m!Bh+Q}?OWHA z)jg>}0&m?Q>wR3$4>8^&+1-NHXX7!^JoUfueCDAO!Dxxbvd0RWA0g<=EqEE~;(nwB zv{Pfn$$zV1JhNQS%E0dFo-4CmqnjaTAUa88P=kE%G0G7_qmnsRyIltcBLPJ(0tg#@ zLjN~q<$N`^bi3$xqR_BVuhMXqn&44T0fg zEPaneark5-TOWR`+Z_L%`SbYRqUgOl$Ji`r{A2Rt)aX~|XMI~1@Z#f?hDk@MFxWA-onO}YqNz$9>dsHZt{8cEmEf2? z<~C&?p(BP$yd2QNTl3cY1BV+uA9H#81b;zazOqI?mdgxYj;w#Jv5x|E^DzD#?4si&u=xc=|gL2|Y0 zRT`e0>m4&x_uxi~RIje8A_^d%4&qbTw&dO^!rpq@o20f57`kZCK%7V=95v)M5PvW8 zB|s=yov7aamkptS6OH|vx-;Z#(w4pg0Y#f0D0*u58kO(HpjsoY@) z3@i#U5D~Mz$1kr?ATLw^G~%Y&JStO!mUoG5r3k0hi?c$Ywx|V zk4Vyi(krjsO|>j3ehGq_3#>Q!Ji&aH&~S3TL_t?{`^*n(#Z`$z>bjVhw8G)3t{*LP zDRNzG8w4=PqQ5sM-#xtvnnVM>*de$FQ8o~j!f{-=_FF-dl_x#H=dbH_hlv~>KGqQt z=mV0AfLindb%9u!OzY>5Ymc?^lj`@}HYhJWd{BW_4epyPNC`OQ3j zi+tWev6T!%3^oWLW_Dw@0f)hYK`2>Z(!%^f)!mnbJ5RMc(~Y?=u;)F!Z9MP@&HYL{ z#ams3OXM(Iq9>!bL5cPgwXL{ar9#{~gre{Rk8ZCouI{ceRpcY*9pt8HwoA-=^ULl{ z2M_wh!{z-Wj(;8WNr!OFfq%Y<8PJ;~NcXQQm4*Rx3Uu@h3`fUctud6D#fDKKDW2 zh~FJGi}S6P(E!dq?A?NgK=L)Q_oZB#)H#f&$4_P3vCXMzM`3HoBQ0vF?SUvI@;(MP_03188L)qU^Bzd97p_3{QQ)^g0Ul*Pp zsLi-nF%W&sDPqb(gX0{jNg|w2HDAs+ZI5kT~!N0$m zWP^+jtHpvy4sB0h`BVZYSpYzDD@L3W(nHIZ%ObK>HjxO0$T&Ki)QW@W2HGiEO zuUlQ8TK9tJ^Q4;x)_Pr?bIi>lQ#+5)x9wZ{{hRlj>ue78^=%K9LRFDph4J4p7My`4 zjgrUU=w}87-p_uba#wAUm18?KvTrNI1kkp7ohNROX{qPtYQ8G$;WKg^-s(EB(zKsR ztd74!zWI~o)irjp%8E*3d#3Pqo_~_jyn_tllPygcxJ5JT+*Bk3?GkI=&AOjdO07lm zS&8SGyx>`Tc9cn162I81S&7Z@?1W0iHYi4;-Zdz6IY(NVhbA3vq}dqL;`;0wL;r|m zgwT91)dtd?ZT!If=~>79vAI?OI7dUR;z&<{H}#^d+M$Mb?8htUBgjjrtA9+WBa0kA z??>FL{D1{OIq&J9P8q{KU-^Lqto0hFmHhO+egPH9SI2vkm}E@Z<92I9ESq|GWmA^` za1?jiuzaNx99b5T(Y_XfL7o=B2y>VWXsdgMY7HDp;Re_RssC!8h)Kb)n>ZQ;Q`OSa(_KF2RY^Vp)zhJ zracANFRAjxR{kCUU(?ea#s=nV#0Yi$nA0%cNa{FsmDDAKH^GCSjW-&F(n)}3QDrXu z7kSLo5J$bfblVj7KaQEHrBNN1*JTV5Z5nHxOVnMb$ktPm8fW^1EVmu+R1fi>w~?7~ zcOB%pwcnSD)ZY3*i+@q)L{<(^-CV=5I9WL^7?h4=`MvVn_d{!0%mE3aeEl)9Lr~$% zoZF3vVEZ!Q%d-e)wC9M=uhEMdchVaU4iPU?NQPy_h?RcT^f?i`b6i$^@8gsmOa{ik zlF)wSK6BoG`d>{3PHjF4g{gzS6JJ@Lz9XRy4S1uU?d?3W-+y%f9M*OF)zc!M4vrN~ zAZwQYXy0+Tt~8}w{|Npxc$?&wtu%v2tTo0>FE~!hcmW2J3%(RL8w*yv+`yZ zuQ`8!r`-kNIQYQz_CjwllqO86>1U6bCCl---O+pfddL1W?QpL-G)z;;c!EJUeA?}r z)B{)l-hV~vLy-sYZy_8aG2bFGemi;op4@ojm7HQi{gDf(GG>HLL*obWAZmyWT$EI8 zH(O?6^n>8arPoWl)G=>pRH+}-fpsHC;~CEJnUY0!hFgOPGTE`?r0bXWyclx{A^+`~ zk~yG|qnSK3cO}e}WIs4(k!X@H*g%<_-?U<+9e*-n#>~ndoG+$f#jFC&xp?&Ar%%8oj6Z=AJ~ zcnn@$Oe+nk&BJTK&KN(|XrHxAZ@sEGMt{x&$d%Hf<9wND~YaW|j04J1uvl1t&pkfZA->-k1% zHV}d(zoe5aT5q_#)c%p~#o)DG=6@Mnu^04p z+sb!7;ml8Pk@;GJhT@&_n?Lwk6>ZxZ>QWuOqyA&v0^UssKV^+#jdww9zi{uK)95l9 z{dreBH&?zBgM7?qjDKA!chn2H=UVje6Lfdx4BUffdajTLV63T^**1S4ZT*6{jW2h zvpoR5k(j3+R4T9Nbk_=1*T1A6qu-Gd6E#ZD6?x~LzLIe7H!l;v)PJ-VBc_vFN*yw0 zI<1~nM={2sTY$876JCQDZN>eFhvDBStk@GWCjNfyK6&vkf+MtU)njmPRAN?cl@T5f zl~Ai?!wk`RRE!LJMC$eNoMN(YVx)6b_q(&Mkt1VfC&AP+@fdZn%d}AGd5~O73aF@6>S37@uBuMc$U zp%>co~;|b9B zRrU#3cYmV0j(--fbK3b6;Kxgz;;U{BQm}VV`BojVogxXC2y=q($1xl67pX0TJfL1r zW)!+fysOP|m7ZGw4rkfPqKW`NJKPSf9sM*{fBWs(597}TT?eiFL2boT%BlOCEf0VF zE3Aw9JCI&C!kH!^aV6=l{0L49LD@X6(0_$`L*DYs9)C@#zN2K{j%&vLH*3+LVi;gF z5;we6IH?MgqD}mmhZeB~q*QU!SXRf$>$rTZN3Mp&vcOAgrSI4c^mCoCv{#BLzOsarkgaWmQVB$$HI! zdK_dhnjuY9Yn<@b4`)!-mP5moBB;jnaQpG8uYbw_#Jg>Vw8%xSyW#ScsGZ29s*Hn% z3L!ji@)3dTy)DS8J^X$1(S1Cb*YdMlQfq)U93$g?F4Ngf_}v#QkW&=_DDJRwv?wR& zeaG$~CpZ_NyCYBeAcl%uTmI~^TCJ^K%**m)_4Eq*-Q4|| z$@E?Q^|=}I^{K1+dhP2W|KlLg8UMXiRpHx~yKMB)XNVo`^ltg2_nq@+_5Q=`m;lA{ z$=CN9GfeuHNOidk^K zq>M#{xvxxANuNcw6+VqoflDuTEu1ML^{uJls%r)kee%2< zWMraHtGXd_RJQ2d8fa+PDb+lbB-p92?fQ>Iz}7R@Nl?c(-|sO&k5DP~vITR*flieU zCxIXDff6l{pb9sZy=)P9^qB)#=YJBy;C1Y9qJTSbLx9{xy?B4L^#clJ9+mtxNNUR) z>lH_4oz+RIMke(q8w)8m)f55dNN<%)&b(}7(PP?5eu9uVrYK2O``msJ*8Pvg;K4aW zVX&A*VzO*IQ*UzC>&Foc@;2LuNuQ+kkh&d&*bm#U8Wy8^mmH_RaPmN-(0_0vTDPJ% zt^ws?U=ANEBAfy`V(P2LmiAsmC4ROWa?ge68lE0H2M$`d#ulwzIP|R;a!u*g7-=AJ zbPMSHR5cc`Th)6DIL+~;*it$ng;@8+?&xLKdB$D#h3Htiu4lYJnB4P`Am&}vJ{{QS z9^Ppi#?l)6Nq7g_=#zBzuYZx!!ehs#N8Ovb5NG=q-t2*X#Sq+QPRKX6O#n@c_cd$% zGtPrEh$D*+Noy}QOx(7Qs5MN0IHw6G!($7~PwH~UBA4@5PW?tMMlSOv{8U+AIMamx zYt!)V!vRZr;Apb3ruT6j8gC5_#Ao1|@gTvjrQ$A)-W2|)|C)XC=zoy^^xj8xKM^v+ zIzrDb*iRLwg|W(kskKe$5Dk08S68sFf;W>gyIO`IfgXl_L%>bz98n7%K}Z_rtF@ci zD8GVPs49|RY`WhRE17;=4=A-Bk5Rj#W_r{PqF# zgg7}WF8FS>%i0(E0aKUd;CaGI)QVhO}g}U z8HPUIfOZknDxSGrdODw+^9 z!@ye!qXU?3rK=gbH>z8DScI(OiDw1eP$%|{s%9r&x%DFD6pRgUumJN$el(b6MC9z* zL;9uh)c>_+_y?_pvPFY32On%Wg%n+P&ekah2)3hKLt+~zxMtx-Aa7Zpkb))t#>Xb* zf%KbuGeFO5@_#rQGc|RzotAz6gqq$S9ntO2XP*(PQRJ~1ytE4pEk~)5rnNcafW2Y+ z*opyg7p!+8C7grqw(?MhG^mjS!2vq^Gvg|_r2E*Ti|MWq^bW0ZGJS0r`JNn|kBopW zZ7EEDXsEU!$G?$R6I|cUw;4kYwN$szsDlAQ}e8})Q9=*IZ!%q~44LEI1 zF;H9K7$AcINUyyh6aK)z07x>%uvsjoW|7>qU!2^JySI*pEE11FZ{KZi z-$C!5;+)~z7ERw#?;h(FKdigUU?XvUg>M>s$bZ*Uu^F9Ld%52w=)YG2`%2&CgLEpB zR>P*whxn~%{pbJ^lyQt&fpH3yhEc$J)Cf{^Y07v7YQrqx9jaU+qo7dwxmyR&2^Nh^ zMIw#VumMO_(W5k=0!#R$N0zTOzzVxawj_~8Y*+%+f;E@mR36YoHIwAj9d+c?1Eon{Np0fhi2E6cf8{H8yGWj< zAScx+4v@q0p?Z=5Nr7aKl54cYB!W_5Qh%qZb)sL})P|YBD=W@asWzE`W7L{BhhktQ zsSe#fF6?SW@2cb)@xC#tn^c?L00OFAl0zaelWeO%&o24a5w=ybO?Q9*^*YHR_1&u# z=(V&fFVUtxKtXny;E=np^o2?ocbf+cCFP~vM}du%@{k!gM9qo2EdrL3UZ&hO0e{U& zc`Lttr3Rc)`RVrm!sf=`1_Jp|pQSt$2l!z>$c9MMM?qm3`pp%I9pb*d5p7R@Ko$P4 zJ!*Ovk=sWw5D;=G5D?}6-5xcmy`7k)ou#vdq@9_Kp^GUg)Bks~x>`k79!(IPZ&6Jv zg&I--Wv)Yowz$r}45sW?{F;U_7=I9$hcxJBv1(_2G1DXw1>8LlU{qwvz&zixLHn3>wK-xcryWeooS#Jahql<1|ms8{mPuf|Y_Tj@!rEtW9o^d~bu zm<3m&bdp?FSS=-Sb&u;3mYW+i-M&f1w>I`5uBAt3EC;~k+2YoM-e||akL*hX}09p@M5*Z z6h`NNq`H<9lkGZ);=_j27%eZ>{H`7qdO%(E4hc{#Tyjn#RYG_CVu+iLU|*waONe!~ zPAjp?@=lv-N1(I%L7MT%?OCCMpK>6NvV|0<41AA^rCERoLoJLkJ%2iFVoI4#2nifD z97PC4r-~wzE1Q=!uPMh1z2_)^|dWX!V9`3x8fH_a}dDGsRefvk0cwL*g0(#siBmF?DK^@&uY50-AK?xf)~& z^AD1-qfBe}H;v{U$2&tu!rZJxGMp^Zrlil#94M)y<_9Ae%PgR!ivv?7f_@9_f-swO z3vY0V2uH?iuz!6+`(x`u1op(rw#jXu z_e=opl5UIPE^WPk*zl`fgqpBY8L?JShIy++Cyagt#DFDmw#Qh2mcpIV{tB)s)TQq0 zSnWrbI|OKA%vAiz8T_l|NQ}&P^aB2WLna1IW}xvOWatq8d&uPN6zm;b9sW;U)xqRH z%>D;5W$ph1*?+g0cFQJQgNJQ941HJ{NMtk;L{1oNy%Ny>ejq5_F0{dgr}J6{en{e# zj{gnMn-M7Pmvkp%`P<54!R96FA$!vOWGct^=k5v5A1lpxjgx0n^ZOLikp}j6&7cN- z(?Q3rT9=AQAkF@?SEvphL@0?xg`4zW8fac6qn(Q|6@Nu;(-f@K|LnM19uXTHn>~E` zC-3jlqcTbsRJ;UFJ}3X4ROPSe-vi%r40YlGu5g#nU@Y2BJaQZ1cfHc*I+6GdfNPW+ z2Z4izef#AYkv!)*9I=XN4e|U(j^LA|Np&0z7U9Nu!78;;jX{&;4$P=A_xR zBeOZWOhc;A{RncPa4(VC$>m|WC98xUvazL9=`SqtSH2GGc91vxXyls8i<|O?ke>)t zFehomLc-f8qJw9ju}kc@Up{uE=E^7{L`b4Bn17?5-{idMO{+S+j_hIL=OopB_Jy3% zifTVss~Kg~51aOhV0EScQZ6^QO!%Q)a9mLqtg!IdmJg$?)l6yo55&prqR+xFl5(ENI74BF znSb7cv@wlX(_b=sz?dhN0!X*9sJW2!iOBZ`SG=_$9^&%C5th&2q1(^6<--_^vb8QQ zxL-5C7aTR<6ATT9)aj;}U&I)}B!taj6c}-rw6V5yf^v)Ye+zkm37I_s5(Fe400N@- zzZ9~mt%J*7Wd}oJQ%M(7TM<)ZdnZE|OMiPiQs)21IGWYAmC@AEf3{7=$%!pQ1pioB z%2>k?fmUFK6E#zk;eLV?E7@F`I!j`*cRJpn=BpLQ`rLT&_|(^CE4pl?r`+|2euIB$ zb1#m+JQz!?-iB6cycVHNgiU>PA2MJK&>NrB*Hbfxyr+t)? z)iGKU>u`vIv;v#x9$8e>Qjx^eQG4gJFzJ|tO*2Iny{$N`v%n}%^W!7qDQFU}FF@GbJS3OEN zZfoA6Pt<)tM&AHT`L?aC2IrD@nompSp}^tROHE$2=8})mC(Q=O&^9C=JbE^1ig6#?Ezxy7IZIzv z%6_}5$g%-I#}$SCB~vE#2@3aV`8D`!b#0+nR3{4utHzpAoy1vu23kAQBsTJ; zwowYYDlBunW!H|l#dmhmhQ;k0Pz#J!@)|pKrnNJ&{QGymF%Cpknt!6k*d5KMgmU1F zI$_iru!uAy+DNVu24rW-84!$?Va=U6j5ooR!gUFG>bMk@1B@-?Y!xK4+p*>LOwdQ~ zh=r5Vti1uDRGaMjylm`Jg|UoPL)j(Yb*63vzXA1H*4S>CDyjL52?>Q`qIXO)3B4RP zXx#UJ(OuH)25R*g@qf5J$dF4sm<7l1{9wG0IA+O~Dwd`J#uqWo+-)J1u_9QV7$baj z>;sp~f6|X)*oW*470BkT=m)M-r0-}tssTAhryugfe-|;gbVsX=GxB{_n&5wz&~!^G zXRxH`56?cZh0Ll9)$Ti6jYcSxGoEWe?#FOm(~SGDCT~ViS$_|V#W3_G6R-e6zhfZ? zAVcaTJ1QHo&F0Yq{=|!gtDnn4chiuN+Nh)rCtwYBF*_k*vJK;mK4dW?;3ZwLXTgm8 z8E^2bHh%pYzT2Ej7Zp~?iKay#p<&;4!S=vbpoCW(Tkj~Mv?oxT-+QhuB8!kp~+WtGjP77D3TO?U^6qi_tHWO$ahN28>TMb)% zJR_YjC;z3V4zA5xvmsyz`d&IG=@4FLma(xU$;!9<1b?!PH2;x^dwg3gpI!o*ykQ^x zj0BX#y|tZH=}^5mySBRY0{)IBDl=7}6Sq7&zqVW^B-!i^R324#Ftd{I3Jg)Rh5Q#| z@q!G8KfjULbmK_nL$v+kc!xr+etWjmPQjU_H{6V&lRE*`Gx$e-6As|o6$&E_S1wB|OLwryLEBRR5Z}kg<9B} z6OUg|mMa#Q_Y;}F|7ItS$b*s#mADo>VtE-iM}I1W+DY~-!79lreVJ?#Z;@<~2qSfw zXp!mx|6v*0y1XD5`2GKy9n>A)m0c8@?W5lv2=DZwfnCo zVrpjSYU3hl>tN&jKPg8^)_(C1vJYOVYvRHJQqKT~-Jf60Y}K41(~wK3hA3J|c{&rO zhkr6k6c?_yc3?2`KSRmj0{%q7*rkFH;ozvr&GzQc-PzgkyDvogy`Ua}&|nPm@_5Pe zdTB$05|Vgio-}gYM^}HTs1icDWN$<=s&9b<0XV}Wn-@~17K?bwRvI%C+gGET$q_Gq zL4`oT?AtSbW~A6|mEi3QCew&g1Kg z-Y)$+oQiCak&+$bu{6#m>mQSs_noX6P`c$*WIXp+j^I~8c{$oe;XPhiA$+cMB^7Va99?(en&3_ zRwWx1;F+5ptKWav=m$6%7uljK=Z(gPZ$#)#s*IRW`8;`_Zak?G_z%7j@%p=(cFScg)U5I)E!(WMJj8RxUzXF{u9f2$Qg5p zbSuu4Q`djW>MK;r^3Ugmx6{k5k!SNppvN1W5h~m8eVd2wON=SYYP!i~*5$IlqLDVq zv6!AVzf%ZDLCwW|P6K76Vt=!&W8xKU+iBQ;0o^sVLwR;Se?Q+v>+dG$2uKK32Hn%v zV)e3$E_N+IdMUHS<4(k#Z?%jEvsqaSWCG$I;skuIvyS8vr(2EXs?-ku3NUW&sVuMA z@x`jD<4F!+h^Yqfz*qjCh+!q>@!oKKh6b=<6WfenYEsSYG4{210e`2fuq~G~{5ynH zh_2UxZq;%l6T;Wc)v1{6XXrU1rO@r3rXd<__Iv(p{`9f^^ijj*-P`3|$mQM0g_|I| zXQ+IXjnA z44oWfzhk+C5YItpNh({YkO#@uq{aZy{FiJ!0N=-JRh(fP##8+VQL_$O~W zfDrJgkQWNhhktrH|0fpGlXouX4~Bk!0s&`$o+l}h(jlMGZSLJ_uH(t(>d=8Wpvv$S zjlKzM)!QrlGUb4QlbD4+EAGoTNL|RI7*a08p#joND9tip9obCVfF9V6>A?cz5Y~uu za6`}n8Q*zxJ`&<|$~WB@My7A+lY*h4yA^~Xvgt$m7JtCpxV7LLxlMb-&6b4z;#MWC zs}4+qt1;?~pub$RaDAiI%-`Yps+%mX@BFF@U6cR6iA40VNvMDa0nx&$ zH+DVyru)X{=Ck+3HizrwH4$W`@jrZ!h_2T?oK-bqN6=N7F?6k?&QaPcnyKk48%)Mj z5mW~g=CKJ=27il@SgAB4N>vbZs6wihy)I(D0+19YuZtOf~+u1%0R`eUh{62p1g&KP#tISC@39Pz! zvFEVH@Ph|i+NLrQ(u(Uzhso0-n#fs31b=7UYwX2mdlpTW99%XEvEm;i#?0f<=e$|j zg$-uRDl$9U$%XOAg00;mxCG3nD2uNg!THu=zo`r$gIIEYoypl>5hAG-MC6a*t3_p) zg3m8n?#X9fG^NySo!KxI4iixVuY&HSX^25Zs-U{mD6Z?{n+ct=iweUe(=ydcEtJ zV~jaxFD{;&Ea`?@+v&y(XqAehi|Bj`gi?eWDRk82h|VBcK8=#uMy&|^`x7HL8|c_A zd@_*^Hhl?#DFWvix?tv94!h<~so;p?5jHo|b^#{5(Tb5{$k`pK>)U+k6{rp3em zyM!rOHHH(kHucjiW~YwwP@|mc4R<%3WiekLeQ_U(I5|6s2QmxYHH>wTN}6Oxl_jQ#N*zu%fK)}|)m}|^8bEFf*P60s zm-o!DzV<_LenO;<3;HL1rof+%wAE2DB&~zpUzIR&9H%I=K zZ3uhAv`oFT#AsCRot{y<41du}_w8@1Xpy+ve(+J@myww!BpOBZxlQ#zj8Rf*tfVG5 zkpd6gkP^BgGi6X{o?{&>PKum-SXnfUMYOV`>^g-$aO2jA@F?7A1CLt!_*wZbPnh|b zG=a(RT3K4LsBn_Sv_S@57w^r%8a<3lO(8fBY20_9@Tabj+qA2wva;QMwdgD;_pn^dTV<+}xGD>}drN)j(nf)a~qS6M;(G9^oViO)7 zgS|o#eB=Vh3I|^hq?DcY8AIjHp$iHV>(7>v=l?c|#37VNw_cd$`t|eqeDLy;&Icn- zadCK`(gORE>VIecE^0`7C9Kp&7a_uQrTC6~MtC!f%} z0_Q6iH91}<;U5#qfPtjKjHaa$6?xCM_mwTvg|l*bu00L6$PSK1of4;>6*+x@7==hr z1cfBHnJx)jM6E}8SbyA~+x*V}avv7?d5q~CKAiFF-+0M-)B={t?IOsd0 zQXJBs4C?8vUd0?_Bz1&AddDryCrqCvD1(8;`VsxZ9!^{KE~&4;R0r9i&>vmp<#AW= zjD#sB=3fMWy80FUzIdD4mrv_b;}!g*{gyJYdcY1?07CNmufUK6j}=s*<6@`lsfVl2 zgi}NZ=6{;Oo%aN$LFVUoBBXYkSUNKsdwSOMP32JXJ;toJ`pE>@6#u>*4wGdFaJ`mKe_<76xp{c}jQuDPS!(JAf+P{aQB>{6 zuZb86QWh?91dM~e>rh@G$_mzf;P`Jpzq)xrXn$VxG`OFAWase^r0Vg&#@QuzXC<`m zOCFNsC_*VhzEkgT3;djr38N^F8*zWb<_mdh>z&-C(|FuWf}rq6oE#5gUGTo0z)1-+ASrQ> zCVw!7$2VpclHLZ7ASpZqhWbK`Tx;yT&4YZ_f+bz4d=xGtBI0A}v*|v8EsWY}kV%?owuzDA4?xo4i z&e9yLCTs1P{09uFBOXIsZn<{-^?S!XOMkPl>8O?&0||N^+&nwu^LO(Ak)Cviw$@0s z8{ooHsY%>`UZQxsXpT(>Xi{!P_FZRu!SUl8PKJT10^Gh4 z(ptb>WrA0l-Fov?6dUnWQZKvlNmn6*t4yw4KtZqPq^?lG2J<>Y>;Pyd47Z}RZx}=KVwel$rt=86SXVU z*mt*&*r)tF?kEEB14Gk_`ok=y8h`Q2a~G~nsj1HKDk)bLW*vj-2hds}_uc4^GBdKw zwBZfcPci1mBi1F9au-1o7$UK=g3F@XJb{R2l_h+H`LHZGYFp&?$A-=is8=an7u+6@ zyMuK8;(N21p8>*4;*o=-@s{I}vqm=k5e8`+hX#2yfP`2!> zTmI|a^`lAq$7!k8EY!u*(~%n14JWyKdEXolZ9NO(ln(hF53P^j#K)xBe&t6Ub3vU&aHciWDLO-BaAtwC;Qr&sgKmj%r z`E9}DAQdiyY-4%pG(R*?k(>-Yi>d5G2X#}Tt`K>Hwk%I<^KTb2^;+-n$rclnl%B6h z6)8EUMH7`}yvIWzoxc4jB&lXsNQM$x<;52Xq7a!;bQ8whD#%;;91@ z&AKr&F)z8;if4BV|9`})?CwA*o5sD2?kp8sU&~J&uTUM=WxKD8#Fa5Q9(g<8)||e` z_s}eSM#4N~#o#qv4W+<3|o`>Q{iU`{$a28x(q{FYoeX zFHqdSZnwOsvx_-CsiT$c*9{@1+o!$Cl({hL@PE`W-p|h|mTgL@fH?|In6_VV#c(?>kr z*oDroLPEo<0Nzb9U0J>}&f1GEPa~1Qo1-0A#63IZ%ASX0dqnQ}#E%g8S8&U%Sw24|JSeV;)s0co>;EaIYx@Y;Q=T zf?IwhI!W7tOz{Ji5k`BaS==!6=riRXbiHm1KBiv>10(zZL+nwav+-cj+;Q3aS3Dw- zl@42! zTR@D7C{G&U$d6NFuXZQWHiNoblYgUyORH9w5J{pu0g#ms_JvX$Pl%`!V=@g5=)vk+ z*0WKvJ85Ev(;d=668!4Rd#ju5Yfsw=I^k^N$1$bxP`@yVv?Hs9{-tlnA1g14#y_Onxe!mY%3iAeBj) zd`xC+HBO|pw)yllz=+nQ=+|EvTMMYBJ@otuQtI9+JJIL z5ent62_+OI7n!xTb&Zf^_K@e|8zqouT7m;lq}HvooyP~C!}@Tzv7Jc5vfw_dOq-wJ z0Jck6%a@h1(c_geMt@i<7o!uo08v1$zZv+@E#W@~*SlNEo^x;g_%ym3WV zaeK+bg8+GA_rMWjek2hiwtT6Ra2C}XD3aWp=&6W#Q2JhbYL+iw6AUOZ(>(?38)|OS&f>yp5hZ6q>J0$dy}dm~R+z>FV-0=<)+QxMHN7fZ1&q zrDct|2w^?_2;UksRsw%&DP^QlX5}&MMj;hD^0q1dKTuAIMmq9b*>9iUuwjyX*EMFb zXAV1F+S@yT&3)?KxC7otfNhNSUdx`<#Pl2{j@|gvJC?aBucja_aP2ghi}*DEToObb ziZoGbCVz{^uR9xswO(6AdnEyQ$P)~9;hL=VaN?ID9CzZE3l4ujmr}z3F$w{gsAv}N zvlQdP*3IjEQWaTASv!sCP`w`jnzn2#rDJY6K*+ZX~`+=g6eybUMo zI>S0N^(3ZWP0xS#%4uwQX_VT+6Tju4vw-rULtj@Q%Sgl|w2M=+RXy{FH$Bg((6v*N zsY?(-f*_xBo=1NRp6hSnW34$UQiB4DZ@ezu zdk&UUwlGptP-V+V91An38(#O<8*Zl?$O46YWSzDbEcBbXC+Tyr&-<(W?`ZFIp?m{% zNY?u7aAYn*snmz=3c0HcJ4*M2Cn)sgK z#eONGPP+Yg*<*!|1R~6PQ}9@%kb5Qh-hkG+ONB1w$6Gi7L5PGAfGIk- zSpCPujEIAsqmljpL+wsF;E7?pn|qw;;f2|YMC`s2_ahmWNO3Sj3ulE=$g9xH$zp%P z%BX>+`qB&WYCOg#RuoC{@lifLbIu{+BZhtFQdNq5C4WWKg>xVXo5|1F8Ts?g;UM#2 z+?)00;O*++LIGl}n;^6U78cLNz{19_;JB5~)yJWH`y%|*hXbX0OWBmN0l77+oFApB z-Im?d-7mF6S=M}&G@dQn9IM!(`0#(AeiQh&Qk9})-iZyZw_}E{fHP|6tAK2<=ews$}BcP(3Q+!UcdvFMX_wMt}siRoE8w6kwpTWt_n-oS2Bl*rn? z)?P=}8*Eq*8}jfRiUL$tD+lkz&R9yUkk2&p;^vDNolnq#vv+EGU3uWha6zkipWNGSV;K@Pt91_(h6+iH8_IZe_A3S_X*(pi#DE1b*fH6FQ_=NafvNN zILZw@thyz;7hs+Q6d?)uRG1XLEshX01j^g>4P9P)@^0F+*NnxE?B0K^o{uTm^JW2P zH%%cgd{e|0Vm64O8oFG`AUf50Azk~@x+@jsokQfFV{7%}t#-|Moob%PAtXAHt80EX zJW4aXw|%&FLB^PXh}n{yh9_D2NBrW+pI>dmEqW)&4voL2tl(B{cxUqRib|MS3vDOS zg@*T)#XnKf`q7p~s8N5`kGaxUd^CXR>`DmLAT7-ycRiz|7trpCbH9>tGvyQb#B~}t zzQHY^Zs?@}1$w>X3cLc%tW6C4dkTkLi}hwlL0V99uaU@pv88h2muvopMTq`O0aoGX zFi7H;6vM#bKV3#w@9UJD^ZnBa5<{}lSm%>Ad)=4F;TDa9o8^C}gR_E@YhEXExF^(T zQ?6^qN>9I?SGFOgZ{ubQpXA4N@|wFECViJGZ8J2%;687O@tja5ccbt{gd#{F2 zjiwe|u6#w&N5_=5+tZ*!A8EOZ^BiSbGAZmj#&Uo0GyHy6h0fsMhSO=s?lUq2ifYCx zpK|u`4@UQ8vq{tob7ly7EvD3^Z8GO)&cW7strJr!n%%!sykL(1XS}3rNG3YeOYEF z!?{LfN`!^1>$2_`I6O$9XFPKepO43W#B+Z<#L9vvZK#ao`f1Kp`h%!AkdH`PDIR4t zGPlm>F(aENzP-1T8*s1Sj%Z>pS19I0xh~IYRcVFAo^$diHr4N@>3^q4EL&JBwn(!{ zk!u!hI(}3KSL&>-G>ixCw)$OKUhd=21PU)2dUBJjKoJX2c=Ay{2hqVR8SK2}oA-Yv zy*ijA5=O%ou2aV7BkzIziGTfm(~ZA-FH<}Mw5g1R);CQ|WzoTkc|c6MDV z-+_+}^h}Uj-!ko!2;CC= z>c~2ULhC8{gq$b+8eTj|MP!Y`Kjn@>O8DySw5!~qC64dQYnWwduqwnj2r>8vpCnc& zmL%3F7D^&<7i$o1kZKS(hzF#^{zWYrsravk7l4Ts8vO|Z0uK@bg6;nwO@x2ltZYq1 z9PG`lEdCQ2Zt&SfY}C&{|x;Wy1*D%84lsq%)i} zLOc?vk7P_VM1k*dk;)vXo=I|L3iD^>I(OHH$2i>_>Ts~g$n#^_XV7P~MPh}J{=W&b zq`U{e6s7b^dXEcWo3HbxZWMnVH^%&)#aJ0)@1PX{JFDAspmvOr=EuGYc>QzR7uv9ItDQy(@K@=Kyoals zXS`#>s!J9|8x3aOm>2DhI}!E(k>niG-kfSr!Sg@qSw+Z!G!bKEYMFXh{Y-I%BfnuB za}rwQ0Jo?Qtj2y_(cOQnef146m}}_0LboV>9&_mw*a18IBD{Aoz<@6r}8CZ*OF5`@dIpivD|5C#9K=7#j0QRSTQ` zCt@jlo+X>8@n@LN!Qp&z9?+<_NMDK0+{Sl29Z`%jBOmq}CNT4Vjl-R-8hd z_K!3DOV%M4*Q#U@5vMhcUdNw!`i6%4pdUX?B~?$ZBKs*Y@z8!!%@04a0>CAdDPjhs zskLa!qUX1Tg3ROk+7?8!dpW++gQ%}sq0P|M!fvYYHqU?5A}r<9p+2lRT3L%BK zb~qqfugYqymnQ7w+CU)EDi<)8GdIBoPWnM>nI9@RYC!#!?ua2&XFAY(Zqr9)D?9{n zKFfECaKnF7xloR$s_BzrL@el~wH0t1v8De##C?z1+6cu2@O$khc;SmieQ(TCvUZ9o z@i;1YU>;;p92eIb)8}BajGh+lqQG2;b)3Q6i2Va?+PJ$3iw!25F&R5pyIe10@%NNP z?E+YPFM=Egr6cZOU`SfUia3WBGh?7=J}vLu)Y5-Xr^mUiRgY~P{yNMsDVw4OR%+!_ zWnI-(jbrC-&!OkuwAj!PcS#(VYuGgNJ@mu^XEddMx800#a^M&AwVBHorqv~aJ_0^l zkjzXHWF;C{7|TwqvA_gxn6w&mT1)hc9=1NiKzmCMTlMY$hcYfFdm=7BZp)O6%x!=1 z&r*N?f5Bn@P-v13^j{PLARwgw%?IYc22lTd5Kvu50Z#(seZV6VItAh&1&Rsu36e`{ zHbpnN&v4eZb%2A7+HSp{(9r1jpYuv7%Xz935r4^_&r@MogrrT%7}Kfcg5@X6O$55T z(g~8E#<@42CbC@255{W!-`-YjAUKtbH9dc?NcnH<=p3+QGOAZHtYk6AA>-C#wR8{5 zx9WzMVrh!6dHK31N5oJ&eixktDh%AWkq>3_ImjAh=A=jXVndohh$QCscQvc|GTL9g z3h5s%bPoKqE9=GjHaZ7CIICuy9sZ4!Ma`IPxMi;1K8n}}a9!PAGvGGA6kB6^e*J%o zK=gZ_iPL1G+juymlMa1pvsYNa**7bxzw#p_p`^uK2Jo{h@M=%n^JS>nqH>bpzG*apJ?V-M7xVu1{1&i*>5EF+jjQbwmT%0 zMT0@4p~Hv{VgrzUtv-Y*!ks3AwcO6!+~jxu`}*VLG`hG@d1CjP1Lfk zv6j{d`Ql7OWqrNu`fa#T>p)d?Wp&lT!jEW{3ObtQ5;s3(A@q~tiH4Mn%>t{R%zOeW zc9g_r)3%2K%IVoUCF6i;JA2M6i=pV44`ead(^7GvLn#^G13E2cTkYE3DKRrXKDlp$ z0};`x6lRSMTq1vTCK1ky!^nTt=$2t4$D^cjIO*p(=tJ)bs=8@oBj_`eid4`k#fkuw zQUNri757=#S(ca{Ud+sbrRzXL`}_xYIVv#(Tf zRYL9F*Cv)=C(6mCQ~3kvn`h%>%A2Z`cDnV(r%t`k6DnB&ZyG1Mcm01QGWWVuiY)kY zCao@^^+Au}B&r?G0J5m!CW6iV`{E+&(C~^-qm}ay0#pNzv;F$&&8vcIl~QVdWjHhL zBssdtB9Jcl4lb}&VW8vNx}FY{-&(38a<L$N_0p}r@Ma;xo%MY9@Tp&OZ%+xesRq)(^E z1RnfjDBUB5E^GFSaZFy9-)OeDWU{nwlPZ}4yntJ8^=?FPnKYzVQS!q=gpiN?8)s&Q zfmDg}va7MZP;V*_c^7dHB+HdSL<1i2_DcvHQu$n2GNWb2P)C0iP{0@s*$len%^>0h zd_Jx>n!TqT=%irdIqH*Yna<88GpY#vU43G9;MfYBAijBTG$kdq=JO#Yb>(&$&BrpvASLq$!hL-?muMa@%= z;W1$&YNu)#S#W>H)Em|&1%4IS13r%Jagf^I_t!Mc+H8E>Ir=e)u)VjEIk0@VJOAkx)hO zaW^ou+-T1lYm)@auev^He5nW*&t|~f=G2wdyM;c9KQcO&_HO>msW5h%3&SB0wrO%xXW*DsI$^~(nT^DW~4J3ce`hkyQ9 zUzc-74_co=DEvN0Uj+}1Wvm9mK+JPB4v>dW!U@I6mT8?L&(vG%h;YZpA;j+ra*#K; zt$Y3+i%bwIAsAth$JpOM5?;{A7(9HC<8prS+Vy|&?sGSY2;p)0eS7=-{JM`*y}#y+ zivgKn6R+$EuQ#I+avOmmgx!{Z+qv*sRJFWbKWSl)!lMY-j7u6{D4)?bT{j&8|3~L@ z^d~^Y-uOGqp8fn6(S56aOd&9;ft@qXi1bzmXmyl6SGJq)QxO)EC(RhQDS;WAX6|XL zMAm;lVzUDz`;N8MdZH?aq{vt<@P0@+QG2WfV`RL;W&9zIrdkmXHFeQKc&kib6(_f7 zko3*~7dR;B_e9}L!GEM?rvwe+V_dKLXWUDfa=?-8hW|*-8thd%ilfW8!HTjWTnnOX ztnQC4YvF7Azy&OZO22aIg)MtMCO&%)jO%~(F7jU1_~nxQ-89;C<9o>7ffD>l_!68s z+2%3FH#fg7OFOBPo5jRX0>&NuPzk#Uslg6Fgn#=)yr2XG!3DD}HyHwWob%q>QN;GT z9ghXyoWW5BGYav8U-2nQbHDATHH+6iWX>t7hl=5cx_Ju11J1$ZkE4i19|RmzbWeXG z5rCcrBZ3I^?0a(|Q*;6dny{#z%JEO`v=CJ>Q|J{4CSE2Fab2pFKd*Ypj{|cjeFPiDR~kwDlU{;h=yD*C$aZ;^R2R8*S1Qvxhlr!b z&x-MBTY25BKxFxsg{kXNgI(8j={bL2asJLZ3th|R?^p$#Mo4~B06|f_MtPKvMMzBt z=z-y{+A534Uvw-KQDH5)V=au#p$rThEsBm*NO|>AM7@zWO}E!d`LGCcvaTZhO*=IP z1>=;I(}R;Jp8J(-WxnL>{d=r|lQ+@5fIu4V$@*Z}WWgeQ1KU8ielN&OdozFK*este zFw_q`*d{5}0OFs2N zwqtenJ<#dM)06{TWG*<{S1k48<#X=dIOzZP}hKC0kKGZ@kz7Q zi81Ddtp-Iv;nrn_<0zGiG@^fHAs5ZgkJ>d$(gE8E{s1?v5RGRsKE9PSPg?hfr$oL? zzD~XbDZLZY@8DcU+~?tIhkpja6`V)okG~)|frWt3_%}gdWNT$%uj*`MVk2a4`d>|6 z*8dLB{tEygQ!tvPCB5*cCa3wY0Z5HBkX2#`^>$P##6Pxs+HCEU$TNRCoGvIDcbB&D z9#MIAWq$sl;_*FV5_rzTpOounk~iQv2IqMHV^-uTTkv76>*L!K!e7u0I$j*lRy`3l z*eh0e3&j2UD!&+*IK*HovW-|R>Q1AxZM{+j*HVtl{zK2R&zHQoUJjK;nR2`>{dMfs z=e`63_!&qT&;Ak?{-S@zi*b&=h;1~B9v0UcnT!V`@V2T`5=eknnUL#AQ`>s+W8Zyf z{iL3*%0=rs#BKd+Ac;$N=GuK5-D>6wY;Ozzgu~$8s)I!R)X4}a1i~QB6JPUNIfRF& zdiG)CXtK*Y4dNI#6>l)hp=F?)Ecqo#TBR7B?opZL;HTHgMyG#_4Nw2j%&E%se@l!m zGS;?;&2xwt{VGrfjpPJS9bfsb4X8zDGF_sA6}3bO`gsYp7ODmm$K+gh zr@UgO``HA9Ci;JShJ%e7B@6&NQ{=)NghClrdIg zx5fw@;IAd*O`V@ksL9}Da`yZx{0e;uIAzDSRYH}{+l8s4l;;@gRCdksdNkcawNs&~ z>*`SyP>-BC~?DPof+hg%kcoNd~X z?RQcl$bFU%E{f~c%zebLE77luZB6JsY0wfA<(WU$?8eqH_#XvxwMIq=Do-janE@WT zKRNS^h<-IGXAAnI+}s?(P4nQ#95I03TJWj@AcMXQV3UXXoFm0^$5y}j+GZ?ubE>{z zddUHwqfme4nA=%by}q&*5=d>R`&1|A=6y3#Yxm1N5}0nRhT5B>gNd2Kw8>c@%o`^B z#(u)KKYe9J9aMU!PQ7O}2W0#0-NS;z?`@efc+?R|=hR}!8SEKlB7d&`La;#e_!vU? z2m}p3mVJ@PFLLp?=F}Wad&PXZh`U-IJ6GPp5f^{=&LMfiH_?8i#Cnc(df|rQ@uxjI zTRhv>=ktq(Wz=?%POwDY*?ptnURodyU!HXqjCQ!&6=C;5=B1x<;wx4=u-Xv0vQxU^6NSrcB5Z_3KjrU7PkY(yUde!AzLIT@x$P z_-!8ea*1gESZf&tS9VmEZAO3M&F64z+Q5JRFpU?+@-q+NGgbSWShb@qRq zyc3&8cwJ7D(m!myfJ>~=PU1-f9Mf;?H4nZay$nC6IFb@j|9xOIz};0VuZolQT5!UD zE)|{4Kt8A^OhAT|=AiJbfJ--E~PQf7qD^T*1jnvy(o@@6qx_LT*YAv>1!Q|bIo@F~1mDBkji z@|YTs0e?2*q2hx>1Ofbe)gBt>mn_xHLxwGowbHL1df$`?P;k6e;g? zD_~KdvNU>Gy6)1hdM3!jNaj)uL8SyfR8-wbJf1Tzh{pOypd)w#ZQ5%{&p`RxD{y%TRkb^~^BX55uFV287a83+(hOgEROSC0|eqoZaz3>tFCoPZ91gg`h zHHkiFyx-TyHXkC8qCoMd?v z^h^!|f*}tDg_3XdxRLILYTGBi3;v55NrX+0hJ=8Kf%+evH2ZJ7sQhOX+d$t)r-neY zSxP5{h|x@J4b6r|npZafg+{tZQ7=xyp4j3om#&hW79(d%T9dnCWWG`b zQ(lhU$Bh2WMIj<<9wU#GhZ+0e+9f3LP5^!YA{43IyepTZ9%an}YfihS}{N|8;>_T~7* zi*KX>e{EM8mS_&`nFi^O8R3-~jC$0xn+YIvbB=J9q8f={VaX#X*|sW+A!Li6z|?3*)!X{kTqXT%>fzXeNRXCmW$MNkD}@ff zW&+%fB}*Pr6?OH?%%7wc#vY!-dF9YaEj0zU?vrIM{?YE_t4CgEVQ@CdoF*tCMRLXNB>*VPPbSs9X;lu~ zo4yg|(a+V@BGFS1VtL!I%0=ZdUZ3~>7S4v>Cg7&ZK>bZ^gxH#2JcJL4Q;6pbQl{jt zQK|{XcefT!4^%@`hh;2(G3FzFKzr^#HzUqyM#0F1-j~-B5pbNXFysT4Jwd!q-3Yot za^ioRGYemuj)c7`4T;_2AZ%F~P|R%-1)xj0Vkh)A>Gegn>WeC%THU_K%AQn4* z=7d*kEowX)gs1|}nTLD+Yy0|bdokAH@4454`u8Wc|6kVr|NH-pHWg+SG2ZQ4n${tx zb6?uR9}VH+-jxPsSpX5w zAS>@qmrfVw$vE%l-NTj(2>l&y@Wir~+kVm?i7Iy#X97{@I?Vatj*|gW3|)AS9{wHc zX+bnU6*uh>y{a3<2c;C`D$r`hJ^sty5@=9=lDVVbj2^=~!$t`{8B4hjs~#}HeBsQvSHFEmNQh{l!-Nw` zGcFkxaJvCFZlim{4zn<(=%E@peL}H9Y!y}(Dr!1Z`P*;``%neiWUciXzrxW;-q7F^ zbF&ra0ON$r0LyBQdu4u|ZHg?Vh$Vl@0bGMlL8`%6r5*SEeQuHhsh8{qHOj0<(6I|b zs=@d>$RlFgZa+mr)b7C`&R8!e(MtTT9WA5BUV=uFA%%o!I3|q~H-8{LbCquLqGZix zd5bzVT_#N!RH5OaFgMmU;=Q?wd~zh3U^yy^2#my}VT=u2i5M)3c5PSPh(&*~D?eGM zf8g&RIr)Wt;#@&MgNSSe;KT`S`jE6VN-^4F)S{NrLhD3mQx2@hxX+hAjT$E|{3ff) zs|-tDM^w7Sgz={<>}x<0zk!zf$K?#qp&`k-iuNNsMgrYCa6lzX*4FeYd5;Ouit!en z@9Y^(X-??Uhu64$6Fhi}y>frMH%gUz0fEzddp6kJ?b#06`JAOaNV{@xqjs}~a8 z`&%`(*jd&{*GM?8l&Op<h_v_^gRj7cVn6ef-@gP+HV$nk2!9o&4Kf6T>c73V z{GTuXuRUdr7Y)2Y%y;p`gkLFk!mr&NOXYNfJ4R52$i~rl(!}bd#L$1jv`KS%RpK+f z)*8!N!|`li0AazKi@-TXTnOS+7$>&qQs9g=g7%@KB-nhlcU@8|hC6 z8@vxi%l;n^L?2L>POm?BnYzf%LMASjH*Gb<}!XYlRV=#E^hPHC7uPFL$S;p*}VK%)L8E!*62|ofmeUFv3usRD*6^$o6+lC zo4d9`?!rf5f&5#fC*I{1XGtqPo%4sgdddlou-F%`pf|a3zkGpw?{JuK4k@qWp%>0f z$UMcHjfYJ;<-$n6(CRsUqPWv9t4Jo)MoI!Hz~uHD&y+mQchq2tB!UJ&LUylPQ3{~Y zLTReNR9fBwxF&yA8f0l<*`Ax(?vh|+xV{!_o{qsq$xM2j&)V9l=zz{ABD8De{)~PIev`YC2C1qBDX93kyeX%|H#N70uT zJCPW-1KDq^b1Y1X)_M1x(^keQF|zt7aR}%72Tn@M%-4L#OHi#L;w0z3g~obMY!EXr zvCY~_>(zgcOte}jF7Ji)cnZbH5%dTEf6~rs zbdxsa>^%RJWW*P$1Wg7sSu#Mpimplp5cZLW?$#r#SWh~yPP5Nn>avL`?HcisczoHG zvNp%-DNNp~9&idZ6k{LpVHtD;<(x{cL+6Xg?NEP1qd(GtBka^-7)C}AO;%>v8_?}p zQqi*<8wk%`0C7H^GiO}8n2y>)XsI~z>_EBnBud{s0fF|?tHfJll*uWF1=#?JN~A^c zO5MJ^GCNXKROkv@Q!*Sv>Z#bnvVu~WvlvzDLHKRNWL}*rgq6ng$hP9I-E&9; zvd@2V0SM9?;HxvlQw(Q>9Owwkil?iYcAU(>3h&q~3(L(yZ#Vj(Tb} zXJ`Op%Zl|2*)r!ta;A~iwIa>F$x5Q3IXl15JR(%fc@w0z0 zMA=lkuyI}Pv?rf-I!(Z)Q_1BQB7 z^rrzvCNEvewz2Wd*M4{dSRVur3(pO9is#;F+x6Jgxz-8j9wMiw%>2QZjZ(Cz8OQin+4fL2lrEcX!vj#gCJmQ(s}AMnsaN|h zO3Z8MqbrJV(uVqxjgM@qaNK;O&{rAm|A=cXykwq%xQD;RI;tXQj_97chU%N9}&qoKYj!1>|?g06na^SCk z?y72<(AnLOUf6XTVA;;q?GzHA5qhInq$NQ%Zr0fvQ$_EXCWj)UeCNj5(+t|>BKLtK zN3KP;EU+f`QlFqp5u8c*-o}5^nRzf`)2iKngI(@9y*q=g;Hpt~iWF*Z+|IhbkuIO) zd#v{B1i4o2*LlX9b#5f5?m2It?}yjw-R;q9#Gm8AF=mf@@e&!o3|{onERI77OANh! zofh2Ss-49g2toMEV6=yUs#Q;=X{KP{v&hA(3;%9CZq$8oHD z`2Tb5)fr?F()+6_TRwk7K*;=?wfA2dI#r3||FBZsn`6zZW>vMh!a`!YN<9#WeIlO+ z!re$>#1iSti10Iva14*!u{?^^OhA1>{^680IkJ4fnF9ahD?63Gpd2>VZ$vlVH}}7@ zAKnHR9UvUBi{bbLcn~5T)|u=HBg3swN0-fif!E17w^1!3J6M0u1ymZg1(5N|=T*;V z7@{zKI<4|40b>)QTy9+Y^Is+)g(2V`)5g8awB|0+2s`1)avGuin?{q>jnE{HyoHeG zP%24F@4HRmX^qg(4~a#(xee_O#AMIE;jO~*&2clq1JrTrVuNoN+RS-n8_XaJjSLku zA?%t}Y#^%6s-b_&n5NdXh%a~cxEy97o62S#R7M+lh@yLkufPIP?gAM&w13iiYDET* z_^4-KZ?z8JC~`902l8VBKsT_7PSF#Ttf_uR3EkTJU5#<{F)u>3sB?>N)^29wHG<2f zuztti%64Gyw3q#*4NINxy~}w}osk`IGHGp~#=M0Qe2IV7%Z_maBD&O+FZfxpKD6_= zlFP{9=srZSxm%@kFEnVs0RsY&xYLMhncSY;Vb6*w3lAbp6CT1Z>eUNn>Qs5GLU`mC zv}U%3uU*GOZM~RPdh0;(j55PX%6-W@nl*YcI#NR#V!^g-mQwT?zbKNIVjm-u>&{~v z1EFOTWh{R_Q8CcL4!WZK7MkN~i2r>9UF|R5CW6w@WwZk3YzKxNQ%K_pVGV5KM)y|P ztADmH*ywdZ)G)vinXn58Xz#dje4qQn2!`MSmN9)yVQC^TP%&ZXsya&b)CQtLLx-df zUIH0Pb`bPm;Q#p)qhhBAG5tNkSTGO}n*X+f{QrLlA5}LU@WfEw?_YNrI2jrjDQE+^WCQIlEqV_1E zM3@ryYjo(A@JQ~2yLRzIHN!6v8`{9Bnz$JZ>thY`XawYfYujzfCbtMLKRu9D-@h{Q zz>-SZVc;CJAtY&r3JBiZDB$cAdQmhM%7=fTMIeQ3OIP5PB&fdsui~ycD#|x)BND=I z2qgqWk&tF+Y5CDZ4Bd>aGs~tjj4Y_ zN0F&xrJ`HA7NOnc9QNGRc|D<X>oB?uAY$rTy5GRl&MG$K!O=b+Yq} zJPtx^m2ZD!h)gPYNXpec8O2lyCXjzs^Dc#2bwlEeH+-w3BMm?rZ#_ed7tN#K0|FnS z!DEo82w?HX!n*EbYxv;$!c6m zPgzr|_CstrAQ@h7{F%qpH-^eLI`+sE44lOA+Tal()jSN-k8(vjq_2@OTf@1zQ2hK^ z-0U$vxB2yF>FrWwN3xqVeR+Q_c-KA}?a1-I3+&HU3aLOyzpF6LA3WWg;M>scUT3{s z-RLUOm~z{dH;1xu=R~F8BJ2eyTF!lG=Vj>YYDpaJ^0EE2R#38_F$>rTG7cf3rm1FSarlHcsE9GiQtA=sExURQa+`R zJk7~xR6ifXNHAfmsgGu!rMZ+97YFYSqi- zpX*@Ja`to4sDRW?C3Antc|5R;1$$Nha(xvz9Xejn)B9OtQ=U7?I!rZANROOxmn1$u z#SnCP>-)@-dS=?z1Qj9euU!l+{}%Q-)0tA92_z~!nOK{x5O#|tX#zj|)ILKldriS@ zbbrcfvJy7y;;mMN=_{-~T*^D;hBb~V@sDDV@(d6_Y&iM$`MiH`piPI!g&8ND)^Iu6 zJ`~@sGPvnKDEuYiF(sa1pfCvjW4Z5scF(#T-2(r;9lGn2O2m4BO2q=BWy!9^JA^j! zgB7m9^Qfi_#g&;T&uSlz^PIot4;(tUP7hu2^)vg3avE`Jyef@yNCLWil2G?xGZ!3* zd=0}a!{6>c_bh+m6<&+bMNO-rGL$ziGI3(>a>$4>4DH8%60>&WH{Vw(`s`KXLK(It z5fODKVZ5Tn^%A1JSEt5+wyBwPOF&OLX^#t zl&Q7}WZK1B;AA1NSaEI5pnf_M9I<~tJbePn#Zalh>;E3_uBKWsb)fA5JVaY+^CYf& z5m!yAy!tj(W`~ZLS_Jn;m!POdkmsG7t$j~7-KoNj%OA8@ot6)a9bvsrJ)(#Q37n%~ z9i;OSl)8Tw^@$uAn_(}GrlfC5LuD%-4fS)UrC9}a-<#*NoMVF*Z|Ic|l}wh=gbuD| ziml4gaxVz0cc4I0J22P{I%M~HRjDe3pR{<&miXu7_-><1p}TZtj$|nr+5RE7tqD#p zxY|dvpI2S_@Q!hBLyM5FaQYAT0>>oEI9|Ta!lZvhI1S=C_o{$au!l)(@O$u$fxXEh zp1s~KXn(@$0Br->Xz7-_HY^$Ef6E`7 zsK2{e0*?EYKfo6LpZvk{^3ZLHx+kA}LR)CKueWjFyg|Y(zl|o8_?6JzRD%2v+>Y(l{S0&ix^L;H&A@LeKIaBk#7MH22mQh7RvaGE_i{<@2?LaJTK) z`{o!~cSiBp3+dv6@UB~~3q9<}t>MGsxER2SuviFW zPZ0zGDS+fbie7%j4DI|iFs2J&Ahkgq1UY~HrJsuP8_F5Xj2)kuJ4+isGgdKix%?(N z;#8ygS84b>js)`0{Xwh`o+|8^CEC7i;@Y-e2iN*Nz+AyAsPM`6h7_IBJcmyQYPUDtbOl!|}zJfc*#yGmqe)2lf7HOqwy^sNRmO$MGN9gHiJZKLGJB1ag?pQ>!ee9u z+)3lp_rjLPr}y%8GD6FA+u^7@$_C4N{Lk9-A$w4Gw{Iu5RK8~48!*K^^NxRW#ae4l z6@LD-?gIv?ib$n-E1rZ{a8yXrv38iIEHcPm(N@Qg< z16h*VlRUZnHRSh5lJ$~3`34-{X7r6PI+#z=m8bR_@dXj4n?lSC=&G!r8Ar_DxZ988 z;EY3dvYe`A331(#nlpGeorm&E>IQVa zzHLbFTze`)=IBtNA}LVEZF+MvsRT_88@+wxI*|lO>_M)y;Hpb0HUZJJS|*KE;n>#) zrMUcXO_?$l`|Oy4;l%s+V%(hGRG?b-%WHv5CXYl7$husqopI!m^of6*W0FOFAxdSD zVtjLIH>ggKW>#V|(mN$ZuX`ydNrO|bDEMn;A0wm>Qt3Fn5(L@PPcSTn>H-SA zlf(DiZgE-D7s_7uCY@V14&XEWcnwyI#Ap?aWcwVh);213NABf1Cem$$+*3i&FMus1 z*|8u{DRgY>^x;~~mwA6Ou1I>p2LHfz?ns}=YtZi?>uh2BG?JwgGJr6|wj4gmrPG(k z`S;sz|JU7y-fz|wH zMn}8XP8tp^2_vq7pkdnQ^z+7b)Zug1#9{8t$VE9AlW@q}m?dY^606t+a+Xxnpn=Kv zuS1TQGPhqeriy=BJM zlHo}_c;Ei1;bCq-zx_TOo_62ft*x2;Vdw@we3tOgGNaY|hi=)ju8`+6_0Y4>yPK=& zh}N?rE#o>S*lD#^g-@o(DP4T`xc%Beb{en9Xha%qDr0{t|FfsDEiw_AY3qaifO@Z$>S76TO-38 zCY;4`NUDOvy%W@+PB(*(81uLBT*$+hT)R^v7dd|uTELcW!54DfNfB=5T_mwV|H8y; z2AcbIFRz1dJ{K==<>mL(QwpMMG^@t*xC<7L+7RK~4MpF@g=0t?iITzb(}}8K2tuv+cst-uiwZ#O-i3BDpJuO?{ywtk!`wb(bqL{?$}7cVvRB zZ0p#o;aB&#XRUgzdTn~GF~y)S1Wl7Xc7c*l%F8{K+?ReY|N3tmhoWij{_G#dp{N^P z`aI&-O|_`E{?zALx%))-toW`G-l3s#w}F3zBudJwJvlL|MP)U)Holm8VjCK}S9P>x zx!p{B?@YBFq2CsGl!ItWIo|l`dbtHZTpXPcU_5Eozg)Uj^|&R4C=nUh>VEk z^*O6eL{P-1_E2cI*sOxvWlZCnx+Z@L-&drtr@H!A@0^S;Tk=}xKK-#9o)UGPjPi5Q zMU8%u(LqsBr6|1>w!-O7YfRyia%<00;?rQnkz zkHu5#g>wOH29x>Bnp~=STpHVxt2tywIwjWT*J5`e6>9AcA$tB+8HY`atachK+ZS_x zs(#^A>Pn>fjEmU64E!0FXZKV$R?6@c`f}Nps-}qU0bIo2HWG_h&W6~t{`((cANj;Q zycVgU%J{=O(im^Y^#j=nHb^8HznKrqJ3=h(uZa0~tbj_0A6ofo%L`b|W;^6bCKwPv zVlqqgUNuVAv2hVS9px=zD3*Fk^N_fPyP2!Sr^2PLfL+;~lfStOI~5IiQlGriU&k{#&JUY4Hie%!>N!WV_52lUD{Lf5 z=$bi4Ca=L~L;~Dav^y;b#7)JwIKP~|VN9i1_%*->q={-PF}xvwaOqE3P3IkdNKX-> zdGx^pcTR4~!hL%I>AX+GIXF}cLL}-#RDC(G1rbQ>!o9%JHBYdiF%5%z_waVzp+PO<}W^$XMkD zZfcZ ziW<=(brF2|9h9OTZN?IR?W4q#o=Y;Z@OU#AW_J{AU_e)1BN1UNs&Z2Uq;p4jX1gxX z4hb91SXQv^A==uax1)Jr3}HY;N$-lR!bEbuug<>=OVP{0K|1;fscFk*mo*G`YBQ6c znf2L?O{(je)R#Ee_O0v9-|n;#g9Y3(n0Ntur9q~gI@1<4Y$ zgGzagnMXYYVE0h~?eK8Pm=luAH;T(g;PQdWXi9L%E6e_$ThGwh{HeLIi#gcV;n`Db zdqX=1v*%CEO^u9=+oS?id&n7(o0R zd;YH*8)yzVY7Y$v$CV7;0}=p^Aw#2->q>@_0SN%dN1@@$d)33FfLwsXOV9`u`cI59 z0rCM3u|NYP`nyM30Br;1`q9V~|Bs0G0|@~|LDA?^ydsHEAO)a~AR3gazgtxhXd9>$ zg+`V373xNR0cikrYS4JE|Jzk-fX0Ec7HHrb{%ax^Knp-=1vI`IUA52xkPEPD{qI(r z+3)OO2igU;R-&rM;_4XG~O9KQ7000OG0000%00000 z00ID$K*^veJ5XQ$T9p6*tEvD13jhEB0000000000q=DO$U&uHDUdEG|$S?we#*@p) zIRdZ7ld-@glPbw70+Pp*R>?O4y~mRg!y1#R$uj~E$&(SoDU%1vDgx2UlQYUU0{qI8 u{=^rPG{_K>ugDCOpUMsbW6hJV$~6Lv&6DQJGXk^ClN-w!2HMR40000h$SFVo delta 49358 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 for (callback in onChipClickedHandler) callback.invoke((view as TagChip).tag) } - }.let { launch(Dispatchers.Main) { galleryblock_tag_group.addView(it) } } - } + } + }.let { launch(Dispatchers.Main) { it.forEach { galleryblock_tag_group.addView(it) } } } } galleryblock_id.text = galleryBlock.id.toString() @@ -279,7 +279,6 @@ class GalleryBlockAdapter(private val glide: RequestManager, private val galleri galleryblock_tag_group.visibility = View.GONE } } - Log.i("PUPILD", "${System.currentTimeMillis() - time}") } } class NextViewHolder(view: LinearLayout) : RecyclerView.ViewHolder(view) diff --git a/app/src/main/java/xyz/quaver/pupil/services/DownloadService.kt b/app/src/main/java/xyz/quaver/pupil/services/DownloadService.kt index 92d6a2ad..3b4eb8bc 100644 --- a/app/src/main/java/xyz/quaver/pupil/services/DownloadService.kt +++ b/app/src/main/java/xyz/quaver/pupil/services/DownloadService.kt @@ -28,6 +28,7 @@ import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat import androidx.core.app.TaskStackBuilder import androidx.core.content.ContextCompat +import com.google.firebase.crashlytics.FirebaseCrashlytics import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -42,6 +43,7 @@ import xyz.quaver.pupil.R import xyz.quaver.pupil.client import xyz.quaver.pupil.interceptors import xyz.quaver.pupil.ui.ReaderActivity +import xyz.quaver.pupil.util.Preferences import xyz.quaver.pupil.util.downloader.Cache import xyz.quaver.pupil.util.downloader.DownloadManager import xyz.quaver.pupil.util.ellipsize @@ -309,6 +311,18 @@ class DownloadService : Service() { progress.put(galleryID, MutableList(reader.galleryInfo.files.size) { 0F }) + FirebaseCrashlytics.getInstance().log( + """ + GALLERYID: $galleryID + CACHE: ${cache.findFile(".metadata")} + PATTERN: ${Preferences["download_folder_name", ""]} + READER ID: ${reader.galleryInfo.id} + READER SIZE: ${reader.galleryInfo.files.size} + CACHE READER ID: ${cache.metadata.reader?.galleryInfo?.id}} + CACHE READER SIZE: ${cache.metadata.reader?.galleryInfo?.files?.size} + """.trimIndent() + ) + cache.metadata.imageList?.let { if (progress[galleryID]?.size != it.size) { cache.metadata.imageList?.filterNotNull()?.forEach { file -> diff --git a/app/src/main/java/xyz/quaver/pupil/ui/dialog/GalleryDialog.kt b/app/src/main/java/xyz/quaver/pupil/ui/dialog/GalleryDialog.kt index e54ace31..6fe1b42a 100644 --- a/app/src/main/java/xyz/quaver/pupil/ui/dialog/GalleryDialog.kt +++ b/app/src/main/java/xyz/quaver/pupil/ui/dialog/GalleryDialog.kt @@ -18,13 +18,13 @@ package xyz.quaver.pupil.ui.dialog -import android.app.Dialog import android.content.Context import android.content.Intent import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.widget.LinearLayout.LayoutParams +import androidx.appcompat.app.AlertDialog import androidx.core.content.ContextCompat import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView @@ -53,7 +53,7 @@ import xyz.quaver.pupil.util.ItemClickSupport import xyz.quaver.pupil.util.downloader.Cache import xyz.quaver.pupil.util.wordCapitalize -class GalleryDialog(context: Context, private val glide: RequestManager, private val galleryID: Int) : Dialog(context) { +class GalleryDialog(context: Context, private val glide: RequestManager, private val galleryID: Int) : AlertDialog(context) { val onChipClickedHandler = ArrayList<((Tag) -> (Unit))>() diff --git a/app/src/main/java/xyz/quaver/pupil/ui/dialog/ProxyDialog.kt b/app/src/main/java/xyz/quaver/pupil/ui/dialog/ProxyDialog.kt index cd79be1d..ef387396 100644 --- a/app/src/main/java/xyz/quaver/pupil/ui/dialog/ProxyDialog.kt +++ b/app/src/main/java/xyz/quaver/pupil/ui/dialog/ProxyDialog.kt @@ -27,6 +27,7 @@ import android.view.View import android.view.ViewGroup import android.widget.AdapterView import android.widget.ArrayAdapter +import androidx.appcompat.app.AlertDialog import kotlinx.android.synthetic.main.dialog_proxy.view.* import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json @@ -40,7 +41,7 @@ import xyz.quaver.pupil.util.getProxyInfo import xyz.quaver.pupil.util.proxyInfo import java.net.Proxy -class ProxyDialog(context: Context) : Dialog(context) { +class ProxyDialog(context: Context) : AlertDialog(context) { override fun onCreate(savedInstanceState: Bundle?) { setContentView(build()) diff --git a/app/src/main/java/xyz/quaver/pupil/util/download/Cache.kt b/app/src/main/java/xyz/quaver/pupil/util/download/Cache.kt deleted file mode 100644 index 46e7b8e7..00000000 --- a/app/src/main/java/xyz/quaver/pupil/util/download/Cache.kt +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Pupil, Hitomi.la viewer for Android - * Copyright (C) 2020 tom5079 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package xyz.quaver.pupil.util.download - -import android.content.Context -import android.content.ContextWrapper -import android.util.Base64 -import android.util.SparseArray -import androidx.preference.PreferenceManager -import com.google.firebase.crashlytics.FirebaseCrashlytics -import kotlinx.coroutines.* -import kotlinx.serialization.decodeFromString -import kotlinx.serialization.encodeToString -import kotlinx.serialization.json.Json -import xyz.quaver.Code -import xyz.quaver.hitomi.GalleryBlock -import xyz.quaver.hitomi.Reader -import xyz.quaver.pupil.util.getCachedGallery -import xyz.quaver.pupil.util.getDownloadDirectory -import xyz.quaver.pupil.util.isParentOf -import xyz.quaver.readBytes -import java.io.BufferedInputStream -import java.io.File -import java.io.FileOutputStream -import java.io.InputStream -import java.net.URL - -@Suppress("DEPRECATION") -@Deprecated("Use downloader.Cache instead") -class Cache(context: Context) : ContextWrapper(context) { - - companion object { - private val moving = mutableListOf() - private val readers = SparseArray() - } - - private val preference = PreferenceManager.getDefaultSharedPreferences(this) - - // Search in this order - // Download -> Cache - fun getCachedGallery(galleryID: Int) = getCachedGallery(this, galleryID).also { - if (!it.exists()) - it.mkdirs() - } - - fun getCachedMetadata(galleryID: Int) : Metadata? { - val file = File(getCachedGallery(galleryID), ".metadata") - - if (!file.exists()) - return null - - return try { - Json.decodeFromString(file.readText()) - } catch (e: Exception) { - //File corrupted - file.delete() - null - } - } - - fun setCachedMetadata(galleryID: Int, metadata: Metadata) { - if (preference.getBoolean("cache_disable", false)) - return - - val file = File(getCachedGallery(galleryID), ".metadata").also { - if (!it.exists()) - it.createNewFile() - } - - file.writeText(Json.encodeToString(metadata)) - } - - suspend fun getThumbnail(galleryID: Int): String? { - val metadata = Cache(this).getCachedMetadata(galleryID) - - @Suppress("BlockingMethodInNonBlockingContext") - val thumbnail = if (metadata?.thumbnail == null) - withContext(Dispatchers.IO) { - val thumbnail = getGalleryBlock(galleryID)?.thumbnails?.firstOrNull() ?: return@withContext null - try { - val data = URL(thumbnail).readBytes().apply { - if (isEmpty()) return@withContext null - } - Base64.encodeToString(data, Base64.DEFAULT) - } catch (e: Exception) { - null - } - } - else - metadata.thumbnail - - setCachedMetadata( - galleryID, - Metadata(Cache(this).getCachedMetadata(galleryID), thumbnail = thumbnail) - ) - - return thumbnail - } - - suspend fun getGalleryBlock(galleryID: Int): GalleryBlock? { - val metadata = Cache(this).getCachedMetadata(galleryID) - - val sources = listOf( - { xyz.quaver.hitomi.getGalleryBlock(galleryID) }, - { xyz.quaver.hiyobi.getGalleryBlock(galleryID) } - ) - - val galleryBlock = if (metadata?.galleryBlock == null) { - withContext(Dispatchers.IO) { - var galleryBlock: GalleryBlock? = null - - for (source in sources) { - galleryBlock = try { - source.invoke() - } catch (e: Exception) { - null - } - - if (galleryBlock != null) - break - } - - galleryBlock - } ?: return null - } - else - metadata.galleryBlock - - setCachedMetadata( - galleryID, - Metadata(Cache(this).getCachedMetadata(galleryID), galleryBlock = galleryBlock) - ) - - return galleryBlock - } - - fun getReaderOrNull(galleryID: Int): Reader? { - return readers[galleryID] ?: getCachedMetadata(galleryID)?.reader - } - - suspend fun getReader(galleryID: Int): Reader? { - val metadata = getCachedMetadata(galleryID) - val mirrors = preference.getString("mirrors", null)?.split('>') ?: listOf() - - val sources = mapOf( - Code.HITOMI to { xyz.quaver.hitomi.getReader(galleryID) }, - Code.HIYOBI to { xyz.quaver.hiyobi.getReader(galleryID) } - ).let { - if (mirrors.isNotEmpty()) - it.toSortedMap{ o1, o2 -> - mirrors.indexOf(o1.name) - mirrors.indexOf(o2.name) - } - else - it - } - - val reader = - if (readers[galleryID] != null) - return readers[galleryID] - else if (metadata?.reader == null) { - var retval: Reader? = null - - for (source in sources) { - retval = try { - withContext(Dispatchers.IO) { - withTimeoutOrNull(1000) { - source.value.invoke() - } - } - } catch (e: Exception) { - FirebaseCrashlytics.getInstance().recordException(e) - null - } - - if (retval != null) - break - } - - retval - } else - metadata.reader - - readers.put(galleryID, reader) - - setCachedMetadata( - galleryID, - Metadata(Cache(this).getCachedMetadata(galleryID), readers = reader) - ) - - return reader - } - - val imageNameRegex = Regex("""^\d+\..+$""") - fun getImages(galleryID: Int): List? { - val gallery = getCachedGallery(galleryID) - - return gallery.list { _, name -> - imageNameRegex.matches(name) - }?.map { - File(gallery, it) - } - } - - val imageExtensions = listOf( - "png", - "jpg", - "webp", - "gif" - ) - fun getImage(galleryID: Int, index: Int): File? { - val gallery = getCachedGallery(galleryID) - - for (ext in imageExtensions) { - File(gallery, "%05d.$ext".format(index)).let { - if (it.exists()) - return it - } - } - - return null - } - - - fun putImage(galleryID: Int, index: Int, ext: String, data: InputStream) { - if (preference.getBoolean("cache_disable", false)) - return - - val cache = File(getCachedGallery(galleryID), "%05d.$ext".format(index)).also { - if (!it.exists()) - it.createNewFile() - } - - try { - BufferedInputStream(data).use { inputStream -> - FileOutputStream(cache).use { outputStream -> - inputStream.copyTo(outputStream) - } - } - } catch (e: Exception) { - cache.delete() - } - } - - fun moveToDownload(galleryID: Int) { - if (preference.getBoolean("cache_disable", false)) - return - - if (moving.contains(galleryID)) - return - - CoroutineScope(Dispatchers.IO).launch { - val cache = getCachedGallery(galleryID).also { - if (!it.exists()) - return@launch - } - val download = File(getDownloadDirectory(this@Cache), galleryID.toString()) - - if (download.isParentOf(cache)) - return@launch - - FirebaseCrashlytics.getInstance().log("MOVING ${cache.canonicalPath} --> ${download.canonicalPath}") - - cache.copyRecursively(download, true) { file, err -> - FirebaseCrashlytics.getInstance().log("MOVING ERROR ${file.canonicalPath} ${err.message}") - OnErrorAction.SKIP - } - FirebaseCrashlytics.getInstance().log("MOVED ${cache.canonicalPath}") - - FirebaseCrashlytics.getInstance().log("DELETING ${cache.canonicalPath}") - cache.deleteRecursively() - FirebaseCrashlytics.getInstance().log("DELETED ${cache.canonicalPath}") - } - } - - fun isDownloading(galleryID: Int) = getCachedMetadata(galleryID)?.isDownloading == true - - fun setDownloading(galleryID: Int, isDownloading: Boolean) { - setCachedMetadata(galleryID, Metadata(getCachedMetadata(galleryID), isDownloading = isDownloading)) - } - -} \ No newline at end of file diff --git a/app/src/main/java/xyz/quaver/pupil/util/download/DownloadWorker.kt b/app/src/main/java/xyz/quaver/pupil/util/download/DownloadWorker.kt deleted file mode 100644 index edd22251..00000000 --- a/app/src/main/java/xyz/quaver/pupil/util/download/DownloadWorker.kt +++ /dev/null @@ -1,389 +0,0 @@ -/* - * Pupil, Hitomi.la viewer for Android - * Copyright (C) 2020 tom5079 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package xyz.quaver.pupil.util.download - -import android.app.PendingIntent -import android.content.Context -import android.content.ContextWrapper -import android.content.Intent -import android.content.SharedPreferences -import android.util.Log -import android.util.SparseArray -import androidx.core.app.NotificationCompat -import androidx.core.app.NotificationManagerCompat -import androidx.core.app.TaskStackBuilder -import androidx.preference.PreferenceManager -import com.google.firebase.crashlytics.FirebaseCrashlytics -import kotlinx.coroutines.* -import okhttp3.* -import okio.* -import xyz.quaver.Code -import xyz.quaver.hitomi.Reader -import xyz.quaver.hitomi.getReferer -import xyz.quaver.hitomi.imageUrlFromImage -import xyz.quaver.hiyobi.createImgList -import xyz.quaver.pupil.R -import xyz.quaver.pupil.client -import xyz.quaver.pupil.interceptors -import xyz.quaver.pupil.ui.ReaderActivity -import java.io.File -import java.io.IOException -import java.util.concurrent.LinkedBlockingQueue - -@Suppress("DEPRECATION") -@Deprecated("Use DownloadService instead") -@OptIn(ExperimentalCoroutinesApi::class) -class DownloadWorker private constructor(context: Context) : ContextWrapper(context) { - - private val preferences : SharedPreferences = PreferenceManager.getDefaultSharedPreferences(this) - - //region ProgressListener - @Suppress("UNCHECKED_CAST") - private val progressListener = object: ProgressListener { - override fun update(tag: Any?, bytesRead: Long, contentLength: Long, done: Boolean) { - val (galleryID, index) = (tag as? Pair) ?: return - - if (!done && progress[galleryID]?.get(index)?.isFinite() == true) - progress[galleryID]?.set(index, bytesRead * 100F / contentLength) - } - } - - interface ProgressListener { - fun update(tag: Any?, bytesRead : Long, contentLength: Long, done: Boolean) - } - - class ProgressResponseBody( - val tag: Any?, - val responseBody: ResponseBody, - val progressListener : ProgressListener - ) : ResponseBody() { - private var bufferedSource : BufferedSource? = null - - override fun contentLength() = responseBody.contentLength() - override fun contentType() = responseBody.contentType() - - override fun source(): BufferedSource { - if (bufferedSource == null) - bufferedSource = Okio.buffer(source(responseBody.source())) - - return bufferedSource!! - } - - private fun source(source: Source) = object: ForwardingSource(source) { - var totalBytesRead = 0L - - override fun read(sink: Buffer, byteCount: Long): Long { - val bytesRead = super.read(sink, byteCount) - - totalBytesRead += if (bytesRead == -1L) 0L else bytesRead - progressListener.update(tag, totalBytesRead, responseBody.contentLength(), bytesRead == -1L) - - return bytesRead - } - - } - } - - init { - interceptors[Pair::class] = { chain -> - val request = chain.request() - var response = chain.proceed(request) - - var retry = 5 - while (!response.isSuccessful && retry > 0) { - response = chain.proceed(request) - retry-- - } - - response.newBuilder() - .body(response.body()?.let { - ProgressResponseBody(request.tag(), it, progressListener) - }).build() - } - } - //endregion - - //region Singleton - companion object { - - @Volatile private var instance: DownloadWorker? = null - - fun getInstance(context: Context) = - instance ?: synchronized(this) { - instance ?: DownloadWorker(context).also { instance = it } - } - } - //endregion - - val notificationManager = NotificationManagerCompat.from(context) - - val queue = LinkedBlockingQueue() - - /* - * KEY - * primary galleryID - * secondary index - * PRIMARY VALUE - * MutableList -> Download in progress - * null -> Loading / Gallery doesn't exist - * SECONDARY VALUE - * 0 <= value < 100 -> Download in progress - * Float.POSITIVE_INFINITY -> Download completed - */ - val progress = SparseArray?>() - val notification = SparseArray() - - private val loop = loop() - private val worker = SparseArray() - - fun stop() { - queue.clear() - - loop.cancel() - for (i in 0 until worker.size()) { - val galleryID = worker.keyAt(i) - - Cache(this@DownloadWorker).setDownloading(galleryID, false) - worker[galleryID]?.cancel() - } - - client.dispatcher().queuedCalls().filter { - it.request().tag() is Pair<*, *> - }.forEach { - it.cancel() - } - client.dispatcher().runningCalls().filter { - it.request().tag() is Pair<*, *> - }.forEach { - it.cancel() - } - - progress.clear() - notification.clear() - notificationManager.cancelAll() - } - - fun cancel(galleryID: Int) { - queue.remove(galleryID) - worker[galleryID]?.cancel() - - client.dispatcher().queuedCalls().filter { - ((it.request().tag() as Pair<*, *>).first as Int) == galleryID - }.forEach { - it.cancel() - } - client.dispatcher().runningCalls().filter { - ((it.request().tag() as Pair<*, *>).first as Int) == galleryID - }.forEach { - it.cancel() - } - - progress.remove(galleryID) - notification.remove(galleryID) - notificationManager.cancel(galleryID) - } - - fun isCompleted(galleryID: Int) = progress[galleryID]?.all { it.isInfinite() } == true - - private fun queueDownload(galleryID: Int, reader: Reader, index: Int, callback: Callback) { - val lowQuality = preferences.getBoolean("low_quality", false) - - val request = Request.Builder().apply { - when (reader.code) { - Code.HITOMI -> { - url( - imageUrlFromImage( - galleryID, - reader.galleryInfo.files[index], - !lowQuality - ) - ) - addHeader("Referer", getReferer(galleryID)) - } - Code.HIYOBI -> { - url(createImgList(galleryID, reader, lowQuality)[index].path) - } - else -> { - //shouldn't be called anyway - } - } - tag(galleryID to index) - }.build() - - client.newCall(request).enqueue(callback) - } - - private fun download(galleryID: Int) = CoroutineScope(Dispatchers.IO).launch { - val reader = Cache(this@DownloadWorker).getReader(galleryID) - - //gallery doesn't exist - if (reader == null) { - progress.put(galleryID, null) - - Cache(this@DownloadWorker).setDownloading(galleryID, false) - return@launch - } - - val cache = Cache(this@DownloadWorker).getImages(galleryID) - - progress.put(galleryID, reader.galleryInfo.files.indices.map { index -> - if (cache?.firstOrNull { it?.nameWithoutExtension?.toIntOrNull() == index } != null) - Float.POSITIVE_INFINITY - else - 0F - }.toMutableList()) - - if (notification[galleryID] == null) - initNotification(galleryID) - - notification[galleryID]?.setContentTitle(reader.galleryInfo.title) - notify(galleryID) - - if (isCompleted(galleryID)) { - with(Cache(this@DownloadWorker)) { - if (isDownloading(galleryID)) { - moveToDownload(galleryID) - setDownloading(galleryID, false) - } - } - - return@launch - } - - for (i in reader.galleryInfo.files.indices) { - val callback = object : Callback { - override fun onFailure(call: Call, e: IOException) { - if (e.message?.contains("cancel", true) != false) - return - - cancel(galleryID) - queue.add(galleryID) - } - - override fun onResponse(call: Call, response: Response) { - if (response.code() != 200) { - response.close() - onFailure(call, IOException()) - return - } - - val ext = call.request().url().encodedPath().split('.').last() - - try { - response.body()!!.use { - Cache(this@DownloadWorker).putImage(galleryID, i, ext, it.byteStream()) - } - progress[galleryID]?.set(i, Float.POSITIVE_INFINITY) - - notify(galleryID) - - CoroutineScope(Dispatchers.IO).launch { - if (isCompleted(galleryID)) { - with(Cache(this@DownloadWorker)) { - if (isDownloading(galleryID)) { - moveToDownload(galleryID) - setDownloading(galleryID, false) - } - } - } - } - } catch (e: Exception) { - FirebaseCrashlytics.getInstance().apply { - log("FAIL ON OK ${call.request().tag()} (${e.message})") - setCustomKey("POS", "FAIL ON OK") - recordException(e) - } - - File(Cache(this@DownloadWorker).getCachedGallery(galleryID), "%05d.$ext".format(i)).delete() - - cancel(galleryID) - queue.add(galleryID) - } - } - } - - if (progress[galleryID]?.get(i)?.isFinite() == true) - queueDownload(galleryID, reader, i, callback) - } - } - - private fun notify(galleryID: Int) { - val max = progress[galleryID]?.size ?: 0 - val progress = progress[galleryID]?.count { it.isInfinite() } ?: 0 - - if (isCompleted(galleryID)) { - notification[galleryID] - ?.setContentText(getString(R.string.reader_notification_complete)) - ?.setSmallIcon(android.R.drawable.stat_sys_download_done) - ?.setProgress(0, 0, false) - ?.setOngoing(false) - - notificationManager.cancel(galleryID) - } else - notification[galleryID] - ?.setProgress(max, progress, false) - ?.setContentText("$progress/$max") - - if (Cache(this).isDownloading(galleryID) && notification[galleryID] != null) - notification[galleryID]?.let { notificationManager.notify(galleryID, it.build()) } - else - notificationManager.cancel(galleryID) - } - - private fun initNotification(galleryID: Int) { - val intent = Intent(this, ReaderActivity::class.java).apply { - putExtra("galleryID", galleryID) - } - val pendingIntent = TaskStackBuilder.create(this).run { - addNextIntentWithParentStack(intent) - getPendingIntent(galleryID, PendingIntent.FLAG_UPDATE_CURRENT) - } - - notification.put(galleryID, NotificationCompat.Builder(this, "download").apply { - setContentTitle(getString(R.string.reader_loading)) - setContentText(getString(R.string.reader_notification_text)) - setSmallIcon(android.R.drawable.stat_sys_download) // had to use this because old android doesn't support VectorDrawable on Notification :P - setContentIntent(pendingIntent) - setProgress(0, 0, true) - setOngoing(true) - }) - } - - private fun loop() = CoroutineScope(Dispatchers.Default).launch { - while (true) { - if (queue.isEmpty()) - continue - - val galleryID = queue.peek() ?: continue - - if (progress.indexOfKey(galleryID) >= 0) // Gallery already downloading! - cancel(galleryID) - - if (notification[galleryID] == null) - initNotification(galleryID) - - if (Cache(this@DownloadWorker).isDownloading(galleryID)) - notification[galleryID]?.let { notificationManager.notify(galleryID, it.build()) } - - worker.put(galleryID, download(galleryID)) - queue.poll() - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/xyz/quaver/pupil/util/download/Metadata.kt b/app/src/main/java/xyz/quaver/pupil/util/download/Metadata.kt deleted file mode 100644 index 8dead901..00000000 --- a/app/src/main/java/xyz/quaver/pupil/util/download/Metadata.kt +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Pupil, Hitomi.la viewer for Android - * Copyright (C) 2020 tom5079 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package xyz.quaver.pupil.util.download - -import kotlinx.serialization.Serializable -import xyz.quaver.hitomi.GalleryBlock -import xyz.quaver.hitomi.Reader - -@Suppress("DEPRECATION") -@Deprecated("Use downloader.Cache.Metadata instead") -@Serializable -data class Metadata( - var thumbnail: String? = null, - var galleryBlock: GalleryBlock? = null, - var reader: Reader? = null, - var isDownloading: Boolean? = null -) { - constructor( - metadata: Metadata?, - thumbnail: String? = null, - galleryBlock: GalleryBlock? = null, - readers: Reader? = null, - isDownloading: Boolean? = null - ) : this( - thumbnail ?: metadata?.thumbnail, - galleryBlock ?: metadata?.galleryBlock, - readers ?: metadata?.reader, - isDownloading ?: metadata?.isDownloading - ) -} \ No newline at end of file diff --git a/app/src/main/res/layout/item_galleryblock.xml b/app/src/main/res/layout/item_galleryblock.xml index efab2973..678208f9 100644 --- a/app/src/main/res/layout/item_galleryblock.xml +++ b/app/src/main/res/layout/item_galleryblock.xml @@ -49,7 +49,7 @@ android:background="@android:color/holo_blue_dark" android:textColor="@android:color/white" android:text="@string/main_download" - android:foreground="?attr/selectableItemBackground" + android:foreground="?android:attr/selectableItemBackground" android:focusable="true" android:clickable="true" tools:ignore="UnusedAttribute" /> @@ -64,7 +64,7 @@ android:background="@android:color/holo_red_dark" android:textColor="@android:color/white" android:text="@string/main_delete" - android:foreground="?attr/selectableItemBackground" + android:foreground="?android:attr/selectableItemBackground" android:focusable="true" android:clickable="true" tools:ignore="UnusedAttribute" /> @@ -74,24 +74,38 @@ + android:layout_height="wrap_content" + android:background="?android:attr/selectableItemBackground" + android:focusable="true" + android:clickable="true"> - - - + app:layout_constraintTop_toTopOf="parent"> + + + + + + + app:layout_constraintTop_toBottomOf="@id/galleryblock_progressbar_layout"/> Date: Tue, 15 Sep 2020 01:12:29 +0900 Subject: [PATCH 4/5] Blink Recognition --- app/build.gradle | 5 +- .../xyz/quaver/pupil/ui/ReaderActivity.kt | 242 +++++++++++++----- .../main/java/xyz/quaver/pupil/util/camera.kt | 18 +- app/src/main/res/drawable/eye_off_white.xml | 8 + app/src/main/res/drawable/eye_white.xml | 8 + app/src/main/res/layout/activity_reader.xml | 2 +- app/src/main/res/layout/item_mirrors.xml | 1 - app/src/main/res/layout/reader_eye_card.xml | 2 +- app/src/main/res/values-ja/strings.xml | 6 +- app/src/main/res/values-ko/strings.xml | 6 +- app/src/main/res/values/strings.xml | 7 +- 11 files changed, 230 insertions(+), 75 deletions(-) create mode 100644 app/src/main/res/drawable/eye_off_white.xml create mode 100644 app/src/main/res/drawable/eye_white.xml diff --git a/app/build.gradle b/app/build.gradle index 1a65c84b..6ee16331 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -66,11 +66,12 @@ dependencies { implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9" //implementation "org.jetbrains.kotlinx:kotlinx-serialization-core:1.0.0-RC" implementation 'androidx.appcompat:appcompat:1.2.0' - implementation 'androidx.constraintlayout:constraintlayout:2.0.1' + implementation "androidx.activity:activity-ktx:1.2.0-alpha08" + implementation 'androidx.fragment:fragment-ktx:1.3.0-alpha08' implementation 'androidx.preference:preference:1.1.1' + implementation 'androidx.constraintlayout:constraintlayout:2.0.1' implementation 'androidx.gridlayout:gridlayout:1.0.0' implementation "androidx.biometric:biometric:1.0.1" - implementation 'androidx.fragment:fragment-ktx:1.2.5' implementation "com.daimajia.swipelayout:library:1.2.0@aar" implementation 'com.google.android.material:material:1.3.0-alpha02' implementation 'com.google.firebase:firebase-core:17.5.0' diff --git a/app/src/main/java/xyz/quaver/pupil/ui/ReaderActivity.kt b/app/src/main/java/xyz/quaver/pupil/ui/ReaderActivity.kt index 4710f246..c5cc4233 100644 --- a/app/src/main/java/xyz/quaver/pupil/ui/ReaderActivity.kt +++ b/app/src/main/java/xyz/quaver/pupil/ui/ReaderActivity.kt @@ -18,11 +18,14 @@ package xyz.quaver.pupil.ui +import android.Manifest import android.content.ComponentName import android.content.Intent import android.content.ServiceConnection +import android.content.pm.PackageManager import android.graphics.drawable.Animatable import android.graphics.drawable.Drawable +import android.os.Build import android.os.Bundle import android.os.IBinder import android.view.* @@ -31,9 +34,9 @@ import android.view.animation.AnticipateInterpolator import android.view.animation.OvershootInterpolator import android.view.animation.TranslateAnimation import android.widget.Toast +import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AlertDialog import androidx.core.content.ContextCompat -import androidx.core.content.res.ResourcesCompat import androidx.preference.PreferenceManager import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.PagerSnapHelper @@ -43,6 +46,7 @@ import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat import com.bumptech.glide.Glide import com.google.android.material.snackbar.Snackbar import com.google.firebase.crashlytics.FirebaseCrashlytics +import com.google.mlkit.vision.face.Face import com.qtalk.recyclerviewfastscroller.RecyclerViewFastScroller import kotlinx.android.synthetic.main.activity_reader.* import kotlinx.android.synthetic.main.activity_reader.view.* @@ -50,6 +54,7 @@ import kotlinx.android.synthetic.main.dialog_numberpicker.view.* import kotlinx.android.synthetic.main.reader_eye_card.view.* import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay import kotlinx.coroutines.launch import xyz.quaver.Code import xyz.quaver.pupil.R @@ -62,7 +67,7 @@ import xyz.quaver.pupil.util.camera import xyz.quaver.pupil.util.closeCamera import xyz.quaver.pupil.util.downloader.Cache import xyz.quaver.pupil.util.downloader.DownloadManager -import xyz.quaver.pupil.util.testCamera +import xyz.quaver.pupil.util.startCamera import java.util.* import kotlin.concurrent.schedule @@ -97,11 +102,29 @@ class ReaderActivity : BaseActivity() { } private val timer = Timer() - private val snapHelper = PagerSnapHelper() - private var menu: Menu? = null + private val requestPermissionLauncher = registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted -> + if (isGranted) + toggleCamera() + else + AlertDialog.Builder(this) + .setTitle(R.string.error) + .setMessage(R.string.camera_denied) + .setPositiveButton(android.R.string.ok) { _, _ ->} + .show() + } + + enum class Eye { + LEFT, + RIGHT + } + + private var cameraEnabled = false + private var eyeType: Eye? = null + private var eyeCount: Int = 0 + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_reader) @@ -226,6 +249,18 @@ class ReaderActivity : BaseActivity() { return true } + override fun onResume() { + super.onResume() + + if (cameraEnabled) + startCamera(this, cameraCallback) + } + + override fun onPause() { + super.onPause() + closeCamera() + } + override fun onDestroy() { super.onDestroy() @@ -390,66 +425,21 @@ class ReaderActivity : BaseActivity() { } with(reader_fab_auto) { - setImageResource(R.drawable.clock_start) + setImageResource(R.drawable.eye_white) setOnClickListener { - val eyes = this@ReaderActivity.eye_card - when (camera) { - null -> { - eyes.apply { - visibility = View.VISIBLE - TranslateAnimation(0F, 0F, -100F, 0F).apply { - duration = 500 - fillAfter = false - interpolator = OvershootInterpolator() - }.let { startAnimation(it) } - } - testCamera(context) { faces -> - eyes.dot.let { - it.visibility = View.VISIBLE - Timer().schedule(50) { - runOnUiThread { - it.visibility = View.GONE - } - } - } - - if (faces.size != 1) - ResourcesCompat.getDrawable(resources, R.drawable.eye_off, context.theme).let { - eyes.left_eye.setImageDrawable(it) - eyes.right_eye.setImageDrawable(it) - - return@testCamera - } - - val left = ResourcesCompat.getDrawable(resources, - if (faces[0].rightEyeOpenProbability?.let { it > 0.4 } == true) R.drawable.eye else R.drawable.eye_closed, - context.theme) - val right = ResourcesCompat.getDrawable(resources, - if (faces[0].leftEyeOpenProbability?.let { it > 0.4 } == true) R.drawable.eye else R.drawable.eye_closed, - context.theme) - - eyes.left_eye.setImageDrawable(left) - eyes.right_eye.setImageDrawable(right) - } + when { + ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED -> { + toggleCamera() } - else -> { - eyes.apply { - TranslateAnimation(0F, 0F, 0F, -100F).apply { - duration = 500 - fillAfter = false - interpolator = AnticipateInterpolator() - setAnimationListener(object: Animation.AnimationListener { - override fun onAnimationStart(p0: Animation?) {} - override fun onAnimationRepeat(p0: Animation?) {} - - override fun onAnimationEnd(p0: Animation?) { - eyes.visibility = View.GONE - } - }) - }.let { startAnimation(it) } - } - closeCamera() + Build.VERSION.SDK_INT >= 23 && shouldShowRequestPermissionRationale(Manifest.permission.CAMERA) -> { + AlertDialog.Builder(this@ReaderActivity) + .setTitle(R.string.warning) + .setMessage(R.string.camera_denied) + .setPositiveButton(android.R.string.ok) { _, _ ->} + .show() } + else -> + requestPermissionLauncher.launch(Manifest.permission.CAMERA) } } } @@ -502,6 +492,17 @@ class ReaderActivity : BaseActivity() { } else { snapHelper.attachToRecyclerView(reader_recyclerview) reader_recyclerview.layoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, Preferences["rtl", false]) + + if (Preferences["rtl", false]) + with(reader_progressbar) { + scaleX = -1F + translationX = 1F + } + else + with(reader_progressbar) { + scaleX = 0F + translationX = 0F + } } (reader_recyclerview.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(currentPage-1, 0) @@ -536,6 +537,125 @@ class ReaderActivity : BaseActivity() { } } + val cameraCallback: (List) -> Unit = callback@{ faces -> + eye_card.dot.let { + it.visibility = View.VISIBLE + CoroutineScope(Dispatchers.Main).launch { + delay(50) + it.visibility = View.INVISIBLE + } + } + + if (faces.size != 1) + ContextCompat.getDrawable(this, R.drawable.eye_off).let { + with(eye_card) { + left_eye.setImageDrawable(it) + right_eye.setImageDrawable(it) + } + + return@callback + } + + val (left, right) = Pair( + faces[0].rightEyeOpenProbability?.let { it > 0.4 } == true, + faces[0].leftEyeOpenProbability?.let { it > 0.4 } == true + ) + + with(eye_card) { + left_eye.setImageDrawable( + ContextCompat.getDrawable( + context, + if (left) R.drawable.eye else R.drawable.eye_closed + ) + ) + right_eye.setImageDrawable( + ContextCompat.getDrawable( + context, + if (right) R.drawable.eye else R.drawable.eye_closed + ) + ) + } + + when { + // Both closed / opened + !left.xor(right) -> { + eyeType = null + eyeCount = 0 + } + !left -> { + if (eyeType != Eye.LEFT) { + eyeType = Eye.LEFT + eyeCount = 0 + } + eyeCount++ + } + !right -> { + if (eyeType != Eye.RIGHT) { + eyeType = Eye.RIGHT + eyeCount = 0 + } + eyeCount++ + } + } + + if (eyeCount > 3) { + (this@ReaderActivity.reader_recyclerview.layoutManager as LinearLayoutManager).let { + it.scrollToPositionWithOffset(when(eyeType!!) { + Eye.RIGHT -> { + if (it.reverseLayout) currentPage - 2 else currentPage + } + Eye.LEFT -> { + if (it.reverseLayout) currentPage else currentPage - 2 + } + }, 0) + } + + eyeType = null + eyeCount = 0 + } + } + + private fun toggleCamera() { + val eyes = this@ReaderActivity.eye_card + when (camera) { + null -> { + reader_fab_auto.labelText = getString(R.string.reader_fab_auto_cancel) + reader_fab_auto.setImageResource(R.drawable.eye_off_white) + eyes.apply { + visibility = View.VISIBLE + TranslateAnimation(0F, 0F, -100F, 0F).apply { + duration = 500 + fillAfter = false + interpolator = OvershootInterpolator() + }.let { startAnimation(it) } + } + startCamera(this, cameraCallback) + cameraEnabled = true + } + else -> { + reader_fab_auto.labelText = getString(R.string.reader_fab_auto) + reader_fab_auto.setImageResource(R.drawable.eye_white) + eyes.apply { + TranslateAnimation(0F, 0F, 0F, -100F).apply { + duration = 500 + fillAfter = false + interpolator = AnticipateInterpolator() + setAnimationListener(object: Animation.AnimationListener { + override fun onAnimationStart(p0: Animation?) {} + override fun onAnimationRepeat(p0: Animation?) {} + + override fun onAnimationEnd(p0: Animation?) { + eyes.visibility = View.GONE + } + }) + }.let { startAnimation(it) } + } + closeCamera() + cameraEnabled = false + } + } + } + override fun onLowMemory() { super.onLowMemory() Glide.get(this).onLowMemory() diff --git a/app/src/main/java/xyz/quaver/pupil/util/camera.kt b/app/src/main/java/xyz/quaver/pupil/util/camera.kt index f783a9e4..1b2e5652 100644 --- a/app/src/main/java/xyz/quaver/pupil/util/camera.kt +++ b/app/src/main/java/xyz/quaver/pupil/util/camera.kt @@ -16,13 +16,14 @@ * along with this program. If not, see . */ -@file:Suppress("DEPRECATION") +@file:Suppress("DEPRECATION", "Recycle") package xyz.quaver.pupil.util import android.content.Context import android.content.pm.PackageManager import android.graphics.ImageFormat +import android.graphics.SurfaceTexture import android.hardware.Camera import android.view.Surface import android.view.WindowManager @@ -68,6 +69,7 @@ private fun getRotation(context: Context, cameraID: Int): Int { } var camera: Camera? = null +var surfaceTexture: SurfaceTexture? = null private val detector = FaceDetection.getClient( FaceDetectorOptions.Builder() .setClassificationMode(FaceDetectorOptions.CLASSIFICATION_MODE_ALL) @@ -75,7 +77,7 @@ private val detector = FaceDetection.getClient( ) private var process: Task>? = null -fun testCamera(context: Context, callback: (List) -> Unit) { +fun startCamera(context: Context, callback: (List) -> Unit) { if (camera != null) closeCamera() val cameraID = openFrontCamera().let { (cam, cameraID) -> @@ -88,9 +90,13 @@ fun testCamera(context: Context, callback: (List) -> Unit) { parameters = parameters.apply { setPreviewSize(640, 480) previewFormat = ImageFormat.NV21 - flashMode = Camera.Parameters.FLASH_MODE_OFF } - setPreviewCallback { bytes, camera -> + + setPreviewTexture(surfaceTexture ?: SurfaceTexture(0).also { + surfaceTexture = it + }) + startPreview() + setPreviewCallback { bytes, _ -> if (process?.isComplete == false) return@setPreviewCallback @@ -100,14 +106,14 @@ fun testCamera(context: Context, callback: (List) -> Unit) { process = detector.process(image) .addOnSuccessListener(callback) } - - startPreview() } } fun closeCamera() { camera?.setPreviewCallback(null) camera?.stopPreview() + surfaceTexture?.release() + surfaceTexture = null camera?.release() camera = null } \ No newline at end of file diff --git a/app/src/main/res/drawable/eye_off_white.xml b/app/src/main/res/drawable/eye_off_white.xml new file mode 100644 index 00000000..15afd4cd --- /dev/null +++ b/app/src/main/res/drawable/eye_off_white.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/eye_white.xml b/app/src/main/res/drawable/eye_white.xml new file mode 100644 index 00000000..c1f3d205 --- /dev/null +++ b/app/src/main/res/drawable/eye_white.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_reader.xml b/app/src/main/res/layout/activity_reader.xml index cfa8c1f1..0c19d226 100644 --- a/app/src/main/res/layout/activity_reader.xml +++ b/app/src/main/res/layout/activity_reader.xml @@ -106,7 +106,7 @@ android:id="@+id/reader_fab_auto" android:layout_width="wrap_content" android:layout_height="wrap_content" - app:srcCompat="@drawable/clock_start" + app:srcCompat="@drawable/eye_white" app:fab_label="@string/reader_fab_auto" app:fab_size="mini"/> diff --git a/app/src/main/res/layout/item_mirrors.xml b/app/src/main/res/layout/item_mirrors.xml index 5c849c09..2b349771 100644 --- a/app/src/main/res/layout/item_mirrors.xml +++ b/app/src/main/res/layout/item_mirrors.xml @@ -42,7 +42,6 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" app:srcCompat="@drawable/menu" - app:tint="?attr/colorControlNormal" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" diff --git a/app/src/main/res/layout/reader_eye_card.xml b/app/src/main/res/layout/reader_eye_card.xml index b199a922..11343d53 100644 --- a/app/src/main/res/layout/reader_eye_card.xml +++ b/app/src/main/res/layout/reader_eye_card.xml @@ -55,7 +55,7 @@ android:id="@+id/dot" android:layout_width="4dp" android:layout_height="4dp" - android:visibility="gone" + android:visibility="invisible" app:srcCompat="@drawable/dot" app:layout_constraintLeft_toLeftOf="@id/left_eye" app:layout_constraintRight_toRightOf="@id/right_eye" diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index ffce239f..8fb154ec 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -132,7 +132,7 @@ ユーザーID ユーザーIDをクリップボードにコピーしました リトライ - 自動スクロール + まばたき検知スクロール 全てのギャラリーを対象に検索 綴じ方向を左にする ブックマーク管理 @@ -148,4 +148,8 @@ オープンソースライセンス お気に入りのタグを見る 履歴を見る + まばたき検知を中止 + カメラ権限が拒否されているため、まばたき検知使用できません + この機器には前面カメラが装着されていません + エラー \ No newline at end of file diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index f18284ed..74ad60e7 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -132,7 +132,7 @@ 유저 ID 유저 ID를 클립보드에 복사했습니다 재시도 - 자동 스크롤 + 눈 깜빡임 감지 스크롤 모든 갤러리 검색 좌측으로 페이지 넘기기 즐겨찾기 관리 @@ -148,4 +148,8 @@ 오픈 소스 라이선스 검색 기록 보기 즐겨찾기 태그 보기 + 눈 깜빡임 감지 중지 + 카메라 권한이 거부되었기 때문에 눈 깜빡임 감지가 불가능합니다 + 이 장치에는 전면 카메라가 없습니다 + 오류 \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7695d3e4..b9c18a0a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -20,6 +20,7 @@ Warning + Error Ignore @@ -99,12 +100,16 @@ Go to page Fullscreen> Retry - Automatic scroll + Scroll with eye blink + Stop scroll with eye blink Background download Cancel background download Downloading… Download complete + Eye blink detection cannot be used without a permission + There is no front facing camera in this device + Downloader running… From b907d3677008124766f8755bae7f26da6c624798 Mon Sep 17 00:00:00 2001 From: tom5079 Date: Tue, 15 Sep 2020 02:13:25 +0900 Subject: [PATCH 5/5] Bug fix --- app/build.gradle | 2 +- app/release/output-metadata.json | 2 +- .../main/java/xyz/quaver/pupil/services/DownloadService.kt | 2 +- app/src/main/java/xyz/quaver/pupil/ui/ReaderActivity.kt | 4 ++-- .../xyz/quaver/pupil/util/downloader/DownloadManager.kt | 6 ++++-- app/src/main/java/xyz/quaver/pupil/util/misc.kt | 4 ++-- app/src/main/res/drawable/menu.xml | 2 +- 7 files changed, 12 insertions(+), 10 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 6ee16331..d61a98a0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -21,7 +21,7 @@ android { minSdkVersion 16 targetSdkVersion 30 versionCode 59 - versionName "5.0.2-hotfix1" + versionName "5.0.3" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true } diff --git a/app/release/output-metadata.json b/app/release/output-metadata.json index 54de8e06..bcad787b 100644 --- a/app/release/output-metadata.json +++ b/app/release/output-metadata.json @@ -12,7 +12,7 @@ "filters": [], "properties": [], "versionCode": 59, - "versionName": "5.0.2-hotfix1", + "versionName": "5.0.3", "enabled": true, "outputFile": "app-release.apk" } diff --git a/app/src/main/java/xyz/quaver/pupil/services/DownloadService.kt b/app/src/main/java/xyz/quaver/pupil/services/DownloadService.kt index 3b4eb8bc..d3055a8e 100644 --- a/app/src/main/java/xyz/quaver/pupil/services/DownloadService.kt +++ b/app/src/main/java/xyz/quaver/pupil/services/DownloadService.kt @@ -339,7 +339,7 @@ class DownloadService : Service() { if (isCompleted(galleryID)) { if (DownloadManager.getInstance(this@DownloadService) - .getDownloadFolder(galleryID) != null) + .getDownloadFolder(galleryID) != null ) Cache.getInstance(this@DownloadService, galleryID).moveToDownload() notificationManager.cancel(galleryID) diff --git a/app/src/main/java/xyz/quaver/pupil/ui/ReaderActivity.kt b/app/src/main/java/xyz/quaver/pupil/ui/ReaderActivity.kt index c5cc4233..f9810946 100644 --- a/app/src/main/java/xyz/quaver/pupil/ui/ReaderActivity.kt +++ b/app/src/main/java/xyz/quaver/pupil/ui/ReaderActivity.kt @@ -410,6 +410,7 @@ class ReaderActivity : BaseActivity() { animateDownloadFAB(false) } else { downloadManager.addDownloadFolder(galleryID) + DownloadService.download(context, galleryID, true) animateDownloadFAB(true) } } @@ -419,8 +420,7 @@ class ReaderActivity : BaseActivity() { with(reader_fab_retry) { setImageResource(R.drawable.refresh) setOnClickListener { - downloader?.cancel(galleryID) - downloader?.download(galleryID) + DownloadService.download(context, galleryID) } } diff --git a/app/src/main/java/xyz/quaver/pupil/util/downloader/DownloadManager.kt b/app/src/main/java/xyz/quaver/pupil/util/downloader/DownloadManager.kt index 2d8e6c76..d9520c82 100644 --- a/app/src/main/java/xyz/quaver/pupil/util/downloader/DownloadManager.kt +++ b/app/src/main/java/xyz/quaver/pupil/util/downloader/DownloadManager.kt @@ -104,8 +104,10 @@ class DownloadManager private constructor(context: Context) : ContextWrapper(con val folder = downloadFolder.getChild(name) - if (!folder.exists()) - folder.mkdir() + if (folder.exists()) + return + + folder.mkdir() downloadFolderMap[galleryID] = folder.name diff --git a/app/src/main/java/xyz/quaver/pupil/util/misc.kt b/app/src/main/java/xyz/quaver/pupil/util/misc.kt index 9f9a6613..48d84ae8 100644 --- a/app/src/main/java/xyz/quaver/pupil/util/misc.kt +++ b/app/src/main/java/xyz/quaver/pupil/util/misc.kt @@ -93,14 +93,14 @@ fun GalleryBlock.formatDownloadFolder(): String = formatMap.entries.fold(it) { str, (k, v) -> str.replace(k, v.invoke(this), true) } - }.replace("/", "") + }.replace(Regex("""[*\\|"?><:/]"""), "") fun GalleryBlock.formatDownloadFolderTest(format: String): String = format.let { formatMap.entries.fold(it) { str, (k, v) -> str.replace(k, v.invoke(this), true) } - }.replace("/", "") + }.replace(Regex("""[*\\|"?><:/]"""), "") val Reader.requestBuilders: List get() { diff --git a/app/src/main/res/drawable/menu.xml b/app/src/main/res/drawable/menu.xml index 2356f143..e058761e 100644 --- a/app/src/main/res/drawable/menu.xml +++ b/app/src/main/res/drawable/menu.xml @@ -1,4 +1,4 @@ - +