Adventure Missions progress

- Viewing the adventure missions completed in a card is now possible.
This commit is contained in:
Nacho 2025-09-10 02:09:15 +02:00
parent cb9fe8e716
commit 7160eb792a
27 changed files with 528 additions and 46 deletions

View File

@ -15,7 +15,7 @@ android {
minSdk = 28 minSdk = 28
targetSdk = 35 targetSdk = 35
versionCode = 1 versionCode = 1
versionName = "Alpha 0.6" versionName = "Alpha 0.6.1"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
} }

View File

@ -31,7 +31,7 @@ interface AdventureDao {
a.finishesAdventure AS finishesAdventure, a.finishesAdventure AS finishesAdventure,
a.originalDuration AS originalTimeInMinutes a.originalDuration AS originalTimeInMinutes
FROM UserCharacter uc FROM UserCharacter uc
JOIN CharacterData c ON uc.charId = c.id JOIN CardCharacter c ON uc.charId = c.id
JOIN Sprite s ON s.id = c.spriteId JOIN Sprite s ON s.id = c.spriteId
JOIN Card d ON c.cardId = d.id JOIN Card d ON c.cardId = d.id
JOIN Adventure a ON uc.id = a.characterId JOIN Adventure a ON uc.id = a.characterId

View File

@ -0,0 +1,58 @@
package com.github.nacabaro.vbhelper.daos
import androidx.room.Dao
import androidx.room.Query
import com.github.nacabaro.vbhelper.dtos.CardDtos
@Dao
interface CardAdventureDao {
@Query("""
INSERT INTO
CardAdventure (cardId, characterId, steps, bossAp, bossHp, bossDp, bossBp)
SELECT
:cardId,
cc.id,
:steps,
:bossAp,
:bossHp,
:bossDp,
:bossBp
FROM
CardCharacter cc
WHERE
cc.charaIndex = :characterId AND
cc.cardId = :cardId
""")
suspend fun insertNewAdventure(
cardId: Long,
characterId: Int,
steps: Int,
bossAp: Int,
bossHp: Int,
bossDp: Int,
bossBp: Int?
)
@Query("""
SELECT
cc.nameSprite as characterName,
cc.nameWidth as characterNameWidth,
cc.nameHeight as characterNameHeight,
s.spriteIdle1 as characterIdleSprite,
s.width as characterIdleSpriteWidth,
s.height as characterIdleSpriteHeight,
ca.bossAp as characterAp,
ca.bossBp as characterBp,
ca.bossDp as characterDp,
ca.bossHp as characterHp,
ca.steps as steps
FROM CardCharacter cc
JOIN Sprite s ON cc.spriteId = s.id
JOIN CardAdventure ca ON cc.id = ca.characterId
WHERE
cc.cardId = :cardId
""")
suspend fun getAdventureForCard(
cardId: Long
): List<CardDtos.CardAdventureWithSprites>
}

View File

@ -21,7 +21,7 @@ interface CardDao {
""" """
SELECT ca.* SELECT ca.*
FROM Card ca FROM Card ca
JOIN CharacterData ch ON ca.id = ch.cardId JOIN CardCharacter ch ON ca.id = ch.cardId
JOIN UserCharacter uc ON ch.id = uc.charId JOIN UserCharacter uc ON ch.id = uc.charId
WHERE uc.id = :id WHERE uc.id = :id
""" """

View File

@ -0,0 +1,32 @@
package com.github.nacabaro.vbhelper.daos
import androidx.room.Dao
import androidx.room.Query
@Dao
interface CardFusionsDao {
@Query("""
INSERT INTO
CardFusions (
fromCharaId,
attribute1Fusion,
attribute2Fusion,
attribute3Fusion,
attribute4Fusion
)
SELECT
(SELECT id FROM CardCharacter WHERE cardId = :cardId AND charaIndex = :fromCharaId),
(SELECT id FROM CardCharacter WHERE cardId = :cardId AND charaIndex = :toCharaIdAttr1),
(SELECT id FROM CardCharacter WHERE cardId = :cardId AND charaIndex = :toCharaIdAttr2),
(SELECT id FROM CardCharacter WHERE cardId = :cardId AND charaIndex = :toCharaIdAttr3),
(SELECT id FROM CardCharacter WHERE cardId = :cardId AND charaIndex = :toCharaIdAttr4)
""")
suspend fun insertNewFusion(
cardId: Long,
fromCharaId: Int,
toCharaIdAttr1: Int,
toCharaIdAttr2: Int,
toCharaIdAttr3: Int,
toCharaIdAttr4: Int
)
}

View File

@ -13,5 +13,5 @@ interface CardProgressDao {
@Query( @Query(
"SELECT currentStage FROM CardProgress WHERE cardId = :cardId" "SELECT currentStage FROM CardProgress WHERE cardId = :cardId"
) )
fun getCardProgress(cardId: Int): Int fun getCardProgress(cardId: Long): Int
} }

View File

@ -3,17 +3,17 @@ package com.github.nacabaro.vbhelper.daos
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Insert import androidx.room.Insert
import androidx.room.Query import androidx.room.Query
import com.github.nacabaro.vbhelper.domain.card.CharacterData import com.github.nacabaro.vbhelper.domain.card.CardCharacter
import com.github.nacabaro.vbhelper.domain.characters.Sprite import com.github.nacabaro.vbhelper.domain.characters.Sprite
import com.github.nacabaro.vbhelper.dtos.CharacterDtos import com.github.nacabaro.vbhelper.dtos.CharacterDtos
@Dao @Dao
interface CharacterDao { interface CharacterDao {
@Insert @Insert
suspend fun insertCharacter(vararg characterData: CharacterData) suspend fun insertCharacter(vararg characterData: CardCharacter)
@Query("SELECT * FROM CharacterData WHERE charaIndex = :monIndex AND cardId = :dimId LIMIT 1") @Query("SELECT * FROM CardCharacter WHERE charaIndex = :monIndex AND cardId = :dimId LIMIT 1")
fun getCharacterByMonIndex(monIndex: Int, dimId: Long): CharacterData fun getCharacterByMonIndex(monIndex: Int, dimId: Long): CardCharacter
@Insert @Insert
suspend fun insertSprite(vararg sprite: Sprite) suspend fun insertSprite(vararg sprite: Sprite)
@ -25,7 +25,7 @@ interface CharacterDao {
c.charaIndex as charId, c.charaIndex as charId,
c.stage as stage, c.stage as stage,
c.attribute as attribute c.attribute as attribute
FROM CharacterData c FROM CardCharacter c
JOIN UserCharacter uc ON c.id = uc.charId JOIN UserCharacter uc ON c.id = uc.charId
JOIN Card d ON c.cardId = d.id JOIN Card d ON c.cardId = d.id
WHERE c.id = :charId WHERE c.id = :charId
@ -37,14 +37,14 @@ interface CharacterDao {
""" """
INSERT INTO PossibleTransformations (charaId, requiredVitals, requiredTrophies, requiredBattles, requiredWinRate, changeTimerHours, requiredAdventureLevelCompleted, toCharaId) INSERT INTO PossibleTransformations (charaId, requiredVitals, requiredTrophies, requiredBattles, requiredWinRate, changeTimerHours, requiredAdventureLevelCompleted, toCharaId)
SELECT SELECT
(SELECT id FROM CharacterData WHERE charaIndex = :fromChraraIndex AND cardId = :cardId), (SELECT id FROM CardCharacter WHERE charaIndex = :fromChraraIndex AND cardId = :cardId),
:requiredVitals, :requiredVitals,
:requiredTrophies, :requiredTrophies,
:requiredBattles, :requiredBattles,
:requiredWinRate, :requiredWinRate,
:changeTimerHours, :changeTimerHours,
:requiredAdventureLevelCompleted, :requiredAdventureLevelCompleted,
(SELECT id FROM CharacterData WHERE charaIndex = :toChraraIndex AND cardId = :cardId) (SELECT id FROM CardCharacter WHERE charaIndex = :toChraraIndex AND cardId = :cardId)
""" """
) )
suspend fun insertPossibleTransformation( suspend fun insertPossibleTransformation(
@ -76,7 +76,7 @@ interface CharacterDao {
pt.requiredAdventureLevelCompleted as requiredAdventureLevelCompleted pt.requiredAdventureLevelCompleted as requiredAdventureLevelCompleted
FROM FROM
PossibleTransformations pt PossibleTransformations pt
JOIN CharacterData c on pt.toCharaId = c.id JOIN CardCharacter c on pt.toCharaId = c.id
JOIN Sprite s ON s.id = c.spriteId JOIN Sprite s ON s.id = c.spriteId
LEFT JOIN Dex d ON d.id = pt.toCharaId LEFT JOIN Dex d ON d.id = pt.toCharaId
WHERE WHERE

View File

@ -11,7 +11,7 @@ interface DexDao {
""" """
INSERT OR IGNORE INTO Dex(id, discoveredOn) INSERT OR IGNORE INTO Dex(id, discoveredOn)
VALUES ( VALUES (
(SELECT id FROM CharacterData WHERE charaIndex = :charIndex AND cardId = :cardId), (SELECT id FROM CardCharacter WHERE charaIndex = :charIndex AND cardId = :cardId),
:discoveredOn :discoveredOn
) )
""" """
@ -34,7 +34,7 @@ interface DexDao {
c.baseAp as baseAp, c.baseAp as baseAp,
c.stage as stage, c.stage as stage,
c.attribute as attribute c.attribute as attribute
FROM CharacterData c FROM CardCharacter c
JOIN Sprite s ON c.spriteId = s.id JOIN Sprite s ON c.spriteId = s.id
LEFT JOIN dex d ON c.id = d.id LEFT JOIN dex d ON c.id = d.id
WHERE c.cardId = :cardId WHERE c.cardId = :cardId
@ -50,8 +50,8 @@ interface DexDao {
c.logo as cardLogo, c.logo as cardLogo,
c.logoWidth as logoWidth, c.logoWidth as logoWidth,
c.logoHeight as logoHeight, c.logoHeight as logoHeight,
(SELECT COUNT(*) FROM CharacterData cc WHERE cc.cardId = c.id) AS totalCharacters, (SELECT COUNT(*) FROM CardCharacter cc WHERE cc.cardId = c.id) AS totalCharacters,
(SELECT COUNT(*) FROM Dex d JOIN CharacterData cc ON d.id = cc.id WHERE cc.cardId = c.id AND d.discoveredOn IS NOT NULL) AS obtainedCharacters (SELECT COUNT(*) FROM Dex d JOIN CardCharacter cc ON d.id = cc.id WHERE cc.cardId = c.id AND d.discoveredOn IS NOT NULL) AS obtainedCharacters
FROM Card c FROM Card c
""" """
) )

View File

@ -5,7 +5,7 @@ import androidx.room.Insert
import androidx.room.OnConflictStrategy import androidx.room.OnConflictStrategy
import androidx.room.Query import androidx.room.Query
import androidx.room.Upsert import androidx.room.Upsert
import com.github.nacabaro.vbhelper.domain.card.CharacterData import com.github.nacabaro.vbhelper.domain.card.CardCharacter
import com.github.nacabaro.vbhelper.domain.device_data.UserCharacter import com.github.nacabaro.vbhelper.domain.device_data.UserCharacter
import com.github.nacabaro.vbhelper.domain.device_data.BECharacterData import com.github.nacabaro.vbhelper.domain.device_data.BECharacterData
import com.github.nacabaro.vbhelper.domain.device_data.SpecialMissions import com.github.nacabaro.vbhelper.domain.device_data.SpecialMissions
@ -47,7 +47,7 @@ interface UserCharacterDao {
c.charaIndex AS monIndex, c.charaIndex AS monIndex,
t.transformationDate AS transformationDate t.transformationDate AS transformationDate
FROM TransformationHistory t FROM TransformationHistory t
JOIN CharacterData c ON c.id = t.stageId JOIN CardCharacter c ON c.id = t.stageId
JOIN Sprite s ON s.id = c.spriteId JOIN Sprite s ON s.id = c.spriteId
WHERE monId = :monId WHERE monId = :monId
""" """
@ -70,7 +70,7 @@ interface UserCharacterDao {
d.isBEm as isBemCard, d.isBEm as isBemCard,
a.characterId = uc.id as isInAdventure a.characterId = uc.id as isInAdventure
FROM UserCharacter uc FROM UserCharacter uc
JOIN CharacterData c ON uc.charId = c.id JOIN CardCharacter c ON uc.charId = c.id
JOIN Card d ON d.id = c.cardId JOIN Card d ON d.id = c.cardId
JOIN Sprite s ON s.id = c.spriteId JOIN Sprite s ON s.id = c.spriteId
LEFT JOIN Adventure a ON a.characterId = uc.id LEFT JOIN Adventure a ON a.characterId = uc.id
@ -94,7 +94,7 @@ interface UserCharacterDao {
d.isBEm as isBemCard, d.isBEm as isBemCard,
a.characterId = uc.id as isInAdventure a.characterId = uc.id as isInAdventure
FROM UserCharacter uc FROM UserCharacter uc
JOIN CharacterData c ON uc.charId = c.id JOIN CardCharacter c ON uc.charId = c.id
JOIN Card d ON c.cardId = d.id JOIN Card d ON c.cardId = d.id
JOIN Sprite s ON s.id = c.spriteId JOIN Sprite s ON s.id = c.spriteId
LEFT JOIN Adventure a ON a.characterId = uc.id LEFT JOIN Adventure a ON a.characterId = uc.id
@ -131,7 +131,7 @@ interface UserCharacterDao {
d.isBEm as isBemCard, d.isBEm as isBemCard,
a.characterId as isInAdventure a.characterId as isInAdventure
FROM UserCharacter uc FROM UserCharacter uc
JOIN CharacterData c ON uc.charId = c.id JOIN CardCharacter c ON uc.charId = c.id
JOIN Card d ON c.cardId = d.id JOIN Card d ON c.cardId = d.id
JOIN Sprite s ON s.id = c.spriteId JOIN Sprite s ON s.id = c.spriteId
LEFT JOIN Adventure a ON a.characterId = uc.id LEFT JOIN Adventure a ON a.characterId = uc.id
@ -153,13 +153,13 @@ interface UserCharacterDao {
@Query( @Query(
""" """
SELECT c.* SELECT c.*
FROM CharacterData c FROM CardCharacter c
join UserCharacter uc on c.id = uc.charId join UserCharacter uc on c.id = uc.charId
where uc.id = :charId where uc.id = :charId
LIMIT 1 LIMIT 1
""" """
) )
suspend fun getCharacterInfo(charId: Long): CharacterData suspend fun getCharacterInfo(charId: Long): CardCharacter
@Query( @Query(
@ -167,7 +167,7 @@ interface UserCharacterDao {
INSERT INTO TransformationHistory(monId, stageId, transformationDate) INSERT INTO TransformationHistory(monId, stageId, transformationDate)
VALUES VALUES
(:monId, (:monId,
(SELECT id FROM CharacterData WHERE charaIndex = :stage AND cardId = :dimId), (SELECT id FROM CardCharacter WHERE charaIndex = :stage AND cardId = :dimId),
:transformationDate) :transformationDate)
""" """
) )
@ -195,7 +195,7 @@ interface UserCharacterDao {
d.isBEm as isBemCard, d.isBEm as isBemCard,
a.characterId = uc.id as isInAdventure a.characterId = uc.id as isInAdventure
FROM UserCharacter uc FROM UserCharacter uc
JOIN CharacterData c ON uc.charId = c.id JOIN CardCharacter c ON uc.charId = c.id
JOIN Card d ON d.id = c.cardId JOIN Card d ON d.id = c.cardId
JOIN Sprite s ON s.id = c.spriteId JOIN Sprite s ON s.id = c.spriteId
LEFT JOIN Adventure a ON a.characterId = uc.id LEFT JOIN Adventure a ON a.characterId = uc.id
@ -220,7 +220,7 @@ interface UserCharacterDao {
d.isBEm as isBemCard, d.isBEm as isBemCard,
a.characterId = uc.id as isInAdventure a.characterId = uc.id as isInAdventure
FROM UserCharacter uc FROM UserCharacter uc
JOIN CharacterData c ON uc.charId = c.id JOIN CardCharacter c ON uc.charId = c.id
JOIN Card d ON d.id = c.cardId JOIN Card d ON d.id = c.cardId
JOIN Sprite s ON s.id = c.spriteId JOIN Sprite s ON s.id = c.spriteId
LEFT JOIN Adventure a ON a.characterId = uc.id LEFT JOIN Adventure a ON a.characterId = uc.id

View File

@ -3,17 +3,21 @@ package com.github.nacabaro.vbhelper.database
import androidx.room.Database import androidx.room.Database
import androidx.room.RoomDatabase import androidx.room.RoomDatabase
import com.github.nacabaro.vbhelper.daos.AdventureDao import com.github.nacabaro.vbhelper.daos.AdventureDao
import com.github.nacabaro.vbhelper.daos.CardAdventureDao
import com.github.nacabaro.vbhelper.daos.CharacterDao import com.github.nacabaro.vbhelper.daos.CharacterDao
import com.github.nacabaro.vbhelper.daos.DexDao import com.github.nacabaro.vbhelper.daos.DexDao
import com.github.nacabaro.vbhelper.daos.CardDao import com.github.nacabaro.vbhelper.daos.CardDao
import com.github.nacabaro.vbhelper.daos.CardFusionsDao
import com.github.nacabaro.vbhelper.daos.CardProgressDao import com.github.nacabaro.vbhelper.daos.CardProgressDao
import com.github.nacabaro.vbhelper.daos.ItemDao import com.github.nacabaro.vbhelper.daos.ItemDao
import com.github.nacabaro.vbhelper.daos.SpecialMissionDao import com.github.nacabaro.vbhelper.daos.SpecialMissionDao
import com.github.nacabaro.vbhelper.daos.SpriteDao import com.github.nacabaro.vbhelper.daos.SpriteDao
import com.github.nacabaro.vbhelper.daos.UserCharacterDao import com.github.nacabaro.vbhelper.daos.UserCharacterDao
import com.github.nacabaro.vbhelper.domain.card.Background import com.github.nacabaro.vbhelper.domain.card.Background
import com.github.nacabaro.vbhelper.domain.card.CharacterData import com.github.nacabaro.vbhelper.domain.card.CardCharacter
import com.github.nacabaro.vbhelper.domain.card.Card import com.github.nacabaro.vbhelper.domain.card.Card
import com.github.nacabaro.vbhelper.domain.card.CardAdventure
import com.github.nacabaro.vbhelper.domain.card.CardFusions
import com.github.nacabaro.vbhelper.domain.card.CardProgress import com.github.nacabaro.vbhelper.domain.card.CardProgress
import com.github.nacabaro.vbhelper.domain.card.PossibleTransformations import com.github.nacabaro.vbhelper.domain.card.PossibleTransformations
import com.github.nacabaro.vbhelper.domain.characters.Sprite import com.github.nacabaro.vbhelper.domain.characters.Sprite
@ -32,7 +36,9 @@ import com.github.nacabaro.vbhelper.domain.items.Items
entities = [ entities = [
Card::class, Card::class,
CardProgress::class, CardProgress::class,
CharacterData::class, CardCharacter::class,
CardAdventure::class,
CardFusions::class,
Sprite::class, Sprite::class,
UserCharacter::class, UserCharacter::class,
BECharacterData::class, BECharacterData::class,
@ -57,4 +63,6 @@ abstract class AppDatabase : RoomDatabase() {
abstract fun adventureDao(): AdventureDao abstract fun adventureDao(): AdventureDao
abstract fun spriteDao(): SpriteDao abstract fun spriteDao(): SpriteDao
abstract fun specialMissionDao(): SpecialMissionDao abstract fun specialMissionDao(): SpecialMissionDao
abstract fun cardAdventureDao(): CardAdventureDao
abstract fun cardFusionsDao(): CardFusionsDao
} }

View File

@ -0,0 +1,32 @@
package com.github.nacabaro.vbhelper.domain.card
import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.PrimaryKey
@Entity(
foreignKeys = [
ForeignKey(
entity = CardCharacter::class,
parentColumns = ["id"],
childColumns = ["characterId"],
onDelete = ForeignKey.CASCADE
),
ForeignKey(
entity = Card::class,
parentColumns = ["id"],
childColumns = ["cardId"],
onDelete = ForeignKey.CASCADE
)
]
)
data class CardAdventure(
@PrimaryKey(autoGenerate = true) val id: Long = 0,
val cardId: Long,
val characterId: Long,
val steps: Int,
val bossHp: Int,
val bossAp: Int,
val bossDp: Int,
val bossBp: Int?
)

View File

@ -28,7 +28,7 @@ import com.github.nacabaro.vbhelper.domain.characters.Sprite
* and monIndex. * and monIndex.
* TODO: Customs will mean this should be unique per cardName and monIndex * TODO: Customs will mean this should be unique per cardName and monIndex
*/ */
data class CharacterData ( data class CardCharacter (
@PrimaryKey(autoGenerate = true) val id: Long = 0, @PrimaryKey(autoGenerate = true) val id: Long = 0,
val cardId: Long, val cardId: Long,
val spriteId: Long, val spriteId: Long,

View File

@ -0,0 +1,48 @@
package com.github.nacabaro.vbhelper.domain.card
import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.PrimaryKey
@Entity(
foreignKeys = [
ForeignKey(
entity = CardCharacter::class,
parentColumns = ["id"],
childColumns = ["fromCharaId"],
onDelete = ForeignKey.CASCADE
),
ForeignKey(
entity = CardCharacter::class,
parentColumns = ["id"],
childColumns = ["attribute1Fusion"],
onDelete = ForeignKey.CASCADE
),
ForeignKey(
entity = CardCharacter::class,
parentColumns = ["id"],
childColumns = ["attribute2Fusion"],
onDelete = ForeignKey.CASCADE
),
ForeignKey(
entity = CardCharacter::class,
parentColumns = ["id"],
childColumns = ["attribute3Fusion"],
onDelete = ForeignKey.CASCADE
),
ForeignKey(
entity = CardCharacter::class,
parentColumns = ["id"],
childColumns = ["attribute4Fusion"],
onDelete = ForeignKey.CASCADE
)
]
)
data class CardFusions(
@PrimaryKey(autoGenerate = true) val id: Long,
val fromCharaId: Long,
val attribute1Fusion: Long?,
val attribute2Fusion: Long?,
val attribute3Fusion: Long?,
val attribute4Fusion: Long?
)

View File

@ -7,13 +7,13 @@ import androidx.room.PrimaryKey
@Entity( @Entity(
foreignKeys = [ foreignKeys = [
ForeignKey( ForeignKey(
entity = CharacterData::class, entity = CardCharacter::class,
parentColumns = ["id"], parentColumns = ["id"],
childColumns = ["charaId"], childColumns = ["charaId"],
onDelete = ForeignKey.CASCADE onDelete = ForeignKey.CASCADE
), ),
ForeignKey( ForeignKey(
entity = CharacterData::class, entity = CardCharacter::class,
parentColumns = ["id"], parentColumns = ["id"],
childColumns = ["toCharaId"], childColumns = ["toCharaId"],
onDelete = ForeignKey.CASCADE onDelete = ForeignKey.CASCADE

View File

@ -3,12 +3,12 @@ package com.github.nacabaro.vbhelper.domain.characters
import androidx.room.Entity import androidx.room.Entity
import androidx.room.ForeignKey import androidx.room.ForeignKey
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
import com.github.nacabaro.vbhelper.domain.card.CharacterData import com.github.nacabaro.vbhelper.domain.card.CardCharacter
@Entity( @Entity(
foreignKeys = [ foreignKeys = [
ForeignKey( ForeignKey(
entity = CharacterData::class, entity = CardCharacter::class,
parentColumns = ["id"], parentColumns = ["id"],
childColumns = ["id"], childColumns = ["id"],
onDelete = ForeignKey.CASCADE onDelete = ForeignKey.CASCADE

View File

@ -3,7 +3,7 @@ package com.github.nacabaro.vbhelper.domain.device_data
import androidx.room.Entity import androidx.room.Entity
import androidx.room.ForeignKey import androidx.room.ForeignKey
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
import com.github.nacabaro.vbhelper.domain.card.CharacterData import com.github.nacabaro.vbhelper.domain.card.CardCharacter
@Entity( @Entity(
foreignKeys = [ foreignKeys = [
@ -14,7 +14,7 @@ import com.github.nacabaro.vbhelper.domain.card.CharacterData
onDelete = ForeignKey.CASCADE onDelete = ForeignKey.CASCADE
), ),
ForeignKey( ForeignKey(
entity = CharacterData::class, entity = CardCharacter::class,
parentColumns = ["id"], parentColumns = ["id"],
childColumns = ["stageId"], childColumns = ["stageId"],
onDelete = ForeignKey.CASCADE onDelete = ForeignKey.CASCADE

View File

@ -5,12 +5,12 @@ import androidx.room.ForeignKey
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
import com.github.cfogrady.vbnfc.data.NfcCharacter import com.github.cfogrady.vbnfc.data.NfcCharacter
import com.github.nacabaro.vbhelper.utils.DeviceType import com.github.nacabaro.vbhelper.utils.DeviceType
import com.github.nacabaro.vbhelper.domain.card.CharacterData import com.github.nacabaro.vbhelper.domain.card.CardCharacter
@Entity( @Entity(
foreignKeys = [ foreignKeys = [
ForeignKey( ForeignKey(
entity = CharacterData::class, entity = CardCharacter::class,
parentColumns = ["id"], parentColumns = ["id"],
childColumns = ["charId"], childColumns = ["charId"],
onDelete = ForeignKey.CASCADE onDelete = ForeignKey.CASCADE

View File

@ -10,4 +10,18 @@ object CardDtos {
val totalCharacters: Int, val totalCharacters: Int,
val obtainedCharacters: Int, val obtainedCharacters: Int,
) )
data class CardAdventureWithSprites (
val characterName: ByteArray,
val characterNameWidth: Int,
val characterNameHeight: Int,
val characterIdleSprite: ByteArray,
val characterIdleSpriteWidth: Int,
val characterIdleSpriteHeight: Int,
val characterAp: Int,
val characterBp: Int?,
val characterDp: Int,
val characterHp: Int,
val steps: Int,
)
} }

View File

@ -35,7 +35,7 @@ object CharacterDtos {
) )
data class CardCharacterInfo( data class CardCharacterInfo(
val cardId: Int, val cardId: Long,
val charId: Int, val charId: Int,
val stage: Int, val stage: Int,
val attribute: NfcCharacter.Attribute val attribute: NfcCharacter.Attribute

View File

@ -34,6 +34,7 @@ import com.github.nacabaro.vbhelper.screens.itemsScreen.ItemsScreenControllerImp
import com.github.nacabaro.vbhelper.screens.settingsScreen.SettingsScreenControllerImpl import com.github.nacabaro.vbhelper.screens.settingsScreen.SettingsScreenControllerImpl
import com.github.nacabaro.vbhelper.screens.adventureScreen.AdventureScreen import com.github.nacabaro.vbhelper.screens.adventureScreen.AdventureScreen
import com.github.nacabaro.vbhelper.screens.adventureScreen.AdventureScreenControllerImpl import com.github.nacabaro.vbhelper.screens.adventureScreen.AdventureScreenControllerImpl
import com.github.nacabaro.vbhelper.screens.cardScreen.CardAdventureScreen
import com.github.nacabaro.vbhelper.screens.cardScreen.CardScreenControllerImpl import com.github.nacabaro.vbhelper.screens.cardScreen.CardScreenControllerImpl
import com.github.nacabaro.vbhelper.screens.settingsScreen.CreditsScreen import com.github.nacabaro.vbhelper.screens.settingsScreen.CreditsScreen
import com.github.nacabaro.vbhelper.screens.spriteViewer.SpriteViewerControllerImpl import com.github.nacabaro.vbhelper.screens.spriteViewer.SpriteViewerControllerImpl
@ -145,7 +146,7 @@ fun AppNavigation(
if (cardId != null) { if (cardId != null) {
CardViewScreen( CardViewScreen(
navController = navController, navController = navController,
dimId = cardId.toLong() cardId = cardId.toLong()
) )
} }
} }
@ -177,6 +178,17 @@ fun AppNavigation(
navController = navController navController = navController
) )
} }
composable(NavigationItems.CardAdventure.route) {
val cardId = it.arguments?.getString("cardId")
if (cardId != null) {
CardAdventureScreen(
navController = navController,
cardId = cardId.toLong(),
cardScreenController = applicationNavigationHandlers
.cardScreenController
)
}
}
} }
} }
} }

View File

@ -11,6 +11,7 @@ sealed class NavigationItems (
object Battles : NavigationItems("Battle", R.drawable.baseline_swords_24, "Battle") object Battles : NavigationItems("Battle", R.drawable.baseline_swords_24, "Battle")
object Home : NavigationItems("Home", R.drawable.baseline_cottage_24, "Home") object Home : NavigationItems("Home", R.drawable.baseline_cottage_24, "Home")
object Dex : NavigationItems("Dex", R.drawable.baseline_menu_book_24, "Dex") object Dex : NavigationItems("Dex", R.drawable.baseline_menu_book_24, "Dex")
object CardAdventure : NavigationItems("CardAdventure/{cardId}", R.drawable.baseline_fort_24, "Card adventure")
object Storage : NavigationItems("Storage", R.drawable.baseline_catching_pokemon_24, "Storage") object Storage : NavigationItems("Storage", R.drawable.baseline_catching_pokemon_24, "Storage")
object Settings : NavigationItems("Settings", R.drawable.baseline_settings_24, "Settings") object Settings : NavigationItems("Settings", R.drawable.baseline_settings_24, "Settings")
object Viewer : NavigationItems("Viewer", R.drawable.baseline_image_24, "Viewer") object Viewer : NavigationItems("Viewer", R.drawable.baseline_image_24, "Viewer")

View File

@ -0,0 +1,122 @@
package com.github.nacabaro.vbhelper.screens.cardScreen
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.material3.Card
import androidx.compose.material3.CardColors
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.contentColorFor
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.FilterQuality
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import com.github.nacabaro.vbhelper.dtos.CardDtos
import com.github.nacabaro.vbhelper.utils.BitmapData
import com.github.nacabaro.vbhelper.utils.getImageBitmap
@Composable
fun CardAdventureEntry(
cardAdventureEntry: CardDtos.CardAdventureWithSprites,
obscure: Boolean
) {
val charaImageBitmapData = BitmapData(
bitmap = cardAdventureEntry.characterIdleSprite,
width = cardAdventureEntry.characterIdleSpriteWidth,
height = cardAdventureEntry.characterIdleSpriteHeight
).getImageBitmap(
context = LocalContext.current,
multiplier = 4,
obscure = obscure
)
val nameImageBitmapData = BitmapData(
bitmap = cardAdventureEntry.characterName,
width = cardAdventureEntry.characterNameWidth,
height = cardAdventureEntry.characterNameHeight
).getImageBitmap(
context = LocalContext.current,
multiplier = 3,
obscure = obscure
)
Card (
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
) {
Row (
modifier = Modifier
.padding(8.dp)
){
Card (
colors = CardColors(
containerColor = MaterialTheme.colorScheme.surfaceVariant,
contentColor = MaterialTheme.colorScheme.contentColorFor(
backgroundColor = MaterialTheme.colorScheme.surfaceVariant,
),
disabledContainerColor = MaterialTheme.colorScheme.surfaceVariant,
disabledContentColor = MaterialTheme.colorScheme.contentColorFor(
backgroundColor = MaterialTheme.colorScheme.surfaceVariant,
)
)
) {
Image(
bitmap = charaImageBitmapData.imageBitmap,
contentDescription = "Icon",
modifier = Modifier
.size(charaImageBitmapData.dpWidth)
.padding(8.dp),
colorFilter = when (obscure) {
true -> ColorFilter.tint(color = MaterialTheme.colorScheme.secondary)
false -> null
},
filterQuality = FilterQuality.None
)
}
Spacer(modifier = Modifier.padding(8.dp))
Column {
if (!obscure) {
Image(
bitmap = nameImageBitmapData.imageBitmap,
contentDescription = "Icon",
modifier = Modifier
.width(nameImageBitmapData.dpWidth)
.height(nameImageBitmapData.dpHeight),
filterQuality = FilterQuality.None
)
Spacer(modifier = Modifier.padding(4.dp))
Text(
text = "HP: ${cardAdventureEntry.characterHp}, DP: ${cardAdventureEntry.characterDp}, AP: ${cardAdventureEntry.characterAp}"
)
if (cardAdventureEntry.characterBp != null) {
Text(text = "BP: ${cardAdventureEntry.characterBp}")
}
Text(text = "Steps: ${cardAdventureEntry.steps}")
} else {
Text(text = "????????????????")
Text(
text = "HP: -, BP: -, AP: -"
)
if (cardAdventureEntry.characterBp != null) {
Text(text = "DP: -")
}
Text(text = "Steps: -")
}
}
}
}
}

View File

@ -0,0 +1,63 @@
package com.github.nacabaro.vbhelper.screens.cardScreen
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.navigation.NavController
import com.github.nacabaro.vbhelper.components.TopBanner
import com.github.nacabaro.vbhelper.dtos.CardDtos
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@Composable
fun CardAdventureScreen(
navController: NavController,
cardScreenController: CardScreenControllerImpl,
cardId: Long
) {
val cardAdventureMissions = remember { mutableStateOf(emptyList<CardDtos.CardAdventureWithSprites>()) }
var currentCardAdventure = remember { 0 }
LaunchedEffect(cardId) {
withContext(Dispatchers.IO) {
cardAdventureMissions.value =
cardScreenController
.getCardAdventureMissions(cardId)
currentCardAdventure =
cardScreenController
.getCardProgress(cardId)
}
}
Scaffold (
topBar = {
TopBanner(
text = "Adventure missions",
onBackClick = {
navController.popBackStack()
}
)
}
) { contentPadding ->
Column (
modifier = Modifier
.padding(top = contentPadding.calculateTopPadding())
.verticalScroll(state = rememberScrollState())
) {
cardAdventureMissions.value.mapIndexed { index, it ->
CardAdventureEntry(
cardAdventureEntry = it,
obscure = index > currentCardAdventure
)
}
}
}
}

View File

@ -1,6 +1,10 @@
package com.github.nacabaro.vbhelper.screens.cardScreen package com.github.nacabaro.vbhelper.screens.cardScreen
import com.github.nacabaro.vbhelper.dtos.CardDtos
interface CardScreenController { interface CardScreenController {
fun renameCard(cardId: Long, newName: String, onRenamed: (String) -> Unit) fun renameCard(cardId: Long, newName: String, onRenamed: (String) -> Unit)
fun deleteCard(cardId: Long, onDeleted: () -> Unit) fun deleteCard(cardId: Long, onDeleted: () -> Unit)
suspend fun getCardAdventureMissions(cardId: Long): List<CardDtos.CardAdventureWithSprites>
suspend fun getCardProgress(cardId: Long): Int
} }

View File

@ -3,6 +3,7 @@ package com.github.nacabaro.vbhelper.screens.cardScreen
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.github.nacabaro.vbhelper.di.VBHelper import com.github.nacabaro.vbhelper.di.VBHelper
import com.github.nacabaro.vbhelper.dtos.CardDtos
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class CardScreenControllerImpl( class CardScreenControllerImpl(
@ -11,7 +12,6 @@ class CardScreenControllerImpl(
private val application = componentActivity.applicationContext as VBHelper private val application = componentActivity.applicationContext as VBHelper
private val database = application.container.db private val database = application.container.db
override fun renameCard(cardId: Long, newName: String, onRenamed: (String) -> Unit) { override fun renameCard(cardId: Long, newName: String, onRenamed: (String) -> Unit) {
componentActivity.lifecycleScope.launch { componentActivity.lifecycleScope.launch {
database database
@ -31,4 +31,16 @@ class CardScreenControllerImpl(
onDeleted() onDeleted()
} }
} }
override suspend fun getCardAdventureMissions(cardId: Long): List<CardDtos.CardAdventureWithSprites> {
return database
.cardAdventureDao()
.getAdventureForCard(cardId)
}
override suspend fun getCardProgress(cardId: Long): Int {
return database
.cardProgressDao()
.getCardProgress(cardId)
}
} }

View File

@ -16,6 +16,7 @@ import com.github.nacabaro.vbhelper.components.CharacterEntry
import com.github.nacabaro.vbhelper.components.TopBanner import com.github.nacabaro.vbhelper.components.TopBanner
import com.github.nacabaro.vbhelper.di.VBHelper import com.github.nacabaro.vbhelper.di.VBHelper
import com.github.nacabaro.vbhelper.dtos.CharacterDtos import com.github.nacabaro.vbhelper.dtos.CharacterDtos
import com.github.nacabaro.vbhelper.navigation.NavigationItems
import com.github.nacabaro.vbhelper.screens.cardScreen.dialogs.DexCharaDetailsDialog import com.github.nacabaro.vbhelper.screens.cardScreen.dialogs.DexCharaDetailsDialog
import com.github.nacabaro.vbhelper.source.DexRepository import com.github.nacabaro.vbhelper.source.DexRepository
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -23,7 +24,7 @@ import kotlinx.coroutines.launch
@Composable @Composable
fun CardViewScreen( fun CardViewScreen(
navController: NavController, navController: NavController,
dimId: Long cardId: Long
) { ) {
val coroutineScope = rememberCoroutineScope() val coroutineScope = rememberCoroutineScope()
val application = LocalContext.current.applicationContext as VBHelper val application = LocalContext.current.applicationContext as VBHelper
@ -36,10 +37,10 @@ fun CardViewScreen(
LaunchedEffect(dexRepository) { LaunchedEffect(dexRepository) {
coroutineScope.launch { coroutineScope.launch {
val newCharacterList = dexRepository.getCharactersByCardId(dimId) val newCharacterList = dexRepository.getCharactersByCardId(cardId)
characterList.value = newCharacterList characterList.value = newCharacterList
val newCardPossibleTransformations = dexRepository.getCardPossibleTransformations(dimId) val newCardPossibleTransformations = dexRepository.getCardPossibleTransformations(cardId)
cardPossibleTransformations.value = newCardPossibleTransformations cardPossibleTransformations.value = newCardPossibleTransformations
} }
} }
@ -50,6 +51,17 @@ fun CardViewScreen(
text = "Discovered characters", text = "Discovered characters",
onBackClick = { onBackClick = {
navController.popBackStack() navController.popBackStack()
},
onAdventureClick = {
navController
.navigate(route = NavigationItems
.CardAdventure
.route
.replace(
"{cardId}",
cardId.toString()
)
)
} }
) )
} }

View File

@ -18,7 +18,7 @@ import com.github.nacabaro.vbhelper.di.VBHelper
import com.github.nacabaro.vbhelper.domain.characters.Sprite import com.github.nacabaro.vbhelper.domain.characters.Sprite
import com.github.nacabaro.vbhelper.domain.card.Card import com.github.nacabaro.vbhelper.domain.card.Card
import com.github.nacabaro.vbhelper.domain.card.CardProgress import com.github.nacabaro.vbhelper.domain.card.CardProgress
import com.github.nacabaro.vbhelper.domain.card.CharacterData import com.github.nacabaro.vbhelper.domain.card.CardCharacter
import com.github.nacabaro.vbhelper.source.ApkSecretsImporter import com.github.nacabaro.vbhelper.source.ApkSecretsImporter
import com.github.nacabaro.vbhelper.source.SecretsImporter import com.github.nacabaro.vbhelper.source.SecretsImporter
import com.github.nacabaro.vbhelper.source.SecretsRepository import com.github.nacabaro.vbhelper.source.SecretsRepository
@ -192,7 +192,7 @@ class SettingsScreenControllerImpl(
false -> 10 false -> 10
} }
val domainCharacters = mutableListOf<CharacterData>() val domainCharacters = mutableListOf<CardCharacter>()
val characters = card val characters = card
.characterStats .characterStats
@ -242,7 +242,7 @@ class SettingsScreenControllerImpl(
domainCharacters.add( domainCharacters.add(
CharacterData( CardCharacter(
cardId = cardId, cardId = cardId,
spriteId = spriteId, spriteId = spriteId,
charaIndex = index, charaIndex = index,
@ -273,6 +273,66 @@ class SettingsScreenControllerImpl(
.insertCharacter(*domainCharacters.toTypedArray()) .insertCharacter(*domainCharacters.toTypedArray())
} }
private suspend fun importAdventureMissions(
cardId: Long,
card: com.github.cfogrady.vb.dim.card.Card<*, *, *, *, *, *>
) {
Log.d("importAdventureMissions", "Importing adventure missions")
if (card is BemCard) {
card.adventureLevels.levels.forEach {
database
.cardAdventureDao()
.insertNewAdventure(
cardId = cardId,
characterId = it.bossCharacterIndex,
steps = it.steps,
bossAp = it.bossAp,
bossHp = it.bossHp,
bossDp = it.bossDp,
bossBp = it.bossBp
)
}
} else if (card is DimCard) {
card.adventureLevels.levels.map {
database
.cardAdventureDao()
.insertNewAdventure(
cardId = cardId,
characterId = it.bossCharacterIndex,
steps = it.steps,
bossAp = it.bossAp,
bossHp = it.bossHp,
bossDp = it.bossDp,
bossBp = null
)
}
}
}
private suspend fun importCardFusions(
cardId: Long,
card: com.github.cfogrady.vb.dim.card.Card<*, *, *, *, *, *>
) {
Log.d("importCardFusions", "Importing card fusions")
if (card is DimCard) {
card
.attributeFusions
.entries
.forEach {
database
.cardFusionsDao()
.insertNewFusion(
cardId = cardId,
fromCharaId = it.characterIndex,
toCharaIdAttr1 = it.attribute1Fusion,
toCharaIdAttr2 = it.attribute2Fusion,
toCharaIdAttr3 = it.attribute3Fusion,
toCharaIdAttr4 = it.attribute4Fusion
)
}
}
}
private fun updateCardProgress( private fun updateCardProgress(
cardId: Long, cardId: Long,
) { ) {
@ -315,6 +375,10 @@ class SettingsScreenControllerImpl(
importCharacterData(cardId, card) importCharacterData(cardId, card)
importEvoData(cardId, card) importEvoData(cardId, card)
importAdventureMissions(cardId, card)
importCardFusions(cardId, card)
} }
inputStream?.close() inputStream?.close()