Nam integration into the app and some small releated fixes.

This commit is contained in:
Andres Gomez, Thomas (ITDV RL) 2025-01-17 10:48:34 +01:00
parent d5736c99ee
commit 5fdf262bde
13 changed files with 19 additions and 146 deletions

View file

@ -10,7 +10,6 @@ import com.pixelized.rplexicon.data.repository.character.ActionRepository
import com.pixelized.rplexicon.data.repository.character.AlterationRepository
import com.pixelized.rplexicon.data.repository.character.CharacterSheetRepository
import com.pixelized.rplexicon.data.repository.character.DescriptionRepository
import com.pixelized.rplexicon.data.repository.character.EquipmentRepository
import com.pixelized.rplexicon.data.repository.character.ItemsRepository
import com.pixelized.rplexicon.data.repository.character.SkillRepository
import com.pixelized.rplexicon.data.repository.character.SpellRepository
@ -44,7 +43,6 @@ class LauncherViewModel @Inject constructor(
skillRepository: SkillRepository,
descriptionRepository: DescriptionRepository,
itemsRepository: ItemsRepository,
equipmentRepository: EquipmentRepository,
removeConRepository: RemoteConfigRepository // Unused but injected to initialize it.
) : ViewModel() {
@ -112,14 +110,6 @@ class LauncherViewModel @Inject constructor(
_error.emit(FetchErrorUio.Structure(type = Type.INVENTORY))
}
}
val equipment = async {
try {
equipmentRepository.fetchEquipment()
} catch (exception: Exception) {
Log.e(TAG, exception.message, exception)
_error.emit(FetchErrorUio.Structure(type = Type.EQUIPMENT))
}
}
awaitAll(characterSheet)
val alteration = async {
@ -156,7 +146,7 @@ class LauncherViewModel @Inject constructor(
}
awaitAll(order, lexicon, location, quest)
awaitAll(description, inventory, equipment, alteration, action, spell, skill)
awaitAll(description, inventory, alteration, action, spell, skill)
withContext(Dispatchers.Main) {
isLoading = false

View file

@ -5,6 +5,7 @@ import androidx.annotation.StringRes
import com.pixelized.rplexicon.R
data class CharacterSheet(
val active: Boolean,
val name: String,
val race: String?,
val proficiency: Int, // Bonus de maîtrise
@ -22,7 +23,7 @@ data class CharacterSheet(
val spell9: Int?, // level 9 spell slot
val dC: Int?, // offensive saving throw.
val armorClass: Int, // Classe d'armure
val speed: Int, // Vitesse
val speed: Float, // Vitesse
val strength: Int, // Force
val dexterity: Int, // Dextérité
val constitution: Int, // Constitution

View file

@ -33,6 +33,7 @@ class CharacterSheetParser @Inject constructor(
val name = item.parse(column = NAME)
if (name != null) {
CharacterSheet(
active = item.parseBool(column = ACTIVE) ?: false,
name = name,
race = item.parse(column = RACE),
proficiency = item.parseInt(column = MASTERY) ?: 2,
@ -50,7 +51,7 @@ class CharacterSheetParser @Inject constructor(
spell9 = item.parseInt(column = SPELL_LEVEL_9),
dC = item.parseInt(column = DD_SAVE_THROW),
armorClass = item.parseInt(column = ARMOR_CLASS) ?: 10,
speed = item.parseInt(column = SPEED) ?: 10,
speed = item.parseFloat(column = SPEED) ?: 10f,
strength = item.parseInt(column = STRENGTH) ?: 10,
dexterity = item.parseInt(column = DEXTERITY) ?: 10,
constitution = item.parseInt(column = CONSTITUTION) ?: 10,
@ -103,6 +104,7 @@ class CharacterSheetParser @Inject constructor(
}
companion object {
private val ACTIVE = column("Actif")
private val NAME = column("Nom")
private val RACE = column("Race")
private val LEVEL = column("Niveau")
@ -157,6 +159,7 @@ class CharacterSheetParser @Inject constructor(
private val ROWS
get() = listOf(
ACTIVE,
NAME,
RACE,
LEVEL,

View file

@ -1,71 +0,0 @@
package com.pixelized.rplexicon.data.parser.inventory
import com.google.api.services.sheets.v4.model.ValueRange
import com.pixelized.rplexicon.data.model.Equipment
import com.pixelized.rplexicon.data.parser.parserScope
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
import javax.inject.Inject
class EquipmentParser @Inject constructor() {
@Throws(IncompatibleSheetStructure::class)
fun parse(data: ValueRange): Map<String, Equipment> = parserScope {
lateinit var characters: List<String>
val equipments = hashMapOf<String, Equipment.Builder>()
data.forEachRowIndexed { index, row ->
when (index) {
// ignore the first column
0 -> characters = row.drop(1).map { it.toString() }
else -> row.drop(1).forEachIndexed { column, item ->
val character = characters[column]
equipments.getEquipment(name = character).let {
when (row[0]) {
BACKGROUND -> it.background = item.toItem()
HEAD -> it.head = item.toItem()
FACE -> it.face = item.toItem()
NECK -> it.neck = item.toItem()
SHOULDER -> it.shoulder = item.toItem()
BODY -> it.body = item.toItem()
CHEST -> it.chest = item.toItem()
ARM -> it.arm = item.toItem()
HAND -> it.hand = item.toItem()
RING_1 -> it.ring1 = item.toItem()
RING_2 -> it.ring2 = item.toItem()
WAIST -> it.waist = item.toItem()
FOOT -> it.foot = item.toItem()
MAIN_HAND -> it.mainHand = item.toItem()
OFF_HAND -> it.offHand = item.toItem()
}
}
}
}
}
return@parserScope characters.associateWith {
equipments.getEquipment(name = it).build()
}
}
private fun HashMap<String, Equipment.Builder>.getEquipment(name: String) =
this.getOrPut(name) { Equipment.Builder() }
companion object {
private const val BACKGROUND = "Silhouette"
private const val HEAD = "Tête"
private const val FACE = "Visage"
private const val NECK = "Gorge"
private const val SHOULDER = "Épaules"
private const val BODY = "Corp"
private const val CHEST = "Torse"
private const val ARM = "Bras"
private const val HAND = "Mains"
private const val RING_1 = "Anneau 1"
private const val RING_2 = "Anneau 2"
private const val WAIST = "Taille"
private const val FOOT = "Pieds"
private const val MAIN_HAND = "Main droite"
private const val OFF_HAND = "Main gauche"
}
}

View file

@ -1,36 +0,0 @@
package com.pixelized.rplexicon.data.repository.character
import com.pixelized.rplexicon.data.model.Equipment
import com.pixelized.rplexicon.data.parser.inventory.EquipmentParser
import com.pixelized.rplexicon.data.repository.CharacterBinder
import com.pixelized.rplexicon.data.repository.GoogleSheetServiceRepository
import com.pixelized.rplexicon.utilitary.Update
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class EquipmentRepository @Inject constructor(
private val googleRepository: GoogleSheetServiceRepository,
private val equipmentParser: EquipmentParser,
) {
private val _data = MutableStateFlow<Map<String, Equipment>>(emptyMap())
val data: StateFlow<Map<String, Equipment>> get() = _data
var lastSuccessFullUpdate: Update = Update.INITIAL
private set
fun find(name: String?): Equipment? = _data.value[name]
@Throws(IncompatibleSheetStructure::class, Exception::class)
suspend fun fetchEquipment() {
googleRepository.fetch { sheet ->
val request = sheet.get(CharacterBinder.ID, CharacterBinder.EQUIPMENT)
val data = equipmentParser.parse(data = request.execute())
_data.tryEmit(data)
lastSuccessFullUpdate = Update.currentTime()
}
}
}

View file

@ -320,7 +320,10 @@ private fun rememberPortrait(): List<Int> = rememberSaveable {
listOf(
R.drawable.im_brulkhai,
R.drawable.im_leandre,
R.drawable.im_nelia,
// listOf(
// R.drawable.im_nelia,
R.drawable.im_nam,
// ).shuffled().first(),
R.drawable.im_tigrane,
R.drawable.im_unathana,
).shuffled()

View file

@ -105,10 +105,7 @@ enum class CharacterTabUio(@StringRes val label: Int) {
Proficiency(R.string.character_sheet_tab_proficiency),
}
@OptIn(
ExperimentalMaterialApi::class,
ExperimentalFoundationApi::class,
)
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun CharacterSheetScreen(
viewModel: CharacterSheetViewModel = hiltViewModel(),
@ -490,7 +487,6 @@ private fun CharacterScreenPreview(
}
}
@OptIn(ExperimentalFoundationApi::class, ExperimentalMaterialApi::class)
@Composable
private fun BackHandler(
sheetState: ModalBottomSheetState,

View file

@ -10,7 +10,6 @@ import com.pixelized.rplexicon.data.repository.character.ActionRepository
import com.pixelized.rplexicon.data.repository.character.AlterationRepository
import com.pixelized.rplexicon.data.repository.character.CharacterSheetRepository
import com.pixelized.rplexicon.data.repository.character.DescriptionRepository
import com.pixelized.rplexicon.data.repository.character.EquipmentRepository
import com.pixelized.rplexicon.data.repository.character.ItemsRepository
import com.pixelized.rplexicon.data.repository.character.SkillRepository
import com.pixelized.rplexicon.data.repository.character.SpellRepository
@ -33,7 +32,6 @@ class CharacterSheetViewModel @Inject constructor(
private val descriptionRepository: DescriptionRepository,
private val alterationRepository: AlterationRepository,
private val itemsRepository: ItemsRepository,
private val equipmentRepository: EquipmentRepository,
private val actionRepository: ActionRepository,
private val spellRepository: SpellRepository,
private val skillRepository: SkillRepository,
@ -93,16 +91,6 @@ class CharacterSheetViewModel @Inject constructor(
}
}
}
val equipment = async {
if (force || equipmentRepository.lastSuccessFullUpdate.shouldUpdate()) {
try {
equipmentRepository.fetchEquipment()
} catch (exception: Exception) {
Log.e(TAG, exception.message, exception)
_error.emit(FetchErrorUio.Structure(type = Type.EQUIPMENT))
}
}
}
awaitAll(characters)
val alterations = async {
if (force || alterationRepository.lastSuccessFullUpdate.shouldUpdate()) {
@ -144,7 +132,7 @@ class CharacterSheetViewModel @Inject constructor(
}
}
}
awaitAll(description, alterations, inventory, equipment, actions, spells, skills)
awaitAll(description, alterations, inventory, actions, spells, skills)
_isLoading.value = false
}

View file

@ -281,7 +281,7 @@ class CharacterSheetUioFactory @Inject constructor() {
),
speed = LabelPointUio(
label = R.string.character_sheet_title_speed,
value = "${max(sheet.speed + status[Property.SPEED].sum, 0)}m",
value = "${max(sheet.speed + status[Property.SPEED].sum.toFloat(), 0f)}m",
),
masteries = MasteriesUio(
martial = sheet.martial,

View file

@ -25,6 +25,9 @@ class SpellUioFactory @Inject constructor(
val modifier = diceThrow.modifier.sumOf {
when (it) {
Property.PROFICIENCY -> characterSheet.proficiency
Property.STRENGTH -> characterSheet.strength.modifier
Property.DEXTERITY -> characterSheet.dexterity.modifier
Property.CONSTITUTION -> characterSheet.constitution.modifier
Property.INTELLIGENCE -> characterSheet.intelligence.modifier
Property.WISDOM -> characterSheet.wisdom.modifier
Property.CHARISMA -> characterSheet.charisma.modifier

View file

@ -146,7 +146,7 @@ class SummaryFactory @Inject constructor(
val data = DataStruct()
characterSheetRepository.data
.combine(activeAlterationRepository.getActiveAlterations()) { sheets, alterations ->
data.sheets = sheets
data.sheets = sheets.filter { entry -> entry.value.active }
data.alterations = alterations
}
.combine(firebaseRepository.getCharacters()) { _, fire ->
@ -216,7 +216,7 @@ class SummaryFactory @Inject constructor(
label = (dexterity.modifier + status[Property.INITIATIVE].sum).toLabel()
)
val speed = label(
label = "${max(sheet.speed + status[Property.SPEED].sum, 0)}m",
label = "${max(sheet.speed + status[Property.SPEED].sum.toFloat(), 0f)}m",
)
val inspiration = proficiency(
label = null,

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

View file

@ -6,10 +6,6 @@ pluginManagement {
}
}
plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "0.6.0"
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {