Refactor the parser system to introduce a column system.
This commit is contained in:
parent
ff1ac694bb
commit
fd30b9c11e
25 changed files with 390 additions and 529 deletions
|
|
@ -88,7 +88,7 @@ class AlterationRepository @Inject constructor(
|
|||
suspend fun fetchAlterationSheet(sheets: List<CharacterSheet>) {
|
||||
googleRepository.fetch { sheet ->
|
||||
val request = sheet.get(CharacterBinder.ID, CharacterBinder.ALTERATION)
|
||||
val data = alterationParser.parse(values = request.execute(), sheets = sheets)
|
||||
val data = alterationParser.parse(sheet = request.execute(), characterSheets = sheets)
|
||||
_assignedAlterations.emit(data)
|
||||
lastSuccessFullUpdate = Update.currentTime()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ class DescriptionRepository @Inject constructor(
|
|||
suspend fun fetchDescription() {
|
||||
googleRepository.fetch { sheet ->
|
||||
val request = sheet.get(CharacterBinder.ID, CharacterBinder.DESCRIPTION)
|
||||
val data = parser.parse(data = request.execute())
|
||||
val data = parser.parse(sheet = request.execute())
|
||||
_data.tryEmit(data)
|
||||
|
||||
lastSuccessFullUpdate = Update.currentTime()
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ class InventoryRepository @Inject constructor(
|
|||
suspend fun fetchInventory() {
|
||||
googleRepository.fetch { sheet ->
|
||||
val request = sheet.get(CharacterBinder.ID, CharacterBinder.INVENTORY)
|
||||
val data = inventoryParser.parse(data = request.execute())
|
||||
val data = inventoryParser.parse(sheet = request.execute())
|
||||
_data.tryEmit(data)
|
||||
lastSuccessFullUpdate = Update.currentTime()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ class SkillRepository @Inject constructor(
|
|||
suspend fun fetchSkills() {
|
||||
googleRepository.fetch { sheet ->
|
||||
val request = sheet.get(CharacterBinder.ID, CharacterBinder.SKILL)
|
||||
val skills = skillParser.parse(data = request.execute())
|
||||
val skills = skillParser.parse(sheet = request.execute())
|
||||
|
||||
_skills.emit(skills)
|
||||
lastSuccessFullUpdate = Update.currentTime()
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@ class SpellRepository @Inject constructor(
|
|||
async { sheet.get(CharacterBinder.ID, CharacterBinder.MAGIC_LEXICON).execute() },
|
||||
async { sheet.get(CharacterBinder.ID, CharacterBinder.MAGIC).execute() },
|
||||
)
|
||||
val spellsBook = spellBookParser.parse(data = lexicon)
|
||||
val assignedSpells = assignedSpellParser.parse(data = magic, spells = spellsBook)
|
||||
val spellsBook = spellBookParser.parse(sheet = lexicon)
|
||||
val assignedSpells = assignedSpellParser.parse(sheet = magic, spells = spellsBook)
|
||||
this@SpellRepository.spellsBook = spellsBook
|
||||
_spells.emit(assignedSpells)
|
||||
lastSuccessFullUpdate = Update.currentTime()
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ class LexiconRepository @Inject constructor(
|
|||
suspend fun fetchLexicon() {
|
||||
googleRepository.fetch { sheet ->
|
||||
val request = sheet.get(LexiconBinder.ID, LexiconBinder.LEXICON)
|
||||
val data = lexiconParser.parse(data = request.execute())
|
||||
val data = lexiconParser.parse(sheet = request.execute())
|
||||
_data.tryEmit(data)
|
||||
|
||||
lastSuccessFullUpdate = Update.currentTime()
|
||||
|
|
|
|||
|
|
@ -46,11 +46,11 @@ class LocationRepository @Inject constructor(
|
|||
@Throws(IncompatibleSheetStructure::class)
|
||||
private suspend fun updateData(map: ValueRange, marquee: ValueRange) {
|
||||
val marquees = marqueeParser
|
||||
.parse(data = marquee)
|
||||
.parse(sheet = marquee)
|
||||
.groupBy { it.map }
|
||||
|
||||
val maps = locationParser
|
||||
.parse(data = map)
|
||||
.parse(sheet = map)
|
||||
.map {
|
||||
val associatedMarquees = marquees[it.name]
|
||||
if (associatedMarquees != null) {
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ class QuestRepository @Inject constructor(
|
|||
|
||||
@Throws(IncompatibleSheetStructure::class, Exception::class)
|
||||
private suspend fun updateData(data: ValueRange) {
|
||||
val questEntries = questParser.parse(value = data)
|
||||
val questEntries = questParser.parse(sheet = data)
|
||||
val questMap = questEntries.groupBy { it.title }
|
||||
val quests = questMap.keys.mapIndexed { index, item ->
|
||||
Quest(
|
||||
|
|
|
|||
|
|
@ -5,8 +5,6 @@ import com.google.api.services.sheets.v4.model.ValueRange
|
|||
import com.pixelized.rplexicon.model.Attack
|
||||
import com.pixelized.rplexicon.model.CharacterSheet
|
||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
|
||||
import com.pixelized.rplexicon.utilitary.extentions.local.checkSheetStructure
|
||||
import com.pixelized.rplexicon.utilitary.extentions.sheet
|
||||
import javax.inject.Inject
|
||||
|
||||
class AttackParser @Inject constructor(
|
||||
|
|
@ -16,34 +14,24 @@ class AttackParser @Inject constructor(
|
|||
fun parse(
|
||||
value: ValueRange,
|
||||
charactersSheets: Map<String, CharacterSheet>,
|
||||
): Map<String, List<Attack>> {
|
||||
val sheet = value.values.sheet()
|
||||
|
||||
lateinit var structure: Map<String, Int>
|
||||
|
||||
): Map<String, List<Attack>> = parserScope {
|
||||
// declare helper method to parse String
|
||||
fun List<*>.parseString(key: String): String? =
|
||||
(getOrNull(structure.getValue(key)) as? String)?.takeIf { it.isNotEmpty() }
|
||||
|
||||
val actions = hashMapOf<String, MutableList<Attack>>()
|
||||
|
||||
sheet?.forEachIndexed { index, row ->
|
||||
when {
|
||||
index == 0 -> {
|
||||
structure = row.checkSheetStructure(model = COLUMNS)
|
||||
}
|
||||
|
||||
row is List<*> -> {
|
||||
value.forEachRow { index, row ->
|
||||
when (index) {
|
||||
0 -> updateStructure(row = row, columns = COLUMNS)
|
||||
else -> {
|
||||
// Assume that the name is the first column.
|
||||
val characterSheet = charactersSheets[row.getOrNull(0) as? String ?: ""]
|
||||
val title = row.parseString(NAME)
|
||||
val characterSheet = charactersSheets[row.parse(CHARACTER)]
|
||||
val title = row.parse(column = NAME)
|
||||
if (characterSheet != null && title != null) {
|
||||
val attack = Attack(
|
||||
title = title,
|
||||
type = parseType(value = row.parseString(TYPE)),
|
||||
range = row.parseString(RANGE),
|
||||
hit = throwParser.parse(value = row.parseString(HIT)),
|
||||
damage = throwParser.parse(value = row.parseString(DAMAGE)),
|
||||
type = parseType(value = row.parse(column = TYPE)),
|
||||
range = row.parse(column = RANGE),
|
||||
hit = throwParser.parse(value = row.parse(column = HIT)),
|
||||
damage = throwParser.parse(value = row.parse(column = DAMAGE)),
|
||||
)
|
||||
actions
|
||||
.getOrPut(characterSheet.name) { mutableListOf() }
|
||||
|
|
@ -53,7 +41,7 @@ class AttackParser @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
return actions
|
||||
actions
|
||||
}
|
||||
|
||||
private fun parseType(value: String?): Attack.Type = try {
|
||||
|
|
@ -64,12 +52,12 @@ class AttackParser @Inject constructor(
|
|||
} ?: Attack.Type.PHYSICAL_MELEE_ATTACK
|
||||
|
||||
companion object {
|
||||
const val NAME = "Nom"
|
||||
const val TYPE = "Type"
|
||||
const val RANGE = "Portée"
|
||||
const val HIT = "Touché"
|
||||
const val DAMAGE = "Dommage"
|
||||
|
||||
val COLUMNS get() = listOf("", NAME, TYPE, RANGE, HIT, DAMAGE)
|
||||
private val CHARACTER = column("")
|
||||
private val NAME = column("Nom")
|
||||
private val TYPE = column("Type")
|
||||
private val RANGE = column("Portée")
|
||||
private val HIT = column("Touché")
|
||||
private val DAMAGE = column("Dommage")
|
||||
private val COLUMNS get() = listOf(CHARACTER, NAME, TYPE, RANGE, HIT, DAMAGE)
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,6 @@ package com.pixelized.rplexicon.repository.parser
|
|||
import com.google.api.services.sheets.v4.model.ValueRange
|
||||
import com.pixelized.rplexicon.model.CharacterSheet
|
||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
|
||||
import com.pixelized.rplexicon.utilitary.extentions.local.checkSheetStructure
|
||||
import com.pixelized.rplexicon.utilitary.extentions.sheet
|
||||
import javax.inject.Inject
|
||||
|
||||
|
|
@ -11,8 +10,7 @@ import javax.inject.Inject
|
|||
class CharacterSheetParser @Inject constructor() {
|
||||
|
||||
@Throws(IncompatibleSheetStructure::class)
|
||||
fun parse(value: ValueRange): Map<String, CharacterSheet> {
|
||||
|
||||
fun parse(value: ValueRange): Map<String, CharacterSheet> = parserScope {
|
||||
// fetch the character sheet
|
||||
val sheet = value.values.sheet() // fetch the List<*>
|
||||
?.mapNotNull { it as? List<*> } // transform the List<*> to a List<List<*>>
|
||||
|
|
@ -20,79 +18,66 @@ class CharacterSheetParser @Inject constructor() {
|
|||
val entryCount = if (sheet.isNotEmpty()) sheet[0].size else 0
|
||||
List(entryCount) { index -> sheet.map { it.getOrNull(index) } }
|
||||
}
|
||||
|
||||
// prepare a hash on the structure & function to get index in it.
|
||||
lateinit var structure: Map<String, Int>
|
||||
|
||||
// declare helper method to parse String
|
||||
fun List<*>.parseString(key: String): String? =
|
||||
(getOrNull(structure.getValue(key)) as? String)?.takeIf { it.isNotEmpty() }
|
||||
|
||||
// declare helper method to parse Int
|
||||
fun List<*>.parseInt(key: String): Int? = parseString(key = key)?.toIntOrNull()
|
||||
|
||||
// parse the sheet
|
||||
return sheet?.mapIndexedNotNull { index, item ->
|
||||
sheet?.mapIndexedNotNull { index, item ->
|
||||
when (index) {
|
||||
0 -> {
|
||||
structure = item.checkSheetStructure(model = ROWS)
|
||||
return@mapIndexedNotNull null
|
||||
updateStructure(row = item, columns = ROWS)
|
||||
null
|
||||
}
|
||||
|
||||
else -> {
|
||||
val name = item.parseString(NAME)
|
||||
val name = item.parse(column = NAME)
|
||||
if (name != null) {
|
||||
CharacterSheet(
|
||||
name = name,
|
||||
race = item.parseString(RACE),
|
||||
proficiency = item.parseInt(MASTERY) ?: 2,
|
||||
level = item.parseInt(LEVEL) ?: 2,
|
||||
characterClass = item.parseString(CLASS) ?: "",
|
||||
hitPoint = item.parseInt(MAX_HIT_POINT) ?: 1,
|
||||
spell1 = item.parseInt(SPELL_LEVEL_1),
|
||||
spell2 = item.parseInt(SPELL_LEVEL_2),
|
||||
spell3 = item.parseInt(SPELL_LEVEL_3),
|
||||
spell4 = item.parseInt(SPELL_LEVEL_4),
|
||||
spell5 = item.parseInt(SPELL_LEVEL_5),
|
||||
spell6 = item.parseInt(SPELL_LEVEL_6),
|
||||
spell7 = item.parseInt(SPELL_LEVEL_7),
|
||||
spell8 = item.parseInt(SPELL_LEVEL_8),
|
||||
spell9 = item.parseInt(SPELL_LEVEL_9),
|
||||
dC = item.parseInt(DD_SAVE_THROW),
|
||||
armorClass = item.parseInt(ARMOR_CLASS) ?: 10,
|
||||
speed = item.parseInt(SPEED) ?: 10,
|
||||
strength = item.parseInt(STRENGTH) ?: 10,
|
||||
dexterity = item.parseInt(DEXTERITY) ?: 10,
|
||||
constitution = item.parseInt(CONSTITUTION) ?: 10,
|
||||
intelligence = item.parseInt(INTELLIGENCE) ?: 10,
|
||||
wisdom = item.parseInt(WISDOM) ?: 10,
|
||||
charisma = item.parseInt(CHARISMA) ?: 10,
|
||||
strengthSavingThrows = item.parseInt(STRENGTH_SAVING_THROW) ?: 0,
|
||||
dexteritySavingThrows = item.parseInt(DEXTERITY_SAVING_THROW) ?: 0,
|
||||
constitutionSavingThrows = item.parseInt(CONSTITUTION_SAVING_THROW)
|
||||
?: 0,
|
||||
intelligenceSavingThrows = item.parseInt(INTELLIGENCE_SAVING_THROW)
|
||||
?: 0,
|
||||
wisdomSavingThrows = item.parseInt(WISDOM_SAVING_THROW) ?: 0,
|
||||
charismaSavingThrows = item.parseInt(CHARISMA_SAVING_THROW) ?: 0,
|
||||
acrobatics = item.parseInt(ACROBATICS) ?: 0,
|
||||
animalHandling = item.parseInt(ANIMAL_HANDLING) ?: 0,
|
||||
arcana = item.parseInt(ARCANA) ?: 0,
|
||||
athletics = item.parseInt(ATHLETICS) ?: 0,
|
||||
deception = item.parseInt(DECEPTION) ?: 0,
|
||||
history = item.parseInt(HISTORY) ?: 0,
|
||||
insight = item.parseInt(INSIGHT) ?: 0,
|
||||
intimidation = item.parseInt(INTIMIDATION) ?: 0,
|
||||
investigation = item.parseInt(INVESTIGATION) ?: 0,
|
||||
medicine = item.parseInt(MEDICINE) ?: 0,
|
||||
nature = item.parseInt(NATURE) ?: 0,
|
||||
perception = item.parseInt(PERCEPTION) ?: 0,
|
||||
performance = item.parseInt(PERFORMANCE) ?: 0,
|
||||
persuasion = item.parseInt(PERSUASION) ?: 0,
|
||||
religion = item.parseInt(RELIGION) ?: 0,
|
||||
sleightOfHand = item.parseInt(SLEIGHT_OF_HAND) ?: 0,
|
||||
stealth = item.parseInt(STEALTH) ?: 0,
|
||||
survival = item.parseInt(SURVIVAL) ?: 0,
|
||||
race = item.parse(column = RACE),
|
||||
proficiency = item.parseInt(column = MASTERY) ?: 2,
|
||||
level = item.parseInt(column = LEVEL) ?: 2,
|
||||
characterClass = item.parse(column = CLASS) ?: "",
|
||||
hitPoint = item.parseInt(column = MAX_HIT_POINT) ?: 1,
|
||||
spell1 = item.parseInt(column = SPELL_LEVEL_1),
|
||||
spell2 = item.parseInt(column = SPELL_LEVEL_2),
|
||||
spell3 = item.parseInt(column = SPELL_LEVEL_3),
|
||||
spell4 = item.parseInt(column = SPELL_LEVEL_4),
|
||||
spell5 = item.parseInt(column = SPELL_LEVEL_5),
|
||||
spell6 = item.parseInt(column = SPELL_LEVEL_6),
|
||||
spell7 = item.parseInt(column = SPELL_LEVEL_7),
|
||||
spell8 = item.parseInt(column = SPELL_LEVEL_8),
|
||||
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,
|
||||
strength = item.parseInt(column = STRENGTH) ?: 10,
|
||||
dexterity = item.parseInt(column = DEXTERITY) ?: 10,
|
||||
constitution = item.parseInt(column = CONSTITUTION) ?: 10,
|
||||
intelligence = item.parseInt(column = INTELLIGENCE) ?: 10,
|
||||
wisdom = item.parseInt(column = WISDOM) ?: 10,
|
||||
charisma = item.parseInt(column = CHARISMA) ?: 10,
|
||||
strengthSavingThrows = item.parseInt(column = STRENGTH_SAVING_THROW) ?: 0,
|
||||
dexteritySavingThrows = item.parseInt(column = DEXTERITY_SAVING_THROW) ?: 0,
|
||||
constitutionSavingThrows = item.parseInt(column = CONSTITUTION_SAVING_THROW) ?: 0,
|
||||
intelligenceSavingThrows = item.parseInt(column = INTELLIGENCE_SAVING_THROW) ?: 0,
|
||||
wisdomSavingThrows = item.parseInt(column = WISDOM_SAVING_THROW) ?: 0,
|
||||
charismaSavingThrows = item.parseInt(column = CHARISMA_SAVING_THROW) ?: 0,
|
||||
acrobatics = item.parseInt(column = ACROBATICS) ?: 0,
|
||||
animalHandling = item.parseInt(column = ANIMAL_HANDLING) ?: 0,
|
||||
arcana = item.parseInt(column = ARCANA) ?: 0,
|
||||
athletics = item.parseInt(column = ATHLETICS) ?: 0,
|
||||
deception = item.parseInt(column = DECEPTION) ?: 0,
|
||||
history = item.parseInt(column = HISTORY) ?: 0,
|
||||
insight = item.parseInt(column = INSIGHT) ?: 0,
|
||||
intimidation = item.parseInt(column = INTIMIDATION) ?: 0,
|
||||
investigation = item.parseInt(column = INVESTIGATION) ?: 0,
|
||||
medicine = item.parseInt(column = MEDICINE) ?: 0,
|
||||
nature = item.parseInt(column = NATURE) ?: 0,
|
||||
perception = item.parseInt(column = PERCEPTION) ?: 0,
|
||||
performance = item.parseInt(column = PERFORMANCE) ?: 0,
|
||||
persuasion = item.parseInt(column = PERSUASION) ?: 0,
|
||||
religion = item.parseInt(column = RELIGION) ?: 0,
|
||||
sleightOfHand = item.parseInt(column = SLEIGHT_OF_HAND) ?: 0,
|
||||
stealth = item.parseInt(column = STEALTH) ?: 0,
|
||||
survival = item.parseInt(column = SURVIVAL) ?: 0,
|
||||
)
|
||||
} else {
|
||||
null
|
||||
|
|
@ -103,54 +88,54 @@ class CharacterSheetParser @Inject constructor() {
|
|||
}
|
||||
|
||||
companion object {
|
||||
private const val NAME = "Nom"
|
||||
private const val RACE = "Race"
|
||||
private const val LEVEL = "Niveau"
|
||||
private const val CLASS = "Classe"
|
||||
private const val MAX_HIT_POINT = "Point de vie MAX"
|
||||
private const val SPELL_LEVEL_1 = "Sort de niveau 1"
|
||||
private const val SPELL_LEVEL_2 = "Sort de niveau 2"
|
||||
private const val SPELL_LEVEL_3 = "Sort de niveau 3"
|
||||
private const val SPELL_LEVEL_4 = "Sort de niveau 4"
|
||||
private const val SPELL_LEVEL_5 = "Sort de niveau 5"
|
||||
private const val SPELL_LEVEL_6 = "Sort de niveau 6"
|
||||
private const val SPELL_LEVEL_7 = "Sort de niveau 7"
|
||||
private const val SPELL_LEVEL_8 = "Sort de niveau 8"
|
||||
private const val SPELL_LEVEL_9 = "Sort de niveau 9"
|
||||
private const val DD_SAVE_THROW = "DD sauvergarde des sorts"
|
||||
private const val ARMOR_CLASS = "Classe d'armure"
|
||||
private const val SPEED = "Vitesse"
|
||||
private const val MASTERY = "Bonus de maîtrise"
|
||||
private const val STRENGTH = "Force"
|
||||
private const val DEXTERITY = "Dextérité"
|
||||
private const val CONSTITUTION = "Constitution"
|
||||
private const val INTELLIGENCE = "Intelligence"
|
||||
private const val WISDOM = "Sagesse"
|
||||
private const val CHARISMA = "Charisme"
|
||||
private const val STRENGTH_SAVING_THROW = "Jet de sauvegarde: Force"
|
||||
private const val DEXTERITY_SAVING_THROW = "Jet de sauvegarde: Dextérité"
|
||||
private const val CONSTITUTION_SAVING_THROW = "Jet de sauvegarde: Constitution"
|
||||
private const val INTELLIGENCE_SAVING_THROW = "Jet de sauvegarde: Intelligence"
|
||||
private const val WISDOM_SAVING_THROW = "Jet de sauvegarde: Sagesse"
|
||||
private const val CHARISMA_SAVING_THROW = "Jet de sauvegarde: Charisme"
|
||||
private const val ACROBATICS = "Acrobaties"
|
||||
private const val ANIMAL_HANDLING = "Dressage"
|
||||
private const val ARCANA = "Arcanes"
|
||||
private const val ATHLETICS = "Athlétisme"
|
||||
private const val DECEPTION = "Tromperie"
|
||||
private const val HISTORY = "Histoire"
|
||||
private const val INSIGHT = "Intuition"
|
||||
private const val INTIMIDATION = "Intimidation"
|
||||
private const val INVESTIGATION = "Investigation"
|
||||
private const val MEDICINE = "Médecine"
|
||||
private const val NATURE = "Nature"
|
||||
private const val PERCEPTION = "Perception"
|
||||
private const val PERFORMANCE = "Représentation"
|
||||
private const val PERSUASION = "Persuasion"
|
||||
private const val RELIGION = "Religion"
|
||||
private const val SLEIGHT_OF_HAND = "Escamotage"
|
||||
private const val STEALTH = "Discrétion"
|
||||
private const val SURVIVAL = "Survie"
|
||||
private val NAME = column("Nom")
|
||||
private val RACE = column("Race")
|
||||
private val LEVEL = column("Niveau")
|
||||
private val CLASS = column("Classe")
|
||||
private val MAX_HIT_POINT = column("Point de vie MAX")
|
||||
private val SPELL_LEVEL_1 = column("Sort de niveau 1")
|
||||
private val SPELL_LEVEL_2 = column("Sort de niveau 2")
|
||||
private val SPELL_LEVEL_3 = column("Sort de niveau 3")
|
||||
private val SPELL_LEVEL_4 = column("Sort de niveau 4")
|
||||
private val SPELL_LEVEL_5 = column("Sort de niveau 5")
|
||||
private val SPELL_LEVEL_6 = column("Sort de niveau 6")
|
||||
private val SPELL_LEVEL_7 = column("Sort de niveau 7")
|
||||
private val SPELL_LEVEL_8 = column("Sort de niveau 8")
|
||||
private val SPELL_LEVEL_9 = column("Sort de niveau 9")
|
||||
private val DD_SAVE_THROW = column("DD sauvergarde des sorts")
|
||||
private val ARMOR_CLASS = column("Classe d'armure")
|
||||
private val SPEED = column("Vitesse")
|
||||
private val MASTERY = column("Bonus de maîtrise")
|
||||
private val STRENGTH = column("Force")
|
||||
private val DEXTERITY = column("Dextérité")
|
||||
private val CONSTITUTION = column("Constitution")
|
||||
private val INTELLIGENCE = column("Intelligence")
|
||||
private val WISDOM = column("Sagesse")
|
||||
private val CHARISMA = column("Charisme")
|
||||
private val STRENGTH_SAVING_THROW = column("Jet de sauvegarde: Force")
|
||||
private val DEXTERITY_SAVING_THROW = column("Jet de sauvegarde: Dextérité")
|
||||
private val CONSTITUTION_SAVING_THROW = column("Jet de sauvegarde: Constitution")
|
||||
private val INTELLIGENCE_SAVING_THROW = column("Jet de sauvegarde: Intelligence")
|
||||
private val WISDOM_SAVING_THROW = column("Jet de sauvegarde: Sagesse")
|
||||
private val CHARISMA_SAVING_THROW = column("Jet de sauvegarde: Charisme")
|
||||
private val ACROBATICS = column("Acrobaties")
|
||||
private val ANIMAL_HANDLING = column("Dressage")
|
||||
private val ARCANA = column("Arcanes")
|
||||
private val ATHLETICS = column("Athlétisme")
|
||||
private val DECEPTION = column("Tromperie")
|
||||
private val HISTORY = column("Histoire")
|
||||
private val INSIGHT = column("Intuition")
|
||||
private val INTIMIDATION = column("Intimidation")
|
||||
private val INVESTIGATION = column("Investigation")
|
||||
private val MEDICINE = column("Médecine")
|
||||
private val NATURE = column("Nature")
|
||||
private val PERCEPTION = column("Perception")
|
||||
private val PERFORMANCE = column("Représentation")
|
||||
private val PERSUASION = column("Persuasion")
|
||||
private val RELIGION = column("Religion")
|
||||
private val SLEIGHT_OF_HAND = column("Escamotage")
|
||||
private val STEALTH = column("Discrétion")
|
||||
private val SURVIVAL = column("Survie")
|
||||
|
||||
private val ROWS
|
||||
get() = listOf(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
package com.pixelized.rplexicon.repository.parser
|
||||
|
||||
data class Column(
|
||||
val names: List<String>,
|
||||
) {
|
||||
override fun toString(): String {
|
||||
return names.toString()
|
||||
}
|
||||
}
|
||||
|
||||
fun column(vararg names: String) = Column(names = names.toList())
|
||||
|
|
@ -3,32 +3,23 @@ package com.pixelized.rplexicon.repository.parser
|
|||
import com.google.api.services.sheets.v4.model.ValueRange
|
||||
import com.pixelized.rplexicon.model.Description
|
||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
|
||||
import com.pixelized.rplexicon.utilitary.extentions.local.checkSheetStructure
|
||||
import com.pixelized.rplexicon.utilitary.extentions.sheet
|
||||
import javax.inject.Inject
|
||||
|
||||
class DescriptionParser @Inject constructor() {
|
||||
|
||||
@Throws(IncompatibleSheetStructure::class)
|
||||
fun parse(data: ValueRange): Map<String, Description> {
|
||||
val sheet = data.values.sheet()
|
||||
val values = hashMapOf<String, Description>()
|
||||
|
||||
lateinit var structure: Map<String, Int>
|
||||
|
||||
sheet?.forEachIndexed { index, item ->
|
||||
when {
|
||||
index == 0 -> {
|
||||
structure = item.checkSheetStructure(model = COLUMNS)
|
||||
}
|
||||
|
||||
item is List<*> -> {
|
||||
val name = item.getOrNull(structure.getValue(NAME)) as? String
|
||||
val translate = item.getOrNull(structure.getValue(TRANSLATE)) as? String
|
||||
val description = item.getOrNull(structure.getValue(DESCRIPTION)) as? String
|
||||
fun parse(sheet: ValueRange): Map<String, Description> = parserScope {
|
||||
val descriptions = hashMapOf<String, Description>()
|
||||
|
||||
sheet.forEachRow { index, row ->
|
||||
when (index) {
|
||||
0 -> updateStructure(row = row, columns = COLUMNS)
|
||||
else -> {
|
||||
val name = row.parse(column = NAME)
|
||||
val translate = row.parse(column = TRANSLATE)
|
||||
val description = row.parse(column = DESCRIPTION)
|
||||
if (name != null && translate != null && description != null) {
|
||||
values[name] = Description(
|
||||
descriptions[name] = Description(
|
||||
name = name,
|
||||
original = translate,
|
||||
description = description,
|
||||
|
|
@ -38,13 +29,13 @@ class DescriptionParser @Inject constructor() {
|
|||
}
|
||||
}
|
||||
|
||||
return values
|
||||
return@parserScope descriptions
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val NAME = "Nom"
|
||||
private const val TRANSLATE = "Traduction"
|
||||
private const val DESCRIPTION = "Description"
|
||||
private val NAME = column("Nom")
|
||||
private val TRANSLATE = column("Traduction")
|
||||
private val DESCRIPTION = column("Description")
|
||||
|
||||
private val COLUMNS = listOf(
|
||||
NAME,
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@ package com.pixelized.rplexicon.repository.parser
|
|||
import com.google.api.services.sheets.v4.model.ValueRange
|
||||
import com.pixelized.rplexicon.model.Lexicon
|
||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
|
||||
import com.pixelized.rplexicon.utilitary.extentions.local.checkSheetStructure
|
||||
import com.pixelized.rplexicon.utilitary.extentions.sheet
|
||||
import javax.inject.Inject
|
||||
|
||||
class LexiconParser @Inject constructor(
|
||||
|
|
@ -12,80 +10,65 @@ class LexiconParser @Inject constructor(
|
|||
private val genderParser: GenderParser,
|
||||
private val raceParser: RaceParser,
|
||||
) {
|
||||
|
||||
@Throws(IncompatibleSheetStructure::class)
|
||||
fun parse(data: ValueRange): List<Lexicon> {
|
||||
val sheet = data.values.sheet()
|
||||
lateinit var sheetStructure: Map<String, Int>
|
||||
fun parse(sheet: ValueRange): List<Lexicon> = parserScope {
|
||||
var id = 0
|
||||
val lexicons = mutableListOf<Lexicon>()
|
||||
|
||||
return sheet?.mapIndexedNotNull { index, row ->
|
||||
when {
|
||||
index == 0 -> {
|
||||
sheetStructure = row.checkSheetStructure(model = COLUMNS)
|
||||
null
|
||||
}
|
||||
|
||||
row is List<*> -> {
|
||||
val name = row.getOrNull(sheetStructure.name) as? String
|
||||
val diminutive = row.getOrNull(sheetStructure.diminutive) as? String
|
||||
val gender = row.getOrNull(sheetStructure.gender) as? String
|
||||
val race = row.getOrNull(sheetStructure.race) as? String
|
||||
val portrait = row.getOrNull(sheetStructure.portrait) as? String
|
||||
val status = row.getOrNull(sheetStructure.status) as? String
|
||||
val location = row.getOrNull(sheetStructure.location) as? String
|
||||
val description = row.getOrNull(sheetStructure.description) as? String
|
||||
val history = row.getOrNull(sheetStructure.history) as? String
|
||||
val tags = row.getOrNull(sheetStructure.tags) as? String
|
||||
sheet.forEachRow { index, row ->
|
||||
when (index) {
|
||||
0 -> updateStructure(row = row, columns = COLUMNS)
|
||||
|
||||
else -> {
|
||||
val name = row.parse(column = NAME)
|
||||
if (name != null) {
|
||||
Lexicon(
|
||||
val lexicon = Lexicon(
|
||||
id = id++,
|
||||
sheetIndex = index,
|
||||
name = name,
|
||||
diminutive = diminutive?.takeIf { it.isNotBlank() },
|
||||
gender = genderParser.parse(gender),
|
||||
race = raceParser.parser(race),
|
||||
portrait = portraitParser.parse(portrait),
|
||||
status = status?.takeIf { it.isNotBlank() },
|
||||
location = location?.takeIf { it.isNotBlank() },
|
||||
description = description?.takeIf { it.isNotBlank() },
|
||||
history = history?.takeIf { it.isNotBlank() },
|
||||
tags = tags?.takeIf { it.isNotBlank() },
|
||||
diminutive = row.parse(column = SHORT),
|
||||
gender = genderParser.parse(row.parse(column = GENDER)),
|
||||
race = raceParser.parser(row.parse(column = RACE)),
|
||||
status = row.parse(column = STATUS),
|
||||
location = row.parse(column = LOCATION),
|
||||
portrait = portraitParser.parse(row.parse(column = PORTRAIT)),
|
||||
description = row.parse(column = DESCRIPTION),
|
||||
history = row.parse(column = HISTORY),
|
||||
tags = row.parse(column = TAGS),
|
||||
)
|
||||
} else {
|
||||
null
|
||||
lexicons.add(lexicon)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else -> null
|
||||
return@parserScope lexicons
|
||||
}
|
||||
} ?: emptyList()
|
||||
}
|
||||
|
||||
private val Map<String, Int>.name: Int get() = getValue(COLUMNS[0])
|
||||
private val Map<String, Int>.diminutive: Int get() = getValue(COLUMNS[1])
|
||||
private val Map<String, Int>.gender: Int get() = getValue(COLUMNS[2])
|
||||
private val Map<String, Int>.race: Int get() = getValue(COLUMNS[3])
|
||||
private val Map<String, Int>.status: Int get() = getValue(COLUMNS[4])
|
||||
private val Map<String, Int>.location: Int get() = getValue(COLUMNS[5])
|
||||
private val Map<String, Int>.portrait: Int get() = getValue(COLUMNS[6])
|
||||
private val Map<String, Int>.description: Int get() = getValue(COLUMNS[7])
|
||||
private val Map<String, Int>.history: Int get() = getValue(COLUMNS[8])
|
||||
private val Map<String, Int>.tags: Int get() = getValue(COLUMNS[9])
|
||||
|
||||
companion object {
|
||||
private val COLUMNS = listOf(
|
||||
"Nom",
|
||||
"Diminutif",
|
||||
"Sexe",
|
||||
"Race",
|
||||
"Statut",
|
||||
"Localisation",
|
||||
"Portrait",
|
||||
"Description",
|
||||
"Histoire",
|
||||
"Mots clés",
|
||||
private val NAME = column("Nom")
|
||||
private val SHORT = column("Diminutif")
|
||||
private val GENDER = column("Sexe")
|
||||
private val RACE = column("Race")
|
||||
private val STATUS = column("Statut")
|
||||
private val LOCATION = column("Localisation")
|
||||
private val PORTRAIT = column("Portrait")
|
||||
private val DESCRIPTION = column("Description")
|
||||
private val HISTORY = column("Histoire")
|
||||
private val TAGS = column("Mots clés")
|
||||
|
||||
private val COLUMNS
|
||||
get() = listOf(
|
||||
NAME,
|
||||
SHORT,
|
||||
GENDER,
|
||||
RACE,
|
||||
STATUS,
|
||||
LOCATION,
|
||||
PORTRAIT,
|
||||
DESCRIPTION,
|
||||
HISTORY,
|
||||
TAGS,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,55 +1,43 @@
|
|||
package com.pixelized.rplexicon.repository.parser
|
||||
|
||||
import android.net.Uri
|
||||
import com.google.api.services.sheets.v4.model.ValueRange
|
||||
import com.pixelized.rplexicon.model.Location
|
||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
|
||||
import com.pixelized.rplexicon.utilitary.extentions.local.checkSheetStructure
|
||||
import com.pixelized.rplexicon.utilitary.extentions.sheet
|
||||
import javax.inject.Inject
|
||||
|
||||
class LocationParser @Inject constructor() {
|
||||
|
||||
@Throws(IncompatibleSheetStructure::class)
|
||||
fun parse(data: ValueRange): List<Location> {
|
||||
fun parse(sheet: ValueRange): List<Location> = parserScope {
|
||||
val locations = mutableListOf<Location>()
|
||||
var id = 0
|
||||
var sheetStructure: Map<String, Int>? = null
|
||||
|
||||
return data.values.sheet()?.mapIndexedNotNull { index, item ->
|
||||
when {
|
||||
index == 0 -> {
|
||||
sheetStructure = item.checkSheetStructure(COLUMNS)
|
||||
null
|
||||
}
|
||||
|
||||
item is List<*> -> {
|
||||
val name = item.getOrNull(sheetStructure.name) as? String
|
||||
val uri = item.getOrNull(sheetStructure.uri)?.toString()?.let { Uri.parse(it) }
|
||||
|
||||
sheet.forEachRow { index, row ->
|
||||
when (index) {
|
||||
0 -> updateStructure(row = row, columns = COLUMNS)
|
||||
else -> {
|
||||
val name = row.parse(column = NAME)
|
||||
val uri = row.parseUri(column = MAP)
|
||||
if (name != null && uri != null) {
|
||||
Location(
|
||||
val location = Location(
|
||||
id = id++,
|
||||
sheetIndex = index,
|
||||
name = name,
|
||||
uri = uri,
|
||||
marquees = emptyList(),
|
||||
)
|
||||
} else {
|
||||
null
|
||||
locations.add(location)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else -> null
|
||||
return@parserScope locations
|
||||
}
|
||||
} ?: emptyList()
|
||||
}
|
||||
|
||||
private val Map<String, Int>?.name: Int get() = this?.getValue(COLUMNS[0]) ?: 0
|
||||
private val Map<String, Int>?.uri: Int get() = this?.getValue(COLUMNS[1]) ?: 1
|
||||
|
||||
companion object {
|
||||
private val COLUMNS = listOf(
|
||||
"Nom", "Carte"
|
||||
)
|
||||
private val NAME = column("Nom")
|
||||
private val MAP = column("Carte")
|
||||
private val COLUMNS get() = listOf(NAME, MAP)
|
||||
}
|
||||
}
|
||||
|
|
@ -3,63 +3,52 @@ package com.pixelized.rplexicon.repository.parser
|
|||
import androidx.compose.ui.geometry.Offset
|
||||
import com.google.api.services.sheets.v4.model.ValueRange
|
||||
import com.pixelized.rplexicon.model.Location
|
||||
import com.pixelized.rplexicon.utilitary.extentions.local.checkSheetStructure
|
||||
import com.pixelized.rplexicon.utilitary.extentions.sheet
|
||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
|
||||
import javax.inject.Inject
|
||||
|
||||
class MarqueeParser @Inject constructor() {
|
||||
|
||||
fun parse(data: ValueRange): List<Location.Marquee> {
|
||||
val sheet = data.values.sheet()
|
||||
lateinit var structure: Map<String, Int>
|
||||
@Throws(IncompatibleSheetStructure::class)
|
||||
fun parse(sheet: ValueRange): List<Location.Marquee> = parserScope {
|
||||
val marquees = mutableListOf<Location.Marquee>()
|
||||
|
||||
return sheet?.mapIndexedNotNull { index, item ->
|
||||
when {
|
||||
index == 0 -> {
|
||||
structure = item.checkSheetStructure(model = COLUMNS)
|
||||
null
|
||||
}
|
||||
sheet.forEachRow { index, item ->
|
||||
when (index) {
|
||||
0 -> updateStructure(row = item, columns = COLUMNS)
|
||||
|
||||
item is List<*> -> {
|
||||
val map = item.getOrNull(structure.map) as? String
|
||||
val name = item.getOrNull(structure.name) as? String?
|
||||
val x = (item.getOrNull(structure.x) as? String)
|
||||
else -> {
|
||||
val map = item.parse(column = MAP)
|
||||
val x = item.parse(column = X)
|
||||
?.replace(oldValue = ",", newValue = ".")
|
||||
?.toFloatOrNull()
|
||||
val y = (item.getOrNull(structure.y) as? String)
|
||||
val y = item.parse(column = Y)
|
||||
?.replace(oldValue = ",", newValue = ".")
|
||||
?.toFloatOrNull()
|
||||
val description = item.getOrNull(structure.description) as? String?
|
||||
|
||||
if (map != null) {
|
||||
Location.Marquee(
|
||||
val marquee = Location.Marquee(
|
||||
map = map,
|
||||
name = name?.takeIf { it.isNotBlank() },
|
||||
name = item.parse(column = NAME),
|
||||
position = when {
|
||||
x != null && y != null -> Offset(x, y)
|
||||
else -> Offset.Unspecified
|
||||
},
|
||||
description = description?.takeIf { it.isNotBlank() },
|
||||
description = item.parse(column = DESCRIPTION),
|
||||
)
|
||||
} else {
|
||||
null
|
||||
marquees.add(marquee)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else -> null
|
||||
return@parserScope marquees
|
||||
}
|
||||
} ?: emptyList()
|
||||
}
|
||||
|
||||
private val Map<String, Int>.map: Int get() = getValue(COLUMNS[0])
|
||||
private val Map<String, Int>.name: Int get() = getValue(COLUMNS[1])
|
||||
private val Map<String, Int>.x: Int get() = getValue(COLUMNS[2])
|
||||
private val Map<String, Int>.y: Int get() = getValue(COLUMNS[3])
|
||||
private val Map<String, Int>.description: Int get() = getValue(COLUMNS[4])
|
||||
|
||||
companion object {
|
||||
private val COLUMNS = listOf(
|
||||
"Carte", "Nom", "X", "Y", "Description"
|
||||
)
|
||||
private val MAP = column("Carte")
|
||||
private val NAME = column("Nom")
|
||||
private val X = column("X")
|
||||
private val Y = column("Y")
|
||||
private val DESCRIPTION = column("Description")
|
||||
private val COLUMNS get() = listOf(MAP, NAME, X, Y, DESCRIPTION)
|
||||
}
|
||||
}
|
||||
|
|
@ -36,8 +36,8 @@ class ObjectActionParser @Inject constructor(
|
|||
}
|
||||
|
||||
companion object {
|
||||
private const val NAME = "Nom"
|
||||
private const val EFFECT = "Effet"
|
||||
private val NAME = column("Nom")
|
||||
private val EFFECT = column("Effet")
|
||||
private val COLUMNS = listOf(NAME, EFFECT)
|
||||
}
|
||||
}
|
||||
|
|
@ -8,28 +8,28 @@ import javax.inject.Inject
|
|||
class QuestParser @Inject constructor(
|
||||
private val imageParser: PortraitParser
|
||||
) {
|
||||
fun parse(value: ValueRange): List<QuestEntry> = parserScope {
|
||||
fun parse(sheet: ValueRange): List<QuestEntry> = parserScope {
|
||||
val quest = mutableListOf<QuestEntry>()
|
||||
|
||||
value.forEachRow { index, item ->
|
||||
sheet.forEachRow { index, item ->
|
||||
when (index) {
|
||||
0 -> updateStructure(row = item, columns = COLUMNS)
|
||||
else -> {
|
||||
val title = item.parse(TITLE)
|
||||
val description = item.parse(DESCRIPTION)
|
||||
val title = item.parse(column = TITLE)
|
||||
val description = item.parse(column = DESCRIPTION)
|
||||
if (title?.isNotEmpty() == true && description?.isNotEmpty() == true) {
|
||||
val entry = QuestEntry(
|
||||
sheetIndex = index,
|
||||
title = title,
|
||||
subtitle = item.parse(SUB_TITLE),
|
||||
complete = item.parseBool(COMPLETED) ?: false,
|
||||
questGiver = item.parse(QUEST_GIVER),
|
||||
area = item.parse(AREA),
|
||||
groupReward = item.parse(GROUP_REWARD),
|
||||
individualReward = item.parse(INDIVIDUAL_REWARD),
|
||||
subtitle = item.parse(column = SUB_TITLE),
|
||||
complete = item.parseBool(column = COMPLETED) ?: false,
|
||||
questGiver = item.parse(column = QUEST_GIVER),
|
||||
area = item.parse(column = AREA),
|
||||
groupReward = item.parse(column = GROUP_REWARD),
|
||||
individualReward = item.parse(column = INDIVIDUAL_REWARD),
|
||||
description = description,
|
||||
images = imageParser.parse(item.parse(IMAGE)),
|
||||
background = item.parseUri(BACKGROUND),
|
||||
images = imageParser.parse(item.parse(column = IMAGE)),
|
||||
background = item.parseUri(column = BACKGROUND),
|
||||
)
|
||||
quest.add(entry)
|
||||
}
|
||||
|
|
@ -37,22 +37,23 @@ class QuestParser @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
quest
|
||||
return@parserScope quest
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TITLE = "Titre"
|
||||
private const val SUB_TITLE = "Sous Titre"
|
||||
private const val COMPLETED = "Compléter"
|
||||
private const val QUEST_GIVER = "Commanditaire"
|
||||
private const val AREA = "Lieu"
|
||||
private const val GROUP_REWARD = "Récompense de groupe"
|
||||
private const val INDIVIDUAL_REWARD = "Récompense individuelle"
|
||||
private const val DESCRIPTION = "Description"
|
||||
private const val IMAGE = "Image"
|
||||
private const val BACKGROUND = "fond" // TODO
|
||||
private val TITLE = column("Titre")
|
||||
private val SUB_TITLE = column("Sous Titre")
|
||||
private val COMPLETED = column("Compléter")
|
||||
private val QUEST_GIVER = column("Commanditaire")
|
||||
private val AREA = column("Lieu")
|
||||
private val GROUP_REWARD = column("Récompense de groupe")
|
||||
private val INDIVIDUAL_REWARD = column("Récompense individuelle")
|
||||
private val DESCRIPTION = column("Description")
|
||||
private val IMAGE = column("Image")
|
||||
private val BACKGROUND = column("fond", "Fond") // TODO remove "fond" after 0.7.0 release
|
||||
|
||||
private val COLUMNS = listOf(
|
||||
private val COLUMNS
|
||||
get() = listOf(
|
||||
TITLE,
|
||||
SUB_TITLE,
|
||||
COMPLETED,
|
||||
|
|
|
|||
|
|
@ -13,9 +13,9 @@ inline fun <reified T> parserScope(
|
|||
}
|
||||
|
||||
class SheetParserScope<T> {
|
||||
private var structure: Map<String, Int> = hashMapOf()
|
||||
private var structure: Map<Column, Int> = hashMapOf()
|
||||
|
||||
fun updateStructure(row: Any, columns: List<String>) {
|
||||
fun updateStructure(row: Any, columns: List<Column>) {
|
||||
structure = row.checkSheetStructure(model = columns)
|
||||
}
|
||||
|
||||
|
|
@ -31,15 +31,15 @@ class SheetParserScope<T> {
|
|||
fun Any?.toItem(): String? =
|
||||
this.toString().takeIf { it.isNotBlank() }
|
||||
|
||||
fun List<*>.parse(column: String): String? =
|
||||
fun List<*>.parse(column: Column): String? =
|
||||
getOrNull(structure.getValue(column))?.toItem()
|
||||
|
||||
fun List<*>.parseInt(column: String): Int? =
|
||||
fun List<*>.parseInt(column: Column): Int? =
|
||||
parse(column)?.toIntOrNull()
|
||||
|
||||
fun List<*>.parseBool(column: String): Boolean? =
|
||||
fun List<*>.parseBool(column: Column): Boolean? =
|
||||
parse(column)?.equals("TRUE", ignoreCase = true)
|
||||
|
||||
fun List<*>.parseUri(column: String): Uri? =
|
||||
fun List<*>.parseUri(column: Column): Uri? =
|
||||
parse(column)?.takeIf { it.isNotBlank() }?.toUri()
|
||||
}
|
||||
|
|
@ -3,30 +3,19 @@ package com.pixelized.rplexicon.repository.parser
|
|||
import com.google.api.services.sheets.v4.model.ValueRange
|
||||
import com.pixelized.rplexicon.model.Skill
|
||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
|
||||
import com.pixelized.rplexicon.utilitary.extentions.local.checkSheetStructure
|
||||
import com.pixelized.rplexicon.utilitary.extentions.sheet
|
||||
import javax.inject.Inject
|
||||
|
||||
class SkillParser @Inject constructor(
|
||||
private val throwParser: ThrowParser,
|
||||
) {
|
||||
|
||||
@Throws(IncompatibleSheetStructure::class)
|
||||
fun parse(data: ValueRange): Map<String, List<Skill>> {
|
||||
val sheet = data.values.sheet()
|
||||
val values = hashMapOf<String, MutableList<Skill>>()
|
||||
fun parse(sheet: ValueRange): Map<String, List<Skill>> = parserScope {
|
||||
val skills = hashMapOf<String, MutableList<Skill>>()
|
||||
|
||||
lateinit var sheetStructure: Map<String, Int>
|
||||
fun List<*>.parse(column: String): String? =
|
||||
(getOrNull(sheetStructure.getValue(column)) as? String)?.takeIf { it.isNotBlank() }
|
||||
|
||||
sheet?.forEachIndexed { index, row ->
|
||||
when {
|
||||
index == 0 -> {
|
||||
sheetStructure = row.checkSheetStructure(model = COLUMNS)
|
||||
}
|
||||
|
||||
row is List<*> -> {
|
||||
sheet.forEachRow { index, row ->
|
||||
when (index) {
|
||||
0 -> updateStructure(row = row, columns = COLUMNS)
|
||||
else -> {
|
||||
val character = row[0] as? String
|
||||
val name = row.parse(column = NAME)
|
||||
if (character?.isNotBlank() == true && name != null) {
|
||||
|
|
@ -37,28 +26,22 @@ class SkillParser @Inject constructor(
|
|||
cost = row.parse(column = COST),
|
||||
effect = throwParser.parse(row.parse(column = EFFECT)),
|
||||
)
|
||||
values.getOrPut(character) { mutableListOf() }.add(skill)
|
||||
skills.getOrPut(character) { mutableListOf() }.add(skill)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return values
|
||||
return@parserScope skills
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val NAME = "Nom"
|
||||
private const val AMOUNT = "Quantité"
|
||||
private const val REST = "Récupération"
|
||||
private const val COST = "Coût"
|
||||
private const val EFFECT = "Effect"
|
||||
private val NAME = column("Nom")
|
||||
private val AMOUNT = column("Quantité")
|
||||
private val REST = column("Récupération")
|
||||
private val COST = column("Coût")
|
||||
private val EFFECT = column("Effect")
|
||||
|
||||
private val COLUMNS = listOf(
|
||||
NAME,
|
||||
AMOUNT,
|
||||
REST,
|
||||
COST,
|
||||
EFFECT,
|
||||
)
|
||||
private val COLUMNS get() = listOf(NAME, AMOUNT, REST, COST, EFFECT)
|
||||
}
|
||||
}
|
||||
|
|
@ -4,11 +4,11 @@ import com.google.api.services.sheets.v4.model.ValueRange
|
|||
import com.pixelized.rplexicon.model.Alteration
|
||||
import com.pixelized.rplexicon.model.CharacterSheet
|
||||
import com.pixelized.rplexicon.model.Property
|
||||
import com.pixelized.rplexicon.repository.parser.column
|
||||
import com.pixelized.rplexicon.repository.parser.parserScope
|
||||
import com.pixelized.rplexicon.repository.parser.roll.DiceParser
|
||||
import com.pixelized.rplexicon.repository.parser.roll.FlatValueParser
|
||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
|
||||
import com.pixelized.rplexicon.utilitary.extentions.local.checkSheetStructure
|
||||
import com.pixelized.rplexicon.utilitary.extentions.sheet
|
||||
import javax.inject.Inject
|
||||
|
||||
class AlterationParser @Inject constructor(
|
||||
|
|
@ -16,30 +16,22 @@ class AlterationParser @Inject constructor(
|
|||
private val flatParser: FlatValueParser,
|
||||
) {
|
||||
@Throws(IncompatibleSheetStructure::class)
|
||||
fun parse(values: ValueRange, sheets: List<CharacterSheet>): Map<String, List<Alteration>> {
|
||||
val sheet = values.values.sheet()
|
||||
|
||||
fun parse(
|
||||
sheet: ValueRange,
|
||||
characterSheets: List<CharacterSheet>,
|
||||
): Map<String, List<Alteration>> = parserScope {
|
||||
val properties = Property.values()
|
||||
val data = hashMapOf<String, MutableList<Alteration>>()
|
||||
val alterations = hashMapOf<String, MutableList<Alteration>>()
|
||||
|
||||
lateinit var alterationStructure: Map<String, Int>
|
||||
lateinit var charactersStructure: Map<String, Int>
|
||||
sheet.forEachRow { index, row ->
|
||||
when (index) {
|
||||
0 -> updateStructure(row = row, columns = COLUMNS + characterSheets.map { column(it.name) })
|
||||
|
||||
fun List<*>.parseString(key: String): String? =
|
||||
(getOrNull(alterationStructure.getValue(key)) as? String)?.takeIf { it.isNotEmpty() }
|
||||
|
||||
sheet?.forEachIndexed { index, row ->
|
||||
when {
|
||||
index == 0 -> {
|
||||
alterationStructure = row.checkSheetStructure(model = COLUMNS)
|
||||
charactersStructure = row.checkSheetStructure(model = sheets.map { it.name })
|
||||
}
|
||||
|
||||
row is List<*> -> {
|
||||
else -> {
|
||||
// Assume that the name is the first column.
|
||||
val name = row.getOrNull(0) as? String
|
||||
val source = row.parseString(SOURCE)
|
||||
val target = row.parseString(TARGET)
|
||||
val source = row.parse(column = SOURCE)
|
||||
val target = row.parse(column = TARGET)
|
||||
val alteration = if (name != null && source != null && target != null) {
|
||||
Alteration(
|
||||
name = name,
|
||||
|
|
@ -48,8 +40,7 @@ class AlterationParser @Inject constructor(
|
|||
active = false,
|
||||
status = properties
|
||||
.mapNotNull { property ->
|
||||
val column = alterationStructure.getValue(property.key)
|
||||
val value = row.getOrNull(column) as? String
|
||||
val value = row.parse(column = column(property.key))
|
||||
if (value?.isNotEmpty() == true) {
|
||||
property to parseAlterationStatus(name, value)
|
||||
} else {
|
||||
|
|
@ -62,26 +53,26 @@ class AlterationParser @Inject constructor(
|
|||
null
|
||||
}
|
||||
if (alteration != null) {
|
||||
sheets
|
||||
characterSheets
|
||||
.filter { // check if the alteration is applicable to the character
|
||||
alteration.target.let { target ->
|
||||
target == ALL || target == it.characterClass || target == it.race || target == it.name
|
||||
}
|
||||
}
|
||||
.forEach { // check the default alteration state for that character
|
||||
val column = charactersStructure.getValue(it.name)
|
||||
val default = (row.getOrNull(column) as? String)?.toBoolean()
|
||||
val default = row.parseBool(column = column(it.name))
|
||||
val assignedAlteration = alteration.copy(
|
||||
active = default ?: false
|
||||
)
|
||||
data.getOrPut(it.name) { mutableListOf() }.add(assignedAlteration)
|
||||
alterations.getOrPut(it.name) { mutableListOf() }
|
||||
.add(assignedAlteration)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return data
|
||||
return@parserScope alterations
|
||||
}
|
||||
|
||||
private fun parseAlterationStatus(name: String, value: String): Alteration.Status =
|
||||
|
|
@ -125,9 +116,9 @@ class AlterationParser @Inject constructor(
|
|||
private const val DISADVANTAGE = "dis"
|
||||
private const val FAIL = "fail"
|
||||
|
||||
private const val TARGET = "Cible"
|
||||
private const val SOURCE = "Source"
|
||||
private val TARGET = column("Cible")
|
||||
private val SOURCE = column("Source")
|
||||
private val COLUMNS
|
||||
get() = listOf(SOURCE, TARGET) + Property.values().map { it.key }
|
||||
get() = listOf(SOURCE, TARGET) + Property.values().map { column(it.key) }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,33 +1,28 @@
|
|||
package com.pixelized.rplexicon.repository.parser.alteration
|
||||
|
||||
import com.google.api.services.sheets.v4.model.ValueRange
|
||||
import com.pixelized.rplexicon.repository.parser.column
|
||||
import com.pixelized.rplexicon.repository.parser.parserScope
|
||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
|
||||
import com.pixelized.rplexicon.utilitary.extentions.local.checkSheetStructure
|
||||
import com.pixelized.rplexicon.utilitary.extentions.sheet
|
||||
import javax.inject.Inject
|
||||
|
||||
class AssignedAlterationParser @Inject constructor() {
|
||||
|
||||
@Throws(IncompatibleSheetStructure::class)
|
||||
fun parse(value: ValueRange, characters: List<String>): Map<String, List<String>> {
|
||||
val sheet = value.values.sheet()
|
||||
|
||||
fun parse(
|
||||
sheet: ValueRange,
|
||||
characterNames: List<String>
|
||||
): Map<String, List<String>> = parserScope {
|
||||
val status = hashMapOf<String, MutableList<String>>()
|
||||
lateinit var structure: Map<String, Int>
|
||||
|
||||
sheet?.mapNotNull { it as? List<*> }?.forEachIndexed { index, row ->
|
||||
sheet.forEachRow { index, row ->
|
||||
when (index) {
|
||||
0 -> {
|
||||
structure = row.checkSheetStructure(model = characters)
|
||||
}
|
||||
|
||||
0 -> updateStructure(row = row, columns = characterNames.map { column(it) })
|
||||
else -> {
|
||||
val alteration = row.getOrNull(0)?.toString()
|
||||
|
||||
if (alteration != null) {
|
||||
characters.forEach { character ->
|
||||
val value = row.getOrNull(structure.getValue(character))
|
||||
if (value == TRUE) {
|
||||
characterNames.forEach { character ->
|
||||
if (row.parseBool(column = column(character)) == true) {
|
||||
status
|
||||
.getOrPut(character) { mutableListOf() }
|
||||
.add(alteration)
|
||||
|
|
@ -38,10 +33,6 @@ class AssignedAlterationParser @Inject constructor() {
|
|||
}
|
||||
}
|
||||
|
||||
return status
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TRUE = "TRUE"
|
||||
return@parserScope status
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ package com.pixelized.rplexicon.repository.parser.inventory
|
|||
|
||||
import com.google.api.services.sheets.v4.model.ValueRange
|
||||
import com.pixelized.rplexicon.model.Inventory
|
||||
import com.pixelized.rplexicon.repository.parser.column
|
||||
import com.pixelized.rplexicon.repository.parser.parserScope
|
||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
|
||||
import javax.inject.Inject
|
||||
|
|
@ -9,10 +10,10 @@ import javax.inject.Inject
|
|||
class InventoryParser @Inject constructor() {
|
||||
|
||||
@Throws(IncompatibleSheetStructure::class)
|
||||
fun parse(data: ValueRange): Map<String, Inventory> = parserScope {
|
||||
fun parse(sheet: ValueRange): Map<String, Inventory> = parserScope {
|
||||
val inventories = hashMapOf<String, Inventory.Builder>()
|
||||
|
||||
data.forEachRow { index, row ->
|
||||
sheet.forEachRow { index, row ->
|
||||
when {
|
||||
index == 0 -> updateStructure(row = row, columns = COLUMNS)
|
||||
|
||||
|
|
@ -46,9 +47,9 @@ class InventoryParser @Inject constructor() {
|
|||
}
|
||||
|
||||
companion object {
|
||||
private const val CONTAINER = "Contenant"
|
||||
private const val NAME = "Name"
|
||||
private const val AMOUNT = "Quantité"
|
||||
private val CONTAINER = column("Contenant")
|
||||
private val NAME = column("Name")
|
||||
private val AMOUNT = column("Quantité")
|
||||
private val COLUMNS = listOf(CONTAINER, NAME, AMOUNT)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,35 +1,28 @@
|
|||
package com.pixelized.rplexicon.repository.parser.spell
|
||||
|
||||
import com.google.api.services.sheets.v4.model.ValueRange
|
||||
import com.pixelized.rplexicon.repository.parser.ThrowParser
|
||||
import com.pixelized.rplexicon.model.AssignedSpell
|
||||
import com.pixelized.rplexicon.model.Spell
|
||||
import com.pixelized.rplexicon.repository.parser.ThrowParser
|
||||
import com.pixelized.rplexicon.repository.parser.column
|
||||
import com.pixelized.rplexicon.repository.parser.parserScope
|
||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
|
||||
import com.pixelized.rplexicon.utilitary.extentions.local.checkSheetStructure
|
||||
import com.pixelized.rplexicon.utilitary.extentions.sheet
|
||||
import javax.inject.Inject
|
||||
|
||||
class AssignedSpellParser @Inject constructor(
|
||||
private val throwParser: ThrowParser,
|
||||
) {
|
||||
@Throws(IncompatibleSheetStructure::class)
|
||||
fun parse(data: ValueRange, spells: List<Spell>): Map<String, List<AssignedSpell>> {
|
||||
val sheet = data.values.sheet()
|
||||
fun parse(
|
||||
sheet: ValueRange,
|
||||
spells: List<Spell>,
|
||||
): Map<String, List<AssignedSpell>> = parserScope {
|
||||
val spellsBook = spells.associateBy { it.name }
|
||||
lateinit var structure: Map<String, Int>
|
||||
val assignedSpells = hashMapOf<String, MutableList<AssignedSpell>>()
|
||||
|
||||
// declare helper method to parse String
|
||||
fun List<*>.parse(key: String): String? =
|
||||
(getOrNull(structure.getValue(key)) as? String)?.takeIf { it.isNotEmpty() }
|
||||
|
||||
sheet?.forEachIndexed { index, row ->
|
||||
when {
|
||||
index == 0 -> {
|
||||
structure = row.checkSheetStructure(model = COLUMNS)
|
||||
}
|
||||
|
||||
row is List<*> -> {
|
||||
sheet.forEachRow { index, row ->
|
||||
when (index) {
|
||||
0 -> updateStructure(row = row, columns = COLUMNS)
|
||||
else -> {
|
||||
val character = row.getOrNull(0) as? String
|
||||
val spell = spellsBook[row.parse(NAME)]
|
||||
if (character != null && spell != null) {
|
||||
|
|
@ -46,22 +39,15 @@ class AssignedSpellParser @Inject constructor(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return assignedSpells
|
||||
return@parserScope assignedSpells
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val NAME = "Nom"
|
||||
private const val HIT = "Touché"
|
||||
private const val EFFECT = "Effet"
|
||||
private const val LEVEL = "Par niveau"
|
||||
private val NAME = column("Nom")
|
||||
private val HIT = column("Touché")
|
||||
private val EFFECT = column("Effet")
|
||||
private val LEVEL = column("Par niveau")
|
||||
|
||||
private val COLUMNS
|
||||
get() = listOf(
|
||||
NAME,
|
||||
HIT,
|
||||
EFFECT,
|
||||
LEVEL,
|
||||
)
|
||||
private val COLUMNS get() = listOf(NAME, HIT, EFFECT, LEVEL)
|
||||
}
|
||||
}
|
||||
|
|
@ -3,40 +3,27 @@ package com.pixelized.rplexicon.repository.parser.spell
|
|||
import android.util.Log
|
||||
import com.google.api.services.sheets.v4.model.ValueRange
|
||||
import com.pixelized.rplexicon.model.Spell
|
||||
import com.pixelized.rplexicon.repository.parser.column
|
||||
import com.pixelized.rplexicon.repository.parser.parserScope
|
||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
|
||||
import com.pixelized.rplexicon.utilitary.extentions.local.checkSheetStructure
|
||||
import com.pixelized.rplexicon.utilitary.extentions.sheet
|
||||
import javax.inject.Inject
|
||||
|
||||
class SpellBookParser @Inject constructor() {
|
||||
|
||||
@Throws(IncompatibleSheetStructure::class)
|
||||
fun parse(data: ValueRange): List<Spell> {
|
||||
|
||||
val sheet = data.values.sheet()
|
||||
|
||||
lateinit var structure: Map<String, Int>
|
||||
|
||||
// declare helper method to parse String
|
||||
fun List<*>.parse(key: String): String? =
|
||||
(getOrNull(structure.getValue(key)) as? String)?.takeIf { it.isNotEmpty() }
|
||||
|
||||
return sheet?.mapIndexedNotNull { index, row ->
|
||||
fun parse(sheet: ValueRange): List<Spell> = parserScope {
|
||||
val spells = mutableListOf<Spell>()
|
||||
sheet.forEachRow { index, row ->
|
||||
when {
|
||||
index == 0 -> {
|
||||
structure = row.checkSheetStructure(model = COLUMNS)
|
||||
null
|
||||
}
|
||||
|
||||
row is List<*> -> {
|
||||
val name = row.parse(NAME)
|
||||
val level = row.parse(LEVEL)?.toIntOrNull()
|
||||
val school = parseSchool(row.parse(SCHOOL))
|
||||
val castingTime = row.parse(CASTING_TIME)
|
||||
val range = row.parse(RANGE)
|
||||
val requirement = row.parse(REQUIREMENT)
|
||||
val duration = row.parse(DURATION)
|
||||
val ritual = row.parse(RITUAL)?.toBoolean() ?: false
|
||||
index == 0 -> updateStructure(row = row, columns = COLUMNS)
|
||||
else -> {
|
||||
val name = row.parse(column = NAME)
|
||||
val level = row.parseInt(column = LEVEL)
|
||||
val school = parseSchool(row.parse(column = SCHOOL))
|
||||
val castingTime = row.parse(column = CASTING_TIME)
|
||||
val range = row.parse(column = RANGE)
|
||||
val requirement = row.parse(column = REQUIREMENT)
|
||||
val duration = row.parse(column = DURATION)
|
||||
if (name != null
|
||||
&& level != null
|
||||
&& school != null
|
||||
|
|
@ -45,7 +32,7 @@ class SpellBookParser @Inject constructor() {
|
|||
&& requirement != null
|
||||
&& duration != null
|
||||
) {
|
||||
Spell(
|
||||
val spell = Spell(
|
||||
name = name,
|
||||
level = level,
|
||||
school = school,
|
||||
|
|
@ -53,16 +40,14 @@ class SpellBookParser @Inject constructor() {
|
|||
range = range,
|
||||
requirement = requirement,
|
||||
duration = duration,
|
||||
ritual = ritual,
|
||||
ritual = row.parseBool(column = RITUAL) ?: false,
|
||||
)
|
||||
} else {
|
||||
null
|
||||
spells.add(spell)
|
||||
}
|
||||
}
|
||||
|
||||
else -> null
|
||||
}
|
||||
} ?: emptyList()
|
||||
}
|
||||
return@parserScope spells
|
||||
}
|
||||
|
||||
private fun parseSchool(value: String?): Spell.School? = try {
|
||||
|
|
@ -73,25 +58,16 @@ class SpellBookParser @Inject constructor() {
|
|||
}
|
||||
|
||||
companion object {
|
||||
private const val NAME = "Nom"
|
||||
private const val SCHOOL = "École"
|
||||
private const val LEVEL = "Niveau"
|
||||
private const val CASTING_TIME = "Temps d'incantation"
|
||||
private const val RANGE = "Portée"
|
||||
private const val REQUIREMENT = "Composantes"
|
||||
private const val DURATION = "Durée"
|
||||
private const val RITUAL = "Rituel"
|
||||
private val NAME = column("Nom")
|
||||
private val SCHOOL = column("École")
|
||||
private val LEVEL = column("Niveau")
|
||||
private val CASTING_TIME = column("Temps d'incantation")
|
||||
private val RANGE = column("Portée")
|
||||
private val REQUIREMENT = column("Composantes")
|
||||
private val DURATION = column("Durée")
|
||||
private val RITUAL = column("Rituel")
|
||||
|
||||
private val COLUMNS
|
||||
get() = listOf(
|
||||
NAME,
|
||||
LEVEL,
|
||||
SCHOOL,
|
||||
CASTING_TIME,
|
||||
RANGE,
|
||||
REQUIREMENT,
|
||||
DURATION,
|
||||
RITUAL,
|
||||
)
|
||||
get() = listOf(NAME, LEVEL, SCHOOL, CASTING_TIME, RANGE, REQUIREMENT, DURATION, RITUAL)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,30 +1,27 @@
|
|||
package com.pixelized.rplexicon.utilitary.extentions.local
|
||||
|
||||
import com.pixelized.rplexicon.repository.parser.Column
|
||||
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
|
||||
|
||||
@Throws(IncompatibleSheetStructure::class)
|
||||
fun Any?.checkSheetStructure(model: List<String>): HashMap<String, Int> {
|
||||
fun Any?.checkSheetStructure(model: List<Column>): Map<Column, Int> {
|
||||
// check if the row is a list
|
||||
if (this !is ArrayList<*>) {
|
||||
throw IncompatibleSheetStructure("First row is not a List: $this")
|
||||
}
|
||||
// parse the first line to find element that we recognize.
|
||||
val sheetStructure = hashMapOf<String, Int>()
|
||||
forEachIndexed { index, cell ->
|
||||
if (cell is String && model.contains(cell)) {
|
||||
sheetStructure[cell] = index
|
||||
val sheetStructure = model.associateWith { key ->
|
||||
indexOfFirst { cell ->
|
||||
key.names.contains(cell)
|
||||
}
|
||||
}
|
||||
// check if we found everything we need.
|
||||
when {
|
||||
sheetStructure.size < model.size -> throw IncompatibleSheetStructure(
|
||||
message = "Sheet header row does not have enough column: $size.\nstructure: $this\nheader: $sheetStructure"
|
||||
)
|
||||
|
||||
sheetStructure.size > model.size -> throw IncompatibleSheetStructure(
|
||||
message = "Sheet header row does have too mush columns: $size.\nstructure: $this\nheader: $sheetStructure"
|
||||
sheetStructure.any { it.value < 0 } -> throw IncompatibleSheetStructure(
|
||||
message = "Sheet header row does not have enough column !" + sheetStructure
|
||||
.filter { it.value < 0 }.keys
|
||||
.joinToString(prefix = "\n- Missing column: ") { it.toString() }
|
||||
)
|
||||
}
|
||||
|
||||
return sheetStructure
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue