~cytrogen/vbhelper

d847f600f138c62d7c29e1c5957f47cec99f610b — Nacho 8 months ago f7a4039
Quite a few things
- Renamed a few objects to avoid legality issues
- Added a few accompanying tables to support the VB/VH
  - While we speak about tables, added an auxiliary table to track card adventure progress
- Extracted NFC character generation and extraction to different classes, should result in a cleaner ScanScreenController
18 files changed, 214 insertions(+), 125 deletions(-)

R app/src/main/java/com/github/nacabaro/vbhelper/daos/{DiMDao => CardDao}.kt
R app/src/main/java/com/github/nacabaro/vbhelper/daos/{DiMProgressDao => CardProgressDao}.kt
M app/src/main/java/com/github/nacabaro/vbhelper/daos/CharacterDao.kt
M app/src/main/java/com/github/nacabaro/vbhelper/database/AppDatabase.kt
R app/src/main/java/com/github/nacabaro/vbhelper/domain/{characters => card}/Card.kt
R app/src/main/java/com/github/nacabaro/vbhelper/domain/{DimProgress => card/CardProgress}.kt
M app/src/main/java/com/github/nacabaro/vbhelper/domain/characters/Character.kt
M app/src/main/java/com/github/nacabaro/vbhelper/domain/device_data/VitalsHistory.kt
M app/src/main/java/com/github/nacabaro/vbhelper/dtos/CharacterDtos.kt
M app/src/main/java/com/github/nacabaro/vbhelper/screens/DexScreen.kt
M app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/ScanScreen.kt
M app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/ScanScreenController.kt
M app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/ScanScreenControllerImpl.kt
M app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/converters/FromNfcConverter.kt
M app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/converters/ToNfcConverter.kt
M app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/SettingsScreenControllerImpl.kt
M app/src/main/java/com/github/nacabaro/vbhelper/source/DexRepository.kt
M app/src/main/java/com/github/nacabaro/vbhelper/source/StorageRepository.kt
R app/src/main/java/com/github/nacabaro/vbhelper/daos/DiMDao.kt => app/src/main/java/com/github/nacabaro/vbhelper/daos/CardDao.kt +2 -18
@@ 4,29 4,13 @@ import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.github.nacabaro.vbhelper.domain.characters.Card
import com.github.nacabaro.vbhelper.domain.card.Card

@Dao
interface DiMDao {
interface CardDao {
    @Insert(onConflict = OnConflictStrategy.IGNORE)
    suspend fun insertNewDim(card: Card): Long

    @Query("SELECT * FROM Card WHERE cardId = :id")
    fun getDimById(id: Int): Card?

    @Query(
        """
        UPDATE Card
        SET currentStage = :currentStage
        WHERE cardId = :id
    """
    )
    fun updateCurrentStage(id: Int, currentStage: Int)

    @Query("""
        SELECT currentStage 
        FROM Card
        WHERE cardId = :id
    """)
    fun getCurrentStage(id: Int): Int
}
\ No newline at end of file

R app/src/main/java/com/github/nacabaro/vbhelper/daos/DiMProgressDao.kt => app/src/main/java/com/github/nacabaro/vbhelper/daos/CardProgressDao.kt +9 -3
@@ 1,11 1,17 @@
package com.github.nacabaro.vbhelper.daos

import androidx.room.Dao
import androidx.room.Query
import androidx.room.Upsert
import com.github.nacabaro.vbhelper.domain.DimProgress
import com.github.nacabaro.vbhelper.domain.card.CardProgress

@Dao
interface DiMProgressDao {
interface CardProgressDao {
    @Upsert
    suspend fun updateDimProgress(vararg dimProgress: DimProgress)
    fun updateDimProgress(vararg cardProgresses: CardProgress)

    @Query(
        "SELECT currentStage FROM CardProgress WHERE cardId = :cardId"
    )
    fun getCardProgress(cardId: Int): Int
}
\ No newline at end of file

M app/src/main/java/com/github/nacabaro/vbhelper/daos/CharacterDao.kt => app/src/main/java/com/github/nacabaro/vbhelper/daos/CharacterDao.kt +7 -8
@@ 18,21 18,20 @@ interface CharacterDao {
    @Insert
    suspend fun insertSprite(vararg sprite: Sprite)

    @Query("SELECT * FROM Sprite")
    suspend fun getAllSprites(): List<Sprite>

    @Query(
        """
        SELECT 
            d.cardId as cardId,
            c.monIndex as charId
            c.monIndex as charId,
            c.stage as stage,
            c.attribute as attribute
        FROM Character c
        JOIN UserCharacter uc ON c.id = uc.charId
        JOIN Card d ON c.dimId = d.id
        WHERE uc.id = :charId
    """
    )
    suspend fun getCharacterInfo(charId: Long): CharacterDtos.DiMInfo
    suspend fun getCharacterInfo(charId: Long): CharacterDtos.CardCharacterInfo

    @Query("""
        INSERT INTO TransformationHistory(monId, stageId, transformationDate)


@@ 44,12 43,12 @@ interface CharacterDao {
    fun insertTransformation(monId: Long, stage: Int, dimId: Long, transformationDate: Long)

    @Query("""
        INSERT INTO VitalsHistory(characterId, date, vitalPoints)
        INSERT INTO VitalsHistory(charId, date, vitalPoints)
        VALUES 
            (:characterId, 
            (:charId, 
            (:date),
            :vitalPoints)
    """)
    fun insertVitals(characterId: Long, date: Long, vitalPoints: Int)
    fun insertVitals(charId: Long, date: Long, vitalPoints: Int)

}
\ No newline at end of file

M app/src/main/java/com/github/nacabaro/vbhelper/database/AppDatabase.kt => app/src/main/java/com/github/nacabaro/vbhelper/database/AppDatabase.kt +9 -3
@@ 5,12 5,14 @@ import androidx.room.RoomDatabase
import com.github.nacabaro.vbhelper.daos.AdventureDao
import com.github.nacabaro.vbhelper.daos.CharacterDao
import com.github.nacabaro.vbhelper.daos.DexDao
import com.github.nacabaro.vbhelper.daos.DiMDao
import com.github.nacabaro.vbhelper.daos.CardDao
import com.github.nacabaro.vbhelper.daos.CardProgressDao
import com.github.nacabaro.vbhelper.daos.ItemDao
import com.github.nacabaro.vbhelper.daos.SpriteDao
import com.github.nacabaro.vbhelper.daos.UserCharacterDao
import com.github.nacabaro.vbhelper.domain.characters.Character
import com.github.nacabaro.vbhelper.domain.characters.Card
import com.github.nacabaro.vbhelper.domain.card.Card
import com.github.nacabaro.vbhelper.domain.card.CardProgress
import com.github.nacabaro.vbhelper.domain.characters.Sprite
import com.github.nacabaro.vbhelper.domain.characters.Adventure
import com.github.nacabaro.vbhelper.domain.characters.Dex


@@ 19,12 21,14 @@ import com.github.nacabaro.vbhelper.domain.device_data.SpecialMissions
import com.github.nacabaro.vbhelper.domain.device_data.TransformationHistory
import com.github.nacabaro.vbhelper.domain.device_data.UserCharacter
import com.github.nacabaro.vbhelper.domain.device_data.VBCharacterData
import com.github.nacabaro.vbhelper.domain.device_data.VitalsHistory
import com.github.nacabaro.vbhelper.domain.items.Items

@Database(
    version = 1,
    entities = [
        Card::class,
        CardProgress::class,
        Character::class,
        Sprite::class,
        UserCharacter::class,


@@ 32,13 36,15 @@ import com.github.nacabaro.vbhelper.domain.items.Items
        VBCharacterData::class,
        SpecialMissions::class,
        TransformationHistory::class,
        VitalsHistory::class,
        Dex::class,
        Items::class,
        Adventure::class
    ]
)
abstract class AppDatabase : RoomDatabase() {
    abstract fun dimDao(): DiMDao
    abstract fun cardDao(): CardDao
    abstract fun cardProgressDao(): CardProgressDao
    abstract fun characterDao(): CharacterDao
    abstract fun userCharacterDao(): UserCharacterDao
    abstract fun dexDao(): DexDao

R app/src/main/java/com/github/nacabaro/vbhelper/domain/characters/Card.kt => app/src/main/java/com/github/nacabaro/vbhelper/domain/card/Card.kt +1 -2
@@ 1,4 1,4 @@
package com.github.nacabaro.vbhelper.domain.characters
package com.github.nacabaro.vbhelper.domain.card

import androidx.room.Entity
import androidx.room.PrimaryKey


@@ 13,6 13,5 @@ data class Card(
    val logoHeight: Int,
    val name: String,
    val stageCount: Int,
    val currentStage: Int,
    val isBEm: Boolean
)

R app/src/main/java/com/github/nacabaro/vbhelper/domain/DimProgress.kt => app/src/main/java/com/github/nacabaro/vbhelper/domain/card/CardProgress.kt +4 -12
@@ 1,29 1,21 @@
package com.github.nacabaro.vbhelper.domain
package com.github.nacabaro.vbhelper.domain.card

import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.PrimaryKey
import com.github.nacabaro.vbhelper.domain.characters.Card

@Entity(
    foreignKeys = [
        ForeignKey(
            entity = User::class,
            parentColumns = ["id"],
            childColumns = ["userId"],
            onDelete = ForeignKey.CASCADE
        ),
        ForeignKey(
            entity = Card::class,
            parentColumns = ["id"],
            childColumns = ["dimId"],
            childColumns = ["cardId"],
            onDelete = ForeignKey.CASCADE
        )
    ]
)
data class DimProgress(
    @PrimaryKey val dimId: Int,
    @PrimaryKey val userId: Int,
data class CardProgress(
    @PrimaryKey val cardId: Int,
    val currentStage: Int,
    val unlocked: Boolean
)

M app/src/main/java/com/github/nacabaro/vbhelper/domain/characters/Character.kt => app/src/main/java/com/github/nacabaro/vbhelper/domain/characters/Character.kt +2 -1
@@ 4,6 4,7 @@ import androidx.room.Entity
import androidx.room.PrimaryKey
import androidx.room.ForeignKey
import com.github.cfogrady.vbnfc.data.NfcCharacter
import com.github.nacabaro.vbhelper.domain.card.Card

@Entity(
    foreignKeys = [


@@ 23,7 24,7 @@ import com.github.cfogrady.vbnfc.data.NfcCharacter
)

/*
 * Character represents a character on a DIM card. There should only be one of these per dimId
 * Character represents a character on a card. There should only be one of these per dimId
 * and monIndex.
 * TODO: Customs will mean this should be unique per cardName and monIndex
 */

M app/src/main/java/com/github/nacabaro/vbhelper/domain/device_data/VitalsHistory.kt => app/src/main/java/com/github/nacabaro/vbhelper/domain/device_data/VitalsHistory.kt +3 -3
@@ 8,15 8,15 @@ import androidx.room.PrimaryKey
    foreignKeys = [
        ForeignKey(
            entity = UserCharacter::class,
            parentColumns = ["characterId"],
            childColumns = ["id"],
            parentColumns = ["id"],
            childColumns = ["charId"],
            onDelete = ForeignKey.CASCADE
        )
    ]
)
data class VitalsHistory (
    @PrimaryKey(autoGenerate = true) val id: Long = 0,
    val characterId: Long,
    val charId: Long,
    val date: Long,
    val vitalPoints: Int
)
\ No newline at end of file

M app/src/main/java/com/github/nacabaro/vbhelper/dtos/CharacterDtos.kt => app/src/main/java/com/github/nacabaro/vbhelper/dtos/CharacterDtos.kt +4 -4
@@ 11,7 11,6 @@ object CharacterDtos {
        var stage: Int,
        var attribute: NfcCharacter.Attribute,
        var ageInDays: Int,
        var nextAdventureMissionStage: Int, // next adventure mission stage on the character's dim
        var mood: Int,
        var vitalPoints: Int,
        var transformationCountdown: Int,


@@ 35,9 34,11 @@ object CharacterDtos {
        val isInAdventure: Boolean
    )

    data class DiMInfo(
    data class CardCharacterInfo(
        val cardId: Int,
        val charId: Int
        val charId: Int,
        val stage: Int,
        val attribute: NfcCharacter.Attribute
    )

    data class TransformationHistory(


@@ 63,7 64,6 @@ object CharacterDtos {
        var stage: Int,
        var attribute: NfcCharacter.Attribute,
        var ageInDays: Int,
        var nextAdventureMissionStage: Int, // next adventure mission stage on the character's dim
        var mood: Int,
        var vitalPoints: Int,
        var transformationCountdown: Int,

M app/src/main/java/com/github/nacabaro/vbhelper/screens/DexScreen.kt => app/src/main/java/com/github/nacabaro/vbhelper/screens/DexScreen.kt +0 -1
@@ 18,7 18,6 @@ import com.github.nacabaro.vbhelper.utils.BitmapData
import com.github.nacabaro.vbhelper.components.DexDiMEntry
import com.github.nacabaro.vbhelper.components.TopBanner
import com.github.nacabaro.vbhelper.di.VBHelper
import com.github.nacabaro.vbhelper.domain.characters.Card
import com.github.nacabaro.vbhelper.dtos.CardDtos
import com.github.nacabaro.vbhelper.navigation.NavigationItems
import com.github.nacabaro.vbhelper.source.DexRepository

M app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/ScanScreen.kt => app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/ScanScreen.kt +1 -0
@@ 283,6 283,7 @@ fun ScanScreenPreview() {
            override fun onClickCheckCard(secrets: Secrets, nfcCharacter: NfcCharacter, onComplete: () -> Unit) {}
            override fun onClickWrite(secrets: Secrets, nfcCharacter: NfcCharacter, onComplete: () -> Unit) {}
            override fun cancelRead() {}
            override fun characterFromNfc(nfcCharacter: NfcCharacter): String { return "" }
            override suspend fun characterToNfc(characterId: Long): NfcCharacter? { return null }
        },
        characterId = null

M app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/ScanScreenController.kt => app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/ScanScreenController.kt +1 -0
@@ 16,5 16,6 @@ interface ScanScreenController {
    fun registerActivityLifecycleListener(key: String, activityLifecycleListener: ActivityLifecycleListener)
    fun unregisterActivityLifecycleListener(key: String)

    fun characterFromNfc(nfcCharacter: NfcCharacter): String
    suspend fun characterToNfc(characterId: Long): NfcCharacter?
}
\ No newline at end of file

M app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/ScanScreenControllerImpl.kt => app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/ScanScreenControllerImpl.kt +22 -9
@@ 11,22 11,17 @@ import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.lifecycle.lifecycleScope
import com.github.cfogrady.vbnfc.TagCommunicator
import com.github.cfogrady.vbnfc.be.BENfcCharacter
import com.github.cfogrady.vbnfc.data.NfcCharacter
import com.github.cfogrady.vbnfc.vb.VBNfcCharacter
import com.github.nacabaro.vbhelper.ActivityLifecycleListener
import com.github.nacabaro.vbhelper.di.VBHelper
import com.github.nacabaro.vbhelper.domain.device_data.BECharacterData
import com.github.nacabaro.vbhelper.domain.device_data.UserCharacter
import com.github.nacabaro.vbhelper.screens.scanScreen.converters.FromNfcConverter
import com.github.nacabaro.vbhelper.screens.scanScreen.converters.ToNfcConverter
import com.github.nacabaro.vbhelper.source.getCryptographicTransformerMap
import com.github.nacabaro.vbhelper.source.isMissingSecrets
import com.github.nacabaro.vbhelper.source.proto.Secrets
import com.github.nacabaro.vbhelper.utils.DeviceType
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import java.util.GregorianCalendar

class ScanScreenControllerImpl(
    override val secretsFlow: Flow<Secrets>,


@@ 49,7 44,7 @@ class ScanScreenControllerImpl(
    override fun onClickRead(secrets: Secrets, onComplete: ()->Unit) {
        handleTag(secrets) { tagCommunicator ->
            val character = tagCommunicator.receiveCharacter()
            val resultMessage = addCharacterScannedIntoDatabase(character)
            val resultMessage = characterFromNfc(character)
            onComplete.invoke()
            resultMessage
        }


@@ 151,6 146,11 @@ class ScanScreenControllerImpl(
        componentActivity.startActivity(Intent(Settings.ACTION_WIRELESS_SETTINGS))
    }

    /*
    // Todo: Move all of this to a separate class
    // Todo: Test the new mess
    // Todo: Remove this

    private fun addCharacterScannedIntoDatabase(nfcCharacter: NfcCharacter): String {
        val application = componentActivity.applicationContext as VBHelper
        val storageRepository = application.container.db


@@ 168,7 168,6 @@ class ScanScreenControllerImpl(
        val characterData = UserCharacter(
            charId = cardCharData.id,
            ageInDays = nfcCharacter.ageInDays.toInt(),
            nextAdventureMissionStage = nfcCharacter.nextAdventureMissionStage.toInt(),
            mood = nfcCharacter.mood.toInt(),
            vitalPoints = nfcCharacter.vitalPoints.toInt(),
            transformationCountdown = nfcCharacter.transformationCountdownInMinutes.toInt(),


@@ 247,5 246,19 @@ class ScanScreenControllerImpl(
        }

        return "Done reading character!"
    }*/

    override fun characterFromNfc(nfcCharacter: NfcCharacter): String {
        val nfcConverter = FromNfcConverter(
            componentActivity = componentActivity
        )
        return nfcConverter.addCharacter(nfcCharacter)
    }

    override suspend fun characterToNfc(characterId: Long): NfcCharacter {
        val nfcGenerator = ToNfcConverter(
            componentActivity = componentActivity
        )
        return nfcGenerator.characterToNfc(characterId)
    }
}
\ No newline at end of file

M app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/converters/FromNfcConverter.kt => app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/converters/FromNfcConverter.kt +84 -26
@@ 5,12 5,12 @@ import com.github.cfogrady.vbnfc.be.BENfcCharacter
import com.github.cfogrady.vbnfc.data.NfcCharacter
import com.github.cfogrady.vbnfc.vb.VBNfcCharacter
import com.github.nacabaro.vbhelper.di.VBHelper
import com.github.nacabaro.vbhelper.domain.characters.Card
import com.github.nacabaro.vbhelper.domain.card.Card
import com.github.nacabaro.vbhelper.domain.card.CardProgress
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.UserCharacter
import com.github.nacabaro.vbhelper.domain.device_data.VBCharacterData
import com.github.nacabaro.vbhelper.domain.device_data.VitalsHistory
import com.github.nacabaro.vbhelper.utils.DeviceType
import java.util.GregorianCalendar



@@ 20,29 20,24 @@ class FromNfcConverter (
    private val application = componentActivity.applicationContext as VBHelper
    private val database = application.container.db



    fun addCharacter(nfcCharacter: NfcCharacter): String {
        val dimData = database
            .dimDao()
        val cardData = database
            .cardDao()
            .getDimById(nfcCharacter.dimId.toInt())

        if (dimData == null)
        if (cardData == null)
            return "Card not found"

        val cardCharData = database
            .characterDao()
            .getCharacterByMonIndex(nfcCharacter.charIndex.toInt(), dimData.id)
            .getCharacterByMonIndex(nfcCharacter.charIndex.toInt(), cardData.id)

        database
            .dimDao()
            .updateCurrentStage(
                id = nfcCharacter.dimId.toInt(),
                currentStage = nfcCharacter.nextAdventureMissionStage.toInt()
            )
        updateCardProgress(nfcCharacter, cardData)

        val characterData = UserCharacter(
            charId = cardCharData.id,
            stage = nfcCharacter.stage.toInt(),
            attribute = nfcCharacter.attribute,
            ageInDays = nfcCharacter.ageInDays.toInt(),
            mood = nfcCharacter.mood.toInt(),
            vitalPoints = nfcCharacter.vitalPoints.toInt(),


@@ 62,6 57,8 @@ class FromNfcConverter (
            isActive = true
        )

        updateCardProgress(cardData, nfcCharacter)

        database
            .userCharacterDao()
            .clearActiveCharacter()


@@ 85,20 82,73 @@ class FromNfcConverter (
        addTransformationHistoryToDatabase(
            characterId = characterId,
            nfcCharacter = nfcCharacter,
            dimData = dimData
            dimData = cardData
        )

        return "Done reading character!"
    }



    private fun updateCardProgress(
        nfcCharacter: NfcCharacter,
        cardData: Card
    ) {
        val currentCardProgress = CardProgress(
            cardId = cardData.cardId,
            currentStage = nfcCharacter.nextAdventureMissionStage.toInt(),
            unlocked = nfcCharacter.nextAdventureMissionStage.toInt() > cardData.stageCount
        )

        database
            .cardProgressDao()
            .updateDimProgress(currentCardProgress)
    }



    private fun updateCardProgress(
        cardData: Card,
        nfcCharacter: NfcCharacter,
    ) {
        val cardProgress = CardProgress(
            cardId = cardData.cardId,
            currentStage = nfcCharacter.nextAdventureMissionStage.toInt(),
            unlocked = nfcCharacter.nextAdventureMissionStage.toInt() > cardData.stageCount
        )

        database
            .cardProgressDao()
            .updateDimProgress(cardProgress)
    }

    private fun addVbCharacterToDatabase(characterId: Long, nfcCharacter: VBNfcCharacter) {


    private fun addVbCharacterToDatabase(
        characterId: Long,
        nfcCharacter: VBNfcCharacter
    ) {
        val extraCharacterData = VBCharacterData(
            id = characterId,
            generation = nfcCharacter.generation.toInt(),
            totalTrophies = nfcCharacter.totalTrophies.toInt()
        )

        database
            .userCharacterDao()
            .insertVBCharacterData(extraCharacterData)

        addSpecialMissionsToDatabase(nfcCharacter, characterId)

        addVitalsHistoryToDatabase(characterId, nfcCharacter)
    }



    private fun addSpecialMissionsToDatabase(
        nfcCharacter: VBNfcCharacter,
        characterId: Long
    ) {
        val specialMissionsWatch = nfcCharacter.specialMissions
        val specialMissionsDb = specialMissionsWatch.map { item ->
            SpecialMissions(


@@ 113,19 163,17 @@ class FromNfcConverter (
            )
        }

        val vitalsHistory = nfcCharacter.vitalHistory


        database
            .userCharacterDao()
            .insertVBCharacterData(extraCharacterData)

        database
            .userCharacterDao()
            .insertSpecialMissions(*specialMissionsDb.toTypedArray())
    }

    private fun addBeCharacterToDatabase(characterId: Long, nfcCharacter: BENfcCharacter) {


    private fun addBeCharacterToDatabase(
        characterId: Long,
        nfcCharacter: BENfcCharacter
    ) {
        val extraCharacterData = BECharacterData(
            id = characterId,
            trainingHp = nfcCharacter.trainingHp.toInt(),


@@ 157,7 205,12 @@ class FromNfcConverter (
            .insertBECharacterData(extraCharacterData)
    }

    private fun addVitalsHistoryToDatabase(characterId: Long, nfcCharacter: NfcCharacter) {


    private fun addVitalsHistoryToDatabase(
        characterId: Long,
        nfcCharacter: NfcCharacter
    ) {
        val vitalsHistoryWatch = nfcCharacter.vitalHistory
        vitalsHistoryWatch.map { item ->
            val date = GregorianCalendar(


@@ 178,7 231,12 @@ class FromNfcConverter (
        }
    }

    private fun addTransformationHistoryToDatabase(characterId: Long, nfcCharacter: NfcCharacter, dimData: Card) {

    private fun addTransformationHistoryToDatabase(
        characterId: Long,
        nfcCharacter: NfcCharacter,
        dimData: Card
    ) {
        val transformationHistoryWatch = nfcCharacter.transformationHistory
        transformationHistoryWatch.map { item ->
            if (item.toCharIndex.toInt() != 255) {

M app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/converters/ToNfcConverter.kt => app/src/main/java/com/github/nacabaro/vbhelper/screens/scanScreen/converters/ToNfcConverter.kt +47 -24
@@ 20,7 20,11 @@ class ToNfcConverter(
    private val application: VBHelper = componentActivity.applicationContext as VBHelper
    private val database: AppDatabase = application.container.db

    suspend fun characterToNfc(characterId: Long): NfcCharacter {


    suspend fun characterToNfc(
        characterId: Long
    ): NfcCharacter {
        val app = componentActivity.applicationContext as VBHelper
        val database = app.container.db



@@ 32,7 36,9 @@ class ToNfcConverter(
            .characterDao()
            .getCharacterInfo(userCharacter.charId)

        val currentCardStage = database.dimDao().getCurrentStage(characterInfo.cardId)
        val currentCardStage = database
            .cardProgressDao()
            .getCardProgress(characterInfo.cardId)

        return if (userCharacter.characterType == DeviceType.BEDevice)
            nfcToBENfc(characterId, characterInfo, currentCardStage, userCharacter)


@@ 40,9 46,11 @@ class ToNfcConverter(
            nfcToVBNfc(characterId, characterInfo, currentCardStage, userCharacter)
    }



    private suspend fun nfcToVBNfc(
        characterId: Long,
        characterInfo: CharacterDtos.DiMInfo,
        characterInfo: CharacterDtos.CardCharacterInfo,
        currentCardStage: Int,
        userCharacter: UserCharacter
    ): VBNfcCharacter {


@@ 50,29 58,15 @@ class ToNfcConverter(
            .userCharacterDao()
            .getVbData(characterId)

        val specialMissions = database
            .userCharacterDao()
            .getSpecialMissions(characterId)

        val paddedTransformationArray = generateTransformationHistory(characterId)

        val watchSpecialMissions = specialMissions.map {
            SpecialMission(
                goal = it.goal.toUShort(),
                id = it.watchId.toUShort(),
                progress = it.progress.toUShort(),
                status = it.status,
                timeElapsedInMinutes = it.timeElapsedInMinutes.toUShort(),
                timeLimitInMinutes = it.timeLimitInMinutes.toUShort(),
                type = it.missionType
            )
        }
        val watchSpecialMissions = generateSpecialMissionsArray(characterId)

        val nfcData = VBNfcCharacter(
            dimId = characterInfo.cardId.toUShort(),
            charIndex = characterInfo.charId.toUShort(),
            stage = userCharacter.stage.toByte(),
            attribute = userCharacter.attribute,
            stage = characterInfo.stage.toByte(),
            attribute = characterInfo.attribute,
            ageInDays = userCharacter.ageInDays.toByte(),
            nextAdventureMissionStage = currentCardStage.toByte(),
            mood = userCharacter.mood.toByte(),


@@ 100,9 94,35 @@ class ToNfcConverter(
        return nfcData
    }



    private suspend fun generateSpecialMissionsArray(
        characterId: Long
    ): List<SpecialMission> {
        val specialMissions = database
            .userCharacterDao()
            .getSpecialMissions(characterId)

        val watchSpecialMissions = specialMissions.map {
            SpecialMission(
                goal = it.goal.toUShort(),
                id = it.watchId.toUShort(),
                progress = it.progress.toUShort(),
                status = it.status,
                timeElapsedInMinutes = it.timeElapsedInMinutes.toUShort(),
                timeLimitInMinutes = it.timeLimitInMinutes.toUShort(),
                type = it.missionType
            )
        }

        return watchSpecialMissions
    }



    private suspend fun nfcToBENfc(
        characterId: Long,
        characterInfo: CharacterDtos.DiMInfo,
        characterInfo: CharacterDtos.CardCharacterInfo,
        currentCardStage: Int,
        userCharacter: UserCharacter
    ): BENfcCharacter {


@@ 115,8 135,8 @@ class ToNfcConverter(
        val nfcData = BENfcCharacter(
            dimId = characterInfo.cardId.toUShort(),
            charIndex = characterInfo.charId.toUShort(),
            stage = userCharacter.stage.toByte(),
            attribute = userCharacter.attribute,
            stage = characterInfo.stage.toByte(),
            attribute = characterInfo.attribute,
            ageInDays = userCharacter.ageInDays.toByte(),
            nextAdventureMissionStage = currentCardStage.toByte(),
            mood = userCharacter.mood.toByte(),


@@ 163,9 183,10 @@ class ToNfcConverter(
        )

        return nfcData

    }



    private suspend fun generateTransformationHistory(
        characterId: Long
    ): Array<NfcCharacter.Transformation> {


@@ 196,6 217,8 @@ class ToNfcConverter(
        return paddedTransformationArray
    }



    private fun padTransformationArray(
        transformationArray: Array<NfcCharacter.Transformation>
    ): Array<NfcCharacter.Transformation> {

M app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/SettingsScreenControllerImpl.kt => app/src/main/java/com/github/nacabaro/vbhelper/screens/settingsScreen/SettingsScreenControllerImpl.kt +17 -5
@@ 16,7 16,8 @@ import com.github.cfogrady.vbnfc.data.NfcCharacter
import com.github.nacabaro.vbhelper.database.AppDatabase
import com.github.nacabaro.vbhelper.di.VBHelper
import com.github.nacabaro.vbhelper.domain.characters.Sprite
import com.github.nacabaro.vbhelper.domain.characters.Card
import com.github.nacabaro.vbhelper.domain.card.Card
import com.github.nacabaro.vbhelper.domain.card.CardProgress
import com.github.nacabaro.vbhelper.domain.characters.Character
import com.github.nacabaro.vbhelper.source.ApkSecretsImporter
import com.github.nacabaro.vbhelper.source.SecretsImporter


@@ 121,17 122,28 @@ class SettingsScreenControllerImpl(
                    logo = card.spriteData.sprites[0].pixelData,
                    name = card.spriteData.text, // TODO Make user write card name
                    stageCount = card.adventureLevels.levels.size,
                    currentStage = 0,
                    logoHeight = card.spriteData.sprites[0].height,
                    logoWidth = card.spriteData.sprites[0].width,
                    isBEm = card is BemCard
                )

                val dimId = database
                    .dimDao()
                    .cardDao()
                    .insertNewDim(cardModel)

                val characters = card.characterStats.characterEntries
                val cardProgress = CardProgress(
                    cardId = cardModel.cardId,
                    currentStage = 0,
                    unlocked = false
                )

                database
                    .cardProgressDao()
                    .updateDimProgress(cardProgress)

                val characters = card
                    .characterStats
                    .characterEntries

                var spriteCounter = when (card is BemCard) {
                    true -> 54


@@ 141,7 153,7 @@ class SettingsScreenControllerImpl(
                val domainCharacters = mutableListOf<Character>()

                for (index in 0 until characters.size) {
                    var domainSprite: Sprite? = null;
                    var domainSprite: Sprite?

                    if (index < 2 && card is DimCard) {
                        domainSprite = Sprite(

M app/src/main/java/com/github/nacabaro/vbhelper/source/DexRepository.kt => app/src/main/java/com/github/nacabaro/vbhelper/source/DexRepository.kt +0 -1
@@ 1,7 1,6 @@
package com.github.nacabaro.vbhelper.source

import com.github.nacabaro.vbhelper.database.AppDatabase
import com.github.nacabaro.vbhelper.domain.characters.Card
import com.github.nacabaro.vbhelper.dtos.CardDtos
import com.github.nacabaro.vbhelper.dtos.CharacterDtos


M app/src/main/java/com/github/nacabaro/vbhelper/source/StorageRepository.kt => app/src/main/java/com/github/nacabaro/vbhelper/source/StorageRepository.kt +1 -5
@@ 19,14 19,10 @@ class StorageRepository (
        return db.userCharacterDao().getBeData(id)
    }

    fun getTransformationHistory(characterId: Long): List<CharacterDtos.TransformationHistory>? {
    suspend fun getTransformationHistory(characterId: Long): List<CharacterDtos.TransformationHistory>? {
        return db.userCharacterDao().getTransformationHistory(characterId)
    }

    suspend fun getCharacterData(id: Long): CharacterDtos.DiMInfo {
        return db.characterDao().getCharacterInfo(id)
    }

    suspend fun getActiveCharacter(): CharacterDtos.CharacterWithSprites? {
        return db.userCharacterDao().getActiveCharacter()
    }