diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 9c3bdf7..814ed65 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -46,6 +46,7 @@ dependencies { ksp(libs.androidx.room.compiler) annotationProcessor(libs.androidx.room.compiler) implementation(libs.androidx.core.ktx) + implementation("androidx.room:room-ktx:2.6.1") implementation(libs.androidx.lifecycle.runtime.ktx) implementation(libs.androidx.activity.compose) implementation(platform(libs.androidx.compose.bom)) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2492ae6..d3a5163 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -6,6 +6,7 @@ { return mapOf( Pair(DeviceType.VitalBraceletBEDeviceType, - CryptographicTransformer(readableHmacKey1 = resources.getString(com.github.cfogrady.vbnfc.R.string.password1), - readableHmacKey2 = resources.getString(com.github.cfogrady.vbnfc.R.string.password2), - aesKey = resources.getString(com.github.cfogrady.vbnfc.R.string.decryptionKey), - substitutionCipher = resources.getIntArray(com.github.cfogrady.vbnfc.R.array.substitutionArray))), + CryptographicTransformer(readableHmacKey1 = resources.getString(R.string.password1), + readableHmacKey2 = resources.getString(R.string.password2), + aesKey = resources.getString(R.string.decryptionKey), + substitutionCipher = resources.getIntArray(R.array.substitutionArray))), // Pair(DeviceType.VitalSeriesDeviceType, // CryptographicTransformer(hmacKey1 = resources.getString(R.string.password1), // hmacKey2 = resources.getString(R.string.password2), @@ -138,4 +147,88 @@ class MainActivity : ComponentActivity() { nfcAdapter.disableReaderMode(this) } } + + // + /* + TODO: + - Make it able to detect the different model of watches + - Support for regular VB + + The good news is that the theory behind inserting to the database should be working + now, it's a matter of implementing the functionality to parse dim/bem cards and use my + domain model. + */ + private fun addCharacterScannedIntoDatabase() { + val beCharacter = nfcCharacter as MutableStateFlow + val temporaryCharacterData = TemporaryCharacterData( + dimId = nfcCharacter.value!!.dimId.toInt(), + charIndex = nfcCharacter.value!!.charIndex.toInt(), + stage = nfcCharacter.value!!.stage.toInt(), + attribute = nfcCharacter.value!!.attribute, + ageInDays = nfcCharacter.value!!.ageInDays.toInt(), + nextAdventureMissionStage = nfcCharacter.value!!.nextAdventureMissionStage.toInt(), + mood = nfcCharacter.value!!.mood.toInt(), + vitalPoints = nfcCharacter.value!!.vitalPoints.toInt(), + transformationCountdown = nfcCharacter.value!!.transformationCountdown.toInt(), + injuryStatus = nfcCharacter.value!!.injuryStatus, + trophies = nfcCharacter.value!!.trophies.toInt(), + currentPhaseBattlesWon = nfcCharacter.value!!.currentPhaseBattlesWon.toInt(), + currentPhaseBattlesLost = nfcCharacter.value!!.currentPhaseBattlesLost.toInt(), + totalBattlesWon = nfcCharacter.value!!.totalBattlesWon.toInt(), + totalBattlesLost = nfcCharacter.value!!.totalBattlesLost.toInt(), + activityLevel = nfcCharacter.value!!.activityLevel.toInt(), + heartRateCurrent = nfcCharacter.value!!.heartRateCurrent.toInt() + ) + + val application = applicationContext as VBHelper + val storageRepository = application.container.db + val characterId = storageRepository + .temporaryMonsterDao() + .insertCharacterData(temporaryCharacterData) + + val temporaryBECharacterData = TemporaryBECharacterData( + id = characterId, + trainingHp = beCharacter.value!!.trainingHp.toInt(), + trainingAp = beCharacter.value!!.trainingAp.toInt(), + trainingBp = beCharacter.value!!.trainingBp.toInt(), + remainingTrainingTimeInMinutes = beCharacter.value!!.remainingTrainingTimeInMinutes.toInt(), + itemEffectActivityLevelValue = beCharacter.value!!.itemEffectActivityLevelValue.toInt(), + itemEffectMentalStateValue = beCharacter.value!!.itemEffectMentalStateValue.toInt(), + itemEffectMentalStateMinutesRemaining = beCharacter.value!!.itemEffectMentalStateMinutesRemaining.toInt(), + itemEffectActivityLevelMinutesRemaining = beCharacter.value!!.itemEffectActivityLevelMinutesRemaining.toInt(), + itemEffectVitalPointsChangeValue = beCharacter.value!!.itemEffectVitalPointsChangeValue.toInt(), + itemEffectVitalPointsChangeMinutesRemaining = beCharacter.value!!.itemEffectVitalPointsChangeMinutesRemaining.toInt(), + abilityRarity = beCharacter.value!!.abilityRarity, + abilityType = beCharacter.value!!.abilityType.toInt(), + abilityBranch = beCharacter.value!!.abilityBranch.toInt(), + abilityReset = beCharacter.value!!.abilityReset.toInt(), + rank = beCharacter.value!!.abilityReset.toInt(), + itemType = beCharacter.value!!.itemType.toInt(), + itemMultiplier = beCharacter.value!!.itemMultiplier.toInt(), + itemRemainingTime = beCharacter.value!!.itemRemainingTime.toInt(), + otp0 = "", //beCharacter.value!!.otp0.toString(), + otp1 = "", //beCharacter.value!!.otp1.toString(), + minorVersion = beCharacter.value!!.characterCreationFirmwareVersion.minorVersion.toInt(), + majorVersion = beCharacter.value!!.characterCreationFirmwareVersion.majorVersion.toInt(), + ) + + storageRepository + .temporaryMonsterDao() + .insertBECharacterData(temporaryBECharacterData) + + val transformationHistoryWatch = beCharacter.value!!.transformationHistory + val domainTransformationHistory = transformationHistoryWatch.map { item -> + TemporaryTransformationHistory( + monId = characterId, + toCharIndex = item.toCharIndex.toInt(), + yearsSince1988 = item.yearsSince1988.toInt(), + month = item.month.toInt(), + day = item.day.toInt() + ) + } + + storageRepository + .temporaryMonsterDao() + .insertTransformationHistory(*domainTransformationHistory.toTypedArray()) + } } diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/database/AppDatabase.kt b/app/src/main/java/com/github/nacabaro/vbhelper/database/AppDatabase.kt index 5dc00c9..c143009 100644 --- a/app/src/main/java/com/github/nacabaro/vbhelper/database/AppDatabase.kt +++ b/app/src/main/java/com/github/nacabaro/vbhelper/database/AppDatabase.kt @@ -2,15 +2,7 @@ package com.github.nacabaro.vbhelper.database import androidx.room.Database import androidx.room.RoomDatabase -import com.github.nacabaro.vbhelper.domain.Dim -import com.github.nacabaro.vbhelper.domain.DimProgress -import com.github.nacabaro.vbhelper.domain.Evolutions -import com.github.nacabaro.vbhelper.domain.Mon -import com.github.nacabaro.vbhelper.domain.User -import com.github.nacabaro.vbhelper.domain.UserHealthData -import com.github.nacabaro.vbhelper.domain.UserMonsters -import com.github.nacabaro.vbhelper.domain.UserMonstersSpecialMissions -import com.github.nacabaro.vbhelper.domain.UserStepsData +import com.github.nacabaro.vbhelper.temporary_daos.TemporaryMonsterDao import com.github.nacabaro.vbhelper.temporary_domain.TemporaryBECharacterData import com.github.nacabaro.vbhelper.temporary_domain.TemporaryCharacterData import com.github.nacabaro.vbhelper.temporary_domain.TemporaryTransformationHistory @@ -24,5 +16,6 @@ import com.github.nacabaro.vbhelper.temporary_domain.TemporaryTransformationHist ] ) abstract class AppDatabase : RoomDatabase() { + abstract fun temporaryMonsterDao(): TemporaryMonsterDao } \ No newline at end of file diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/di/VBHelper.kt b/app/src/main/java/com/github/nacabaro/vbhelper/di/VBHelper.kt new file mode 100644 index 0000000..0c66c99 --- /dev/null +++ b/app/src/main/java/com/github/nacabaro/vbhelper/di/VBHelper.kt @@ -0,0 +1,13 @@ +package com.github.nacabaro.vbhelper.di + +import DefaultAppContainer +import android.app.Application + +class VBHelper : Application() { + lateinit var container: DefaultAppContainer + + override fun onCreate() { + super.onCreate() + container = DefaultAppContainer(applicationContext) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/screens/StorageScreen.kt b/app/src/main/java/com/github/nacabaro/vbhelper/screens/StorageScreen.kt index d0bc9b2..30e100b 100644 --- a/app/src/main/java/com/github/nacabaro/vbhelper/screens/StorageScreen.kt +++ b/app/src/main/java/com/github/nacabaro/vbhelper/screens/StorageScreen.kt @@ -1,5 +1,6 @@ package com.github.nacabaro.vbhelper.screens +import android.util.Log import androidx.compose.foundation.Image import androidx.compose.foundation.gestures.Orientation import androidx.compose.foundation.gestures.scrollable @@ -9,35 +10,75 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.LazyVerticalGrid +import androidx.compose.foundation.lazy.grid.items import androidx.compose.foundation.rememberScrollState import androidx.compose.material3.Card import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateListOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import com.github.nacabaro.vbhelper.R import com.github.nacabaro.vbhelper.components.TopBanner +import com.github.nacabaro.vbhelper.di.VBHelper +import com.github.nacabaro.vbhelper.source.StorageRepository +import com.github.nacabaro.vbhelper.temporary_domain.TemporaryCharacterData +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.launch + @Composable fun StorageScreen() { + val coroutineScope = rememberCoroutineScope() + val application = LocalContext.current.applicationContext as VBHelper + val storageRepository = StorageRepository(application.container.db) + val monList = remember { mutableStateListOf() } + + + LaunchedEffect(storageRepository) { + coroutineScope.launch { + monList.clear() + monList.addAll(storageRepository.getAllCharacters()) + Log.d("StorageScreen", "Updated data: $monList") + } + } + + Log.d("StorageScreen", "monList: $monList") + Scaffold ( topBar = { TopBanner(text = "My Digimon") } ) { contentPadding -> + if (monList.isEmpty()) { + Text( + text = "Nothing to see here", + modifier = Modifier + .padding(8.dp) + ) + } + LazyVerticalGrid( columns = GridCells.Fixed(3), modifier = Modifier .scrollable(state = rememberScrollState(), orientation = Orientation.Vertical) .padding(top = contentPadding.calculateTopPadding()) ) { - items(100) { i -> + items(monList) { index -> StorageEntry( - name = "Digimon $i", - icon = R.drawable.baseline_question_mark_24 + name = index.dimId.toString() + " - " + index.charIndex.toString(), + icon = R.drawable.ic_launcher_foreground, + modifier = Modifier + .padding(8.dp) ) } } diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/source/StorageRepository.kt b/app/src/main/java/com/github/nacabaro/vbhelper/source/StorageRepository.kt new file mode 100644 index 0000000..bf3e035 --- /dev/null +++ b/app/src/main/java/com/github/nacabaro/vbhelper/source/StorageRepository.kt @@ -0,0 +1,12 @@ +package com.github.nacabaro.vbhelper.source + +import com.github.nacabaro.vbhelper.database.AppDatabase +import com.github.nacabaro.vbhelper.temporary_domain.TemporaryCharacterData + +class StorageRepository ( + private val db: AppDatabase +) { + suspend fun getAllCharacters(): List { + return db.temporaryMonsterDao().getAllCharacters() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/temporary_daos/TemporaryMonsterDao.kt b/app/src/main/java/com/github/nacabaro/vbhelper/temporary_daos/TemporaryMonsterDao.kt new file mode 100644 index 0000000..33283ab --- /dev/null +++ b/app/src/main/java/com/github/nacabaro/vbhelper/temporary_daos/TemporaryMonsterDao.kt @@ -0,0 +1,27 @@ +package com.github.nacabaro.vbhelper.temporary_daos + +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import com.github.nacabaro.vbhelper.temporary_domain.TemporaryBECharacterData +import com.github.nacabaro.vbhelper.temporary_domain.TemporaryCharacterData +import com.github.nacabaro.vbhelper.temporary_domain.TemporaryTransformationHistory + +@Dao +interface TemporaryMonsterDao { + @Insert + fun insertCharacterData(temporaryCharacterData: TemporaryCharacterData): Int + + @Insert + fun insertBECharacterData(temporaryBECharacterData: TemporaryBECharacterData) + + @Insert(onConflict = OnConflictStrategy.REPLACE) + fun insertTransformationHistory(vararg transformationHistory: TemporaryTransformationHistory) + + @Query("SELECT * FROM TemporaryTransformationHistory WHERE monId = :monId") + fun getTransformationHistory(monId: Int): List + + @Query("SELECT * FROM TemporaryCharacterData") + suspend fun getAllCharacters(): List +} \ No newline at end of file diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/temporary_domain/TemporaryBECharacterData.kt b/app/src/main/java/com/github/nacabaro/vbhelper/temporary_domain/TemporaryBECharacterData.kt index cff7c7e..f7e2674 100644 --- a/app/src/main/java/com/github/nacabaro/vbhelper/temporary_domain/TemporaryBECharacterData.kt +++ b/app/src/main/java/com/github/nacabaro/vbhelper/temporary_domain/TemporaryBECharacterData.kt @@ -3,6 +3,7 @@ package com.github.nacabaro.vbhelper.temporary_domain import androidx.room.Entity import androidx.room.ForeignKey import androidx.room.PrimaryKey +import com.github.cfogrady.vbnfc.be.BENfcCharacter import com.github.cfogrady.vbnfc.be.FirmwareVersion import com.github.cfogrady.vbnfc.data.NfcCharacter @@ -11,32 +12,33 @@ import com.github.cfogrady.vbnfc.data.NfcCharacter ForeignKey( entity = TemporaryCharacterData::class, parentColumns = ["id"], - childColumns = ["userId"], + childColumns = ["id"], onDelete = ForeignKey.CASCADE ) ] ) data class TemporaryBECharacterData ( @PrimaryKey(autoGenerate = true) val id: Int, - val trainingHp: UShort, - val trainingAp: UShort, - val trainingBp: UShort, - val remainingTrainingTimeInMinutes: UShort, - val itemEffectMentalStateValue: Byte, - val itemEffectMentalStateMinutesRemaining: Byte, - val itemEffectActivityLevelValue: Byte, - val itemEffectActivityLevelMinutesRemaining: Byte, - val itemEffectVitalPointsChangeValue: Byte, - val itemEffectVitalPointsChangeMinutesRemaining: Byte, + val trainingHp: Int, + val trainingAp: Int, + val trainingBp: Int, + val remainingTrainingTimeInMinutes: Int, + val itemEffectMentalStateValue: Int, + val itemEffectMentalStateMinutesRemaining: Int, + val itemEffectActivityLevelValue: Int, + val itemEffectActivityLevelMinutesRemaining: Int, + val itemEffectVitalPointsChangeValue: Int, + val itemEffectVitalPointsChangeMinutesRemaining: Int, val abilityRarity: NfcCharacter.AbilityRarity, - val abilityType: UShort, - val abilityBranch: UShort, - val abilityReset: Byte, - val rank: Byte, - val itemType: Byte, - val itemMultiplier: Byte, - val itemRemainingTime: Byte, + val abilityType: Int, + val abilityBranch: Int, + val abilityReset: Int, + val rank: Int, + val itemType: Int, + val itemMultiplier: Int, + val itemRemainingTime: Int, val otp0: String, val otp1: String, - var characterCreationFirmwareVersion: FirmwareVersion, + val minorVersion: Int, + val majorVersion: Int, ) \ No newline at end of file diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/temporary_domain/TemporaryCharacterData.kt b/app/src/main/java/com/github/nacabaro/vbhelper/temporary_domain/TemporaryCharacterData.kt index 640328d..e3cc6b6 100644 --- a/app/src/main/java/com/github/nacabaro/vbhelper/temporary_domain/TemporaryCharacterData.kt +++ b/app/src/main/java/com/github/nacabaro/vbhelper/temporary_domain/TemporaryCharacterData.kt @@ -4,46 +4,24 @@ import androidx.room.Entity import androidx.room.PrimaryKey import com.github.cfogrady.vbnfc.data.NfcCharacter -/* -dimId=16, -charIndex=8, -stage=4, -attribute=Free, -ageInDays=0, -nextAdventureMissionStage=9, -mood=99, -vitalPoints=9999, -transformationCountdown=1101, -injuryStatus=None, -trophies=0, -currentPhaseBattlesWon=19, -currentPhaseBattlesLost=4, -totalBattlesWon=36, -totalBattlesLost=10, -activityLevel=0, -heartRateCurrent=71, -*/ - - @Entity data class TemporaryCharacterData ( - @PrimaryKey(autoGenerate = true) val id: Int, - val dimId: UShort, - var charIndex: UShort, - var stage: Byte, + @PrimaryKey(autoGenerate = true) val id: Int = 0, + val dimId: Int, + var charIndex: Int, + var stage: Int, var attribute: NfcCharacter.Attribute, - var ageInDays: Byte, - var nextAdventureMissionStage: Byte, // next adventure mission stage on the character's dim - var mood: Byte, - var vitalPoints: UShort, - var transformationCountdown: UShort, + var ageInDays: Int, + var nextAdventureMissionStage: Int, // next adventure mission stage on the character's dim + var mood: Int, + var vitalPoints: Int, + var transformationCountdown: Int, var injuryStatus: NfcCharacter.InjuryStatus, - var trophies: UShort, - var currentPhaseBattlesWon: UShort, - var currentPhaseBattlesLost: UShort, - var totalBattlesWon: UShort, - var totalBattlesLost: UShort, - var activityLevel: Byte, - var heartRateCurrent: UByte, - var transformationHistory: Int + var trophies: Int, + var currentPhaseBattlesWon: Int, + var currentPhaseBattlesLost: Int, + var totalBattlesWon: Int, + var totalBattlesLost: Int, + var activityLevel: Int, + var heartRateCurrent: Int, ) \ No newline at end of file diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/temporary_domain/TemporaryTransformationHistory.kt b/app/src/main/java/com/github/nacabaro/vbhelper/temporary_domain/TemporaryTransformationHistory.kt index 4b23364..75ed5ca 100644 --- a/app/src/main/java/com/github/nacabaro/vbhelper/temporary_domain/TemporaryTransformationHistory.kt +++ b/app/src/main/java/com/github/nacabaro/vbhelper/temporary_domain/TemporaryTransformationHistory.kt @@ -1,13 +1,25 @@ package com.github.nacabaro.vbhelper.temporary_domain import androidx.room.Entity +import androidx.room.ForeignKey +import androidx.room.PrimaryKey -@Entity +@Entity( + foreignKeys = [ + ForeignKey( + entity = TemporaryCharacterData::class, + parentColumns = ["id"], + childColumns = ["monId"], + onDelete = ForeignKey.CASCADE + ) + ] +) // Bit lazy, will correct later... data class TemporaryTransformationHistory ( + @PrimaryKey(autoGenerate = true) val id: Int = 0, val monId: Int, - val toCharIndex: Byte, - val yearsSince1988: Byte, - val month: Byte, - val day: Byte + val toCharIndex: Int, + val yearsSince1988: Int, + val month: Int, + val day: Int ) diff --git a/app/src/main/java/com/github/nacabaro/vbhelper/vm/StorageViewModel.kt b/app/src/main/java/com/github/nacabaro/vbhelper/vm/StorageViewModel.kt new file mode 100644 index 0000000..9b01721 --- /dev/null +++ b/app/src/main/java/com/github/nacabaro/vbhelper/vm/StorageViewModel.kt @@ -0,0 +1,2 @@ +package com.github.nacabaro.vbhelper.vm +