class DemoScoreModule(private val viewModel: IPlayBaseInfoVM, containerView: ViewGroup) :
Scene(containerView), ScoreDialog.OnClickListener, BaseScoreDialog.OnClickListener{
override val TAG = "DemoScore"
/** 打分辅助类 */
private var mIntonationDelegate: SingIntonationDelegate? = null
private var mScoreDialog: ScoreDialog? = null
private var multiScoreDialog:MultiScoreDialog?=null
private var containerView: ViewGroup? = null
private var intonationViewer: AbstractIntonationView? = null
private var pkScoreBar: SimpleScoreBar? = null
private var pkScoreBarNew:PkScoreBar?=null
private var perfectAnimView: PerfectAnimView? = null
private var ktvScoreCallBackImpl:KtvScoreCallbackImpl?=null
private var scoreListenerImpl: ScoreListenerImpl? = null
private val mHandler = Handler(Looper.getMainLooper())
private var isScoreDialogShown = false
private var isEnterEdit = false
private var isPlayEnd = false
private val multiScoreLogBuilder = StringBuilder()
private var mSingCompetitor: SingCompetitor? = null
private var multiScoreResultInfo=MultiScoreResultInfo()
override val owner = containerView.context as LifecycleOwner
/**
* 初始化视图组件
* 包括音准视图、打分条、完美动画视图等
*/
override fun initView() {
setRootView(R.layout.play_scene_score)
val userService = KServiceManager.getService(IKUser::class.java)
mRootView?.let {
containerView = it.findViewById(R.id.intonation_container)
intonationViewer = it.findViewById(R.id.player_float_intonation_viewer)
pkScoreBar = it.findViewById(R.id.pk_score_bar)
pkScoreBarNew=it.findViewById(R.id.pkScoreBar)
perfectAnimView = it.findViewById(R.id.karaoke_perfect_view)
mIntonationDelegate =
SingIntonationDelegate(
containerView,
intonationViewer,
pkScoreBar,
perfectAnimView,
)
}
}
/**
* 更新打分条的可见性
* 控制普通打分条和新版PK打分条的显示状态
*/
private fun updateScoreBarVisibility(){
pkScoreBar?.visibility = View.VISIBLE
pkScoreBarNew?.visibility = View.GONE
}
private fun log(msg:String) {
Log.i(TAG, msg)
}
/**
* 初始化监听器
* 监听歌曲信息变化、打分开关、播放下一首等事件
*/
override fun initListener() {
// 监听当前歌曲信息变化
viewModel.currSongInfo().observe(owner) {
log("currSongInfo ${it?.mid}")
if (ktvScoreCallBackImpl==null){
ktvScoreCallBackImpl = KtvScoreCallbackImpl()
}
if (scoreListenerImpl==null){
scoreListenerImpl = ScoreListenerImpl()
}
//KtvPlayerImpl中可能会将所有的回调都清除掉,所以这里重新添加一下
viewModel.currPlayer()?.apply {
removeOnScoreListener(scoreListenerImpl)
removeCallback(ktvScoreCallBackImpl)
addOnScoreListener(scoreListenerImpl)
addCallback(ktvScoreCallBackImpl)
}
}
//听歌/K歌切换时,更新打分条的可见性
PlayConsole.get().songType.observe(owner) {
updateScoreViewVisibility()
}
//打开/关闭打分时,更新打分条的可见性
PlayConsole.get().openScore.observe(owner) {
updateScoreViewVisibility()
if (it) {
//开启打分
viewModel.currSongInfo().value?.apply {
val isKSong = songType == SongType.SONG_TYPE_K_SONG
PlayConsole.get().setShowPk(isKSong && isSupportPk)
}
}else {
PlayConsole.get().setShowPk(false)
PlayConsole.get().setShowChorus(false)
}
}
//播放下一首时,检查是否需要显示打分结果弹框
PlayConsole.get().showScoreOrPlayNext.value = null
PlayConsole.get().showScoreOrPlayNext.observe(owner) {
if(it.isNullOrEmpty()) {
return@observe
}
checkShowScoreDialog(TotalScoreResultInfo.SCENE_PLAY_NEXT)
}
//记录当前打分结果。PlayConsole类只是示例,厂商可用类似方式自行保存此结果
//val scoreResultInfo = MutableLiveData<TotalScoreResultInfo?>()
PlayConsole.get().scoreResultInfo.postValue(null)
}
/**
* 获取手动触发的打分结果信息
* @param scene 触发场景(播放下一首、退出页面等)
* @return 打分结果信息,如果没有打分数据则返回null
*/
private fun getManualTriggerResultInfo(scene: String?): TotalScoreResultInfo? {
//mSingCompetitor 从onPrepareScore获取
val singCompetitor = mSingCompetitor ?: return null
val scoreResultInfo = TotalScoreResultInfo()
scoreResultInfo.scoreScene = scene
scoreResultInfo.isMultiScore = singCompetitor.isMultiScorer
if(!scoreResultInfo.isMultiScore) {
scoreResultInfo.totalScore = singCompetitor.totalScore
scoreResultInfo.scoreLevelString = singCompetitor.scoreLevelString
scoreResultInfo.scoreLevel =
ScoreUtil.scoreLevelStringToInt(scoreResultInfo.scoreLevelString)
} else {
scoreResultInfo.multiScoreResult = singCompetitor.multiScoreResult
}
return scoreResultInfo
}
/**
* 更新打分视图的可见性
* 根据歌曲类型、打分开关、编辑模式等条件决定是否显示打分相关视图
*/
private fun updateScoreViewVisibility() {
val isShow = isShowScore()
log(
"updateScoreViewVisibility isShow: $isShow, isEnableScore: ${KtvPlayerConfig.getInstance().isEnableScore}" +
", songType: ${PlayConsole.get().songType.value}" +
", openScore: ${PlayConsole.get().openScore.value}" +
", editMode: ${PlayConsole.get().editMode.value}"
)
if (isShow) {
containerView?.post {
containerView?.visibility = View.VISIBLE
intonationViewer?.visibility = View.VISIBLE
perfectAnimView?.visibility = View.VISIBLE
updateScoreBarVisibility()
}
} else {
if(viewModel.currSongInfo().value != null) {
log("not support score")
}
containerView?.post {
containerView?.visibility = View.GONE
intonationViewer?.visibility = View.GONE
pkScoreBar?.visibility = View.GONE
pkScoreBarNew?.visibility=View.GONE
perfectAnimView?.visibility = View.GONE
}
}
}
/**
* 判断是否应该显示打分功能。这里的判断方式仅供参考,厂商可根据自身需求进行判断
* @return true表示应该显示打分,false表示不显示
*/
private fun isShowScore(): Boolean {
return PlayConsole.get().songType.value == SongType.SONG_TYPE_K_SONG
&& PlayConsole.get().openScore.value != false
&& PlayConsole.get().editMode.value != true
&& viewModel.currSongInfo().value?.mNoteBytes != null
&& KtvPlayerConfig.getInstance().isEnableScore
&& !KtvPlayerConfig.getInstance().isCloseScoreUI
}
/**
* 打分监听器实现类
* 处理打分准备、打分进行中、打分完成等回调
*/
inner class ScoreListenerImpl : KaraokePlayer.OnScoreListener() {
override fun onPrepareScore(competitor: SingCompetitor?, nums: Int) {
Logger.d(TAG, "onPrepareScore")
mSingCompetitor = competitor
if (KtvPlayerConfig.getInstance().isCloseScoreUI) {
return
}
setScoreDialogShown(false, null)
}
override fun onDoingScore(score: Int, level: String?, timeStamp: Int,sentenceIndex:Int) {
refreshScore(score, timeStamp.toLong(), null,sentenceIndex)
}
override fun onDoingMultiScore(
lastScore: Int,
timeStamp: Long,
lastLongToneScore: Int,
lastRhythmScore: Int,
lastStableScore: Int,
dynamicScore: Int,
skillScore: Int,
lastSkillTrillCount: Int,
lastSkillGlintCount: Int,
lastSkillTransliterationCount: Int,
lyricIndex:Int
) {
if (KtvPlayerConfig.getInstance().isCloseScoreUI) {
return
}
multiScoreResultInfo.resetAll()
multiScoreResultInfo.lastLongToneScore = lastLongToneScore
multiScoreResultInfo.lastRhythmScore = lastRhythmScore
multiScoreResultInfo.lastStableScore = lastStableScore
multiScoreResultInfo.lastDynamicScore = dynamicScore
multiScoreResultInfo.lastSkillScore = skillScore
multiScoreResultInfo.lastSkillTrillCount = lastSkillTrillCount
multiScoreResultInfo.lastSkillTransliterationCount = lastSkillGlintCount
multiScoreLogBuilder.append("lastLongToneScore: ").append(lastLongToneScore)
.append("lastScore: ").append(lastScore)
.append(" lastRhythmScore: ").append(lastRhythmScore)
.append(" lastStableScore: ").append(lastStableScore)
.append(" dynamicScore: ").append(dynamicScore)
.append(" skillScore: ").append(skillScore)
.append(" lastSkillTrillCount: ").append(lastSkillTrillCount)
.append(" lastSkillGlintCount: ").append(lastSkillGlintCount)
Logger.i(TAG, "sentence score info: $multiScoreLogBuilder")
multiScoreLogBuilder.setLength(0)
refreshScore(lastScore, timeStamp, multiScoreResultInfo,lyricIndex)
}
/**
* 五维打分完成的回调
* @param lastSentenceIndex 最后一句索引
* @param totalSentences 总句数
*/
override fun onMultiScoreFinish(
finalLongToneScore: Int,
finalRhythmScore: Int,
finalStableScore: Int,
finalDynamicScore: Int,
finalSkillScore: Int,
lastSentenceIndex: Int,
totalSentences: Int
) {
val multiScoreResult = MultiScoreResultInfo()
multiScoreResult.totalLongToneScore = finalLongToneScore
multiScoreResult.totalRhythmScore = finalRhythmScore
multiScoreResult.totalStableScore = finalStableScore
multiScoreResult.totalDynamicScore = finalDynamicScore
multiScoreResult.totalSkillScore = finalSkillScore
multiScoreResult.lastSentenceIndex = lastSentenceIndex
multiScoreResult.totalSentences = totalSentences
val scoreResult = TotalScoreResultInfo()
scoreResult.scoreScene = TotalScoreResultInfo.SCENE_ON_MULTI_SCORE_FINISH
scoreResult.isMultiScore = true
scoreResult.multiScoreResult = multiScoreResult
Logger.i(TAG, "onMultiScoreFinish result: $scoreResult")
checkShowMultiScoreDialog(scoreResult)
}
/**
* 普通打分完成的回调
* @param totalScore 总分
* @param level 评级
*/
override fun onFinishScore(totalScore: Int, level: String?) {
Logger.d(TAG, "onFinishScore totalScore $totalScore")
mSingCompetitor?.let {
val scoreResult = TotalScoreResultInfo()
scoreResult.scoreScene = TotalScoreResultInfo.SCENE_ON_SCORE_FINISH
scoreResult.totalScore = totalScore
scoreResult.scoreLevelString = level ?: ""
scoreResult.scoreLevel = ScoreUtil.scoreLevelStringToInt(level)
checkShowNormalScoreDialog(scoreResult)
}
}
}
/**
* 刷新打分显示
* @param lastSentenceScore 上一句分数
* @param timeStamp 时间戳
* @param multiScoreResultInfo 五维打分信息
* @param sentenceIndex 句子索引
*/
private fun refreshScore(lastSentenceScore: Int, timeStamp: Long, multiScoreResultInfo: MultiScoreResultInfo?,sentenceIndex: Int) {
if (lastSentenceScore > 70) {
SingCompetition.get().isLastScorePositive = true
}
if (lastSentenceScore != -1 && lastSentenceScore != 0) {
postUpdateScore(lastSentenceScore, timeStamp.toFloat(), multiScoreResultInfo,sentenceIndex)
}
}
/**
* 设置打分弹窗的显示状态
* @param isShown 是否显示
* @param resultInfo 打分结果信息
*/
private fun setScoreDialogShown(isShown: Boolean, resultInfo: TotalScoreResultInfo?) {
Logger.i(TAG, "setScoreDialogShown $isShown")
isScoreDialogShown = isShown
PlayConsole.get().isScoreDialogShown.postValue(isShown)
if(resultInfo != PlayConsole.get().scoreResultInfo.value) {
PlayConsole.get().scoreResultInfo.postValue(resultInfo)
}
}
/**
* 发送更新分数的消息
* @param score 分数
* @param timeStamp 时间戳
* @param multiScoreInfo 五维打分信息
* @param sentenceIndex 句子索引
*/
private fun postUpdateScore(score: Int, timeStamp: Float, multiScoreInfo: MultiScoreResultInfo?,sentenceIndex: Int) {
mIntonationDelegate?.postUpdateScore(score,timeStamp,multiScoreInfo,sentenceIndex)
}
/**
* KTV播放器回调实现类
* 处理播放开始、暂停、恢复、播放结束等事件
*/
inner class KtvScoreCallbackImpl : KaraokePlayerListener() {
/**
* 歌词资源变化的回调
* 检查歌曲是否支持打分,并启动MIDI视图
* @param request 播放请求对象
*/
override fun onLyricResourceChanged(request: KaraokePlayRequest) {
super.onLyricResourceChanged(request)
if (request.songInfoObject.mNoteBytes == null && request.songInfoObject.songType == SongType.SONG_TYPE_K_SONG) {
Logger.d(TAG, "current song has no noteBytes, close score")
if (KtvPlayerConfig.getInstance().isEnableScore && PlayConsole.get().openScore.value == true) {
PlayConsole.get().setScoreOpen(false)
mIntonationDelegate?.stopMidi()
KGToast.show("该歌曲不支持打分,已为您关闭打分")
}
}
startMidiView()
}
/**
* 播放位置变化的回调
* 同步MIDI视图的播放进度
* @param mKtvPlayRequest 播放请求
* @param currentTime 当前播放时间
* @param duration 总时长
*/
override fun onPlayPositionChange(
mKtvPlayRequest: KaraokePlayRequest,
currentTime: Long,
duration: Long
) {
if (KtvPlayerConfig.getInstance().isCloseScoreUI) {
return
}
// Logger.d(TAG, "onPlayPositionChange:currentTime=$currentTime,duration=$duration")
getActivity()?.let {
if (!KGDialog.isActivityDestroyed(it)) {
mIntonationDelegate?.seekMidi(currentTime.toLong())
}
}
}
/**
* 播放恢复的回调
* 重新启动MIDI视图
* @param mKtvPlayRequest 播放请求对象
*/
override fun onResume(mKtvPlayRequest: KaraokePlayRequest) {
Logger.d(TAG, "call onResume")
startMidiView()
}
/**
* 启动MIDI视图
* 开始显示音准线和打分相关视图
*/
private fun startMidiView() {
if (KtvPlayerConfig.getInstance().isCloseScoreUI) {
return
}
if (KtvPlayerConfig.getInstance().isEnableScore) {
log("startMidiView")
mIntonationDelegate?.startMidi(viewModel.currPlayer()?.timeLineTime ?: 0)
}
updateScoreViewVisibility()
}
/**
* 播放暂停的回调
* 停止MIDI视图
* @param mKtvPlayRequest 播放请求对象
*/
override fun onPause(mKtvPlayRequest: KaraokePlayRequest) {
Logger.d(TAG, "onPause")
if (KtvPlayerConfig.getInstance().isCloseScoreUI) {
return
}
mIntonationDelegate?.stopMidi()
}
/**
* 缓冲开始的回调
* @param mKtvPlayRequest 播放请求对象
*/
override fun onBufferingStart(mKtvPlayRequest: KaraokePlayRequest) {
Logger.d(TAG, "onBufferingStart.")
mIntonationDelegate?.onBuffingStart()
}
/**
* 缓冲结束的回调
* @param mKtvPlayRequest 播放请求对象
*/
override fun onBufferingEnd(mKtvPlayRequest: KaraokePlayRequest) {
Logger.d(TAG, "onBufferingEnd.")
mIntonationDelegate?.onBufferingEnd()
}
/**
* 播放结束的回调
* 处理打分弹窗显示和播放下一首逻辑
* @param request 播放请求对象
* @param endInfo 播放结束信息
*/
override fun onPlayEnd(request: KaraokePlayRequest, endInfo: PlayEndInfo) {
Logger.d(
TAG,
"onPlayEnd " + multiScoreDialog?.isShowing + " " + isScoreDialogShown + " isEnd " + endInfo.isPlayFinish + " isSegmentPlay " + request.songInfoObject.isSegmentPlay
)
isPlayEnd = true
if (endInfo.isPlayFinish && !isShowScore()) {
playNextIfNeed()
}
if (multiScoreDialog?.isShowing != true && !isScoreDialogShown) {
//五维打分结果还没有回调,最多等待3s
mHandler.postDelayed({
if (multiScoreDialog?.isShowing == false) {
onPlayEndInternal(endInfo)
}
}, 3000L)
} else {
onPlayEndInternal(endInfo)
}
}
/**
* 进度跳转完成的回调
* 同步MIDI视图到指定位置
* @param request 播放请求对象
* @param position 跳转位置
*/
override fun onSeekComplete(request: KaraokePlayRequest, position: Long) {
Logger.d(TAG, "onSeekComplete currentTime $position")
if (KtvPlayerConfig.getInstance().isCloseScoreUI) {
return
}
mIntonationDelegate?.seekMidi(position)
}
}
/**
* 播放结束内部处理
* 处理播放结束后的逻辑,包括播放下一首和进入编辑模式
* @param endInfo 播放结束信息
*/
private fun onPlayEndInternal(endInfo: PlayEndInfo){
mHandler.post {
// mIntonationDelegate?.onSongPlayComplete()
// mIntonationDelegate?.stopMidi()
// mIntonationDelegate?.releaseMidi()
val openScore =
viewModel.currSongInfo().value?.mNoteBytes != null && viewModel.currSongInfo().value?.songType == SongType.SONG_TYPE_K_SONG
if (endInfo.isPlayFinish && (!openScore || mScoreDialog?.isShowing == false)) {
playNextIfNeed()
}
//如果是由finishScore触发的打分弹窗,那么就显示编辑页面
if (isEnterEdit) {
viewModel.currEditSongInfo().value = viewModel.currSongInfo().value
PlayConsole.get().editMode.value = true
}
}
}
/**
* 点击打分弹窗的左侧按钮的回调(保存发布)
* 停止播放并进入编辑模式
* @param dialog 弹窗对象
*/
override fun onClickLeftBtn(dialog: DialogInterface?) {
dialog?.dismiss()
isEnterEdit = true
if (isPlayEnd) {
viewModel.currEditSongInfo().value = viewModel.currSongInfo().value
PlayConsole.get().editMode.value = true
}
viewModel.currPlayer()?.stop()
PopupManager.get().dismiss(PlayConsolePopupView::class.java.name, null)
}
/**
* 点击打分弹窗的右侧按钮的回调(下一首)
* 播放下一首歌曲
* @param dialog 弹窗对象
*/
override fun onClickRightBtn(dialog: DialogInterface?) {
playNextIfNeed()
dialog?.dismiss()
}
/**
* 点击下一首按钮的回调
* 播放下一首并关闭打分弹窗
*/
override fun onClickNextSong() {
playNextIfNeed()
dismissScoreDialog()
}
/**
* 检查是否显示打分弹窗
* @param scene 触发场景
* @return true表示显示了弹窗,false表示未显示
*/
private fun checkShowScoreDialog(scene: String?): Boolean {
if (!shouldShowScoreDialog()) {
if(Objects.equals(scene, TotalScoreResultInfo.SCENE_PLAY_NEXT)) {
playNextIfNeed()
}
return false
}
viewModel.currPlayer()?.pause()
val scoreResultInfo = getManualTriggerResultInfo(scene)
if(scoreResultInfo == null) {
if(Objects.equals(scene, TotalScoreResultInfo.SCENE_PLAY_NEXT)) {
playNextIfNeed()
}
return false
}
if (scoreResultInfo.isMultiScore) {
return checkShowMultiScoreDialog(scoreResultInfo)
} else {
return checkShowNormalScoreDialog(scoreResultInfo)
}
}
/**
* 检查并显示普通打分弹窗(单维度打分)
* @param totalScoreResult 总打分结果信息
* @return true表示显示了弹窗,false表示未显示
*/
private fun checkShowNormalScoreDialog(totalScoreResult: TotalScoreResultInfo?): Boolean {
PlayConsole.get().scoreResultInfo.postValue(totalScoreResult)
val scene = totalScoreResult?.scoreScene ?: ""
if(totalScoreResult == null) {
if(!Objects.equals(scene, TotalScoreResultInfo.SCENE_EXIT_PAGE)) {
playNextIfNeed()
}
return false
}
if (!isAlive() || totalScoreResult.totalScore <= 0) {
if(!Objects.equals(scene, TotalScoreResultInfo.SCENE_EXIT_PAGE)) {
playNextIfNeed()
}
return false
}
Logger.i(TAG, "checkShowNormalScoreDialog result: $totalScoreResult")
containerView?.post {
PopupManager.get().forceShow(ScorePopupView::class.java.name)
val dialog = ScoreDialog(
getActivity(),
ScoreDialogInfo(
viewModel.currSongInfo().value?.songName ?: "",
totalScoreResult.totalScore,
totalScoreResult.scoreLevel,
0,
true,
PlayerManager.playList.size() > 0
)
)
// if (viewModel.getPkChorus()?.isChorus()==true){
// Logger.i(TAG,"dialog.setChorusInfo chorusRank=${chorusRank}")
// if (chorusRank!=-1){
// dialog.setChorusInfo(chorusRank,pkChorusIniator,pkChorusChallenger)
// }
// }else if(viewModel.getPkChorus()?.isPk()==true){
// Logger.i(TAG,"dialog.setPkInfo UserType=${pkChorusIniator.getUserType()}")
// if (pkChorusIniator.getUserType()!= PkAndChorusUserType.UNKNOWN){
// dialog.setPkInfo(pkChorusIniator,pkChorusChallenger)
// }
// }
dialog.setOnClickListener(this@DemoScoreModule)
dialog.show()
mScoreDialog = dialog
setScoreDialogShown(true, totalScoreResult)
}
return true
}
/**
* 显示五维打分弹窗
* scoreResult是总分数信息,multiScoreResultInfo是最新分数信息,先不合并
*/
private fun checkShowMultiScoreDialog(totalScoreResult: TotalScoreResultInfo?): Boolean {
val scene = totalScoreResult?.scoreScene ?: ""
if(totalScoreResult == null) {
if(!Objects.equals(scene, TotalScoreResultInfo.SCENE_EXIT_PAGE)) {
playNextIfNeed()
}
return false
}
val scoreResult = totalScoreResult.multiScoreResult
val cause= totalScoreResult.scoreScene
if (scoreResult == null) {
if(!Objects.equals(scene, TotalScoreResultInfo.SCENE_EXIT_PAGE)) {
playNextIfNeed()
}
return false
}
Logger.i(TAG, "checkShowMultiScoreDialog cause: $cause, result: $scoreResult")
if (!isAlive() || this.multiScoreResultInfo == null || KtvPlayerConfig.getInstance().isCloseScoreUI) {
Logger.d(
TAG,
"setMultiScoreData fail bcs isNotAlive: " + (this.multiScoreResultInfo == null)
)
if(!Objects.equals(scene, TotalScoreResultInfo.SCENE_EXIT_PAGE)) {
playNextIfNeed()
}
return false
}
if (scoreResult.lastSentenceIndex < 0 || scoreResult.totalSentences <= 0
) {
if(!Objects.equals(scene, TotalScoreResultInfo.SCENE_EXIT_PAGE)) {
playNextIfNeed()
}
return false
}
val arrayList: ArrayList<RadarScore> = ArrayList<RadarScore>()
val adjust = MultiScoreAdjustor()
adjust.totalStableScore = scoreResult.totalStableScore
adjust.totalRhythmScore = scoreResult.totalRhythmScore
adjust.totalSkillScore = scoreResult.totalSkillScore
adjust.totalLongToneScore = scoreResult.totalLongToneScore
adjust.totalDynamicScore = scoreResult.totalDynamicScore
//技巧这个维度的分数并不好打 或者打的偏低 这里做个兜底策略
val originTotalSkillScore: Int = adjust.totalSkillScore
//originTotalSkillScore只会>=0
if (originTotalSkillScore >= 0) {
//其他四个维度的总分的平均值
//如果技巧的总分低于其他四个维度的总分的平均值 那么需要对技巧分进行加权
val totalMultiScoreExpSkill: Int = adjust.getTotalMultiScoreExpSkill()
if (totalMultiScoreExpSkill - originTotalSkillScore > 0) {
val random = Random()
var skillScoreAfterWeight = random.nextInt(10) + totalMultiScoreExpSkill
if (skillScoreAfterWeight > 100) skillScoreAfterWeight = 100
adjust.totalSkillScore = skillScoreAfterWeight
scoreResult.totalSkillScore = skillScoreAfterWeight
Logger.i(TAG, "originTotalSkillScore: $originTotalSkillScore skillScoreAfterWeight: $skillScoreAfterWeight")
}
}
arrayList.add(RadarScore(adjust.totalStableScore, "音准"))
arrayList.add(RadarScore(adjust.totalRhythmScore, "节奏"))
arrayList.add(RadarScore(adjust.totalSkillScore, "技巧"))
arrayList.add(RadarScore(adjust.totalLongToneScore, "气息"))
arrayList.add(RadarScore(adjust.totalDynamicScore, "情感"))
val totalScore = mIntonationDelegate?.getTotalScore() ?: 0
if (totalScore <= 0) {
if(!Objects.equals(scene, TotalScoreResultInfo.SCENE_EXIT_PAGE)) {
playNextIfNeed()
}
return false
}
totalScoreResult.totalScore = totalScore
val singSentences = Math.min(scoreResult.lastSentenceIndex + 1, scoreResult.totalSentences)
totalScoreResult.scoreLevel= ScoreUtil.getRankIndex(totalScore, singSentences)
totalScoreResult.scoreLevelString = ""
containerView?.post{
val scoreDialog = MultiScoreDialog(getActivity())
multiScoreDialog=scoreDialog
scoreDialog.setTotalMultiScore(adjust.getTotalMultiScore())
// if (viewModel.getPkChorus()?.isChorus()==true){
// Logger.i(TAG,"multi scoreDialog.setChorusInfo chorusRank=${chorusRank}")
// if (chorusRank!=-1){
// scoreDialog.setChorusInfo(chorusRank,pkChorusIniator,pkChorusChallenger)
// }
// }else if(viewModel.getPkChorus()?.isPk()==true){
// Logger.i(TAG,"multi scoreDialog.setPkInfo UserType=${pkChorusIniator.getUserType()}")
// if (pkChorusIniator.getUserType()!= PkAndChorusUserType.UNKNOWN){
// scoreDialog.setPkInfo(pkChorusIniator,pkChorusChallenger)
// }
// }
scoreDialog.songName(viewModel.currSongInfo().value?.songName ?: "")
scoreDialog.scoreValue(totalScoreResult.totalScore)
scoreDialog.scoreLevel(totalScoreResult.scoreLevel)
scoreDialog.setOnClickListener(this@DemoScoreModule)
scoreDialog.setLeftBtnName("保存发布")
scoreDialog.setRightBtnName("下一首")
scoreDialog.setData(arrayList)
scoreDialog.show()
scoreDialog.refreshMultiScoreUI()
setScoreDialogShown(true, totalScoreResult)
}
return true
}
/**
* 判断是否应该显示打分弹窗
* @return true表示应该显示,false表示不应该显示
*/
private fun shouldShowScoreDialog(): Boolean {
if(isScoreDialogShown || !isShowScore()) {
return false
}
// 如果没有达到保存录音文件阈值,不显示打分弹窗
if(viewModel.currPlayer()?.hasReachSaveRecordFileThreshold() != true) {
return false
}
return true
}
/**
* 返回键事件回调
* @param dialog 弹窗对象
*/
override fun onKeyBackEvent(dialog: DialogInterface?) {
onKeyBackInternal(dialog, "onKeyBackEvent")
}
/**
* 点击保存并发布按钮的回调
* 进入编辑模式并停止播放
*/
override fun onClickSaveAndPush() {
Logger.d(TAG, "onClickSaveAndPush")
val scoreScene = PlayConsole.get().scoreResultInfo.value?.scoreScene
dismissScoreDialog()
isEnterEdit = true
viewModel.currEditSongInfo().value = viewModel.currSongInfo().value
PlayConsole.get().editMode.value = true
//获取分数结果后就可以停止播放器了
if(Objects.equals(scoreScene, TotalScoreResultInfo.SCENE_PLAY_NEXT)
|| Objects.equals(scoreScene, TotalScoreResultInfo.SCENE_EXIT_PAGE)) {
viewModel.currPlayer()?.stop()
}
}
/**
* 倒计时结束的回调
* 自动播放下一首
* @param totalCountDownTime 总倒计时时间
*/
override fun onCountDownFinish(totalCountDownTime: Int) {
Logger.d(TAG, "onCountDownFinish")
playNextIfNeed()
}
/**
* 页面销毁的回调
* 清理资源和监听器
*/
override fun onDismiss() {
mHandler.removeCallbacksAndMessages(null)
viewModel.currPlayer()?.removeOnScoreListener(scoreListenerImpl)
viewModel.currPlayer()?.removeCallback(ktvScoreCallBackImpl)
mIntonationDelegate?.stopMidi()
mIntonationDelegate?.releaseMidi()
dismissScoreDialog()
super.onDismiss()
}
/**
* 分发按键事件
* 处理返回键事件,在适当时机显示打分弹窗
* @param keyEvent 按键事件
* @return true表示消费了事件,false表示未消费
*/
override fun dispatchKeyEvent(keyEvent: KeyEvent): Boolean {
Logger.i(TAG, "dispatchKeyEvent $keyEvent")
if(keyEvent.action == KeyEvent.ACTION_DOWN && keyEvent.keyCode == KeyEvent.KEYCODE_BACK) {
if(checkShowScoreDialog(TotalScoreResultInfo.SCENE_EXIT_PAGE)) {
return true
}
}
return false
}
/**
* 关闭打分弹窗
* 关闭普通打分弹窗和五维打分弹窗
*/
private fun dismissScoreDialog() {
Logger.i(TAG, "dismissScoreDialog")
if (mScoreDialog?.isShowing == true) {
mScoreDialog?.dismiss()
PopupManager.get().dismiss(ScorePopupView::class.java.name, null)
}
if (multiScoreDialog?.isShowing==true){
multiScoreDialog?.dismiss()
}
}
/**
* 如果需要则播放下一首
* 根据播放列表和歌曲类型决定是播放下一首还是关闭页面
*/
fun playNextIfNeed() {
dismissScoreDialog()
Logger.d(TAG, "playNextIfNeed PlayConsole.get().replay.value " + PlayConsole.get().replay.value)
if (PlayerManager.playList.size() <= 0 && PlayConsole.get().editMode.value == false
|| PlayConsole.get().songType.value == SongType.SONG_TYPE_UGC_SONG || PlayConsole.get().songType.value == SongType.SONG_TYPE_KG_MV
|| PlayConsole.get().songType.value == SongType.SONG_TYPE_KSONG_LISTEN
) {
Logger.d(TAG, "finish self")
getActivity()?.finish()
} else {
PlayerManager.playNext()
}
if (PlayConsole.get().replay.value == true) {
return
}
}
/**
* 判断页面是否还活着
* @return true表示页面正常,false表示页面已销毁
*/
fun isAlive(): Boolean {
val activity = getActivity()
return activity != null && !activity.isFinishing
}
/**
* 获取Activity实例
* @return Activity实例,可能为null
*/
private fun getActivity(): Activity? {
return when (owner) {
is Fragment -> {
(owner as Fragment).activity
}
is Activity -> {
owner as Activity
}
else -> {
null
}
}
}
/**
* 返回键内部处理
* 根据不同场景处理返回键逻辑
* @param dialog 弹窗对象
* @param cause 触发原因
*/
private fun onKeyBackInternal(dialog: DialogInterface?, cause: String?) {
val scoreScene = PlayConsole.get().scoreResultInfo.value?.scoreScene
val playState = viewModel.currPlayer()?.playState
Logger.d(TAG, "$cause, scoreScene: $scoreScene, playState: $playState")
if (Objects.equals(scoreScene, TotalScoreResultInfo.SCENE_PLAY_NEXT)) {
if (playState == VideoState.STATE_PAUSE) {
viewModel.currPlayer()?.resume()
}
} else if (Objects.equals(scoreScene, TotalScoreResultInfo.SCENE_EXIT_PAGE)) {
if (playState == VideoState.STATE_PAUSE) {
viewModel.currPlayer()?.resume()
}
} else {
playNextIfNeed()
dialog?.dismiss()
}
}
}