From c680a1b68a67ba56b7010187c028ca8ffa4153b5 Mon Sep 17 00:00:00 2001 From: darthpaul Date: Sun, 27 Nov 2022 14:31:51 +0000 Subject: [PATCH] handle countdown timer sounds --- .../camera/activities/MainActivity.kt | 16 ++ .../camera/helpers/MediaActionSound.kt | 168 ++++++++++-------- .../camera/helpers/MediaSoundHelper.kt | 14 ++ .../implementations/CameraXInitializer.kt | 3 + .../camera/implementations/CameraXPreview.kt | 9 +- app/src/main/res/raw/beep.mp3 | Bin 0 -> 2522 bytes app/src/main/res/raw/beep_2_secs.mp3 | Bin 0 -> 25983 bytes 7 files changed, 128 insertions(+), 82 deletions(-) create mode 100644 app/src/main/res/raw/beep.mp3 create mode 100644 app/src/main/res/raw/beep_2_secs.mp3 diff --git a/app/src/main/kotlin/com/simplemobiletools/camera/activities/MainActivity.kt b/app/src/main/kotlin/com/simplemobiletools/camera/activities/MainActivity.kt index e46440a1..2d9ab417 100644 --- a/app/src/main/kotlin/com/simplemobiletools/camera/activities/MainActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/camera/activities/MainActivity.kt @@ -53,6 +53,7 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera const val PHOTO_MODE_INDEX = 1 const val VIDEO_MODE_INDEX = 0 private const val MIN_SWIPE_DISTANCE_X = 100 + private const val TIMER_2_SECONDS = 2001 } private lateinit var defaultScene: Scene @@ -60,6 +61,7 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera private lateinit var timerScene: Scene private lateinit var mOrientationEventListener: OrientationEventListener private lateinit var mFocusCircleView: FocusCircleView + private lateinit var mediaSoundHelper: MediaSoundHelper private var mPreview: MyPreview? = null private var mediaSizeToggleGroup: MaterialButtonToggleGroup? = null private var mPreviewUri: Uri? = null @@ -172,6 +174,7 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera override fun onDestroy() { super.onDestroy() mPreview = null + mediaSoundHelper.release() } override fun onBackPressed() { @@ -182,6 +185,8 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera private fun initVariables() { mIsHardwareShutterHandled = false + mediaSoundHelper = MediaSoundHelper(this) + mediaSoundHelper.loadSounds() } override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean { @@ -321,6 +326,7 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera mPreview = CameraXInitializer(this).createCameraXPreview( preview_view, listener = this, + mediaSoundHelper = mediaSoundHelper, outputUri = outputUri, isThirdPartyIntent = isThirdPartyIntent, initInPhotoMode = isInPhotoMode, @@ -487,6 +493,7 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera } private fun cancelTimer() { + mediaSoundHelper.stopTimerCountdown2SecondsSound() countDownTimer?.cancel() countDownTimer = null resetViewsOnTimerFinish() @@ -855,10 +862,19 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera hideViewsOnTimerStart() shutter.setImageState(intArrayOf(R.attr.state_timer_cancel), true) timer_text.beVisible() + var playSound = true countDownTimer = object : CountDownTimer(timerMode.millisInFuture, 1000) { override fun onTick(millisUntilFinished: Long) { val seconds = (TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished) + 1).toString() timer_text.setText(seconds) + if (playSound && config.isSoundEnabled) { + if (millisUntilFinished <= TIMER_2_SECONDS) { + mediaSoundHelper.playTimerCountdown2SecondsSound() + playSound = false + } else { + mediaSoundHelper.playTimerCountdownSound() + } + } } override fun onFinish() { diff --git a/app/src/main/kotlin/com/simplemobiletools/camera/helpers/MediaActionSound.kt b/app/src/main/kotlin/com/simplemobiletools/camera/helpers/MediaActionSound.kt index a8ac8dda..1a848c52 100644 --- a/app/src/main/kotlin/com/simplemobiletools/camera/helpers/MediaActionSound.kt +++ b/app/src/main/kotlin/com/simplemobiletools/camera/helpers/MediaActionSound.kt @@ -8,6 +8,8 @@ import android.net.Uri import android.os.Handler import android.os.Looper import android.util.Log +import androidx.annotation.RawRes +import com.simplemobiletools.camera.R import java.io.File /** @@ -15,59 +17,59 @@ import java.io.File */ class MediaActionSound(private val context: Context) { companion object { + val SHUTTER_CLICK = MediaSound.ManufacturerSound("camera_click.ogg") + val FOCUS_COMPLETE = MediaSound.ManufacturerSound("camera_focus.ogg") + val START_VIDEO_RECORDING = MediaSound.ManufacturerSound("VideoRecord.ogg") + val STOP_VIDEO_RECORDING = MediaSound.ManufacturerSound("VideoStop.ogg") + val TIMER_COUNTDOWN = MediaSound.RawResSound(R.raw.beep) + val TIMER_COUNTDOWN_2_SECONDS = MediaSound.RawResSound(R.raw.beep_2_secs) + private const val NUM_MEDIA_SOUND_STREAMS = 1 private val SOUND_DIRS = arrayOf( - "/product/media/audio/ui/", - "/system/media/audio/ui/" - ) - private val SOUND_FILES = arrayOf( - "camera_click.ogg", - "camera_focus.ogg", - "VideoRecord.ogg", - "VideoStop.ogg" + "/product/media/audio/ui/", "/system/media/audio/ui/" ) private const val TAG = "MediaActionSound" - const val SHUTTER_CLICK = 0 - const val FOCUS_COMPLETE = 1 - const val START_VIDEO_RECORDING = 2 - const val STOP_VIDEO_RECORDING = 3 private const val STATE_NOT_LOADED = 0 private const val STATE_LOADING = 1 private const val STATE_LOADING_PLAY_REQUESTED = 2 private const val STATE_LOADED = 3 + private val SOUNDS = arrayOf(SHUTTER_CLICK, FOCUS_COMPLETE, START_VIDEO_RECORDING, STOP_VIDEO_RECORDING, TIMER_COUNTDOWN, TIMER_COUNTDOWN_2_SECONDS) } - private class SoundState(val name: Int) { - var id = 0 // 0 is an invalid sample ID. + sealed class MediaSound { + class ManufacturerSound(val fileName: String, var path: String = "") : MediaSound() + class RawResSound(@RawRes val resId: Int) : MediaSound() + } + + private class SoundState( + val mediaSound: MediaSound, + // 0 is an invalid sample ID. + var loadId: Int = 0, + var streamId: Int = 0, var state: Int = STATE_NOT_LOADED - var path: String? = null - } + ) - private var soundPool: SoundPool? = SoundPool.Builder() - .setMaxStreams(NUM_MEDIA_SOUND_STREAMS) - .setAudioAttributes( - AudioAttributes.Builder() - .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) - .setFlags(AudioAttributes.FLAG_AUDIBILITY_ENFORCED) - .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) - .build() - ).build() + private var soundPool: SoundPool? = SoundPool.Builder().setMaxStreams(NUM_MEDIA_SOUND_STREAMS).setAudioAttributes( + AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION).setFlags(AudioAttributes.FLAG_AUDIBILITY_ENFORCED) + .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION).build() + ).build() private var mediaPlayer: MediaPlayer? = null private var playCompletionRunnable: Runnable? = null - private val mSounds: Array = arrayOfNulls(SOUND_FILES.size) + private val sounds = SOUNDS.map { SoundState(it) } + private val playTimeHandler = Handler(Looper.getMainLooper()) private val mLoadCompleteListener = SoundPool.OnLoadCompleteListener { _, sampleId, status -> - for (sound in mSounds) { - if (sound!!.id != sampleId) { + for (sound in sounds) { + if (sound.loadId != sampleId) { continue } var soundToBePlayed: SoundState? = null synchronized(sound) { if (status != 0) { sound.state = STATE_NOT_LOADED - sound.id = 0 - Log.e(TAG, "OnLoadCompleteListener() error: $status loading sound: ${sound.name}") + sound.loadId = 0 + Log.e(TAG, "OnLoadCompleteListener() error: $status loading sound: ${sound.mediaSound}") return@OnLoadCompleteListener } when (sound.state) { @@ -76,11 +78,11 @@ class MediaActionSound(private val context: Context) { soundToBePlayed = sound sound.state = STATE_LOADED } - else -> Log.e(TAG, "OnLoadCompleteListener() called in wrong state: ${sound.state} for sound: ${sound.name}") + else -> Log.e(TAG, "OnLoadCompleteListener() called in wrong state: ${sound.state} for sound: ${sound.mediaSound}") } } if (soundToBePlayed != null) { - playSoundPool(soundToBePlayed!!) + playWithSoundPool(soundToBePlayed!!) } break } @@ -88,89 +90,113 @@ class MediaActionSound(private val context: Context) { init { soundPool!!.setOnLoadCompleteListener(mLoadCompleteListener) - for (i in mSounds.indices) { - mSounds[i] = SoundState(i) - } } - private fun loadSound(sound: SoundState?): Int { - val soundFileName = SOUND_FILES[sound!!.name] - for (soundDir in SOUND_DIRS) { - val soundPath = soundDir + soundFileName - sound.path = soundPath - val id = soundPool!!.load(soundPath, 1) - if (id > 0) { - sound.state = STATE_LOADING - sound.id = id - return id + private fun loadSound(sound: SoundState): Int { + var id = 0 + when (val mediaSound = sound.mediaSound) { + is MediaSound.ManufacturerSound -> { + for (soundDir in SOUND_DIRS) { + val soundPath = soundDir + mediaSound.fileName + mediaSound.path = soundPath + id = soundPool!!.load(soundPath, 1) + break + } + } + is MediaSound.RawResSound -> { + id = soundPool!!.load(context, mediaSound.resId, 1) } } + + if (id > 0) { + sound.state = STATE_LOADING + sound.loadId = id + return id + } + return 0 } - fun load(soundName: Int) { - if (soundName < 0 || soundName >= SOUND_FILES.size) { - throw RuntimeException("Unknown sound requested: $soundName") - } - val sound = mSounds[soundName] - synchronized(sound!!) { + fun load(mediaSound: MediaSound) { + val sound = sounds.first { it.mediaSound == mediaSound } + synchronized(sound) { when (sound.state) { STATE_NOT_LOADED -> { loadSound(sound).let { soundId -> if (soundId <= 0) { - Log.e(TAG, "load() error loading sound: $soundName") + Log.e(TAG, "load() error loading sound: $mediaSound") } } } - else -> Log.e(TAG, "load() called in wrong state: $sound for sound: $soundName") + else -> Log.e(TAG, "load() called in wrong state: $sound for sound: $mediaSound") } } } - fun play(soundName: Int, onPlayComplete: (() -> Unit)? = null) { - if (soundName < 0 || soundName >= SOUND_FILES.size) { - throw RuntimeException("Unknown sound requested: $soundName") - } + fun play(mediaSound: MediaSound, onPlayComplete: (() -> Unit)? = null) { removeHandlerCallbacks() if (onPlayComplete != null) { playCompletionRunnable = Runnable { onPlayComplete.invoke() } } - val sound = mSounds[soundName] - synchronized(sound!!) { + val sound = sounds.first { it.mediaSound == mediaSound } + synchronized(sound) { when (sound.state) { STATE_NOT_LOADED -> { val soundId = loadSound(sound) if (soundId <= 0) { - Log.e(TAG, "play() error loading sound: $soundName") + Log.e(TAG, "play() error loading sound: $mediaSound") } else { sound.state = STATE_LOADING_PLAY_REQUESTED } } STATE_LOADING -> sound.state = STATE_LOADING_PLAY_REQUESTED STATE_LOADED -> { - playSoundPool(sound) + playWithSoundPool(sound) } - else -> Log.e(TAG, "play() called in wrong state: ${sound.state} for sound: $soundName") + else -> Log.e(TAG, "play() called in wrong state: ${sound.state} for sound: $mediaSound") } } } - private fun playSoundPool(sound: SoundState) { + private fun playWithSoundPool(sound: SoundState) { if (playCompletionRunnable != null) { - val duration = getSoundDuration(sound.path!!) + val duration = getSoundDuration(sound.mediaSound) playTimeHandler.postDelayed(playCompletionRunnable!!, duration) } - soundPool!!.play(sound.id, 1.0f, 1.0f, 0, 0, 1.0f) + val streamId = soundPool!!.play(sound.loadId, 1.0f, 1.0f, 0, 0, 1.0f) + sound.streamId = streamId + } + + private fun getSoundDuration(mediaSound: MediaSound): Long { + releaseMediaPlayer() + mediaPlayer = when (mediaSound) { + is MediaSound.ManufacturerSound -> MediaPlayer.create(context, Uri.fromFile(File(mediaSound.path))) + is MediaSound.RawResSound -> MediaPlayer.create(context, mediaSound.resId) + } + return mediaPlayer!!.duration.toLong() + } + + fun stop(mediaSound: MediaSound) { + val sound = sounds.first { it.mediaSound == mediaSound } + synchronized(sound) { + when (sound.state) { + STATE_LOADED -> { + soundPool!!.stop(sound.streamId) + } + else -> Log.w(TAG, "stop() should be called after sound is loaded for sound: $mediaSound") + } + } } fun release() { if (soundPool != null) { - for (sound in mSounds) { - synchronized(sound!!) { + for (sound in sounds) { + synchronized(sound) { sound.state = STATE_NOT_LOADED - sound.id = 0 + sound.loadId = 0 + sound.streamId = 0 } } soundPool?.release() @@ -189,10 +215,4 @@ class MediaActionSound(private val context: Context) { mediaPlayer?.release() mediaPlayer = null } - - private fun getSoundDuration(soundPath: String): Long { - releaseMediaPlayer() - mediaPlayer = MediaPlayer.create(context, Uri.fromFile(File(soundPath))) - return mediaPlayer!!.duration.toLong() - } } diff --git a/app/src/main/kotlin/com/simplemobiletools/camera/helpers/MediaSoundHelper.kt b/app/src/main/kotlin/com/simplemobiletools/camera/helpers/MediaSoundHelper.kt index 1e32a822..c7ab0e8c 100644 --- a/app/src/main/kotlin/com/simplemobiletools/camera/helpers/MediaSoundHelper.kt +++ b/app/src/main/kotlin/com/simplemobiletools/camera/helpers/MediaSoundHelper.kt @@ -9,6 +9,8 @@ class MediaSoundHelper(context: Context) { mediaActionSound.load(MediaActionSound.START_VIDEO_RECORDING) mediaActionSound.load(MediaActionSound.STOP_VIDEO_RECORDING) mediaActionSound.load(MediaActionSound.SHUTTER_CLICK) + mediaActionSound.load(MediaActionSound.TIMER_COUNTDOWN) + mediaActionSound.load(MediaActionSound.TIMER_COUNTDOWN_2_SECONDS) } fun playShutterSound() { @@ -23,6 +25,18 @@ class MediaSoundHelper(context: Context) { mediaActionSound.play(MediaActionSound.STOP_VIDEO_RECORDING) } + fun playTimerCountdownSound() { + mediaActionSound.play(MediaActionSound.TIMER_COUNTDOWN) + } + + fun playTimerCountdown2SecondsSound() { + mediaActionSound.play(MediaActionSound.TIMER_COUNTDOWN_2_SECONDS) + } + + fun stopTimerCountdown2SecondsSound() { + mediaActionSound.stop(MediaActionSound.TIMER_COUNTDOWN_2_SECONDS) + } + fun release() { mediaActionSound.release() } diff --git a/app/src/main/kotlin/com/simplemobiletools/camera/implementations/CameraXInitializer.kt b/app/src/main/kotlin/com/simplemobiletools/camera/implementations/CameraXInitializer.kt index 4a28c7f8..88b01e69 100644 --- a/app/src/main/kotlin/com/simplemobiletools/camera/implementations/CameraXInitializer.kt +++ b/app/src/main/kotlin/com/simplemobiletools/camera/implementations/CameraXInitializer.kt @@ -4,6 +4,7 @@ import android.net.Uri import androidx.camera.view.PreviewView import com.simplemobiletools.camera.helpers.CameraErrorHandler import com.simplemobiletools.camera.helpers.MediaOutputHelper +import com.simplemobiletools.camera.helpers.MediaSoundHelper import com.simplemobiletools.commons.activities.BaseSimpleActivity class CameraXInitializer(private val activity: BaseSimpleActivity) { @@ -11,6 +12,7 @@ class CameraXInitializer(private val activity: BaseSimpleActivity) { fun createCameraXPreview( previewView: PreviewView, listener: CameraXPreviewListener, + mediaSoundHelper: MediaSoundHelper, outputUri: Uri?, isThirdPartyIntent: Boolean, initInPhotoMode: Boolean, @@ -20,6 +22,7 @@ class CameraXInitializer(private val activity: BaseSimpleActivity) { return CameraXPreview( activity, previewView, + mediaSoundHelper, mediaOutputHelper, cameraErrorHandler, listener, diff --git a/app/src/main/kotlin/com/simplemobiletools/camera/implementations/CameraXPreview.kt b/app/src/main/kotlin/com/simplemobiletools/camera/implementations/CameraXPreview.kt index b9295223..23aef8b2 100644 --- a/app/src/main/kotlin/com/simplemobiletools/camera/implementations/CameraXPreview.kt +++ b/app/src/main/kotlin/com/simplemobiletools/camera/implementations/CameraXPreview.kt @@ -37,6 +37,7 @@ import com.simplemobiletools.commons.helpers.ensureBackgroundThread class CameraXPreview( private val activity: AppCompatActivity, private val previewView: PreviewView, + private val mediaSoundHelper: MediaSoundHelper, private val mediaOutputHelper: MediaOutputHelper, private val cameraErrorHandler: CameraErrorHandler, private val listener: CameraXPreviewListener, @@ -49,14 +50,12 @@ class CameraXPreview( private const val AF_SIZE = 1.0f / 6.0f private const val AE_SIZE = AF_SIZE * 1.5f private const val CAMERA_MODE_SWITCH_WAIT_TIME = 500L - private const val TOGGLE_FLASH_DELAY = 700L } private val config = activity.config private val contentResolver = activity.contentResolver private val mainExecutor = ContextCompat.getMainExecutor(activity) private val displayManager = activity.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager - private val mediaSoundHelper = MediaSoundHelper(activity) private val windowMetricsCalculator = WindowMetricsCalculator.getOrCreate() private val videoQualityManager = VideoQualityManager(activity) private val imageQualityManager = ImageQualityManager(activity) @@ -123,7 +122,6 @@ class CameraXPreview( init { bindToLifeCycle() - mediaSoundHelper.loadSounds() } private fun bindToLifeCycle() { @@ -354,11 +352,6 @@ class CameraXPreview( orientationEventListener.disable() } - override fun onDestroy(owner: LifecycleOwner) { - super.onDestroy(owner) - mediaSoundHelper.release() - } - override fun isInPhotoMode(): Boolean { return isPhotoCapture } diff --git a/app/src/main/res/raw/beep.mp3 b/app/src/main/res/raw/beep.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..e0d6cc314882ba65069df59bedf7a914429a9b23 GIT binary patch literal 2522 zcmdUxdo(SfUAJLIhM7+BX>~ktHy!oLwYl3l;#Y@Y6Ao zp~sm~SnA0D7S<`yF_gs$jsfDeZ05J6{|(Pj)^UlhAQ?yiHUU8S4r$+G{(FeOhh(pV zbgGjL!Ne4T5D))!Zw0H5c$*Gjv)}xPBHqgUQ}}8X;s%9RPy>A%6czmV9u7loY9(7(&dS4BdPH{@Hdc>l)3|?vY$s&JB{^ zZ$J?*jfSXG&Fif%KoCGc031pSZNfAbW=GkddBIK|S~q$o*&vMzB@I*+@ZsIB#P zzuAnN5e`KDh5g5$%FWr@>a{xm@G+md=Ys3Rla~P$Ed6{|M3YKCe&Ke)Yp3*HX178X zt+8$We#`s}BPvfY@oJN;Fe_|o?S2Y3iTriuoy7zITc228UmwH-nkMnJ{krn1kt~1oItRcIA`xLU|79ju=a3Q!r9RcD%v9TsK*DkcuJ^y*wp?)uvm$$W(x-sEy z@V+-rwN|dYPh_f^+3@`otKYp>@ROd-yw3Kxeh)q@>|SpI1}iemYx~W@^wyWDBsll;^+5+heWl%D22D##K!I(m%L(~ z@*VT*pYCg|4}>in6shkqLJADi5R`Zrpy#LdAnna6P#IJlst(p8b;oGLw=D0K4tE{KBr+sN)sp(Y0bbiFg zX5mejtIAR*-Sv_#(Y4rv`)8*A z;=E6ggm%ZfEp#Uz6m49L{xE+gA*hOfz_%1g)sER)zU!?n&ShjcM7ycBhiusyzt44` z=C95858YUN$g<%VQM*WVsWxEXM1`u?h@-Ld#8iP%$ZlGFj_nQsnt$(C6<3#0n&}Z_ zh4i*}SYphj;9Ljl;9i9*@3SA{9ChSQH4?5n^9t)~jw$t(>L1bcIBenZ(S~4|>GD(h z1YcOY7e-+A>gig{R4pSzfFfMVJ7UtkLWr#J7^Js04sFWR*# zsSkzObB#I_0Hi)nPH+~5E#b2+a*(2|Nj#V5t)|cQM9U-TnrOO(H$9Xy=p0QKWMOAZ z7v#%r*Sq#x(bYQYIws`Oq`Ao$@RA~5ck=mYYWQmIZ$@)gEw|RY8J5Jiay zSiHZdoGLRf_30j*bm#Np(<0X5Q6om?kke@DLL>%bO3<*Mvv1KCF7Wk#EZUorrGI@z z;h_VSWH#a*MkVDDaG9)xTT%0llnoW;-_V*~UmWz$2hW!quoG~S9DU$U`t~0xCmsDN zdQ1a=_=*6dAe7)RF4pDY0c;?&1xA4T?}F4&mz0M+A)JC9giKdP5u6FBP^4m(aZe>t zS!fNt=AI*%s;ojiodu?0G^}Y=XC`Dwp?0pu=OZA0glwyT3zrpGgT>3R3hkl0>KRC& zYjzXqubB?C01KFbyXtecwR!uzaqwiR z%7N`LmbcISSM%$HG4^6)cYc-+e^;7quq&Ba6*IkLDZ0QBbyGgzQECcd1~Z>;SE~13 zFQ4(k^Caig;-p_r&Hx~!t#K~<3FC$+Kxj6sU%UdrLXIM~`O_aMDcGA0Xn4ERkV?9# zRa3RwxfvY=_E%NA;BTy*FZYr0P2uvcKODuACu;hdpSi(11U22=C-x6LI~M7&LDI@8 z*+~(vF_wo;$Ma z6<1Nv(yJZpL{~;9CDi!rGvLU(M*->j1^_Jk=sRa}Is7i}I_F>g#6PC%fzChY8^!1U S-ACN{PZ(4?Nu>T~i2nem2fLF1 literal 0 HcmV?d00001 diff --git a/app/src/main/res/raw/beep_2_secs.mp3 b/app/src/main/res/raw/beep_2_secs.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..03fb66bbff27b5c4114142e48b8ec2102355dc7d GIT binary patch literal 25983 zcmeFZ2UJtt)-JqK2@o*!AjQy&l+XkbB~+Au%{15DyZ*Ce>*;%jeti%9O9sHr z7ND@~_`Q7m0)qPpLL$-%DhE{6)DEg2I;^W}c--9F!qUq6gpIwkhnKg{SzkZ@bLTHy zxe^`~9TR&!Atm!}_Pw0kyyC|-wNL8m8>!SzT5n(fz?=7zpTA5^&n)~{-`v{Xfgt*` z%uKXQ^_1ikh(u%q{q(P-LJ&opCIZ;RZarGpSy2D@{r|HEXtTx@z?K0Br2v4TH!?j7 zL)KgK)T{su3vdpn03;SaNy1QekjHm$?UyT?O>#xi5i!4=ks@-~6P?6JoijucS*+%c z87|f?ITk|+#+=`YrP5mjjtS#~w=;#A9O3oT2{$U@VyNrDvr}M9%pO#NBHH=Y?bae3 z@bQ=Z%_6yHK&3CDO+KbdnL>sqBzJ~Iwm5Cp9t-bdcY;fNDV^wDz{ zr-o-j0C!18il)No(BhfOuOFIow%RoM*K>C8aKO86vS$Y=nY#~?Taf15?NUi4zuUFf zsRIN6uy9hEK8S`>Abu?!#6SY^ItrJ|i^n4x04M$`d?frPDl4Vr5^Rrv!@e#&XCk)s zO80X~{;o+TDy{YYyN)*~Ogpcp2K5W#jje(XFaxa`Zh90m>s(9F^~F9t1rU(Wjn0vrycbUDUe7{~?v zUL7`OG(+s^TA6RwrOK&kH)9vxOYHq{wcs^nCQLO5nmOqA?? zv6K=PX{)b~@8fK}ZLfaU37pZ@y01Bi(@IA-8B`w^T@${n`XS?`sMQmNdDCz`!SwzT zlaPHc(+dhOKlXSiW;?qU|H@({RR0F<;>^@MN4iHr;D}vz-^Y8a2NdUQJ~i0h>%X8d zT)t?pr(k))zxnuKm-2YEmuGj*FLjL7M)d}S8oT$>Ao-o(F-5j3Z#Zs_GnOIsS=#sdn>565 zPivgkmWbxhts!F(?r@4WKZ97I*$Leha|pVWZX+{OQhlXoxy^Cx;P!sD+atlm7R!C3 zr<~VM$4os6U0f{-c)2!{y~lSgGnhFsqUmLA|K{)0W8Q+!y>mH9PJWA1e$e{n*m8&0 zhcu*&LMbCFi(1kd$DvW{FQq_Y(~u8`x{@EqS{C(_RZW55UbdF~#h11%L~y<4kBwm} zDk}5waa2~7S9g!)l|mgPtv@gwOrMS|^y6<$IpU^z!7;$q+w^j(@BC}GD#l_i;Tdzg zEUu7ZBc&sSmPNg(hHICti%TrB#ob+5N4Ufn%eqSLiKy)8kCb+L|432Z|IO;#K`fyY zi}^v`_V*&Z#4U+jG8e4`QF?JuIz{J=FdIU&Os{I$Qk5FA-LQp&75q z+lTC`?nc(F+Ezurb%2R~;YXvn%@1GY@6I=!vQ(!CLLTq;6?b@ar!^!;#i`*?cYmTv z;l0MX7&`FzQ^Zp zC$7vUoEY+ZGkk6HGUbQI&{G)N`apZ<69!Zqw~X6!rqaC}oW@7T4%#~2ZoR`ZIQ{s% zi@3Z=N0&>Rww(HuufgX}6kYs=bxF4ieK`H7tT~b*vY!dTdBv5Ga6O3=DXWaAQ~xc0UO()gVueaEIVa$ z`~hPJ=4UqVbXLhhJ2qZ!=O3;Fm#(ll-_{iTd_!rtYHTgNWudEbQGIbe+SXx7?%meo zna$240jsCpuB~qOWT)n~>O4FSSkTWq1$BPdWZuL9M(B`D?Cc50T4r)NCkMLC(=QDLHFBD{l3sD2Z_9|?;f^5V^yZ(<}f*eS(P__XYl z(wmg!myz{CVP;DB-*?$^y3N<4r#TH%m=(!YdirRxP##V-fr+HTxz8Ov0Dq8+#=}Sm zJbSJ{`lZi-UZ!{i1>j*+20S3a@qmJ8GBepHoYt9TK!QhA5McnWAEiz|?9o!{qokEw z7;m0b-IZ@M0L7f@hJKyzTmupv^YebdgwHn-;wUQgq`Yi}L0hPp6 zJ3%ebjKzUMk7&m8v9TWRRQfaM>e>J&=R8gf++Z{v?-n|$hitQ|3;$%ZXsY3I%9Tv~ z7PfQS*=FChZ(l-asILHY8M2f1?U?Nq=}05j2oJV&L+Bgatk5u1^sRpqC+q)p`mfyk zKcfBLvewY1uIncN8)Y}Sb{fDr!ZN-*&j277f#nB)fTIZM(D~c{*ld4$j*0$o%pWi; z?f-5n(T_Swfv!bep9nNHl46Ss$YwT>(sih{crfUesCJ&01AJ=+Iq#`M;Qwz5KKwB^4>|SV-({=I&om_g-Z=m1BLZHun`X`@$ zO3x}&06?B$U`mR~u(f-bEwHj8X?0d64QP<`)x`r0+6PZu(0D=M(4Ych?(MY&OU0f& zvoRB0Y7RtQh9L>f0Iom5mmub|qh5ygx*{x$EmD`F3Bk8h7d75ku_Gk2LO6^$U5 z2_Ru%BzmDnqYp1j{t5m^<5?H?(2Q{?QFBX_aM0Z8IjK7)*klL?)nelb;aLe}a$XKrDM4t;Uc7i28h~r)ux>B6SW@ScoC4 zpKrejL!iQxDij~Jsv{VP9|=TM7#v|yD2r1d!cQYGYJY-{n;;64G!Zae7?CJSJcdTaSRNKUZ|{|Wx@P7Wk7Mv{qw zRusAN3hC^EkkLD;oUNvjA$-lX(Dco@kf6rYMzp(|Uhx~+ldail*8$f+EcRw--A~TH z!{4E|C;G}E3**!U-EwPfn>e3#F zF@}4HTUELX!ayR??2ftH^FCQcsT~LT7i*#4QKK(#062;ER=mTas_t%jA1QH5(v>X^7iWzT(&5kHr?2lP#N-F;ius)^#$4&&v<&>a}GGLo0>0 zbNLI-FS2`_rV-90OV<&!I0_!!i(e!A%%_(}{?U0X^ zTcLv1Gmz$$!ZC|G0y{I!(52{5T6NQA87F?Jd*M<>fdY)DEWKV_wv~-dMA1e@h9Z-A zo}3_iM&-cCCGG6bWHqvuBH@Jm%@e0BzE_^_sZ7Ck=vkzA_F}CZ6#_au^K_3s5YbWb zD*7Zdo2}n<@Pl|nqrOD3c;0Lq*CB#yZC<_v_u>OpVwJICZoKzct+$FJkEv=%Zns2k zbzw1|dzRQ*sEKt}eGt9BS5ic!7L_Ep8e^&O`-Nyc0l|hz&xmz9Cx($MdY97s%xBdZ z%bXmFl|rgvpmy(i{=Mrt~5(9j_3fHN2qG3lq z1jx7wSUf&*&Zv2-{bTLG{hq*a)Z~PJXKhsa)gHm{yj$G&#y1}a9yIi$efSdHlsPtP zKb3m0^F5h|_m^%LEzIj~eGv(GZ@p4hc?jck9Fp|AZNZ;#R-WogxRgG&DsCM<@pLux zkzx5@u`i@d``Gx+DI>UCz{;r(-d4UaI>>q#y@ovWim~?cM8Qz8(~q6t(Q95l;X}Qy zeQG0Evcg5h%A?0}BT#KFT^r(68BTrE@A{c8Trq(WJpchiUwhh05*`!}chfKgh5Pt{ z<2wAGSjrwDL?i8hj9%taA+>TfJMtb!=VK%%}wiN*LAJ={JS=jN7~ zQRrKfaz@dlH7HrhB9q%XDA-^cD2e+6puFP zsxp~1w|H$|ZXg~d?wINO@G_5SN_nP-M8P-XgL*s`7|~g=lMGf35pt>hSK>UX-F8I^ zQngNrN}-FC3L&=ei$^mq#as_tmdk)4Q{%{y=xA)NFPx}^7>Fclvv6RR&D9Hdbr>w< z56WmpzzHr2!QwiYUso()za?KYP2Lhw`69Oht6_^knc#9Oc;X+>SjnsjfCw!3`578L zip!LO)-d2Ml^>`zpkV}rMh=<)YgSm0eDH7{dzR4)TN^`>mGb%pxdU~l z1xnnauR5exvrnHK=5M%nf>@lr;dSZ<~hA!X8%ZY4u$}xupp`?b$c3xm=v{ zA98bzpV+ss)aC>QHw4Q=9cylOdL$%3VqPr#jNX0q=t$2wg{@N(2ZUz>Ed8ylS)1Dp z88X&dnfKYT3T*j6q0q_Urt!W`{|`!`=Sz=a_vAD-yb2avOUHTMmG}yQMCivu-SNe5 zkvaAw@_JeIUknLy}=CI94vCI9vGUnsk4x7-E{DK;iMAzvtV`HYWgt~gY? zo@izQz?h;%Qkjy$zg6JBfdBuCvOsDt(A~sg<@mUsN_K0kv?>R-0x}27gR|NO-x8l5 zZ=1;fczr}@U(pvveDuCpp-3V21y=PVDD6mnpRjZ${=%j}d0N9&86Ar#CPLS{>-V{B z!`TYq`N6rKbUvW_d6!Ry#?VJSf`l=f_%}YOCuUvo>D2YAhAwAQDJdCesMmHV$vLbG z^J@Ge2-^@ir@46C^nzz{3KrZ#`ww%{XD|SAz#Wk*p8R)w<6rq|G?)+%7lBdyu!slD z&R2=60ukbat!%KcFp5}aU+&0FJQjbSRqF0nFT7gvxms6`uov!HRF{a4TarQRv_Sy69&V=^a4--fTS%iDT>$S%r*5g7$prfc?ufUy z)K$wrM;PD!z_KT4QtV1q%;jivw(}Rp`qv*3^aTG7|6loJVviKh_-1y%%lWI%9qN_Y z3=s&ZXHN?xZS8jtf?oK^=28JXMC>fOqbX~G2ZNo<6L7oshJKn1oJ++}X}bjo zZA-a_Rtz9-Ebc(J_B#&Stu4PCQ?5*S41N9$t!)0D>79ADB47UaZGehg2PVKq#6)wD z?=>b+UdflNq%9bJq_LQPvS3Sa#0@zhK5^-K{ghz7;-rkbugAq(diSzL2Z$;LlksOb zOqEAqZUu&O)*KYW1v zb}v<cB>FnAe9_#mu*w z<@Ro0{WM}3+~o0PkLr`*;L9fq8y9M`gBKR~Zj{JMvZ|drOUb0TOKp0s2vGoHTls8U z{j-7Z-nZ1nMZ?oYq}|xT6XY5j29F(y_Kq^d3Q`^VEBbn6Td|yCk)%FdB$9-F%p0;~ z=zvW32+R~o(P#IVQ?I`Bxe|Yox)$|`_l4fbJBL^)zdKJnZb#SGX5SS%HfVACUfhlp zgXQHnALJj`4%_1oPy+9~H^VV^3H*E{ecx!S{4BO{slMW6TO)Z=$HRc(%rY~ENW|#^ z;{A^=i!IX{OvY&?&p)&m+dj7)t8Qo&yEEwQOOg#AY6p`0_)Z*Iw%Pn~gi z{-W1ze5Nk?MwRAU$p3MZ-Ar_4>Dtb=_pq!@xyx|Hw%;wE)1%I^Tb_%-O~Y!A4Yz0^ z0am~L=I26V6nZXidkr7D9dM_!aauDwX>Psr>hlV-qC4|`oUYTxM>gz5c+Uu&`O3`7 zZ2n_HkNZ9NJ&FSrXk?Q6{)Z8AXbjy>tGf`XE3DVM*`ucx8{7TZuPcb_u%^N)eLZqa zczUPKABj_U~O z!r#D25~dE-B0IxF7aouR;JWbMk}g^Rs}WxN)4Tk>R zS-wN#?rp24!ittQUh?ERu}oOX7CXj+D+01O2Ul~ z#A9HShzA;UHx`RZSK1;Qm5QJt0dq8kG0mu4)pda4S}9p62{W3fvI4eTO)?24{&4-? z&j&*?zArevq(2$R9m-sS_!X9jn{O9aE@&=K(KNp=+Ui#9eC%w>ZM$23+yCv<c$sB~VD<{rac__^{d+|=5|Hlh=GWjwYz8Uhc zV52G=It-J|JP3w2s+bZtW{GXObH&OhOOnmkEX(&bGi5g>yWM|V`s=6Dsqp!o8n0`M zy+e-*WN)+xcb|^OQ(0gGCio^DdJX7_f+S}#bKO}ab7GXhfIR?3%e)q&L|1vfd%zM@aSYnxyMBYEee_m@LH9OEz>+0NR+)~ewasGV&g6a{u$+2$z9Er z_8)Y3aAc!?@$s^*a^;?#e#omvjS7HB>u)|gZ8OSljhU`$)H`G#2XXA24Y*@m&DTFM zo?0bwIs%Cuaa@^^!w`w&;hmt74AW2Evt{zUDwU!WMv{E}v~o)N56R&l-u7?&arcM+ zTlRm_EHHLKaMhcxuXP9aET^&Rb|T3b_WK?g6B)bq$$#Yo-|z;TQdxeje3Pjh+=`U04hI@_9yt& z$E}{%U`<#k{@aMeBqD}1RmV+Zf%{Ms(AwbeJ4GJW0StkOaxgqs3C{sA0}RdOcA!swdiPw?@*^+#9$pmL^kTlIZu$<{x0N~kLs^QLN=?`7EY$C}Dl zmtJk|d@|j*{qasWiIwy6FKg)Ai^fcWI;Yovf^Qy~v^fO58I`7#L2=T(oe^}u;_7}`{*$zsuham z*{?`1lyt2;cGtfU1ulbcpE?aNdnlNUTmTaovZwpS*kRi2Goi#P(jB~dP__lbP17S} zpNrp9q{Q2cJ(G_$UI-dZIhkHI*j4tfbwo7V*gliJ)L6?ax5mQkwfa1PTzTc_t#g3AMk(+55Typ1I) zYHbjoqK_v*{E3dr#Bb6cc;A8=xDApJssp+=DKA%dPjBh zW9RXY8yBTff)bmI>nuURs>gB>t4-a=Li+rzas7-$iCY{C^`&A0k6vn-mw|E09#UA? z_PswPCEgsBCFABiWLH8wZ%)uH8gy?hzFTaUaBHj2LqDcg+}c|GONO6`aZ{1=;*#sh z_4kEcTtdn3Kiq00d3>(qNWL6F4vXS-i)QISTR%`+ui8<++OS}pcBm!8LG{r<0(Vel z>Kz-tv;dye%wIn~<)_^5HN8{(008DsH$|nYLQm)z$ZCZXst8_`=XGo#Zj69ydrGBh zVcA|>q^2>`fP@2If%A=RodsLhz4B^B5nL86y*Y|R z*86!p`-<`h-zJ-@^!RI=f6YoT=5-*Ms4Ev<{`Be5zN5z^o+&pb)$&aiC+_u=MYx3f zQ$EQDfB9W-%33`aww>RnuqMc38k5SBjXBB)4@yCGjSy5!_t>A4gP%S;WXbh9?8)_2 zzj*K0HqkE!8z0$Bx9YSg99~?suDe_GJU1*l<05Z2Z*hL(htbDR%QQ#NR@a>SX2Ovy8?$E9C*DnJ`} zXfa0Rg`Id}f$U3M`henofF-Q*a?k-uF8h<~ zzX2z+&(i0sp_{`JPog~hg<5WHF{G{bdVZgk8b%5gWyOvh3G%u!x3@!~#p`!dZ*lWn z=(J#6nOAkU&vXm-9ot`h<#Rsv(D&lU+siAewci~sPcP4w&GGfgt6Y_MbS6Fc>NeBE z-@ag()qmvbZ!5aP1kky+z7*Bh2y~z(WG!ALWwdA9#I1*!X=Lz4JPj4WR46G(>pnmN zE@C2E(QD#?i&v^uCms@mSWaWi5Elrk!mkn(PO=6t;V47`%+P9-;j(isvXF=JoIH(q zLE@GRIKHH2f)Phh&^Y7^fJei)shgJF;w{j&@!gKB52U0=tI%V*&Zu=s-=6n_)V%uX zPJFKlMlxnX&icLCGI_U-@Mi&8qa+OLjc9=c7Ct7c!}g9v3wznD=g0tkWxJ&IiM=VK zuvD61%BoqoP`2G;i=Aq-YEBYAfOam}8st7Q)(ZM3Vf$N`?Y~|4e^BI~82<;Ag*F3S ze^XGBQWiTQ-9Sw1rC(bt0g1Ha&~T+l(qjj2hm%qNtoQ#a^MBBL{e4xdNyHEt99_x|+8Lo7VY z3QTWs+FwHsfoRV*-}IIM|DQ9O_yUpjh$>fr15JlYxEWbgp z@K5~z#9trQ#zY~IWq%Vhfa3&(je*7?Z^F$&6;J*uO^y|I`I_K9De0`J9onDN)lI^6 zNirsQ>tAV0J<{9PCiN%y=cK!k1k(r*b}M6w!91d9Z-y|%`?~WsQ3Xb%7!a9(5(39U z+zZp*uqr+n6-H)0#--%=ZSql`ONsKI;Nv`yp%AqFRP`Qf>6uE)ee?;vo8Brd*0%hW zqtnDEoDW0omr2&p?2Poq>bM2*un9CE1A5%!|2m!_{wQ6g0T?YKWYviJeP)^NX_!(DQpm#H_d7;pz zLl%kuAhdlp`9rB0-5x$VZYx|m!VyW(CZZ@I)x%oI5{xQXZ}5f(r)SNQn-Pw=&X zzd&Y(4%@BYgZR^t=8=;0n5^@Cj>Msi;R``&^fop+tz1J-wLZf=GEJkQQ>jkPMb&L2tk8IO6$D3Rh5^A@0EPD>oiluxkYVA;S zKkqcH?&PFFzP0w&svm>=915D;W8_XQs-AzGKG|P6-u55-6SjeGKdVWPCZXbkasl8G zosw!82e8xm9uP6t%pU5`DVy85`gUf_*}E>-haP<)IR38vR4v~|g?m_fhNRaC$2(ES zFEl@`ua}L{TU|AUPSU#^nug?a-`d^V7_yJ!DnFGhzl2a&yKC+I#QU&oSdNO6Kn!PC zEZdTX!26T>p`~6ds^xxc=jKd4*uFU!w6*}R+gPXE)DbhF2)<(y4s7PUee};q=aPaPBkW0*Ixrf^XL~VHPh9FCDarHs)4}&;QTulJ z=MEC(ZP6F%N5uqpU2mD!fN^E&$j`5zoqR4;*c{0!QyYIxKTfuZxi66Vy^fO0v6oiI zY@n8MlxT3PPc%4E)J356&FQ3bbq}YQm@R4FMUPG&TTiH$(Eq5NfhK-!qn1 zG-jNRI2TUl$-q%=Qp~{p>K^5tp71(a!((5WX;YnR$@hq;6qxULTDA2xwG#E3_1lft zqn1i;VHvX>eAG$rO_LOb2E`YD-9599-N7I*yP$3)+M%buC(lA{?aR%+7Y-k#DCpns z-|wr3r%P65oFhtJ^!TdCYZdL%%;QU%U~b z$Ch-5p609@r1Dx_b91JYT+nt>0FrG41ria1Sk4{;RG$i7il;6ZX0)+Ccbo^MoS6?6-_pt zHJ7fr9$NIihTFHhoJFN-1ntV^*@kNPBByV+M>}OyjF4!OlOH~9ydBsTS7M5YQ?fri z?3LBao1($1v@TV2hd#-EoOmU2{+EA&kB^lU=SkaoQ%Gf1Zou&2eqJ!8xi!_wQ4LSw#zWDv3zq1se&2O1zU?R$(|(Ku1DE zfgVZ0WR^>yjhjKqsPBl zm=@l7Q_ysxw&Ba*6ceyuOvPRcPLAtv1j!8GwRgQBg3i=H>lG=QUb_Rei-QW*_vjR| zPDG!+0Nfdcl*ze*LjG7H4=e&x6{dc{AOcPeRCv69f{eNaY_STR2SC3giw~Az*&MXS zAP4yJ#mVF-ki6U8xugC}$Sd-(E@u9)h%_CNB!Wm}1f1wD1n`HMb&*CM7?G3#2@jh9 zQA6@rc(V!;RHmALFEd2 z`OwJ{%jP2_3*Bejs8WUFdDBVpRV~}s#-R~zC%UoIyj&iFhVmYKnuLge;YNZdyZkRO4Z+22{C#a3t zeVijkp2eQN#?__&tp9()Z@aDKxw#K~Z89$|skz|%-eyBjs(R$uwAB2&^5ceS&(hcS zd-I*|>Qjv8tR8$gntJm7t?duomkbX%Nx8P~;(z%oK7m5#WB>5~f-(elxAXtOf0EvM z+m7~~_PWieoR@m&{Jjf>n-+dgG;^XiH)eKt0~%&>0;Yp=+}~LB&_jBGFSM7bZc#@3 zD;hqmIJLVzqQ@&%;oEu-PXG)FzZS$rCoLwOP(pjvD>u^b8r`ohZ0tQ_)z%$CC#!&xULzu=ynV`y`NffMuvXu+#)9`&W z#8SWMV)@V6_6{@OI@bDv?UeT858t|!zNXg{wfJb?%TmHwr-)I#sXR9 z``PlfPn}%zc|B(Gq&4(XTvhi<-?(t?*~%B*R#vuIr{r!|2o)1v+!Xy>=y3Xse#NYi zs^ZE#Q`ec+ZoVJCK5yHavh^ZLD@yd-X{~TgE4$E{kka_ZbUJCBt9^2)XwJeT&P>~j zEi7GShselO)Ma*8*p;e5#3GRXt+~83CB&82Lj|T6BV5}=_h8v6R@5s14y*}x4B#TR z`!6Vav)-ys`&F3p%I_)5P0D!IFV3g~Z)MD4MuaWzT(4r#(-XF3Q4I77IguYFEOKMi zyMFf0^w`AyQ?vZRHs3AB4sYzM7D-LOT0A|&@u>Bg;dbM+$y~znMKDX=HbAB-cf+xU}fd+|4ISkD0s*7VW*n zolj4FVuj1+9g$&-P0m;^u1&uaY4?_d501Z{SqINpySX0w`$UFWM16%AU1w9xkf~vf z61rcGy&dV4Hdr`pQmnGR#CmOSr`-;F&+6ntKpp{wC%S-;F;2TmzhedEkGD4F}*{Nm$*85QH@Wozoc489Dub=+llAj+N#{DZWdbIi4HJ3 z(ILiut5n&o|CIX)HNXuX`JK`86iq>&@y@%G@7_6RadhCo8HJNcnJC@E)ww|r`x*`3 zkmu7Tue#3`?*>v1Uqy0XZ^v?&4=Y&8d>S3hcvUR7cDy;gz*|2)ue&^3A}B*V5uqAB zxs>;QngW3SlleTlm;lH`GR2HYe1z4#PTYfxfRWjW5iAoVkl_t)4O8PqX#J+*Y>y=gFLa#0AJWa2*Gplh_Wj zi9dbj$Q|M*NOQSyJ-Xk%1~WZ*?|XUr`p4zY6SFFbJMWJ6VpZLAG+yD=>P_omX=&ufdA2z|BPwnPrgxyg| zt}Ehp)XDegWvr)6is;C-^m6u!p20v5cD+vxI5CG>c;(_5{~}@KiTC!>lB6*Gecjxzx$M7$-d54a3t+G zmqrJm+sA}?BFU(Kd&YkO|KG~u1R($gLYq&+`>x6GXeo=O%Gf%=UDVQ#JJ`aIuf{o2 z$It#IARNy?pZu>JsaewDW+A^}G1Y|a_78f=G46E+LB~oaA8L%|G@j3 zt@O0r1Hv``%0cxQ5qNYviMacuH8!PptsK<*M?QreITQ9`ybM~&p|81S-{;b=>YT7m zrQZXPYQun^+bdTXvIA@ASe3q0_r?2$#;gc6}TK@ z63Fe{&>ncn1nU|S$uXhQ^}FuWKlM8U0Yi^8htWUzba=u)_Op~T(8hiQPINM0GFsn) zX5yF-MInM>!3qm(HG-iYJvV_3z_~VJ7{L`Xn!?EmSQzKH2G{|wlbE&3pYRiahy|QD zx*k10AR_uKPS#W8?dcDfM?Zc)=lsqkNBG^)<5A1g9~;)!vWqu5@3w_(2k`MN)`rxi z2z=i76Z~Xvpc&PLH+RE{CDMI_;!X@dqNM2~uYM1{QvFqv`reKh{7_(deV|jYx;QBKh zDG?)D&1wd`4~!n3+u1sCd!V+~oiwo(!AxMOj{S`I{`+*jWFu)UF6tXJ}acxh+ zfmik%(*bDb_m+xfqhm(dQgk4vhG1^NXY=Y_U9D3H(MC(rUH)hTX^N1L&roAUPk}ME)MMHe%I#~cJ+in=&0<@IVdq_ z^{)H-7v7gc=1z9B(0+$~f9mzFuchu^Eo;6qVjoNlYPt8~H+;YkO)I9^wl}ugQqy6*5NmYG)g}etH zX1|t=pB?z3`@!GY`i6UOKw{uw7KQn$A0>AE*`lSsnD6I~sJUk@sS+U?8 ztVkn?9R8&ov&CMP(4cA`&P&o3sH$}++w=1Bk(#>cpUWHeFm zs+XzKnr<$mmND)Pmg!gq^=nFmRI~!-*Aqday1b=G+J^8(t$d93x1R&O)julF%d-Zn zE&O1+wC)-L-*Y|j?IXF#ms<;G_q>iPk&2c<;t@$#*oh|Aqw#2PpE7}#`YNO)oPK_5e(JbiP;GEd$kVr)Pn3oi zUoJU>t&Bmz(kpwGR3m#wm+HzVPZfO7cnsa!+Ys`jaQO=P|#|?$I5s(y6quphA{`py>DB{;zu$#{j)sf=%%byV#ytisQbj`S01zJLgwj( zg#)i!T>kPeFGM0&?0Q0SEQ9sB=3nmt0W;2pn`3W@R#Lzp_x&U z!YCI(vm>Ur+1<~RZ1^1pmDACLR;7Oqj`14vji!8O--w))YWBf>WqxKo?aKMEy(| zrN_K*5z$mOHVVcXma7YHQceL5)x@?w11cyoi%yiSJ4=I2u+Zp%Uq)16B0a{F2qW#i zZcuyc$lG*|hPT}h>&go8F{6*>G#71Gu>R$}j`;<2c4_ATU7Hd=XgR())IbZ}?{q_{ zXK4uveq{G@3HsFmIYQ8wUFgo@+RoHc-!xR`H(DMFT{?Anq;>X|9$mWtg%eKCswngf zUv~#)PxnuwG%?odLD@6EjEmSO-vM^5wmfc;Rl={coWpq=bEkDVu%|q_iZq|j)-RA= zymHq&Rx8_#@aGL^p__c5R~*ly_h_q6Lp%H>!0FkJMW))h9hQh@^oYU`jD ztlk60-XAim{~d1gzf%^lTS}AnjX|TEzYOgbkS+0XL)PZqv+7NU z^doInUdw;7R9gAXwqMaw%Zf{Xxy6j$adi7f3#zSO2EX&*^YfV|cZIzfO)zKA5|}|C z`$3-+ZGPO;UUXDg&%{$3GC>-n8^yrz*nM@jbWp5sV0dvZVC~t;uj02M4KA{qBm&Mt zloR}XN_ZJ<;b`+rM)ei6zDtsJEY3ur=uaXthz+JwcAr_V52uJr!wNCvC!8PvLH1(> zD@+5)@(q-)2Qs7(nUO^43=0%vMzKwXalCWQ59bVc{K1zWv|-6x2L|v3T86Ol6#D^Q z8;TdSDXKekW7!0>718Y*%=a&504YnlJ?dZiPgp)1M-e{O86OtT&2o`$=i~)AW&-&Z zMFU3FhMB=h)NhDn`D7M=M8h-ae|I86@j(Lul0e2%;M`ahGiIPJlI)W#4d_v_1URY* zPUlyD$1DEzxfCSGMFB}XhL{`v3C>KsxKH~fvy*hOgck6n#a}s?zGoy%%MJ=;~_Fqbp*dxn@ zpw${tk7cP4rcn9l93K!6R4N{DS~5_E+P_P@GUO5-`LVgL@lA@PlDLpmQ)2Z2Ek5Zt z1DDgHT{BbU+OeGKDMC$(?p!4lcsjoQFFbMa@}QddRvR0N;-k%BS--mJ z8wa^V26+!3P9`8vJ+ z2f`xeU5;8x-bCrh3T|$pkl1SvT$(kX%dzTy zn5JIJD;M-({2bY~K0nY@oxkHurc#!GdG<%u=2|1k!m-)Hh_8b~skX05iIbmej`yBk zT#tX>^Tes$cv3y*$$`A`?aQM@b*S0}_VX}K?P@!-uLRV!U-{8%M=B;hC0}pF3I{XQ z8kv{VuG!vwW3(!DW<<8MaVB8thvTEQ<~Est2CW!buko1>CfV1gG6*6$my@E;FeULv zmfoB^UG%G3%+49bFLHOV$!OibYVm?=;QPSlhe2<&PKxedQjg(efN^a@(=&=(5|7&7 zEt-V!@|hFri-0zRjoU|Iz|*WVm_Vh9Fsfm%lQcvJI=6ayP3F@+P!40o;Qmw!8;zah zLsfIehI)sO zoR2*D3m3~CK0=-AD_3j76#4vfi7AHeg=cPRiJOYM4ru9Lipr*0n)=+5YBxLfwd%=9 zX``OA$^zM{fknl`Gn`q&wMAq7_b-Vh)5Q)uCVJ;&3X<*;Ixt@3rExo>6~`~2fLE8+ zVf0rfYQRo2P&|li%+&;?I27=_+v=AgzvtYO#R*tug^mHdng)^AoBs44od75&f9V_SKl7u57DHH^PA3i}81d0-= zk~f^Ug++*Y2VLL8pIJ=6!yG5>PDF>|p0_0dRU zPf?xgb327Z+0BsRUq2d=JY;2T#7*zeFOQ)&9BRj*;U5gYMjNsu0l2pX7`oETGTLgbA1~6Nfz#OSAY{_5gEJUuthmanp(PbipRxf@!;8 zNba+-akupWb$YnOQ=hfKCzsN#iyN5pswT`%h`&Gqm@UllD}b$rS9nyYh($N*KD=}; z?BQPo2r0=>v^PS}DK;j$URgjCfS0fi^+HagB22nqaFM#0-ak0ZF7Mi)F!(w4(B&u2 zNmr`B^9v4pB~@WN0Z2Mf#Omn0i%9(YD5Sr=@=uQRw|D&gh266BtL$-)l7C;~_{}gm zu)&-a-UB}(b1tX4xa(kgzwmv1*{}I=@8{=keyZ%>+AoYj2%dp7=NN`Ey~2talQS`q zV-ym-U*VW^4K|9w!KBn8GEvj+qzR>+D5hyALn$nKGstNtL7dlrE_wCrx2?AnQX+zNM510q^ z-7>)tP80eaS|jxwNWy_A+<=MBKIk@k%zta=+T)q--~M+;r^TE{XpU_qS&WEGmYgHx zoMlKza>$`#LrWvaltTw;=3FEdbu&ala!RFWN)m-a>Sp$Q_4~b^*Zn;A?|zhHG2#feCkksZRQUg(wQ=tR6?#0L}x0&Cn+fF@ncye z&`BRC?REr^z&)_4a*bX{$Ss7p(Mb}yC>XOtJ01~^%oy61ybcD35QuN~njx{S`WVHz zZPlc`Fm$L=wax*lAedw&EL3}VxCI8K$Z@oTIB1a=fQ#b%tUG-bn~MU>)^L}2b7?dH z69RG3AMryz6axbwl3Wagvi&L%0fb1Pe{xFUV&q`#?liEg*Ib%}g=Ea30Ku&pwCf!= zkp^39N_|^IGD`jmpZpPDT~>7vLIyB1oK^5JksJ4ki0ig_YA*u<*tJ%Xze#!@2#S!5 zODHqhH{8Q3CHl8~R>jBNO?o=CV0j;m?=SGCz%htGcQYxkUeU+4Yrii(4faj7JML&9T0=SJO?xs_;o3(0k7*j@a<+PtHV2S!l9#gi)(F#85G)%{M@;hKJ2a0iCdk=LS(t0qQG*4MMCfZTj0OG!BPIpPWq8LcXb zAbjqkh&U7X%QeS)4bay6=y|DM*&S$6?>Etb_07YD1a#zdU)U?Bq~lmb>>gyka<(Em zvH}^C75iSYyL=Tb3ZnuodZVf;+!D3!aOXjwoiQ3{KQXCCf#TV2u3`Q?+WsP>Zi)t+ zOG1gzgpD+JT!eaTFg#n#JX|8}HTT>pD!3w=<}Y#Qb(d&FY(Y^&WmUH1k^4!7GmoPL z+F-Yb+*7wN= z<7I9H!QYkKOD@WGj9?@Y*7}CypzefuPkb0hFlNf_>L&|`M2rD(O)qX5=f^vfrm1ea z2eQbOpt{@cDKI=UAEAD3<;Sx+y|;A}>bYa?H3U(aaDXh7ecWUCg?opRh1nHc5_+~$ zT>RLH>p5SqpY(HioPJ*!V|An`xChI?oYy_q`O4j3AYP?xSS?zA<^->k`Pgxd@sz_d z5z5V^0nMBx45yGasoAhcre>=Uz*d&Z+bK_3IXm*6ZH&}B68b~{%98LgSDFwj#89H) z=1`6{8M5X6EP|9Ja_Y191v@`)(IC&Er8gCoVIwbHHn-*;xz_JA9+3uk3HByqeL|RsXOeA*OZxgm z;|S}vfsaLzNN^@3yU)T~$qO-MmsRduTk@jOXHijmXMVO}+rm(A9o9b~^(nTX09#k| ztcP&6q_TIEb#b>`!-!t7t?u)nz6eFDD$5P(UtQj#0RSCk+s^_2c!53z9asiYTOF44 zL|YO5;X8*c*9p<(jBjq{h*EZnw2MKjkACmx_JwSJXK4nR^CQIK=UpPdv`R*=e@D)e z8NlEKvf-ZcX3zz}aM%OkMa_@&3vgvxH$brmB%#|OSS(QH(K&#GOhVXDnm{|)0DH(0 z1W)cQTND}`{h-Qg_;7@V(EOWT9AnDhDySEy)aRvB59-C$vnTi)c9Cd;8p^&Ra})$k zivj^87#2Jjxu7ypbFRqYRbMB2QY3(7%;do;r0QI#tMvR_0e~sgjJ=P5IVab8MfODN8a~y)#g( zH^Ih9xLwPa_Vv@$@n!th<@l1`Df65BGV9~}giZu{^ZOjH8057DCI`3(9z1j0-??z@ z-2j+{RjuU(2E2AL&Bp*YHZ`|n5Nfk@-xjnJrT&dUMSOtHPP5sJ^UxxPZc~^2y2OvN? z8Vy7IS=0ld>q`6*00Ahim#g*J>0&)C7lqM8IwWz~r#X0BDnL(aVaeEtKSn< zfY95ar5Gd!9BCpukubfq2v`{OIoSsZe21})2_nT_NEc$jxe_P|!Cb2k^wS{264r5t z0I2k}@8>cxS)lvWTQ((iFmY4Vj$323q8Y7CT%z_raiq<5mDWVi}Iv=>?p z5cI_=0MC~jt>x`)P53W|76$ly(ujGwX%nAs7eGmg=kvWQOG<`<6}P{O2F4;FfdVi( zxF-Z=rQzSNu~#P}KMbn{Tz=fPyRW=tId?LC^`HTSHp1tIUTV=kx`MU_4K&`!1IaSb z@MX*?4LVJ~nscztQ|g!MKi2}(FbAaVVbGM}20(>MyqsDutW&$t(rvdcZuWe4sb@FT z6k=e?Q3Lzav#rOys-{TnFMGK;b9;0p2j5(P6?j^H*XOn%22hHPk$YxtW-~+17P0 zx+-FM{UiSD3Uy}i&U_Q^g+QRJOn!_Ome`awG0xK%&RjbmmjOhHmo=DQWb7Ev-|(mu zDmw=1NPv9-+2Ue8*teo@QoPXh_T>BDPw!dx`IYjJs>!rL?EA90wu{4b4}$@x^usD$ zAp3Ca?UwMXyzxOV>anVi)~y#&36Rr=_^ngB@^iuCPwbL|#QMb1TQ7D6m)2T}(?T*& z(Q$@%z!5tRRtSYQt85Oiv5}zxEoyeQ)S8pS-QG{#Xag4AG#p$@6fj*JoiZOSZ7T>n zs}%2eJYeYwpO{Wq38A`aV^1p9SHyResh{xhWBR*pFU@Ri%Q`c;Q|ng3Jh?3*Ep$lU zc>9yemnZ$?d()rRp`Z7YdGRtGx4&hdue;B#J(wxR$zj34E!w$k_~X=J8AWrwTlVK7`7TFQL#|c%Y&^uS^G>rk+fFt^=!!^2JxC3)g%rn#Bp~;yRRVE|N!FP@Bl4 zo?BYyWFCgLSV(rGIH4R1NHYn3!`G2efxYKc-xH}JDlI-4+6qSJ7y!k$&JaDc%*|g+ zoAx>Ef9HF*Tsz##-GOAZ=b6ORrB|}(v96DTR;*+Vg{}=J`=XE+WZa4lT4t%Cc9JOd}M?CU!5itL)qbX(JT zkf5*W@roAdULQ=@h-74U9R3~0kOmqkac~9UiJSQoPn( zN4!leQzL3$uc=U3-OVEQ#`6n~y9eA~#)R$@s!m+JeyTRoc@uDYHA{~nwORDN_BM$^ zBfRcL%mXRB%%vP_>D=-l}OtVjLsd70(Dh?t97iwhPVi&=YSzsl}F z!1sdeP#se+69Ri(ik6*}wL5}91|SaGg?We-0x7DT+d?QLZF{r*W*g0x;Fe?s8wefF z@f2!iB}GlJG&Zu3!4||ZjuoXyiWIo;f{oM*jVbi0L7FU@I--9zkn3LAp;J=_%J~iISM!xqaZ}XLP=tv=r1q_Nr7*# zESkHTZ02k8B$0uK2r(j9n-5JF)lzlEx7!p*wwF9fkKdY)@3hFrhUC4Qrm{_@h*P^t zJOT+s{_nxQ0gUVHk(h^(21ymU)!@hmL}hCOi33JRx>^ z)c&iwU*-{uaIWhqNyhGXnGb1pomG#k8s$TDQtSX27Q$bZ&NxRG`HIcm%>Qcj?}+A4 zJf8pV!vB2bzl{6+r;qS|<@28$DKB5s<9(U_#YAfNAp%WUoSqy#rUveV|4^U#2h0BD cm;MTeus~