Remove Int id from Quest
This commit is contained in:
parent
3880807372
commit
865b9abf5e
9 changed files with 57 additions and 51 deletions
|
|
@ -5,7 +5,7 @@ import androidx.compose.runtime.Stable
|
||||||
|
|
||||||
@Stable
|
@Stable
|
||||||
data class Quest(
|
data class Quest(
|
||||||
val id: Int,
|
val id: String,
|
||||||
val title: String,
|
val title: String,
|
||||||
val entries: List<QuestEntry>,
|
val entries: List<QuestEntry>,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -2,25 +2,26 @@ package com.pixelized.rplexicon.data.parser
|
||||||
|
|
||||||
|
|
||||||
import com.google.api.services.sheets.v4.model.ValueRange
|
import com.google.api.services.sheets.v4.model.ValueRange
|
||||||
|
import com.pixelized.rplexicon.data.model.Quest
|
||||||
import com.pixelized.rplexicon.data.model.QuestEntry
|
import com.pixelized.rplexicon.data.model.QuestEntry
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class QuestParser @Inject constructor(
|
class QuestParser @Inject constructor(
|
||||||
private val imageParser: PortraitParser
|
private val imageParser: PortraitParser
|
||||||
) {
|
) {
|
||||||
fun parse(sheet: ValueRange): List<QuestEntry> = parserScope {
|
fun parse(sheet: ValueRange): List<Quest> = parserScope {
|
||||||
val quest = mutableListOf<QuestEntry>()
|
val entries = hashMapOf<String, MutableList<QuestEntry>>()
|
||||||
|
|
||||||
sheet.forEachRowIndexed { index, item ->
|
sheet.forEachRowIndexed { index, item ->
|
||||||
when (index) {
|
when (index) {
|
||||||
0 -> updateStructure(row = item, columns = COLUMNS)
|
0 -> updateStructure(row = item, columns = COLUMNS)
|
||||||
else -> {
|
else -> {
|
||||||
val title = item.parse(column = TITLE)
|
val quest = item.parse(column = TITLE)
|
||||||
val description = item.parse(column = DESCRIPTION)
|
val description = item.parse(column = DESCRIPTION)
|
||||||
if (title?.isNotEmpty() == true && description?.isNotEmpty() == true) {
|
if (quest != null && description != null) {
|
||||||
val entry = QuestEntry(
|
val entry = QuestEntry(
|
||||||
sheetIndex = index,
|
sheetIndex = index,
|
||||||
title = title,
|
title = quest,
|
||||||
subtitle = item.parse(column = SUB_TITLE),
|
subtitle = item.parse(column = SUB_TITLE),
|
||||||
complete = item.parseBool(column = COMPLETED) ?: false,
|
complete = item.parseBool(column = COMPLETED) ?: false,
|
||||||
questGiver = item.parse(column = QUEST_GIVER),
|
questGiver = item.parse(column = QUEST_GIVER),
|
||||||
|
|
@ -31,13 +32,21 @@ class QuestParser @Inject constructor(
|
||||||
images = imageParser.parse(item.parse(column = IMAGE)),
|
images = imageParser.parse(item.parse(column = IMAGE)),
|
||||||
background = item.parseUri(column = BACKGROUND),
|
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 {
|
companion object {
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,8 @@ class LocationRepository @Inject constructor(
|
||||||
var lastSuccessFullUpdate: Update = Update.INITIAL
|
var lastSuccessFullUpdate: Update = Update.INITIAL
|
||||||
private set
|
private set
|
||||||
|
|
||||||
fun find(id: String): Location? {
|
fun find(id: String?): Location? {
|
||||||
return _data.value.firstOrNull { it.id == id }
|
return id?.let { _data.value.firstOrNull { it.id == id } }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(IncompatibleSheetStructure::class, Exception::class)
|
@Throws(IncompatibleSheetStructure::class, Exception::class)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
package com.pixelized.rplexicon.data.repository.lexicon
|
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.model.Quest
|
||||||
import com.pixelized.rplexicon.data.parser.QuestParser
|
import com.pixelized.rplexicon.data.parser.QuestParser
|
||||||
import com.pixelized.rplexicon.data.repository.GoogleSheetServiceRepository
|
import com.pixelized.rplexicon.data.repository.GoogleSheetServiceRepository
|
||||||
|
|
@ -23,27 +22,17 @@ class QuestRepository @Inject constructor(
|
||||||
var lastSuccessFullUpdate: Update = Update.INITIAL
|
var lastSuccessFullUpdate: Update = Update.INITIAL
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
fun find(id: String?): Quest? {
|
||||||
|
return id?.let { data.value.firstOrNull { it.id == id } }
|
||||||
|
}
|
||||||
|
|
||||||
@Throws(IncompatibleSheetStructure::class, Exception::class)
|
@Throws(IncompatibleSheetStructure::class, Exception::class)
|
||||||
suspend fun fetchQuests() {
|
suspend fun fetchQuests() {
|
||||||
googleRepository.fetch { sheet ->
|
googleRepository.fetch { sheet ->
|
||||||
val request = sheet.get(LexiconBinder.ID, LexiconBinder.QUEST_JOURNAL)
|
val request = sheet.get(LexiconBinder.ID, LexiconBinder.QUEST_JOURNAL)
|
||||||
val data = request.execute()
|
val quests = questParser.parse(sheet = request.execute())
|
||||||
updateData(data = data)
|
_data.emit(quests)
|
||||||
lastSuccessFullUpdate = Update.currentTime()
|
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -21,7 +21,7 @@ val QUEST_DETAIL_ROUTE = "$ROUTE?${ARG_ID.ARG}"
|
||||||
@Stable
|
@Stable
|
||||||
@Immutable
|
@Immutable
|
||||||
data class QuestDetailArgument(
|
data class QuestDetailArgument(
|
||||||
val id: Int,
|
val id: String,
|
||||||
)
|
)
|
||||||
|
|
||||||
val SavedStateHandle.questDetailArgument: QuestDetailArgument
|
val SavedStateHandle.questDetailArgument: QuestDetailArgument
|
||||||
|
|
@ -34,7 +34,7 @@ fun NavGraphBuilder.composableQuestDetail() {
|
||||||
route = QUEST_DETAIL_ROUTE,
|
route = QUEST_DETAIL_ROUTE,
|
||||||
arguments = listOf(
|
arguments = listOf(
|
||||||
navArgument(name = ARG_ID) {
|
navArgument(name = ARG_ID) {
|
||||||
type = NavType.IntType
|
type = NavType.StringType
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
animation = NavigationAnimation.Push,
|
animation = NavigationAnimation.Push,
|
||||||
|
|
@ -44,7 +44,7 @@ fun NavGraphBuilder.composableQuestDetail() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun NavHostController.navigateToQuestDetail(
|
fun NavHostController.navigateToQuestDetail(
|
||||||
id: Int,
|
id: String,
|
||||||
option: NavOptionsBuilder.() -> Unit = {},
|
option: NavOptionsBuilder.() -> Unit = {},
|
||||||
) {
|
) {
|
||||||
val route = "$ROUTE?$ARG_ID=$id"
|
val route = "$ROUTE?$ARG_ID=$id"
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ import com.pixelized.rplexicon.utilitary.extentions.scrollOffset
|
||||||
|
|
||||||
@Stable
|
@Stable
|
||||||
data class QuestDetailUio(
|
data class QuestDetailUio(
|
||||||
val id: Int,
|
val id: String,
|
||||||
val background: Uri?,
|
val background: Uri?,
|
||||||
val completed: Boolean,
|
val completed: Boolean,
|
||||||
val title: String,
|
val title: String,
|
||||||
|
|
@ -110,7 +110,7 @@ fun QuestDetailScreen(
|
||||||
private fun QuestDetailContent(
|
private fun QuestDetailContent(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
state: ScrollState = rememberScrollState(),
|
state: ScrollState = rememberScrollState(),
|
||||||
item: State<QuestDetailUio>,
|
item: State<QuestDetailUio?>,
|
||||||
onBack: () -> Unit,
|
onBack: () -> Unit,
|
||||||
onGiver: (String) -> Unit,
|
onGiver: (String) -> Unit,
|
||||||
onLocation: (String) -> Unit,
|
onLocation: (String) -> Unit,
|
||||||
|
|
@ -149,9 +149,9 @@ private fun QuestDetailContent(
|
||||||
) {
|
) {
|
||||||
BackgroundImage(
|
BackgroundImage(
|
||||||
modifier = Modifier.matchParentSize(),
|
modifier = Modifier.matchParentSize(),
|
||||||
model = quest.background,
|
model = quest?.background,
|
||||||
)
|
)
|
||||||
if (quest.completed) {
|
if (quest?.completed == true) {
|
||||||
Text(
|
Text(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.align(Alignment.TopEnd)
|
.align(Alignment.TopEnd)
|
||||||
|
|
@ -168,8 +168,8 @@ private fun QuestDetailContent(
|
||||||
.verticalScroll(state)
|
.verticalScroll(state)
|
||||||
.padding(
|
.padding(
|
||||||
top = when {
|
top = when {
|
||||||
quest.background == null && quest.completed -> 96.dp
|
quest?.background == null && quest?.completed == true -> 96.dp
|
||||||
quest.background == null -> 16.dp
|
quest?.background == null -> 16.dp
|
||||||
else -> MaterialTheme.lexicon.dimens.detailPadding
|
else -> MaterialTheme.lexicon.dimens.detailPadding
|
||||||
},
|
},
|
||||||
bottom = 16.dp,
|
bottom = 16.dp,
|
||||||
|
|
@ -184,12 +184,12 @@ private fun QuestDetailContent(
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
style = MaterialTheme.typography.headlineLarge,
|
style = MaterialTheme.typography.headlineLarge,
|
||||||
text = annotateWithDropCap(
|
text = annotateWithDropCap(
|
||||||
text = quest.title,
|
text = quest?.title ?: "",
|
||||||
style = MaterialTheme.lexicon.typography.headlineLargeDropCap,
|
style = MaterialTheme.lexicon.typography.headlineLargeDropCap,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
quest.steps.forEach { quest ->
|
quest?.steps?.forEach { quest ->
|
||||||
Column(
|
Column(
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||||
) {
|
) {
|
||||||
|
|
@ -347,7 +347,7 @@ private class QuestDetailPreviewProvider : PreviewParameterProvider<State<QuestD
|
||||||
override val values: Sequence<State<QuestDetailUio>> = sequenceOf(
|
override val values: Sequence<State<QuestDetailUio>> = sequenceOf(
|
||||||
mutableStateOf(
|
mutableStateOf(
|
||||||
QuestDetailUio(
|
QuestDetailUio(
|
||||||
id = 0,
|
id = "La chasse aux loups",
|
||||||
completed = true,
|
completed = true,
|
||||||
background = Uri.parse("https://as1.ftcdn.net/v2/jpg/05/50/22/58/1000_F_550225869_jAkLTRVb7ym7EHJYvDApVXQnpANvRd8O.jpg"),
|
background = Uri.parse("https://as1.ftcdn.net/v2/jpg/05/50/22/58/1000_F_550225869_jAkLTRVb7ym7EHJYvDApVXQnpANvRd8O.jpg"),
|
||||||
title = "La chasse aux loups",
|
title = "La chasse aux loups",
|
||||||
|
|
@ -369,7 +369,7 @@ private class QuestDetailPreviewProvider : PreviewParameterProvider<State<QuestD
|
||||||
),
|
),
|
||||||
mutableStateOf(
|
mutableStateOf(
|
||||||
QuestDetailUio(
|
QuestDetailUio(
|
||||||
id = 1,
|
id = "Les enfants de la caravanes",
|
||||||
completed = false,
|
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"),
|
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",
|
title = "Les enfants de la caravanes",
|
||||||
|
|
|
||||||
|
|
@ -18,25 +18,27 @@ class QuestDetailViewModel @Inject constructor(
|
||||||
lexiconRepository: LexiconRepository,
|
lexiconRepository: LexiconRepository,
|
||||||
locationRepository: LocationRepository,
|
locationRepository: LocationRepository,
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
val quest: State<QuestDetailUio>
|
private val _quest = mutableStateOf<QuestDetailUio?>(null)
|
||||||
|
val quest: State<QuestDetailUio?> get() = _quest
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val argument = savedStateHandle.questDetailArgument
|
val argument = savedStateHandle.questDetailArgument
|
||||||
val source = questRepository.data.value[argument.id]
|
val source = questRepository.find(id = argument.id)
|
||||||
|
|
||||||
quest = mutableStateOf(
|
if (source != null) {
|
||||||
QuestDetailUio(
|
_quest.value = QuestDetailUio(
|
||||||
id = source.id,
|
id = source.id,
|
||||||
completed = source.entries.all { it.complete },
|
completed = source.entries.all { it.complete },
|
||||||
background = source.entries.mapNotNull { it.background }.randomOrNull(),
|
background = source.entries.mapNotNull { it.background }.randomOrNull(),
|
||||||
title = source.title,
|
title = source.title,
|
||||||
steps = source.entries.map { entry ->
|
steps = source.entries.map { entry ->
|
||||||
|
val location = locationRepository.find(id = entry.area)
|
||||||
QuestDetailUio.QuestStep(
|
QuestDetailUio.QuestStep(
|
||||||
subtitle = entry.subtitle,
|
subtitle = entry.subtitle,
|
||||||
giverId = lexiconRepository.findId(entry.questGiver),
|
giverId = lexiconRepository.findId(entry.questGiver),
|
||||||
giver = entry.questGiver,
|
giver = entry.questGiver,
|
||||||
placeId = entry.area, // TODO proper ID.
|
placeId = location?.id,
|
||||||
place = entry.area,
|
place = location?.name,
|
||||||
globalReward = entry.groupReward,
|
globalReward = entry.groupReward,
|
||||||
individualReward = entry.individualReward,
|
individualReward = entry.individualReward,
|
||||||
description = entry.description,
|
description = entry.description,
|
||||||
|
|
@ -44,6 +46,6 @@ class QuestDetailViewModel @Inject constructor(
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -28,14 +28,14 @@ import com.pixelized.rplexicon.utilitary.extentions.placeholder
|
||||||
|
|
||||||
@Stable
|
@Stable
|
||||||
data class QuestItemUio(
|
data class QuestItemUio(
|
||||||
val id: Int,
|
val id: String,
|
||||||
val title: String,
|
val title: String,
|
||||||
val complete: Boolean,
|
val complete: Boolean,
|
||||||
val placeholder: Boolean = false,
|
val placeholder: Boolean = false,
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
fun preview(
|
fun preview(
|
||||||
id: Int = 0,
|
id: String = "La chasse aux loups",
|
||||||
title: String = "La chasse aux loups",
|
title: String = "La chasse aux loups",
|
||||||
complete: Boolean = false,
|
complete: Boolean = false,
|
||||||
placeHolder: Boolean = false,
|
placeHolder: Boolean = false,
|
||||||
|
|
|
||||||
|
|
@ -152,8 +152,14 @@ private fun QuestListPreview() {
|
||||||
items = remember {
|
items = remember {
|
||||||
mutableStateOf(
|
mutableStateOf(
|
||||||
listOf(
|
listOf(
|
||||||
QuestItemUio.preview(id = 0, title = "La chasse aux loups"),
|
QuestItemUio.preview(
|
||||||
QuestItemUio.preview(id = 1, title = "Les enfants de la caravanes"),
|
id = "La chasse aux loups",
|
||||||
|
title = "La chasse aux loups",
|
||||||
|
),
|
||||||
|
QuestItemUio.preview(
|
||||||
|
id = "Les enfants de la caravanes",
|
||||||
|
title = "Les enfants de la caravanes",
|
||||||
|
),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue