Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,6 @@ object CharactersDataSource {
fun getCharacterById(id: Int): Character? {
return charactersCache?.firstOrNull { it.id == id }
}
fun resetCharacters(context: Context) {
charactersCache = createCharacters(context).toMutableList()
}

private fun createCharacters(context: Context): List<Character> = listOf(
Character(
id = 1,
Expand Down
31 changes: 31 additions & 0 deletions app/src/main/java/com/thechance/qurio/data/local/UserDataSource.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.thechance.qurio.data.local
import android.content.Context
import com.thechance.qurio.R
import com.thechance.qurio.domain.entity.Character


object UserDataSource{

private var currentCharacter: Character?=null

private var lives: Int = 4
private var points: Int = 700
private var awards: Int = 0
private var currentStreak: Int = 0

fun getUserCharacter() = currentCharacter
fun updateUserCharacter(newCharacter: Character) { currentCharacter = newCharacter }

fun getUserStatistics(): Triple<Int, Int, Int> = Triple(lives, points, awards)
fun updateLives(newLives: Int) { lives = newLives }

fun updatePoints(newPoints: Int) { points = newPoints }
fun addPoints(pointsToAdd: Int) { points += pointsToAdd }
fun updateAwards(newAwards: Int) { awards = newAwards }
fun incrementAwards() { awards++ }

fun getUserStreak() = currentStreak
fun updateStreak(newStreak: Int) { currentStreak = newStreak }
fun incrementStreak() { currentStreak++ }
fun resetStreak() { currentStreak = 0 }
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import com.thechance.qurio.domain.entity.Character
import com.thechance.qurio.domain.repository.CharactersRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import javax.inject.Inject

class CharactersRepositoryImpl(private val context: Context) : CharactersRepository {
class CharactersRepositoryImpl @Inject constructor(private val context: Context) : CharactersRepository {

override suspend fun getAllCharacters(): List<Character> = withContext(Dispatchers.IO) {
CharactersDataSource.getAllCharacters(context)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.thechance.qurio.data.repository

import android.content.Context
import com.thechance.qurio.data.local.CharactersDataSource
import com.thechance.qurio.data.local.UserDataSource
import com.thechance.qurio.domain.entity.Character
import com.thechance.qurio.domain.repository.user.UserRepository
import javax.inject.Inject

class UserRepositoryImpl @Inject constructor(
private val context: Context,
) : UserRepository {


override suspend fun getUserCharacter(): Character {
return UserDataSource?.getUserCharacter() ?: CharactersDataSource.getAllCharacters(context=context)[0]
}

override suspend fun updateUserCharacter(character: Character) {
UserDataSource.updateUserCharacter(character)
}

override suspend fun getUserStatistics(): Triple<Int, Int, Int> {
return UserDataSource.getUserStatistics()
}

override suspend fun getUserStreak(): Int {
return UserDataSource.getUserStreak()
}

override suspend fun updateStreak(streak: Int) {
UserDataSource.updateStreak(streak)
}

override suspend fun incrementStreak() {
UserDataSource.incrementStreak()
}

override suspend fun addPoints(points: Int) {
UserDataSource.addPoints(points)
}

override suspend fun updateLives(lives: Int) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can u add also current heart live , or get live heart ?cuz i want it in game screen so i can make a check when i lose and remove heart

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Screenshot 2025-10-18 at 5 42 56 AM

already exist

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know I saw it, but sorry for overthinking, my way of thinking is I'm here i wanna implement in game screen so the name i think will express it is get live heart or smth like that, so when i lose a game i easily can use update live and make sure it's updated in home screen, I think we can put the name is get live heart so we can update &get in same time

UserDataSource.updateLives(lives)
}

override suspend fun updatePoints(points: Int) {
UserDataSource.updatePoints(points)
}

}
6 changes: 6 additions & 0 deletions app/src/main/java/com/thechance/qurio/di/DataModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ import androidx.datastore.preferences.preferencesDataStoreFile
import androidx.room.Room
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import com.thechance.qurio.data.ApiService
import com.thechance.qurio.data.local.UserDataSource
import com.thechance.qurio.data.local.dao.GameSessionDao
import com.thechance.qurio.data.util.LoggingInterceptor
import com.thechance.qurio.presentation.main.QurioApp
import com.thechance.qurio.data.remote.service.GameService
import com.thechance.qurio.data.repository.GameRepositoryImpl
import com.thechance.qurio.domain.repository.game.GameRepository
import com.thechance.qurio.data.local.dao.PlayedGameDao
import com.thechance.qurio.data.local.database.QurioDatabase
import com.thechance.qurio.data.remote.service.GameService
Expand Down
10 changes: 9 additions & 1 deletion app/src/main/java/com/thechance/qurio/di/FragmentModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ package com.thechance.qurio.di

import com.thechance.qurio.presentation.screen.achievements.AchievementsDialogFragment
import com.thechance.qurio.presentation.screen.buylife.BuyLifeDialogFragment
import com.thechance.qurio.presentation.screen.characters.CharacterBuyDialogFragment
import com.thechance.qurio.presentation.screen.characters.CharacterDescDialogFragment
import com.thechance.qurio.presentation.screen.characters.CharacterDialogFragment
import com.thechance.qurio.presentation.screen.difficulty.DifficultyLevelDialogFragment
import com.thechance.qurio.presentation.screen.example.ExampleFragment
import com.thechance.qurio.presentation.screen.games_screen.GamesFragment
Expand Down Expand Up @@ -46,7 +49,12 @@ abstract class FragmentModule {

@ContributesAndroidInjector
abstract fun contributeBuyLifeDialogFragment(): BuyLifeDialogFragment

@ContributesAndroidInjector
abstract fun contributeCharacterDialogFragment(): CharacterDialogFragment
@ContributesAndroidInjector
abstract fun contributeCharacterDescDialogFragment(): CharacterDescDialogFragment
@ContributesAndroidInjector
abstract fun contributeCharacterBuyDialogFragment(): CharacterBuyDialogFragment
@ContributesAndroidInjector
abstract fun contributeDifficultyLevelDialogFragment(): DifficultyLevelDialogFragment
}
14 changes: 14 additions & 0 deletions app/src/main/java/com/thechance/qurio/di/RepositoryModule.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.thechance.qurio.di

import com.thechance.qurio.data.repository.AchievementsRepositoryImpl
import com.thechance.qurio.data.repository.CharactersRepositoryImpl
import com.thechance.qurio.data.repository.ExampleRepositoryImpl
import com.thechance.qurio.data.repository.TGameRepository
import com.thechance.qurio.data.repository.TGameRepositoryImpl
Expand All @@ -9,11 +10,14 @@ import com.thechance.qurio.data.repository.GameSessionRepositoryImpl
import com.thechance.qurio.data.repository.ResultsRepositoryImpl
import com.thechance.qurio.data.repository.UserPreferencesRepositoryImpl
import com.thechance.qurio.data.repository.GameRepositoryImpl
import com.thechance.qurio.data.repository.UserRepositoryImpl
import com.thechance.qurio.domain.repository.AchievementsRepository
import com.thechance.qurio.domain.repository.CharactersRepository
import com.thechance.qurio.domain.repository.ExampleRepository
import com.thechance.qurio.domain.repository.ResultsRepository
import com.thechance.qurio.domain.repository.UserPreferencesRepository
import com.thechance.qurio.domain.repository.game.GameRepository
import com.thechance.qurio.domain.repository.user.UserRepository
import dagger.Binds
import dagger.Module

Expand Down Expand Up @@ -54,4 +58,14 @@ abstract class RepositoryModule {
abstract fun bindGameRepository(
impl: GameRepositoryImpl
): GameRepository


@Binds
abstract fun bindUserRepository(
impl: UserRepositoryImpl
): UserRepository
@Binds
abstract fun bindCharacterRepository(
impl: CharactersRepositoryImpl
): CharactersRepository
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.thechance.qurio.domain.entity

data class UserStatistics(
val lives: Int,
val points: Int,
val awards: Int
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.thechance.qurio.domain.repository.user

import com.thechance.qurio.domain.entity.Character

interface UserRepository {
suspend fun getUserCharacter(): Character
suspend fun updateUserCharacter(character: Character)
suspend fun getUserStatistics(): Triple<Int, Int, Int>
suspend fun getUserStreak(): Int
suspend fun updateStreak(streak: Int)
suspend fun incrementStreak()
suspend fun addPoints(points: Int)
suspend fun updateLives(lives: Int)
suspend fun updatePoints(points: Int)
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,13 @@ class BuyLifeDialogFragment : DialogFragment(), BuyLifeView {
// Optionally hide a loading indicator
binding.buttonBuy.isEnabled = true
}
override fun enableBuyButton() {
binding.buttonBuy.isEnabled = true
}

override fun disableBuyButton() {
binding.buttonBuy.isEnabled = false
}
override fun showError(message: String) {
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
}
Expand All @@ -99,6 +105,12 @@ class BuyLifeDialogFragment : DialogFragment(), BuyLifeView {
showError("Failed to buy life")
}
}
override fun onLifeBoughtSuccessfully() {
parentFragmentManager.setFragmentResult("life_bought", Bundle().apply {
putBoolean("success", true)
})
dismiss()
}

override fun onDestroyView() {
super.onDestroyView()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,73 @@
package com.thechance.qurio.presentation.screen.buylife

import com.thechance.qurio.domain.repository.user.UserRepository
import com.thechance.qurio.presentation.base.BasePresenter
import javax.inject.Inject

class BuyLifePresenter @Inject constructor() : BasePresenter<BuyLifeView>() {
class BuyLifePresenter @Inject constructor(
private val userRepository: UserRepository
) : BasePresenter<BuyLifeView>() {

private var lifeCount: Int = 1
private var price: Int = 200
private var userPoints: Int = 0

fun loadLifeInfo() {
tryToExecute(
callee = { userRepository.getUserStatistics() },
onSuccess = ::onLoadLifeInfoSuccess,
onError = ::onError
)
}

private fun onLoadLifeInfoSuccess(statistics: Triple<Int, Int, Int>) {
val (_, points, _) = statistics
userPoints = points

view.showLifeCount(lifeCount)
view.showPrice(price)

if (userPoints < price) {
view.showError("Not enough points to buy a life!")
view.disableBuyButton()
} else {
view.enableBuyButton()
}
}

fun buyLife() {
view.showLoading()
// TODO: Add the business logic

// Simulate success
tryToExecute(
callee = { userRepository.getUserStatistics() },
onSuccess = ::onBuyLifeSuccess,
onError = ::onBuyLifeError
)
}

private suspend fun onBuyLifeSuccess(statistics: Triple<Int, Int, Int>) {
val (lives, points, _) = statistics

if (points >= price) {
userRepository.updateLives(lives + 1)
userRepository.updatePoints(points - price)
view.hideLoading()
view.onLifeBoughtSuccessfully()
} else {
view.hideLoading()
view.showError("Not enough points to buy a life!")
view.disableBuyButton()
view.onLifeBought(false)
}
}

private fun onBuyLifeError(throwable: Throwable) {
view.hideLoading()
view.onLifeBought(true)
view.showError(throwable.message ?: "Failed to buy life")
view.onLifeBought(false)
}
}

private fun onError(throwable: Throwable) {
view.showError(throwable.message ?: "Failed to load life info")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ interface BuyLifeView : BaseView {
fun showPrice(price: Int)
fun showLoading()
fun hideLoading()
fun onLifeBoughtSuccessfully()
fun showError(message: String)
fun onLifeBought(success: Boolean)
fun enableBuyButton()
fun disableBuyButton()
}

Loading
Loading