Link the player character ribbon to the server.
This commit is contained in:
parent
ed1b27039d
commit
4ed11660c3
17 changed files with 228 additions and 72 deletions
|
|
@ -20,6 +20,7 @@ import com.pixelized.desktop.lwa.repository.roll_history.RollHistoryRepository
|
|||
import com.pixelized.desktop.lwa.repository.settings.SettingsFactory
|
||||
import com.pixelized.desktop.lwa.repository.settings.SettingsRepository
|
||||
import com.pixelized.desktop.lwa.repository.settings.SettingsStore
|
||||
import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.CharacterDetailFactory
|
||||
import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.CharacterDetailViewModel
|
||||
import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.CharacterDiminishedViewModel
|
||||
import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.PlayerRibbonFactory
|
||||
|
|
@ -105,6 +106,7 @@ val factoryDependencies
|
|||
factoryOf(::SettingsFactory)
|
||||
factoryOf(::CampaignJsonFactory)
|
||||
factoryOf(::PlayerRibbonFactory)
|
||||
factoryOf(::CharacterDetailFactory)
|
||||
}
|
||||
|
||||
val viewModelDependencies
|
||||
|
|
@ -134,4 +136,4 @@ val useCaseDependencies
|
|||
factoryOf(::ExpressionUseCase)
|
||||
factoryOf(::SettingsUseCase)
|
||||
factoryOf(::CharacterSheetUseCase)
|
||||
}
|
||||
}
|
||||
|
|
@ -99,6 +99,10 @@ class ExpressionUseCase(
|
|||
rollUseCase.roll(expression.dice)
|
||||
}
|
||||
|
||||
is Expression.UrlExpression -> {
|
||||
0 // Ignore this case.
|
||||
}
|
||||
|
||||
is Expression.WordExpression -> when (expression.word.type) {
|
||||
Word.Type.BDC -> evaluate(expressionParser.parse(sheet.damageBonus))
|
||||
Word.Type.BDD -> evaluate(expressionParser.parse(sheet.damageBonus))
|
||||
|
|
|
|||
|
|
@ -67,6 +67,14 @@ sealed interface Expression {
|
|||
}
|
||||
}
|
||||
|
||||
data class UrlExpression(
|
||||
val url: String,
|
||||
) : Expression {
|
||||
override fun toString(): String {
|
||||
return url
|
||||
}
|
||||
}
|
||||
|
||||
data class DiceExpression(
|
||||
val dice: Dice,
|
||||
) : Expression {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@ package com.pixelized.desktop.lwa.parser.expression
|
|||
|
||||
import com.pixelized.desktop.lwa.parser.dice.DiceParser
|
||||
import com.pixelized.desktop.lwa.parser.word.WordParser
|
||||
import org.jetbrains.skia.toIPoint
|
||||
import java.net.URI
|
||||
import java.net.URL
|
||||
|
||||
/**
|
||||
* Highly inspired by the following javascript implementation:
|
||||
|
|
@ -15,6 +18,12 @@ class ExpressionParser(
|
|||
private val tokenBreak = arrayOf(
|
||||
'+', '-', '/', '*', '(', ')', ','
|
||||
)
|
||||
private val tokenBreakException = mapOf(
|
||||
'/' to listOf("http:", "https:"),
|
||||
'.' to listOf("http:", "https:"),
|
||||
'+' to listOf("http:", "https:"),
|
||||
'-' to listOf("http:", "https:"),
|
||||
)
|
||||
private val operators = mapOf(
|
||||
'+' to Operator(
|
||||
evaluations = { first, second -> Expression.Add(first, second) },
|
||||
|
|
@ -50,8 +59,11 @@ class ExpressionParser(
|
|||
* Every characters that are not un the [Companion.tokenBreak] list can be part of a token.
|
||||
* @see Companion.tokenBreak
|
||||
*/
|
||||
private fun isToken(): Boolean = stack.peek().let {
|
||||
it != null && !tokenBreak.contains(it)
|
||||
private fun isToken(
|
||||
currentToken: String? = null,
|
||||
): Boolean = stack.peek().let {
|
||||
it != null && !tokenBreak.contains(it) ||
|
||||
(tokenBreakException[it]?.any { currentToken?.contains(it) ?: false } ?: false)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -69,7 +81,7 @@ class ExpressionParser(
|
|||
val token = StringBuilder()
|
||||
do {
|
||||
stack.pull().let(token::append)
|
||||
} while (isToken())
|
||||
} while (isToken(token.toString()))
|
||||
return token.toString()
|
||||
}
|
||||
|
||||
|
|
@ -186,6 +198,16 @@ class ExpressionParser(
|
|||
return Expression.DiceExpression(dice)
|
||||
}
|
||||
|
||||
val url = try {
|
||||
println(token)
|
||||
URI.create(token).toString()
|
||||
} catch (_: Exception) {
|
||||
null
|
||||
}
|
||||
if (url != null) {
|
||||
return Expression.UrlExpression(url)
|
||||
}
|
||||
|
||||
throw Error.UnRecognizedToken(actual = token, expression = stack.input)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ class AlterationRepository(
|
|||
private val activeAlterationIdMapFlow: HashMap<CharacterId, MutableStateFlow<List<AlterationId>>> =
|
||||
hashMapOf("0f2117e9-e077-4354-8d77-20150df1c462" to MutableStateFlow(listOf("7c00dafa-a67d-4351-8ea9-67d933012cde", "65e37d32-3031-4bf8-9369-d2c45d2efac0")))
|
||||
|
||||
fun alterations(characterId: String): Flow<Map<String, List<FieldAlteration>>> {
|
||||
fun alterationsFlow(characterId: String): Flow<Map<String, List<FieldAlteration>>> {
|
||||
return activeAlterationIdMapFlow
|
||||
.getOrPut(characterId) { MutableStateFlow(emptyList()) }
|
||||
.map { activeAlterationIds ->
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import kotlinx.coroutines.flow.SharingStarted
|
|||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class CharacterSheetRepository(
|
||||
private val store: CharacterSheetStore,
|
||||
|
|
@ -17,6 +16,7 @@ class CharacterSheetRepository(
|
|||
private val scope = CoroutineScope(Dispatchers.IO + Job())
|
||||
|
||||
val characterSheetPreviewFlow get() = store.previewFlow
|
||||
val characterDetailFlow get() = store.detailFlow
|
||||
|
||||
fun characterPreview(characterId: String?): CharacterSheetPreview? {
|
||||
return characterSheetPreviewFlow.value.firstOrNull { it.id == characterId }
|
||||
|
|
@ -35,17 +35,8 @@ class CharacterSheetRepository(
|
|||
|
||||
fun characterDetailFlow(
|
||||
characterId: String?,
|
||||
forceUpdate: Boolean = false,
|
||||
): StateFlow<CharacterSheet?> {
|
||||
val initial = store.detailFlow.value[characterId]
|
||||
if (forceUpdate || initial == null) {
|
||||
scope.launch {
|
||||
characterDetail(
|
||||
characterId = characterId,
|
||||
forceUpdate = forceUpdate,
|
||||
)
|
||||
}
|
||||
}
|
||||
return store.detailFlow
|
||||
.map { sheets ->
|
||||
sheets[characterId]
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ import org.jetbrains.compose.resources.painterResource
|
|||
import org.koin.compose.viewmodel.koinViewModel
|
||||
|
||||
@Stable
|
||||
data class CharacterDetailUio(
|
||||
data class CharacterDetailHeaderUio(
|
||||
val id: String,
|
||||
val portrait: String?,
|
||||
val name: String,
|
||||
|
|
@ -55,7 +55,7 @@ data class CharacterDetailUio(
|
|||
)
|
||||
|
||||
@Stable
|
||||
data class CharacterDynDetailUio(
|
||||
data class CharacterDetailHeaderInstanceUio(
|
||||
val hp: String,
|
||||
val pp: String,
|
||||
)
|
||||
|
|
@ -109,8 +109,8 @@ fun CharacterDetail(
|
|||
@Composable
|
||||
fun CharacterDetailContent(
|
||||
modifier: Modifier = Modifier,
|
||||
character: CharacterDetailUio,
|
||||
dynDetail: State<CharacterDynDetailUio?>,
|
||||
character: CharacterDetailHeaderUio,
|
||||
dynDetail: State<CharacterDetailHeaderInstanceUio?>,
|
||||
onDismissRequest: () -> Unit,
|
||||
onDiminished: () -> Unit,
|
||||
onHp: () -> Unit,
|
||||
|
|
@ -139,7 +139,7 @@ fun CharacterDetailContent(
|
|||
@Composable
|
||||
private fun Background(
|
||||
modifier: Modifier = Modifier,
|
||||
character: CharacterDetailUio,
|
||||
character: CharacterDetailHeaderUio,
|
||||
) {
|
||||
Surface(
|
||||
modifier = modifier.fillMaxSize(),
|
||||
|
|
@ -168,8 +168,8 @@ private fun Background(
|
|||
@Composable
|
||||
private fun CharacterHeader(
|
||||
modifier: Modifier = Modifier,
|
||||
character: CharacterDetailUio,
|
||||
dynDetail: State<CharacterDynDetailUio?>,
|
||||
character: CharacterDetailHeaderUio,
|
||||
dynDetail: State<CharacterDetailHeaderInstanceUio?>,
|
||||
onDismissRequest: () -> Unit,
|
||||
onDiminished: () -> Unit,
|
||||
onHp: () -> Unit,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
package com.pixelized.desktop.lwa.ui.screen.campaign.player.detail
|
||||
|
||||
import com.pixelized.desktop.lwa.business.ExpressionUseCase
|
||||
import com.pixelized.desktop.lwa.parser.expression.Expression
|
||||
import com.pixelized.desktop.lwa.repository.alteration.model.FieldAlteration
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet.CharacteristicId.HP
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet.CharacteristicId.MOV
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet.CharacteristicId.PORTRAIT
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet.CharacteristicId.PP
|
||||
|
||||
class CharacterDetailFactory(
|
||||
private val expressionUseCase: ExpressionUseCase,
|
||||
) {
|
||||
|
||||
fun convertToCharacterDetailHeaderUio(
|
||||
sheet: CharacterSheet?,
|
||||
alterations: Map<String, List<FieldAlteration>>,
|
||||
): CharacterDetailHeaderUio? {
|
||||
if (sheet == null) return null
|
||||
|
||||
fun List<FieldAlteration>?.sum(): Int {
|
||||
return this?.sumOf {
|
||||
expressionUseCase.computeExpression(sheet = sheet, expression = it.expression)
|
||||
} ?: 0
|
||||
}
|
||||
|
||||
return CharacterDetailHeaderUio(
|
||||
id = sheet.id,
|
||||
portrait = alterations[PORTRAIT]
|
||||
?.firstNotNullOfOrNull { (it.expression as? Expression.UrlExpression)?.url }
|
||||
?: sheet.portrait,
|
||||
name = sheet.name,
|
||||
hp = "${sheet.hp + alterations[HP].sum()}",
|
||||
pp = "${sheet.pp + alterations[PP].sum()}",
|
||||
mov = "${sheet.movement + alterations[MOV].sum()}"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -13,33 +13,43 @@ import com.pixelized.desktop.lwa.repository.campaign.CampaignRepository
|
|||
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository
|
||||
import com.pixelized.shared.lwa.model.campaign.damage
|
||||
import com.pixelized.shared.lwa.model.campaign.power
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.mapNotNull
|
||||
import kotlinx.coroutines.flow.emptyFlow
|
||||
import kotlinx.coroutines.flow.flatMap
|
||||
import kotlinx.coroutines.flow.flatMapConcat
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
||||
class CharacterDetailViewModel(
|
||||
private val characterRepository: CharacterSheetRepository,
|
||||
private val campaignRepository: CampaignRepository,
|
||||
private val alterationRepository: AlterationRepository,
|
||||
private val characterDetailFactory: CharacterDetailFactory,
|
||||
) : ViewModel() {
|
||||
|
||||
private val displayedCharacterId = MutableStateFlow<String?>(null)
|
||||
|
||||
val detail: StateFlow<CharacterDetailUio?> = displayedCharacterId.map { id ->
|
||||
val sheet = characterRepository.characterDetail(id) ?: return@map null
|
||||
CharacterDetailUio(
|
||||
id = sheet.id,
|
||||
portrait = sheet.portrait,
|
||||
name = sheet.name,
|
||||
hp = "${sheet.hp}",
|
||||
pp = "${sheet.pp}",
|
||||
mov = "${sheet.movement}"
|
||||
)
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
val detail: StateFlow<CharacterDetailHeaderUio?> = displayedCharacterId.flatMapLatest { id ->
|
||||
if (id != null) {
|
||||
combine(
|
||||
characterRepository.characterDetailFlow(characterId = id),
|
||||
alterationRepository.alterationsFlow(characterId = id),
|
||||
) { sheet, alteration ->
|
||||
characterDetailFactory.convertToCharacterDetailHeaderUio(
|
||||
sheet = sheet,
|
||||
alterations = alteration,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
flowOf(null)
|
||||
}
|
||||
}.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.Eagerly,
|
||||
|
|
@ -48,15 +58,15 @@ class CharacterDetailViewModel(
|
|||
|
||||
@Composable
|
||||
@Stable
|
||||
fun collectDynamicDetailAsState(id: String): State<CharacterDynDetailUio?> {
|
||||
fun collectDynamicDetailAsState(id: String): State<CharacterDetailHeaderInstanceUio?> {
|
||||
val scope = rememberCoroutineScope()
|
||||
val flow: StateFlow<CharacterDynDetailUio?> = remember(id) {
|
||||
val flow: StateFlow<CharacterDetailHeaderInstanceUio?> = remember(id) {
|
||||
combine(
|
||||
characterRepository.characterDetailFlow(id),
|
||||
campaignRepository.characterInstanceFlow(id = id),
|
||||
) { sheet, instance ->
|
||||
if (sheet == null) return@combine null
|
||||
CharacterDynDetailUio(
|
||||
CharacterDetailHeaderInstanceUio(
|
||||
hp = "${sheet.hp - instance.damage}",
|
||||
pp = "${sheet.power - instance.power}",
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,24 +1,48 @@
|
|||
package com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon
|
||||
|
||||
import com.pixelized.desktop.lwa.business.ExpressionUseCase
|
||||
import com.pixelized.desktop.lwa.parser.expression.Expression
|
||||
import com.pixelized.desktop.lwa.repository.alteration.model.FieldAlteration
|
||||
import com.pixelized.shared.lwa.model.campaign.Campaign
|
||||
import com.pixelized.shared.lwa.model.campaign.damage
|
||||
import com.pixelized.shared.lwa.model.campaign.power
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet.CharacteristicId.HP
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet.CharacteristicId.PP
|
||||
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet.CharacteristicId.THUMBNAIL
|
||||
|
||||
class PlayerRibbonFactory {
|
||||
class PlayerRibbonFactory(
|
||||
private val expressionUseCase: ExpressionUseCase,
|
||||
) {
|
||||
|
||||
fun convertToPlayerPortraitUio(
|
||||
characterSheet: CharacterSheet?,
|
||||
characterInstance: Campaign.CharacterInstance,
|
||||
alterations: Map<String, List<FieldAlteration>>,
|
||||
): PlayerPortraitUio? {
|
||||
if (characterSheet == null) return null
|
||||
|
||||
fun List<FieldAlteration>?.sum(): Int {
|
||||
return this?.sumOf {
|
||||
expressionUseCase.computeExpression(
|
||||
sheet = characterSheet,
|
||||
expression = it.expression,
|
||||
)
|
||||
} ?: 0
|
||||
}
|
||||
|
||||
val maxHp = characterSheet.hp + alterations[HP].sum()
|
||||
val maxPp = characterSheet.pp + alterations[PP].sum()
|
||||
|
||||
return PlayerPortraitUio(
|
||||
id = characterSheet.id,
|
||||
portrait = characterSheet.thumbnail,
|
||||
hp = characterSheet.hp - characterInstance.damage,
|
||||
maxHp = characterSheet.hp,
|
||||
pp = characterSheet.pp - characterInstance.power,
|
||||
maxPp = characterSheet.pp,
|
||||
portrait = alterations[THUMBNAIL]
|
||||
?.firstNotNullOfOrNull { (it.expression as? Expression.UrlExpression)?.url }
|
||||
?: characterSheet.thumbnail,
|
||||
hp = maxHp - characterInstance.damage,
|
||||
maxHp = maxHp,
|
||||
pp = maxPp - characterInstance.power,
|
||||
maxPp = maxPp,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -8,30 +8,49 @@ import androidx.compose.runtime.State
|
|||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.pixelized.desktop.lwa.repository.alteration.AlterationRepository
|
||||
import com.pixelized.desktop.lwa.repository.campaign.CampaignRepository
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository
|
||||
import com.pixelized.desktop.lwa.repository.roll_history.RollHistoryRepository
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.flatMapMerge
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class PlayerRibbonViewModel(
|
||||
private val rollHistoryRepository: RollHistoryRepository,
|
||||
characterRepository: CharacterSheetRepository,
|
||||
alterationRepository: AlterationRepository,
|
||||
private val ribbonFactory: PlayerRibbonFactory,
|
||||
campaignRepository: CampaignRepository,
|
||||
) : ViewModel() {
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
val characters: StateFlow<List<PlayerPortraitUio>> = campaignRepository.campaignFlow
|
||||
.map { campaign ->
|
||||
campaign.characters.mapNotNull { entry ->
|
||||
ribbonFactory.convertToPlayerPortraitUio(
|
||||
characterSheet = characterRepository.characterDetail(characterId = entry.key),
|
||||
characterInstance = entry.value,
|
||||
)
|
||||
}
|
||||
}.stateIn(
|
||||
.flatMapMerge { campaign ->
|
||||
combine<PlayerPortraitUio?, List<PlayerPortraitUio>>(
|
||||
flows = campaign.characters.map { entry ->
|
||||
combine(
|
||||
characterRepository.characterDetailFlow(characterId = entry.key),
|
||||
alterationRepository.alterationsFlow(characterId = entry.key),
|
||||
) { sheet, alterations ->
|
||||
ribbonFactory.convertToPlayerPortraitUio(
|
||||
characterSheet = sheet,
|
||||
characterInstance = entry.value,
|
||||
alterations = alterations,
|
||||
)
|
||||
}
|
||||
},
|
||||
transform = { headers ->
|
||||
headers.mapNotNull { it }.toList()
|
||||
}
|
||||
)
|
||||
}
|
||||
.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.Eagerly,
|
||||
initialValue = emptyList()
|
||||
|
|
@ -39,6 +58,19 @@ class PlayerRibbonViewModel(
|
|||
|
||||
private val rolls = hashMapOf<String, MutableState<PlayerPortraitRollUio?>>()
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
campaignRepository.campaignFlow.collectLatest {
|
||||
it.characters.keys.forEach { id ->
|
||||
characterRepository.characterDetail(
|
||||
characterId = id,
|
||||
forceUpdate = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Stable
|
||||
fun roll(characterId: String): State<PlayerPortraitRollUio?> {
|
||||
|
|
|
|||
|
|
@ -46,7 +46,6 @@ class CharacterSheetFactory(
|
|||
private val skillUseCase: ExpressionUseCase,
|
||||
private val expressionUseCase: ExpressionUseCase,
|
||||
) {
|
||||
|
||||
suspend fun convertToUio(
|
||||
sheet: CharacterSheet?,
|
||||
campaign: Campaign,
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ class CharacterSheetViewModel(
|
|||
private val sheetFlow = combine(
|
||||
characterRepository.characterDetailFlow(characterId = argument.id),
|
||||
campaignRepository.campaignFlow,
|
||||
alteration.alterations(characterId = argument.id),
|
||||
alteration.alterationsFlow(characterId = argument.id),
|
||||
transform = { sheet, campaign, alterations ->
|
||||
factory.convertToUio(
|
||||
sheet = sheet,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.pixelized.desktop.lwa.business
|
||||
|
||||
import com.pixelized.shared.lwa.usecase.CharacterSheetUseCase
|
||||
import org.junit.Test
|
||||
|
||||
class DamageBonusUseCaseTest {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.pixelized.desktop.lwa.business
|
||||
|
||||
import com.pixelized.shared.lwa.usecase.CharacterSheetUseCase
|
||||
import org.junit.Test
|
||||
|
||||
class SkillNormalizerUseCaseText {
|
||||
|
|
|
|||
|
|
@ -62,6 +62,26 @@ class ExpressionParserTest {
|
|||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun textUrlExpression() {
|
||||
val parser = ExpressionParser(
|
||||
diceParser = DiceParser(),
|
||||
wordParser = WordParser(),
|
||||
)
|
||||
parser.test(
|
||||
expression = "https://drive.google.com/uc?export=view&id=19ME-r7LiDQSrDCq8faVlTNQ7tfX8UUOO",
|
||||
expected = Expression.UrlExpression("https://drive.google.com/uc?export=view&id=19ME-r7LiDQSrDCq8faVlTNQ7tfX8UUOO"),
|
||||
)
|
||||
parser.test(
|
||||
expression = "www.google.fr",
|
||||
expected = Expression.UrlExpression("www.google.fr"),
|
||||
)
|
||||
parser.test(
|
||||
expression = "google.fr",
|
||||
expected = Expression.UrlExpression("google.fr"),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testFunctionExpression() {
|
||||
val parser = ExpressionParser(
|
||||
|
|
|
|||
|
|
@ -48,6 +48,26 @@ data class CharacterSheet(
|
|||
val roll: String,
|
||||
)
|
||||
|
||||
object CharacteristicId {
|
||||
const val PORTRAIT = "PORTRAIT"
|
||||
const val THUMBNAIL = "THUMBNAIL"
|
||||
const val LVL = "LEVEL"
|
||||
const val STR = "STR"
|
||||
const val DEX = "DEX"
|
||||
const val CON = "CON"
|
||||
const val HEI = "HEI"
|
||||
const val INT = "INT"
|
||||
const val POW = "POW"
|
||||
const val CHA = "CHA"
|
||||
const val MOV = "MOV"
|
||||
const val HP = "HP"
|
||||
const val PP = "PP"
|
||||
const val DMG = "DMG"
|
||||
const val ARMOR = "ARMOR"
|
||||
const val LB = "LEARNING"
|
||||
const val GHP = "HP_GROW"
|
||||
}
|
||||
|
||||
object CommonSkillId {
|
||||
const val COMBAT_ID = "COMBAT"
|
||||
const val DODGE_ID = "DODGE"
|
||||
|
|
@ -66,21 +86,4 @@ data class CharacterSheet(
|
|||
const val SLEIGHT_OF_HAND_ID = "SLEIGHT_OF_HAND"
|
||||
const val AID_ID = "AID"
|
||||
}
|
||||
|
||||
object CharacteristicId {
|
||||
const val STR = "STR"
|
||||
const val DEX = "DEX"
|
||||
const val CON = "CON"
|
||||
const val HEI = "HEI"
|
||||
const val INT = "INT"
|
||||
const val POW = "POW"
|
||||
const val CHA = "CHA"
|
||||
const val MOV = "MOV"
|
||||
const val HP = "HP"
|
||||
const val PP = "PP"
|
||||
const val DMG = "DMG"
|
||||
const val ARMOR = "ARMOR"
|
||||
const val LB = "LEARNING"
|
||||
const val GHP = "HP_GROW"
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue