|
|
@@ -2,130 +2,50 @@ package com.adealink.weparty.headline.fragment
|
|
|
|
|
|
import android.os.Bundle
|
|
|
import androidx.fragment.app.viewModels
|
|
|
-import androidx.lifecycle.lifecycleScope
|
|
|
import com.adealink.frame.aab.util.getCompatString
|
|
|
-import com.adealink.frame.base.Rlt
|
|
|
import com.adealink.frame.base.fastLazy
|
|
|
-import com.adealink.frame.coroutine.dispatcher.Dispatcher
|
|
|
-import com.adealink.frame.data.json.froJsonErrorNull
|
|
|
-import com.adealink.frame.effect.data.IEffectEntity
|
|
|
-import com.adealink.frame.effect.listener.IPlayListener
|
|
|
-import com.adealink.frame.effect.view.EffectView
|
|
|
-import com.adealink.frame.effect.view.IEffectView
|
|
|
-import com.adealink.frame.ext.isViewBindingValid
|
|
|
-import com.adealink.frame.log.Log
|
|
|
import com.adealink.frame.mvvm.view.viewBinding
|
|
|
import com.adealink.frame.room.data.FlowStateInfo
|
|
|
import com.adealink.frame.router.Router
|
|
|
import com.adealink.frame.router.annotation.RouterUri
|
|
|
-import com.adealink.frame.util.runOnUiThread
|
|
|
import com.adealink.weparty.commonui.BaseFragment
|
|
|
import com.adealink.weparty.commonui.dialogfragment.BaseDialogFragment
|
|
|
-import com.adealink.weparty.commonui.ext.show
|
|
|
import com.adealink.weparty.commonui.toast.util.showToast
|
|
|
-import com.adealink.weparty.commonui.widget.floatview.view.HideMode
|
|
|
-import com.adealink.weparty.commonui.widget.floatview.view.ITouchDispatchEventListener
|
|
|
-import com.adealink.weparty.commonui.widget.floatview.view.SwipeToTopConstraintLayout
|
|
|
import com.adealink.weparty.headline.R
|
|
|
-import com.adealink.weparty.headline.data.TAG_HEADLINE
|
|
|
import com.adealink.weparty.headline.databinding.FragmentHealineBinding
|
|
|
-import com.adealink.weparty.headline.effect.data.GiftTreasureEffectEntity
|
|
|
-import com.adealink.weparty.headline.effect.data.GlobalHeadlineEntity
|
|
|
+import com.adealink.weparty.headline.manager.headlineManager
|
|
|
import com.adealink.weparty.headline.viewmodel.HeadlineViewModel
|
|
|
import com.adealink.weparty.headline.viewmodel.HeadlineViewModelFactory
|
|
|
import com.adealink.weparty.module.game.GameModule
|
|
|
-import com.adealink.weparty.module.game.data.GameEntranceType
|
|
|
-import com.adealink.weparty.module.game.rocket.effect.IHeadlineBtnClickListener
|
|
|
-import com.adealink.weparty.module.game.rocket.effect.RocketHeadlineEffectEntity
|
|
|
import com.adealink.weparty.module.gift.Gift
|
|
|
import com.adealink.weparty.module.gift.GiftModule
|
|
|
import com.adealink.weparty.module.gift.data.LuckyGiftLotteryNotify
|
|
|
-import com.adealink.weparty.module.gift.effect.luckygift.LuckyGiftRewardEffectEntity
|
|
|
import com.adealink.weparty.module.headline.Headline
|
|
|
-import com.adealink.weparty.module.headline.listener.IHeadlineOpListener
|
|
|
-import com.adealink.weparty.module.profile.Profile
|
|
|
import com.adealink.weparty.module.profile.ProfileModule
|
|
|
-import com.adealink.weparty.module.room.Room
|
|
|
import com.adealink.weparty.module.room.RoomModule
|
|
|
-import com.adealink.weparty.module.room.data.RoomMicMode
|
|
|
-import com.adealink.weparty.module.room.data.RoomNotifyType
|
|
|
import com.adealink.weparty.module.room.listener.IRoomListener
|
|
|
-import com.adealink.weparty.module.room.wedding.IHeadlineClickListener
|
|
|
-import com.adealink.weparty.module.share.ShareModule
|
|
|
-import com.adealink.weparty.module.webview.Web
|
|
|
-import com.adealink.weparty.room.data.EnterRoomInfo
|
|
|
-import com.adealink.weparty.url.H5Page
|
|
|
-import com.adealink.weparty.url.urlConfigService
|
|
|
-import com.adealink.weparty.util.goLocalLinkPage
|
|
|
-import kotlinx.coroutines.delay
|
|
|
-import kotlinx.coroutines.launch
|
|
|
-import kotlinx.coroutines.withContext
|
|
|
-import java.util.TreeMap
|
|
|
|
|
|
@RouterUri(path = [Headline.Fragment.PATH], desc = "头条fragment")
|
|
|
-class HeadlineFragment : BaseFragment(R.layout.fragment_healine), IHeadlineOpListener,
|
|
|
- IPlayListener, IRoomListener, IHeadlineBtnClickListener, IHeadlineClickListener {
|
|
|
+class HeadlineFragment : BaseFragment(R.layout.fragment_healine), IRoomListener {
|
|
|
private val binding by viewBinding(FragmentHealineBinding::bind)
|
|
|
private val headlineViewModel by viewModels<HeadlineViewModel> { HeadlineViewModelFactory() }
|
|
|
- private var isShowInviteRebate: Boolean? = null
|
|
|
|
|
|
- private val gameViewModel by fastLazy { GameModule.getGameViewModel(this) }
|
|
|
private val giftViewModel by fastLazy { GiftModule.getGiftViewModel(this) }
|
|
|
- private val shareViewModel by fastLazy { ShareModule.getShareViewModel(this) }
|
|
|
private val rocketViewModel by fastLazy { GameModule.getRocketViewModel(this) }
|
|
|
- private val giftTreasureViewMode by fastLazy { GiftModule.getTreasureGiftViewModel(requireActivity()) }
|
|
|
- private var regionRandomQueueEnable = false
|
|
|
- private var isDelayed = false
|
|
|
|
|
|
- //头条队列
|
|
|
- private val entityPriorityQueue = TreeMap<String, IEffectEntity<out IEffectView>>()
|
|
|
|
|
|
override fun initViews() {
|
|
|
super.initViews()
|
|
|
RoomModule.registerListener(this)
|
|
|
- binding.swipeLayout.hideView()
|
|
|
- binding.swipeLayout.setOnHideListener {
|
|
|
- if (it == HideMode.MODE_MANUAL) {
|
|
|
- stopHeadlineEffect()
|
|
|
- showContainerDelayed()
|
|
|
- }
|
|
|
- }
|
|
|
- if (parentFragment is ITouchDispatchEventListener) {
|
|
|
- binding.swipeLayout.setTouchDispatchEventListener(parentFragment as ITouchDispatchEventListener)
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
override fun observeViewModel() {
|
|
|
super.observeViewModel()
|
|
|
headlineViewModel.globalHeadlineNotifyLD.observe(viewLifecycleOwner) {
|
|
|
- addHeadline(
|
|
|
- GlobalHeadlineEntity(
|
|
|
- headlineNotify = it,
|
|
|
- path = it.broadcastUri,
|
|
|
- headlineOpListener = this,
|
|
|
- playListener = this
|
|
|
- )
|
|
|
- )
|
|
|
+ headlineManager.addHeadLine(it)
|
|
|
}
|
|
|
rocketViewModel?.levelUpgradedLD?.observeWithoutCache(viewLifecycleOwner) {
|
|
|
- addHeadline(
|
|
|
- RocketHeadlineEffectEntity(
|
|
|
- path = "",
|
|
|
- levelUpgradeNotify = it,
|
|
|
- playListener = this,
|
|
|
- headlineOpListener = this
|
|
|
- )
|
|
|
- )
|
|
|
- }
|
|
|
- giftTreasureViewMode?.treasureGiftGlobalNotifyLd?.observeWithoutCache(viewLifecycleOwner) {
|
|
|
- addHeadline(
|
|
|
- GiftTreasureEffectEntity(
|
|
|
- path = "",
|
|
|
- notify = it,
|
|
|
- playListener = this,
|
|
|
- headlineOpListener = this
|
|
|
- )
|
|
|
- )
|
|
|
+ headlineManager.addRocketHeadlineEffectEntity(it)
|
|
|
}
|
|
|
giftViewModel?.luckyGiftRewardNotifyLD?.observeWithoutCache(viewLifecycleOwner) {
|
|
|
handleLuckGiftRewardNotify(it)
|
|
|
@@ -138,7 +58,8 @@ class HeadlineFragment : BaseFragment(R.layout.fragment_healine), IHeadlineOpLis
|
|
|
//幸运礼物combo弹toast提醒
|
|
|
showToast(
|
|
|
getCompatString(
|
|
|
- com.adealink.weparty.R.string.common_lucky_gift_reward, notify.giftInfo.name,
|
|
|
+ com.adealink.weparty.R.string.common_lucky_gift_reward,
|
|
|
+ notify.giftInfo.name,
|
|
|
notify.lotteryRatio
|
|
|
)
|
|
|
)
|
|
|
@@ -151,327 +72,23 @@ class HeadlineFragment : BaseFragment(R.layout.fragment_healine), IHeadlineOpLis
|
|
|
}
|
|
|
}
|
|
|
if (notify.showPlace == 1 && notify.lotteryRatio in 100..299) {
|
|
|
- addHeadline(LuckyGiftRewardEffectEntity("", notify))
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private fun showContainerImmediately() {
|
|
|
- if (!binding.swipeLayout.isViewHidden()) {
|
|
|
- return
|
|
|
- }
|
|
|
- binding.swipeLayout.resetToInitialPositionImmediately()
|
|
|
- }
|
|
|
-
|
|
|
- private fun showContainerDelayed() {
|
|
|
- if (isDelayed) {
|
|
|
- return
|
|
|
- }
|
|
|
- isDelayed = true
|
|
|
- //如果隐藏了,5s后重新展示
|
|
|
- lifecycleScope.launch(Dispatcher.WENEXT_THREAD_POOL) {
|
|
|
- delay(SwipeToTopConstraintLayout.DEFAULT_DELAY_TIME)
|
|
|
- if (entityPriorityQueue.isEmpty()) {
|
|
|
- isDelayed = false
|
|
|
- return@launch
|
|
|
- }
|
|
|
- withContext(Dispatcher.UI) {
|
|
|
- showContainerImmediately()
|
|
|
- showNextHeadLine()
|
|
|
- isDelayed = false
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private fun hideContainerImmediately() {
|
|
|
- if (binding.swipeLayout.isViewHidden()) {
|
|
|
- return
|
|
|
- }
|
|
|
- binding.swipeLayout.hideView()
|
|
|
- }
|
|
|
-
|
|
|
- private fun addHeadline(entity: IEffectEntity<out IEffectView>) {
|
|
|
- entityPriorityQueue[entity.priority] = entity
|
|
|
- if (!isDelayed) {
|
|
|
- showNextHeadLine()
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- override fun onComplete() {
|
|
|
- Log.d(TAG_HEADLINE, "onComplete, showNextHeadLine")
|
|
|
- if (!isViewBindingValid()) {
|
|
|
- return
|
|
|
- }
|
|
|
- if (animatorPlayEnd()) {
|
|
|
- hideContainerImmediately()
|
|
|
- return
|
|
|
- }
|
|
|
- showNextHeadLine()
|
|
|
- }
|
|
|
-
|
|
|
- override fun onError(errCode: Int) {
|
|
|
- Log.d(TAG_HEADLINE, "onError($errCode), showNextHeadLine")
|
|
|
- if (!isViewBindingValid()) {
|
|
|
- return
|
|
|
- }
|
|
|
- if (animatorPlayEnd()) {
|
|
|
- hideContainerImmediately()
|
|
|
- return
|
|
|
- }
|
|
|
- showNextHeadLine()
|
|
|
- }
|
|
|
-
|
|
|
- private fun findIdleEffectView(): EffectView? {
|
|
|
- if (!isViewBindingValid()) {
|
|
|
- return null
|
|
|
- }
|
|
|
- if (!binding.headlineEffectView1.isEffectPlaying()
|
|
|
- && binding.headlineEffectView1.isQueueEmpty()
|
|
|
- ) {
|
|
|
- Log.d(TAG_HEADLINE, "findIdleEffectView, headlineEffectView1")
|
|
|
- return binding.headlineEffectView1
|
|
|
- }
|
|
|
- val micMode = RoomModule.getJoinedRoomMicMode()
|
|
|
- when (micMode?.first) {
|
|
|
- RoomMicMode.ROOM_MIC_VIDEO_ROOM -> {
|
|
|
- return null
|
|
|
- }
|
|
|
-
|
|
|
- else -> {
|
|
|
- if (!binding.headlineEffectView2.isEffectPlaying()
|
|
|
- && binding.headlineEffectView2.isQueueEmpty()
|
|
|
- ) {
|
|
|
- Log.d(TAG_HEADLINE, "findIdleEffectView, headlineEffectView2")
|
|
|
- return binding.headlineEffectView2
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return null
|
|
|
- }
|
|
|
-
|
|
|
- private fun showNextHeadLine() {
|
|
|
- Log.d(TAG_HEADLINE, "showNextHeadLine")
|
|
|
- playHeadlineEffect()
|
|
|
- val effectView = findIdleEffectView()
|
|
|
- if (effectView == null) {
|
|
|
- Log.d(TAG_HEADLINE, "showNextHeadLine return, for no idle effectView")
|
|
|
- return
|
|
|
- }
|
|
|
- val firstEffectEntry = pollNext()
|
|
|
- if (firstEffectEntry == null) {
|
|
|
- Log.d(TAG_HEADLINE, "showNextHeadLine return, effect entity is empty")
|
|
|
- return
|
|
|
- }
|
|
|
- effectView.show()
|
|
|
- showContainerImmediately()
|
|
|
- effectView.add(firstEffectEntry)
|
|
|
- }
|
|
|
-
|
|
|
- private fun pollNext(): IEffectEntity<out IEffectView>? {
|
|
|
- if (entityPriorityQueue.isEmpty()) {
|
|
|
- return null
|
|
|
- }
|
|
|
-
|
|
|
- if (!regionRandomQueueEnable || entityPriorityQueue.size < 2) {
|
|
|
- val pollFirstEntry = entityPriorityQueue.pollFirstEntry()
|
|
|
- return pollFirstEntry?.value
|
|
|
- }
|
|
|
-
|
|
|
- val keys = mutableListOf<String>()
|
|
|
- for (item in entityPriorityQueue) {
|
|
|
- keys += item.key
|
|
|
- }
|
|
|
-
|
|
|
- val random = (0 until keys.size).random()
|
|
|
- val key = keys[random]
|
|
|
- return entityPriorityQueue.remove(key)
|
|
|
- }
|
|
|
-
|
|
|
- override fun loadData() {
|
|
|
- super.loadData()
|
|
|
- shareViewModel?.isShowInviteRebate()?.observe(viewLifecycleOwner) {
|
|
|
- val show = (it as? Rlt.Success)?.data?.data?.show
|
|
|
- isShowInviteRebate = (show == true)
|
|
|
- }
|
|
|
-
|
|
|
- headlineViewModel.getHeadlineQueueRandomConfig().observe(viewLifecycleOwner) {
|
|
|
- if (it == null) {
|
|
|
- regionRandomQueueEnable = false
|
|
|
- return@observe
|
|
|
- }
|
|
|
-
|
|
|
- val regionMap = froJsonErrorNull<Map<String, Boolean>>(it.firstOrNull())
|
|
|
- regionRandomQueueEnable = regionMap?.containsKey(ProfileModule.getMyUserInfo()?.region) == true
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 进房间
|
|
|
- */
|
|
|
- private fun enterRoomClick(roomId: Long, from: String) {
|
|
|
- val activity = activity ?: return
|
|
|
- hideContainerImmediately()
|
|
|
- Router.build(activity, Room.Room.PATH)
|
|
|
- .putExtra(
|
|
|
- Room.Room.EXTRA_ENTER_ROOM_INFO,
|
|
|
- EnterRoomInfo(roomId, from)
|
|
|
- )
|
|
|
- .start()
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 去个人主页
|
|
|
- */
|
|
|
- private fun goUserProfile(uid: Long) {
|
|
|
- val activity = activity ?: return
|
|
|
- Router.build(activity, Profile.UserProfile.PATH)
|
|
|
- .putExtra(Profile.Common.EXTRA_UID, uid).start()
|
|
|
- }
|
|
|
-
|
|
|
- private fun goSuperGiftWeb() {
|
|
|
- if (!GameModule.isShowSuperGift()) {
|
|
|
- showToast(R.string.headline_super_gift_level_limit)
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- val activity = activity ?: return
|
|
|
- Router.build(activity, Web.FullScreen.PATH)
|
|
|
- .putExtra(Web.Common.EXTRA_URL, urlConfigService.getH5Url(H5Page.SUPER_GIFT))
|
|
|
- .start()
|
|
|
- }
|
|
|
-
|
|
|
- override fun onHeadlineRightBtnClick(type: RoomNotifyType?, params: Bundle?) {
|
|
|
- when (type) {
|
|
|
- RoomNotifyType.SendRedPacket, RoomNotifyType.SendGift -> {
|
|
|
- params?.getLong(Headline.Common.EXTRA_ROOM_ID)?.let {
|
|
|
- enterRoomClick(it, params.getString(Headline.Common.EXTRA_ENTER_ROOM_FROM, ""))
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- RoomNotifyType.SVIP_GLOBAL_NOTIFY -> {
|
|
|
- val svipParams = params ?: return
|
|
|
- val roomId = svipParams.getLong(Headline.Common.EXTRA_ROOM_ID)
|
|
|
- if(roomId > 0L) {
|
|
|
- enterRoomClick(roomId, svipParams.getString(Headline.Common.EXTRA_ENTER_ROOM_FROM, ""))
|
|
|
- } else {
|
|
|
- goUserProfile(svipParams.getLong(Headline.Common.EXTRA_UID))
|
|
|
- }
|
|
|
- }
|
|
|
- RoomNotifyType.SuperGift -> {
|
|
|
- goSuperGiftWeb()
|
|
|
- }
|
|
|
-
|
|
|
- RoomNotifyType.COMMON_GLOBAL_ROOM_BROADCAST_NOTIFY -> {
|
|
|
- params?.getString(Headline.Common.EXTRA_DEEPLINK)?.let {
|
|
|
- val activity = activity ?: return
|
|
|
- goLocalLinkPage(activity, it)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- RoomNotifyType.LuckyFruit -> {
|
|
|
- GameModule.navigateToGame(GameEntranceType.LUCKY_FRUIT)
|
|
|
- }
|
|
|
-
|
|
|
- RoomNotifyType.Slot -> {
|
|
|
- GameModule.navigateToGame(GameEntranceType.JACKPOT)
|
|
|
- }
|
|
|
-
|
|
|
- RoomNotifyType.SlotPro -> {
|
|
|
- GameModule.navigateToGame(GameEntranceType.JACKPOT_SLOT)
|
|
|
- }
|
|
|
-
|
|
|
- RoomNotifyType.GREEDY_BOX_NOTIFY -> {
|
|
|
- GameModule.navigateToGame(GameEntranceType.GREEDY_BOX)
|
|
|
- }
|
|
|
-
|
|
|
- RoomNotifyType.TEEN_PATTI_REWARD_NOTIFY -> {
|
|
|
- GameModule.navigateToGame(GameEntranceType.TEEN_PATTI)
|
|
|
- }
|
|
|
-
|
|
|
- RoomNotifyType.GREEDY_PRO_NOTIFY -> {
|
|
|
- GameModule.navigateToGame(GameEntranceType.GREEDY_PRO)
|
|
|
- }
|
|
|
-
|
|
|
- RoomNotifyType.NEW_GREEDY_PRO_REWARD_NOTIFY -> {
|
|
|
- GameModule.navigateToGame(GameEntranceType.LUCKY_PRO)
|
|
|
- }
|
|
|
-
|
|
|
- RoomNotifyType.DRAGON_TIGER_FIGHT_REWARD_NOTIFY -> {
|
|
|
- GameModule.navigateToGame(GameEntranceType.DRAGON_TIGER_FIGHT)
|
|
|
- }
|
|
|
-
|
|
|
- RoomNotifyType.RUSSIA_ROULETTE_REWARD_NOTIFY -> {
|
|
|
- GameModule.navigateToGame(GameEntranceType.RUSSIAN_ROULETTE)
|
|
|
- }
|
|
|
-
|
|
|
- RoomNotifyType.TEXAS_COWBOY_REWARD_NOTIFY -> {
|
|
|
- GameModule.navigateToGame(GameEntranceType.TEXAS_COWBOY)
|
|
|
- }
|
|
|
-
|
|
|
- RoomNotifyType.ADMIN_LOTTERY_ACTIVITY_REWARD_NOTIFY -> {
|
|
|
- val act = activity ?: return
|
|
|
- val webUrl = params?.getString(Headline.Common.EXTRA_WEB_URL) ?: return
|
|
|
- Router.build(act, Web.FullScreen.PATH)
|
|
|
- .putExtra(Web.Common.EXTRA_URL, webUrl)
|
|
|
- .start()
|
|
|
- }
|
|
|
-
|
|
|
- RoomNotifyType.GREEDY_PERSONAL_REWARD_NOTIFY -> {
|
|
|
- GameModule.navigateToGame(GameEntranceType.GREEDY_PERSONAL)
|
|
|
- }
|
|
|
-
|
|
|
- else -> {
|
|
|
- //ntd.
|
|
|
- }
|
|
|
+ headlineManager.addLuckyGiftLotteryNotify(notify)
|
|
|
}
|
|
|
- hideContainerImmediately()
|
|
|
}
|
|
|
|
|
|
override fun onDestroyView() {
|
|
|
super.onDestroyView()
|
|
|
RoomModule.unregisterListener(this)
|
|
|
- entityPriorityQueue.clear()
|
|
|
}
|
|
|
|
|
|
override fun onRoomIn(roomId: Long, flowStateInfo: FlowStateInfo) {
|
|
|
super.onRoomIn(roomId, flowStateInfo)
|
|
|
- entityPriorityQueue.clear()
|
|
|
- stopHeadlineEffect()
|
|
|
- playHeadlineEffect()
|
|
|
- }
|
|
|
-
|
|
|
- private fun stopHeadlineEffect() {
|
|
|
- runOnUiThread {
|
|
|
- if (!isViewBindingValid()) {
|
|
|
- return@runOnUiThread
|
|
|
- }
|
|
|
- binding.headlineEffectView1.stop()
|
|
|
- binding.headlineEffectView2.stop()
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private fun playHeadlineEffect() {
|
|
|
- runOnUiThread {
|
|
|
- if (!isViewBindingValid()) {
|
|
|
- return@runOnUiThread
|
|
|
- }
|
|
|
- binding.headlineEffectView1.play()
|
|
|
- binding.headlineEffectView2.play()
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
- private fun animatorPlayEnd(): Boolean {
|
|
|
- if (!isViewBindingValid()) {
|
|
|
- return false
|
|
|
- }
|
|
|
- return !binding.headlineEffectView1.isEffectPlaying() && !binding.headlineEffectView2.isEffectPlaying() && entityPriorityQueue.isEmpty()
|
|
|
+ override fun onRoomLeaved(roomId: Long, flowStateInfo: FlowStateInfo) {
|
|
|
+ super.onRoomLeaved(roomId, flowStateInfo)
|
|
|
+ headlineManager.clearWhenExitRoom(roomId)
|
|
|
}
|
|
|
|
|
|
- override fun onHeadlineBtnClick(type: RoomNotifyType?, params: Bundle?) {
|
|
|
- hideContainerImmediately()
|
|
|
- }
|
|
|
-
|
|
|
- override fun onHeadlineClick(type: RoomNotifyType?, params: Bundle?) {
|
|
|
- hideContainerImmediately()
|
|
|
- }
|
|
|
|
|
|
}
|