Remove Int id from Quest

This commit is contained in:
Thomas Andres Gomez 2023-11-12 18:56:17 +01:00
parent 3880807372
commit 865b9abf5e
9 changed files with 57 additions and 51 deletions

View file

@ -5,7 +5,7 @@ import androidx.compose.runtime.Stable
@Stable
data class Quest(
val id: Int,
val id: String,
val title: String,
val entries: List<QuestEntry>,
)

View file

@ -2,25 +2,26 @@ package com.pixelized.rplexicon.data.parser
import com.google.api.services.sheets.v4.model.ValueRange
import com.pixelized.rplexicon.data.model.Quest
import com.pixelized.rplexicon.data.model.QuestEntry
import javax.inject.Inject
class QuestParser @Inject constructor(
private val imageParser: PortraitParser
) {
fun parse(sheet: ValueRange): List<QuestEntry> = parserScope {
val quest = mutableListOf<QuestEntry>()
fun parse(sheet: ValueRange): List<Quest> = parserScope {
val entries = hashMapOf<String, MutableList<QuestEntry>>()
sheet.forEachRowIndexed { index, item ->
when (index) {
0 -> updateStructure(row = item, columns = COLUMNS)
else -> {
val title = item.parse(column = TITLE)
val quest = item.parse(column = TITLE)
val description = item.parse(column = DESCRIPTION)
if (title?.isNotEmpty() == true && description?.isNotEmpty() == true) {
if (quest != null && description != null) {
val entry = QuestEntry(
sheetIndex = index,
title = title,
title = quest,
subtitle = item.parse(column = SUB_TITLE),
complete = item.parseBool(column = COMPLETED) ?: false,
questGiver = item.parse(column = QUEST_GIVER),
@ -31,13 +32,21 @@ class QuestParser @Inject constructor(
images = imageParser.parse(item.parse(column = IMAGE)),
background = item.parseUri(column = BACKGROUND),
)
quest.add(entry)
entries.getOrPut(quest) { mutableListOf() }.add(entry)
}
}
}
}
return@parserScope quest
val quests = entries.keys.map { quest ->
Quest(
id = "$quest-1", // TODO refactor that when quest have ids in the google sheet.
title = quest,
entries = entries[quest] ?: emptyList()
)
}
return@parserScope quests
}
companion object {

View file

@ -24,8 +24,8 @@ class LocationRepository @Inject constructor(
var lastSuccessFullUpdate: Update = Update.INITIAL
private set
fun find(id: String): Location? {
return _data.value.firstOrNull { it.id == id }
fun find(id: String?): Location? {
return id?.let { _data.value.firstOrNull { it.id == id } }
}
@Throws(IncompatibleSheetStructure::class, Exception::class)

View file

@ -1,6 +1,5 @@
package com.pixelized.rplexicon.data.repository.lexicon
import com.google.api.services.sheets.v4.model.ValueRange
import com.pixelized.rplexicon.data.model.Quest
import com.pixelized.rplexicon.data.parser.QuestParser
import com.pixelized.rplexicon.data.repository.GoogleSheetServiceRepository
@ -23,27 +22,17 @@ class QuestRepository @Inject constructor(
var lastSuccessFullUpdate: Update = Update.INITIAL
private set
fun find(id: String?): Quest? {
return id?.let { data.value.firstOrNull { it.id == id } }
}
@Throws(IncompatibleSheetStructure::class, Exception::class)
suspend fun fetchQuests() {
googleRepository.fetch { sheet ->
val request = sheet.get(LexiconBinder.ID, LexiconBinder.QUEST_JOURNAL)
val data = request.execute()
updateData(data = data)
val quests = questParser.parse(sheet = request.execute())
_data.emit(quests)
lastSuccessFullUpdate = Update.currentTime()
}
}
@Throws(IncompatibleSheetStructure::class, Exception::class)
private suspend fun updateData(data: ValueRange) {
val questEntries = questParser.parse(sheet = data)
val questMap = questEntries.groupBy { it.title }
val quests = questMap.keys.mapIndexed { index, item ->
Quest(
id = index,
title = item,
entries = questMap[item] ?: emptyList(),
)
}
_data.emit(quests)
}
}

View file

@ -21,7 +21,7 @@ val QUEST_DETAIL_ROUTE = "$ROUTE?${ARG_ID.ARG}"
@Stable
@Immutable
data class QuestDetailArgument(
val id: Int,
val id: String,
)
val SavedStateHandle.questDetailArgument: QuestDetailArgument
@ -34,7 +34,7 @@ fun NavGraphBuilder.composableQuestDetail() {
route = QUEST_DETAIL_ROUTE,
arguments = listOf(
navArgument(name = ARG_ID) {
type = NavType.IntType
type = NavType.StringType
},
),
animation = NavigationAnimation.Push,
@ -44,7 +44,7 @@ fun NavGraphBuilder.composableQuestDetail() {
}
fun NavHostController.navigateToQuestDetail(
id: Int,
id: String,
option: NavOptionsBuilder.() -> Unit = {},
) {
val route = "$ROUTE?$ARG_ID=$id"

View file

@ -62,7 +62,7 @@ import com.pixelized.rplexicon.utilitary.extentions.scrollOffset
@Stable
data class QuestDetailUio(
val id: Int,
val id: String,
val background: Uri?,
val completed: Boolean,
val title: String,
@ -110,7 +110,7 @@ fun QuestDetailScreen(
private fun QuestDetailContent(
modifier: Modifier = Modifier,
state: ScrollState = rememberScrollState(),
item: State<QuestDetailUio>,
item: State<QuestDetailUio?>,
onBack: () -> Unit,
onGiver: (String) -> Unit,
onLocation: (String) -> Unit,
@ -149,9 +149,9 @@ private fun QuestDetailContent(
) {
BackgroundImage(
modifier = Modifier.matchParentSize(),
model = quest.background,
model = quest?.background,
)
if (quest.completed) {
if (quest?.completed == true) {
Text(
modifier = Modifier
.align(Alignment.TopEnd)
@ -168,8 +168,8 @@ private fun QuestDetailContent(
.verticalScroll(state)
.padding(
top = when {
quest.background == null && quest.completed -> 96.dp
quest.background == null -> 16.dp
quest?.background == null && quest?.completed == true -> 96.dp
quest?.background == null -> 16.dp
else -> MaterialTheme.lexicon.dimens.detailPadding
},
bottom = 16.dp,
@ -184,12 +184,12 @@ private fun QuestDetailContent(
textAlign = TextAlign.Center,
style = MaterialTheme.typography.headlineLarge,
text = annotateWithDropCap(
text = quest.title,
text = quest?.title ?: "",
style = MaterialTheme.lexicon.typography.headlineLargeDropCap,
),
)
quest.steps.forEach { quest ->
quest?.steps?.forEach { quest ->
Column(
verticalArrangement = Arrangement.spacedBy(8.dp),
) {
@ -347,7 +347,7 @@ private class QuestDetailPreviewProvider : PreviewParameterProvider<State<QuestD
override val values: Sequence<State<QuestDetailUio>> = sequenceOf(
mutableStateOf(
QuestDetailUio(
id = 0,
id = "La chasse aux loups",
completed = true,
background = Uri.parse("https://as1.ftcdn.net/v2/jpg/05/50/22/58/1000_F_550225869_jAkLTRVb7ym7EHJYvDApVXQnpANvRd8O.jpg"),
title = "La chasse aux loups",
@ -369,7 +369,7 @@ private class QuestDetailPreviewProvider : PreviewParameterProvider<State<QuestD
),
mutableStateOf(
QuestDetailUio(
id = 1,
id = "Les enfants de la caravanes",
completed = false,
background = Uri.parse("https://cdnb.artstation.com/p/assets/images/images/008/823/761/large/jon-pintar-adventurers-caravan-jon-pintar.jpg?1515529013"),
title = "Les enfants de la caravanes",

View file

@ -18,25 +18,27 @@ class QuestDetailViewModel @Inject constructor(
lexiconRepository: LexiconRepository,
locationRepository: LocationRepository,
) : ViewModel() {
val quest: State<QuestDetailUio>
private val _quest = mutableStateOf<QuestDetailUio?>(null)
val quest: State<QuestDetailUio?> get() = _quest
init {
val argument = savedStateHandle.questDetailArgument
val source = questRepository.data.value[argument.id]
val source = questRepository.find(id = argument.id)
quest = mutableStateOf(
QuestDetailUio(
if (source != null) {
_quest.value = QuestDetailUio(
id = source.id,
completed = source.entries.all { it.complete },
background = source.entries.mapNotNull { it.background }.randomOrNull(),
title = source.title,
steps = source.entries.map { entry ->
val location = locationRepository.find(id = entry.area)
QuestDetailUio.QuestStep(
subtitle = entry.subtitle,
giverId = lexiconRepository.findId(entry.questGiver),
giver = entry.questGiver,
placeId = entry.area, // TODO proper ID.
place = entry.area,
placeId = location?.id,
place = location?.name,
globalReward = entry.groupReward,
individualReward = entry.individualReward,
description = entry.description,
@ -44,6 +46,6 @@ class QuestDetailViewModel @Inject constructor(
)
},
)
)
}
}
}

View file

@ -28,14 +28,14 @@ import com.pixelized.rplexicon.utilitary.extentions.placeholder
@Stable
data class QuestItemUio(
val id: Int,
val id: String,
val title: String,
val complete: Boolean,
val placeholder: Boolean = false,
) {
companion object {
fun preview(
id: Int = 0,
id: String = "La chasse aux loups",
title: String = "La chasse aux loups",
complete: Boolean = false,
placeHolder: Boolean = false,

View file

@ -152,8 +152,14 @@ private fun QuestListPreview() {
items = remember {
mutableStateOf(
listOf(
QuestItemUio.preview(id = 0, title = "La chasse aux loups"),
QuestItemUio.preview(id = 1, title = "Les enfants de la caravanes"),
QuestItemUio.preview(
id = "La chasse aux loups",
title = "La chasse aux loups",
),
QuestItemUio.preview(
id = "Les enfants de la caravanes",
title = "Les enfants de la caravanes",
),
)
)
},