coding-blocks/CBOnlineApp

View on GitHub
app/src/main/java/com/codingblocks/cbonlineapp/mycourse/MyCourseRepository.kt

Summary

Maintainability
F
5 days
Test Coverage
package com.codingblocks.cbonlineapp.mycourse

import com.codingblocks.cbonlineapp.database.BookmarkDao
import com.codingblocks.cbonlineapp.database.ContentDao
import com.codingblocks.cbonlineapp.database.CourseWithInstructorDao
import com.codingblocks.cbonlineapp.database.HBRankDao
import com.codingblocks.cbonlineapp.database.RunAttemptDao
import com.codingblocks.cbonlineapp.database.RunPerformanceDao
import com.codingblocks.cbonlineapp.database.SectionDao
import com.codingblocks.cbonlineapp.database.SectionWithContentsDao
import com.codingblocks.cbonlineapp.database.models.BookmarkModel
import com.codingblocks.cbonlineapp.database.models.ContentCodeChallenge
import com.codingblocks.cbonlineapp.database.models.ContentCsvModel
import com.codingblocks.cbonlineapp.database.models.ContentDocument
import com.codingblocks.cbonlineapp.database.models.ContentLecture
import com.codingblocks.cbonlineapp.database.models.ContentModel
import com.codingblocks.cbonlineapp.database.models.ContentQnaModel
import com.codingblocks.cbonlineapp.database.models.ContentVideo
import com.codingblocks.cbonlineapp.database.models.HBRankModel
import com.codingblocks.cbonlineapp.database.models.RunAttemptModel
import com.codingblocks.cbonlineapp.database.models.RunPerformance
import com.codingblocks.cbonlineapp.database.models.SectionContentHolder
import com.codingblocks.cbonlineapp.database.models.SectionModel
import com.codingblocks.cbonlineapp.util.extensions.sameAndEqual
import com.codingblocks.onlineapi.CBOnlineLib
import com.codingblocks.onlineapi.ResultWrapper
import com.codingblocks.onlineapi.models.LectureContent
import com.codingblocks.onlineapi.models.PerformanceResponse
import com.codingblocks.onlineapi.models.RankResponse
import com.codingblocks.onlineapi.models.ResetRunAttempt
import com.codingblocks.onlineapi.models.RunAttempts
import com.codingblocks.onlineapi.models.SendFeedback
import com.codingblocks.onlineapi.safeApiCall
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

class MyCourseRepository(
    private val sectionWithContentsDao: SectionWithContentsDao,
    private val contentsDao: ContentDao,
    private val sectionDao: SectionDao,
    private val courseWithInstructorDao: CourseWithInstructorDao,
    private val runPerformanceDao: RunPerformanceDao,
    private val bookmarkDao: BookmarkDao,
    private val hbRankDao: HBRankDao,
    private val attemptDao: RunAttemptDao
) {
    suspend fun getSectionWithContentNonLive(attemptId: String) = sectionWithContentsDao.getSectionWithContentNonLive(attemptId)

    fun getSectionWithContent(attemptId: String) = sectionWithContentsDao.getSectionWithContent(attemptId)

//    fun getSectionWithContentComputer(attemptId: String) = sectionWithContentsDao.getSectionWithContentComputed(SimpleSQLiteQuery("""
// SELECT s.*, swc.content_id as "content_id", c.contentDuration as "contentDuration", s."sectionOrder" as "sectionOrder", count (c.ccid)  as "completedContents" FROM SectionModel s LEFT OUTER join SectionWithContent swc on swc."section_id" = s.csid LEFT OUTER join ContentModel c on c.ccid = swc.content_id where s.attemptId = 44872 ORDER BY s."sectionOrder"         """))

    fun getRunById(attemptId: String) = courseWithInstructorDao.getRunById(attemptId)

    fun getRunStats(attemptId: String) = runPerformanceDao.getPerformance(attemptId)

    fun getNextContent(attemptId: String) = sectionWithContentsDao.resumeCourse(attemptId)

    suspend fun insertSections(runAttempt: RunAttempts, refresh: Boolean = false) {
        val runAttemptModel = RunAttemptModel(
            runAttempt.id,
            runAttempt.certificateApproved,
            runAttempt.end,
            runAttempt.premium,
            runAttempt.revoked,
            runAttempt.approvalRequested,
            runAttempt.doubtSupport ?: "",
            runAttempt.completedContents,
            runAttempt.lastAccessedAt ?: "",
            runAttempt.run?.id ?: "",
            runAttempt.certifcate?.url ?: "",
            runAttempt.runTier ?: "PREMIUM",
            runAttempt.paused,
            runAttempt.pauseTimeLeft,
            runAttempt.lastPausedLeft
        )
        attemptDao.update(runAttemptModel)

        runAttempt.run?.sections?.forEach { courseSection ->
            courseSection.run {
                val newSection = SectionModel(
                    id, name ?: "",
                    order ?: 0, premium ?: false, status ?: "",
                    runId ?: "", runAttempt.id
                )
                if (refresh)
                    sectionDao.insert(newSection)
                else
                    sectionDao.insertNew(newSection)
            }
            getSectionContent(courseSection.id, runAttempt.id, courseSection.name)
        }
        deleteOldSections(runAttempt.run?.sections?.map { it.id }!!, runAttempt.run?.id)
    }

    /**
     *Function to delete [SectionModel] which are no longer part of course content.
     */
    private suspend fun deleteOldSections(newList: List<String>, id: String?) {
        val oldList = withContext(Dispatchers.IO) { sectionDao.getCourseSection(id!!) }
        oldList.forEach {
            if (!newList.contains(it)) {
                sectionDao.deleteSection(it)
            }
        }
    }

    private suspend fun getSectionContent(sectionId: String, runAttemptId: String, name: String?) {
        when (val response = safeApiCall { CBOnlineLib.onlineV2JsonApi.getSectionContents(sectionId) }) {
            is ResultWrapper.Success -> {
                if (response.value.isSuccessful)
                    response.value.body()?.let {
                        insertContents(it, runAttemptId, sectionId, name)
                    }
            }
        }
    }

    private suspend fun insertContents(
        contentList: List<LectureContent>,
        attemptId: String,
        sectionId: String,
        name: String?
    ) {
        contentList.forEach { content ->
            var contentDocument =
                ContentDocument()
            var contentLecture =
                ContentLecture()
            var contentVideo =
                ContentVideo()
            var contentQna =
                ContentQnaModel()
            var contentCodeChallenge =
                ContentCodeChallenge()
            var contentCsv =
                ContentCsvModel()
            var bookmark =
                BookmarkModel()

            when (content.contentable) {
                "lecture" -> content.lecture?.let { contentLectureType ->
                    contentLecture =
                        ContentLecture(
                            contentLectureType.id,
                            contentLectureType.name
                                ?: "",
                            contentLectureType.duration
                                ?: 0,
                            contentLectureType.videoId
                                ?: "",
                            content.sectionContent?.sectionId
                                ?: "",
                            contentLectureType.updatedAt
                        )
                }
                "document" -> content.document?.let { contentDocumentType ->
                    contentDocument =
                        ContentDocument(
                            contentDocumentType.id,
                            contentDocumentType.name
                                ?: "",
                            contentDocumentType.pdfLink
                                ?: "",
                            content.sectionContent?.sectionId
                                ?: "",
                            contentDocumentType.updatedAt
                        )
                }
                "video" -> content.video?.let { contentVideoType ->
                    contentVideo =
                        ContentVideo(
                            contentVideoType.id,
                            contentVideoType.name
                                ?: "",
                            contentVideoType.duration
                                ?: 0L,
                            contentVideoType.description
                                ?: "",
                            contentVideoType.url
                                ?: "",
                            content.sectionContent?.sectionId
                                ?: "",
                            contentVideoType.updatedAt
                        )
                }
                "qna" -> content.qna?.let { contentQna1 ->
                    contentQna =
                        ContentQnaModel(
                            contentQna1.id,
                            contentQna1.name
                                ?: "",
                            contentQna1.qId
                                ?: 0,
                            content.sectionContent?.sectionId
                                ?: "",
                            contentQna1.updatedAt
                        )
                }
                "code-challenge" -> content.codeChallenge?.let { codeChallenge ->
                    contentCodeChallenge =
                        ContentCodeChallenge(
                            codeChallenge.id,
                            codeChallenge.name
                                ?: "",
                            codeChallenge.hbProblemId
                                ?: 0,
                            codeChallenge.hbContestId
                                ?: 0,
                            content.sectionContent?.sectionId
                                ?: "",
                            codeChallenge.updatedAt
                        )
                }
                "csv" -> content.csv?.let {
                    contentCsv =
                        ContentCsvModel(
                            it.id,
                            it.name
                                ?: "",
                            it.description
                                ?: "",
                            it.contentId
                                ?: "",
                            it.updatedAt
                        )
                }
            }

            var progressId = ""
            val status: String
            if (content.progress != null) {
                status =
                    content.progress?.status
                    ?: ""
                progressId =
                    content.progress?.id
                    ?: ""
            } else {
                status =
                    "UNDONE"
            }
            content.bookmark?.let {
                bookmark = BookmarkModel(
                    it.id ?: "",
                    it.runAttemptId ?: "",
                    it.contentId ?: "",
                    it.sectionId ?: "",
                    it.createdAt ?: ""
                )
            }

            val newContent =
                ContentModel(
                    content.id,
                    status,
                    progressId,
                    content.title ?: "",
                    content.duration
                        ?: 0,
                    content.contentable ?: "",
                    content.sectionContent?.order
                        ?: 0,
                    attemptId,
                    name ?: "",
                    contentLecture,
                    contentDocument,
                    contentVideo,
                    contentQna,
                    contentCodeChallenge,
                    contentCsv
                )

            val oldModel: ContentModel? = contentsDao.getContent(content.id)
            if (oldModel != null && !oldModel.sameAndEqual(newContent)) {
                contentsDao.update(newContent)
            } else {
                contentsDao.insertNew(
                    newContent
                )
            }
            if (bookmark.bookmarkUid != "")
                bookmarkDao.insert(bookmark)

            sectionWithContentsDao.insert(
                SectionContentHolder.SectionWithContent(
                    sectionId,
                    content.id,
                    content.sectionContent?.order
                        ?: 0

                )
            )
        }
    }

    suspend fun saveStats(body: PerformanceResponse, id: String) {
        runPerformanceDao.insert(
            RunPerformance(
                id,
                body.performance?.percentile ?: 0,
                body.performance?.remarks ?: "Average",
                body.averageProgress,
                body.userProgress
            )
        )
    }

    suspend fun saveRank(rank: RankResponse) {
        hbRankDao.insert(
            HBRankModel(
                rank.bestRank,
                rank.bestRankAchievedOn,
                rank.currentMonthScore,
                rank.currentOverallRank,
                rank.previousMonthScore,
                rank.previousOverallRank
            )
        )
    }

    fun getHackerBlocksPerformance() = hbRankDao.getRank()

    suspend fun resetProgress(attemptId: ResetRunAttempt) = safeApiCall { CBOnlineLib.api.resetProgress(attemptId) }

    private suspend fun clearCart() = safeApiCall { CBOnlineLib.api.clearCart() }

    suspend fun addToCart(id: String) = safeApiCall {
        clearCart()
        CBOnlineLib.api.addToCart(id)
    }

    suspend fun fetchLeaderboard(runId: String) = safeApiCall { CBOnlineLib.api.leaderboardById(runId) }

    suspend fun fetchSections(attemptId: String) = safeApiCall { CBOnlineLib.onlineV2JsonApi.enrolledCourseById(attemptId) }

    suspend fun getStats(id: String) = safeApiCall { CBOnlineLib.api.getMyStats(id) }

    suspend fun requestApproval(attemptId: String) = safeApiCall { CBOnlineLib.api.requestApproval(attemptId) }

    suspend fun getPerformance() = safeApiCall { CBOnlineLib.api.getHackerBlocksPerformance() }

    suspend fun pauseCourse(id: String?) = safeApiCall {
        checkNotNull(id) { "RunAttempt Id cannot be null" }
        CBOnlineLib.onlineV2JsonApi.pauseCourse(id)
    }

    suspend fun unPauseCourse(id: String?) = safeApiCall {
        checkNotNull(id) { "RunAttempt Id cannot be null" }
        CBOnlineLib.onlineV2JsonApi.unPauseCourse(id)
    }

    suspend fun sendFeedback(id: String, feedback: SendFeedback) = safeApiCall { CBOnlineLib.api.sendFeedback(id, feedback) }

    suspend fun getFeedback(id: String) = safeApiCall { CBOnlineLib.api.getFeedback(id) }

    suspend fun updateRunAttempt(runAttempt: RunAttempts) {
        attemptDao.updatePause(runAttempt.id, runAttempt.paused, runAttempt.pauseTimeLeft, runAttempt.lastPausedLeft)
    }

    fun getRunAttempt(id: String) = attemptDao.getRunAttempt(id)
}