diff --git a/app/src/main/res/layout/activity_detail.xml b/app/src/main/res/layout/activity_detail.xml index 67a7c37e5..bdb6bafac 100644 --- a/app/src/main/res/layout/activity_detail.xml +++ b/app/src/main/res/layout/activity_detail.xml @@ -16,6 +16,7 @@ --> @@ -190,173 +191,26 @@ app:layout_constraintStart_toEndOf="@id/weight" app:layout_constraintTop_toBottomOf="@id/height" /> - - - - - - - - - - - - - - - - - - - - - + app:barrierDirection="bottom" + app:constraint_referenced_ids="weight_title,height_title" /> + + + + - \ No newline at end of file diff --git a/app/src/main/res/layout/stats_layout.xml b/app/src/main/res/layout/stats_layout.xml new file mode 100644 index 000000000..b0683dc34 --- /dev/null +++ b/app/src/main/res/layout/stats_layout.xml @@ -0,0 +1,195 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/core-database/schemas/com.skydoves.pokedex.core.database.PokedexDatabase/3.json b/core-database/schemas/com.skydoves.pokedex.core.database.PokedexDatabase/3.json new file mode 100644 index 000000000..bbfe17f2d --- /dev/null +++ b/core-database/schemas/com.skydoves.pokedex.core.database.PokedexDatabase/3.json @@ -0,0 +1,132 @@ +{ + "formatVersion": 1, + "database": { + "version": 3, + "identityHash": "cc488f72b5ee2f40a7376fb08cb8c85d", + "entities": [ + { + "tableName": "PokemonEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`page` INTEGER NOT NULL, `name` TEXT NOT NULL, `url` TEXT NOT NULL, PRIMARY KEY(`name`))", + "fields": [ + { + "fieldPath": "page", + "columnName": "page", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "url", + "columnName": "url", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "name" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "PokemonInfoEntity", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `name` TEXT NOT NULL, `height` INTEGER NOT NULL, `weight` INTEGER NOT NULL, `experience` INTEGER NOT NULL, `types` TEXT NOT NULL, `hp` INTEGER NOT NULL, `attack` INTEGER NOT NULL, `defense` INTEGER NOT NULL, `speed` INTEGER NOT NULL, `exp` INTEGER NOT NULL, `stats` TEXT NOT NULL, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "height", + "columnName": "height", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "weight", + "columnName": "weight", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "experience", + "columnName": "experience", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "types", + "columnName": "types", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "hp", + "columnName": "hp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "attack", + "columnName": "attack", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "defense", + "columnName": "defense", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "speed", + "columnName": "speed", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "exp", + "columnName": "exp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "stats", + "columnName": "stats", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + } + ], + "views": [], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'cc488f72b5ee2f40a7376fb08cb8c85d')" + ] + } +} \ No newline at end of file diff --git a/core-database/src/main/kotlin/com/skydoves/pokedex/core/database/PokedexDatabase.kt b/core-database/src/main/kotlin/com/skydoves/pokedex/core/database/PokedexDatabase.kt index e33460eec..3aebbd675 100644 --- a/core-database/src/main/kotlin/com/skydoves/pokedex/core/database/PokedexDatabase.kt +++ b/core-database/src/main/kotlin/com/skydoves/pokedex/core/database/PokedexDatabase.kt @@ -24,10 +24,10 @@ import com.skydoves.pokedex.core.database.entitiy.PokemonInfoEntity @Database( entities = [PokemonEntity::class, PokemonInfoEntity::class], - version = 2, + version = 3, exportSchema = true, ) -@TypeConverters(value = [TypeResponseConverter::class]) +@TypeConverters(value = [TypeResponseConverter::class, StatsResponseConverter::class]) abstract class PokedexDatabase : RoomDatabase() { abstract fun pokemonDao(): PokemonDao diff --git a/core-database/src/main/kotlin/com/skydoves/pokedex/core/database/StatsResponseConverter.kt b/core-database/src/main/kotlin/com/skydoves/pokedex/core/database/StatsResponseConverter.kt new file mode 100644 index 000000000..bccf587f2 --- /dev/null +++ b/core-database/src/main/kotlin/com/skydoves/pokedex/core/database/StatsResponseConverter.kt @@ -0,0 +1,47 @@ +/* + * Designed and developed by 2022 skydoves (Jaewoong Eum) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.skydoves.pokedex.core.database + +import androidx.room.ProvidedTypeConverter +import androidx.room.TypeConverter +import com.skydoves.pokedex.core.model.PokemonInfo +import com.squareup.moshi.JsonAdapter +import com.squareup.moshi.Moshi +import com.squareup.moshi.Types +import javax.inject.Inject + +@ProvidedTypeConverter +class StatsResponseConverter @Inject constructor( + private val moshi: Moshi, +) { + + @TypeConverter + fun fromString(value: String): List? { + val listType = + Types.newParameterizedType(List::class.java, PokemonInfo.StatsResponse::class.java) + val adapter: JsonAdapter> = moshi.adapter(listType) + return adapter.fromJson(value) + } + + @TypeConverter + fun fromInfoType(type: List?): String { + val listType = + Types.newParameterizedType(List::class.java, PokemonInfo.StatsResponse::class.java) + val adapter: JsonAdapter> = moshi.adapter(listType) + return adapter.toJson(type) + } +} diff --git a/core-database/src/main/kotlin/com/skydoves/pokedex/core/database/di/DatabaseModule.kt b/core-database/src/main/kotlin/com/skydoves/pokedex/core/database/di/DatabaseModule.kt index a25e5e8ba..2987282e7 100644 --- a/core-database/src/main/kotlin/com/skydoves/pokedex/core/database/di/DatabaseModule.kt +++ b/core-database/src/main/kotlin/com/skydoves/pokedex/core/database/di/DatabaseModule.kt @@ -21,6 +21,7 @@ import androidx.room.Room import com.skydoves.pokedex.core.database.PokedexDatabase import com.skydoves.pokedex.core.database.PokemonDao import com.skydoves.pokedex.core.database.PokemonInfoDao +import com.skydoves.pokedex.core.database.StatsResponseConverter import com.skydoves.pokedex.core.database.TypeResponseConverter import com.squareup.moshi.Moshi import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory @@ -47,11 +48,13 @@ internal object DatabaseModule { fun provideAppDatabase( application: Application, typeResponseConverter: TypeResponseConverter, + statsResponseConverter: StatsResponseConverter, ): PokedexDatabase { return Room .databaseBuilder(application, PokedexDatabase::class.java, "Pokedex.db") .fallbackToDestructiveMigration() .addTypeConverter(typeResponseConverter) + .addTypeConverter(statsResponseConverter) .build() } @@ -72,4 +75,10 @@ internal object DatabaseModule { fun provideTypeResponseConverter(moshi: Moshi): TypeResponseConverter { return TypeResponseConverter(moshi) } + + @Provides + @Singleton + fun provideStatsResponseConverter(moshi: Moshi): StatsResponseConverter { + return StatsResponseConverter(moshi) + } } diff --git a/core-database/src/main/kotlin/com/skydoves/pokedex/core/database/entitiy/PokemonInfoEntity.kt b/core-database/src/main/kotlin/com/skydoves/pokedex/core/database/entitiy/PokemonInfoEntity.kt index e3f86edd0..0cb998b14 100644 --- a/core-database/src/main/kotlin/com/skydoves/pokedex/core/database/entitiy/PokemonInfoEntity.kt +++ b/core-database/src/main/kotlin/com/skydoves/pokedex/core/database/entitiy/PokemonInfoEntity.kt @@ -33,4 +33,5 @@ data class PokemonInfoEntity( val defense: Int, val speed: Int, val exp: Int, + val stats: List, ) diff --git a/core-database/src/main/kotlin/com/skydoves/pokedex/core/database/entitiy/mapper/PokemonInfoEntityMapper.kt b/core-database/src/main/kotlin/com/skydoves/pokedex/core/database/entitiy/mapper/PokemonInfoEntityMapper.kt index f63217ca5..5421915e1 100644 --- a/core-database/src/main/kotlin/com/skydoves/pokedex/core/database/entitiy/mapper/PokemonInfoEntityMapper.kt +++ b/core-database/src/main/kotlin/com/skydoves/pokedex/core/database/entitiy/mapper/PokemonInfoEntityMapper.kt @@ -34,6 +34,7 @@ object PokemonInfoEntityMapper : EntityMapper { defense = domain.defense, speed = domain.speed, exp = domain.exp, + stats = domain.stats, ) } @@ -50,6 +51,7 @@ object PokemonInfoEntityMapper : EntityMapper { defense = entity.defense, speed = entity.speed, exp = entity.exp, + stats = entity.stats, ) } } diff --git a/core-model/src/main/kotlin/com/skydoves/pokedex/core/model/PokemonInfo.kt b/core-model/src/main/kotlin/com/skydoves/pokedex/core/model/PokemonInfo.kt index 6532f43f2..6b67446fd 100644 --- a/core-model/src/main/kotlin/com/skydoves/pokedex/core/model/PokemonInfo.kt +++ b/core-model/src/main/kotlin/com/skydoves/pokedex/core/model/PokemonInfo.kt @@ -29,6 +29,7 @@ data class PokemonInfo( @field:Json(name = "weight") val weight: Int, @field:Json(name = "base_experience") val experience: Int, @field:Json(name = "types") val types: List, + @field:Json(name = "stats") val stats: List, val hp: Int = Random.nextInt(MAX_HP), val attack: Int = Random.nextInt(MAX_ATTACK), val defense: Int = Random.nextInt(MAX_DEFENSE), @@ -56,6 +57,18 @@ data class PokemonInfo( @field:Json(name = "name") val name: String, ) + @JsonClass(generateAdapter = true) + data class StatsResponse( + @field:Json(name = "base_stat") val baseStat: Int, + @field:Json(name = "effort") val effort: Int, + @field:Json(name = "stat") val stat: Stat, + ) + + @JsonClass(generateAdapter = true) + data class Stat( + @field:Json(name = "name") val name: String, + ) + companion object { const val MAX_HP = 300 const val MAX_ATTACK = 300