Refactor the SpellBook part of the caracter page. remove the getValue usage.

This commit is contained in:
Thomas Andres Gomez 2023-11-12 17:44:13 +01:00
parent 0d81f72635
commit aa4fd5dc4b
3 changed files with 103 additions and 63 deletions

View file

@ -0,0 +1,88 @@
package com.pixelized.rplexicon.business
import com.pixelized.rplexicon.data.model.AssignedSpell
import com.pixelized.rplexicon.data.model.CharacterSheet
import com.pixelized.rplexicon.data.model.CharacterSheetFire
import com.pixelized.rplexicon.ui.screens.character.composable.actions.SpellHeaderUio
import com.pixelized.rplexicon.ui.screens.character.composable.actions.SpellUio
import com.pixelized.rplexicon.ui.screens.character.factory.SpellUioFactory
import com.pixelized.rplexicon.utilitary.extentions.local.firstSpellSlot
import com.pixelized.rplexicon.utilitary.extentions.local.spell
import javax.inject.Inject
class SpellBookUseCase @Inject constructor(
private val factory: SpellUioFactory,
) {
fun toSpells(
character: CharacterSheet?,
fire: CharacterSheetFire?,
spellBook: List<AssignedSpell>,
): List<Pair<SpellHeaderUio, List<SpellUio>>> {
// sort the spells by alphabetical order and then by level.
val spells = spellBook
.sortedBy { it.spell.name }
.sortedBy { it.spell.level }
return when {
// the character sheet is null, build a empty spell list.
character == null -> emptyList()
// Special rules apply for the Warlock.
character.isWarlock -> {
val firstSpellSlot = character.firstSpellSlot()
spells.groupBy { it.spell.level == 0 }.map { entry ->
val header = when {
// it.spell.level == 0, that mean we are in the cantrip section.
entry.key -> SpellHeaderUio(
level = 0,
count = null,
)
// default case, spell level > 1
else -> SpellHeaderUio(
level = firstSpellSlot ?: 1,
count = character.spell(level = firstSpellSlot ?: 1)?.let { max ->
SpellHeaderUio.Count(
value = fire?.spell(level = firstSpellSlot ?: 1) ?: 0,
max = max,
)
}
)
}
val spellList = entry.value.map {
factory.toSpellUio(
assignedSpell = it,
characterSheet = character
)
}
header to spellList
}
}
// Default case, we build a header per level then the list of associated spells.
else -> {
spells.groupBy { it.spell.level }.map { entry ->
val header = SpellHeaderUio(
level = entry.key,
count = when (entry.key) {
0 -> null
else -> character.spell(level = entry.key)?.let { max ->
SpellHeaderUio.Count(
value = fire?.spell(level = entry.key) ?: 0,
max = max
)
}
},
)
val spellList = entry.value.map {
factory.toSpellUio(
assignedSpell = it,
characterSheet = character
)
}
header to spellList
}
}
}
}
}

View file

@ -2,11 +2,15 @@ package com.pixelized.rplexicon.ui.screens.character.factory
import com.pixelized.rplexicon.data.model.AssignedSpell
import com.pixelized.rplexicon.data.model.CharacterSheet
import com.pixelized.rplexicon.data.model.CharacterSheetFire
import com.pixelized.rplexicon.data.model.Property
import com.pixelized.rplexicon.data.repository.character.DescriptionRepository
import com.pixelized.rplexicon.ui.screens.character.composable.actions.SpellHeaderUio
import com.pixelized.rplexicon.ui.screens.character.composable.actions.SpellUio
import com.pixelized.rplexicon.utilitary.extentions.icon
import com.pixelized.rplexicon.utilitary.extentions.local.firstSpellSlot
import com.pixelized.rplexicon.utilitary.extentions.local.icon
import com.pixelized.rplexicon.utilitary.extentions.local.spell
import com.pixelized.rplexicon.utilitary.extentions.modifier
import javax.inject.Inject
@ -14,7 +18,7 @@ class SpellUioFactory @Inject constructor(
private val descriptionRepository: DescriptionRepository,
) {
fun toUio(assignedSpell: AssignedSpell, characterSheet: CharacterSheet): SpellUio {
fun toSpellUio(assignedSpell: AssignedSpell, characterSheet: CharacterSheet): SpellUio {
val hit = assignedSpell.hit?.let { dice ->
val modifier = dice.modifier.sumOf {
when (it) {

View file

@ -7,6 +7,7 @@ import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.viewModelScope
import com.pixelized.rplexicon.R
import com.pixelized.rplexicon.business.SpellBookUseCase
import com.pixelized.rplexicon.data.model.AssignedSpell
import com.pixelized.rplexicon.data.model.CharacterSheet
import com.pixelized.rplexicon.data.model.CharacterSheetFire
@ -21,7 +22,6 @@ import com.pixelized.rplexicon.ui.navigation.screens.characterSheetArgument
import com.pixelized.rplexicon.ui.screens.character.composable.actions.SpellHeaderUio
import com.pixelized.rplexicon.ui.screens.character.composable.actions.SpellLevelUio
import com.pixelized.rplexicon.ui.screens.character.composable.actions.SpellUio
import com.pixelized.rplexicon.ui.screens.character.factory.SpellUioFactory
import com.pixelized.rplexicon.ui.screens.character.pages.chooser.SpellChooserUio
import com.pixelized.rplexicon.utilitary.extentions.icon
import com.pixelized.rplexicon.utilitary.extentions.local.firstSpellSlot
@ -42,7 +42,7 @@ class SpellsViewModel @Inject constructor(
private val firebaseRepository: FirebaseRepository,
private val spellRepository: SpellRepository,
application: Application,
spellFactory: SpellUioFactory,
spellBookUseCase: SpellBookUseCase,
savedStateHandle: SavedStateHandle,
) : AndroidViewModel(application) {
private var character: CharacterSheet? = null
@ -59,11 +59,10 @@ class SpellsViewModel @Inject constructor(
val preparedSpellLevel: State<SpellChooserUio?> get() = _preparedSpellLevel
init {
// TODO rework that part. use factory
viewModelScope.launch(Dispatchers.IO) {
characterRepository.data
.combine(spellRepository.spells) { sheets, spells ->
character = sheets.getValue(characterName)
character = sheets[characterName]
Struct(sheets = sheets, spells = spells)
}
.combine(firebaseRepository.getCharacter(character = characterName)) { struct, fire ->
@ -71,65 +70,14 @@ class SpellsViewModel @Inject constructor(
struct.also { it.fire = fire }
}
.collect { data ->
val spellsBook = data.spells[characterName]
val character = data.sheets.getValue(characterName)
val spells = if (character.isWarlock) {
spellsBook
?.sortedBy { it.spell.name }
?.sortedBy { it.spell.level }
?.groupBy { it.spell.level == 0 }
?.map { entry ->
if (entry.key) {
SpellHeaderUio(
level = 0,
count = null,
)
} else {
val firstSpellSlot = character.firstSpellSlot()
SpellHeaderUio(
level = firstSpellSlot ?: 1,
count = character.spell(level = firstSpellSlot ?: 1)
?.let { max ->
SpellHeaderUio.Count(
value = data.fire.spell(
level = firstSpellSlot ?: 1
) ?: 0,
max = max
)
}
)
} to entry.value.map {
spellFactory.toUio(
assignedSpell = it,
characterSheet = character
)
}
}
?: emptyList()
} else {
spellsBook
?.sortedBy { it.spell.name }
?.sortedBy { it.spell.level }
?.groupBy { it.spell.level }
?.map { entry ->
SpellHeaderUio(
level = entry.key,
count = character.spell(level = entry.key)?.let { max ->
SpellHeaderUio.Count(
value = data.fire.spell(level = entry.key) ?: 0,
max = max
)
},
) to entry.value.map {
spellFactory.toUio(
assignedSpell = it,
characterSheet = character
)
}
}
?: emptyList()
val spells = spellBookUseCase.toSpells(
character = data.sheets[characterName],
fire = data.fire,
spellBook = data.spells[characterName] ?: emptyList(),
)
withContext(Dispatchers.Main) {
_spells.value = spells
}
withContext(Dispatchers.Main) { _spells.value = spells }
}
}
}