From 2b69f0fc244085fe4acbfee374cf66358da5fdd5 Mon Sep 17 00:00:00 2001 From: ElEgEv <112943269+ElEgEv@users.noreply.github.com> Date: Fri, 22 Dec 2023 22:24:57 +0400 Subject: [PATCH] First big update :) --- compose/.gradle/file-system.probe | Bin 8 -> 8 bytes .../ru/ulstu/is/pmu/tank/api/ServerService.kt | 11 ++++- .../tank/api/mediator/TankRemoteMediator.kt | 26 +++++----- .../tank/api/model/UserTankCrossRefRemote.kt | 12 +++-- .../tank/api/repository/RestTankRepository.kt | 38 ++++++++------- .../ulstu/is/pmu/tank/database/AppDatabase.kt | 13 ++--- .../is/pmu/tank/database/DateSerializer.kt | 22 +++++++++ .../java/ru/ulstu/is/pmu/tank/model/Tank.kt | 4 -- .../is/pmu/tank/model/UserTankCrossRef.kt | 29 ++++++++++- .../tank/repository/OfflineTankRepository.kt | 5 +- .../is/pmu/tank/repository/TankRepository.kt | 3 +- compose/server/data.json | 45 ++++++++++++++++-- compose/server/package-lock.json | 4 +- 13 files changed, 157 insertions(+), 55 deletions(-) create mode 100644 compose/app/src/main/java/ru/ulstu/is/pmu/tank/database/DateSerializer.kt diff --git a/compose/.gradle/file-system.probe b/compose/.gradle/file-system.probe index 0fb77eeb406937ea47eafd66bd7777cf90941eb5..d26467106c2fa04985c561fd4bbab3ce0ba3fbc2 100644 GIT binary patch literal 8 PcmZQzVC + @GET(ApiRoutes.TANK) + suspend fun getTanks( + @Query("id") id: List + ): List + @GET("${ApiRoutes.TANK}/{id}") suspend fun getTank( @Path("id") id: Long @@ -144,8 +149,10 @@ interface ServerService { // :[USER_TANK_CROSS_REF] - @GET(ApiRoutes.USER_TANK) - suspend fun getUserTankCrossRef(): List + @GET("${ApiRoutes.USER_TANK}") + suspend fun getUserTankCrossRef( + @Query("id") id: Long + ): List @POST(ApiRoutes.USER_TANK) suspend fun insertUserTankCrossRef( diff --git a/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/mediator/TankRemoteMediator.kt b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/mediator/TankRemoteMediator.kt index a2143db..3950939 100644 --- a/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/mediator/TankRemoteMediator.kt +++ b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/mediator/TankRemoteMediator.kt @@ -7,13 +7,11 @@ import androidx.paging.RemoteMediator import androidx.room.withTransaction import retrofit2.HttpException import ru.ulstu.`is`.pmu.tank.api.ServerService -import ru.ulstu.`is`.pmu.tank.api.model.toNation import ru.ulstu.`is`.pmu.tank.api.model.toTank import ru.ulstu.`is`.pmu.tank.database.AppDatabase -import ru.ulstu.`is`.pmu.tank.model.Nation import ru.ulstu.`is`.pmu.tank.model.RemoteKeyType import ru.ulstu.`is`.pmu.tank.model.RemoteKeys -import ru.ulstu.`is`.pmu.tank.repository.OfflineNationRepository +import ru.ulstu.`is`.pmu.tank.model.Tank import ru.ulstu.`is`.pmu.tank.repository.OfflineRemoteKeyRepository import ru.ulstu.`is`.pmu.tank.repository.OfflineTankRepository import java.io.IOException @@ -24,7 +22,7 @@ class TankRemoteMediator( private val dbTankRepository: OfflineTankRepository, private val dbRemoteKeyRepository: OfflineRemoteKeyRepository, private val database: AppDatabase -) : RemoteMediator() { +) : RemoteMediator() { override suspend fun initialize(): InitializeAction { return InitializeAction.LAUNCH_INITIAL_REFRESH @@ -32,7 +30,7 @@ class TankRemoteMediator( override suspend fun load( loadType: LoadType, - state: PagingState + state: PagingState ): MediatorResult { val page = when (loadType) { LoadType.REFRESH -> { @@ -85,26 +83,26 @@ class TankRemoteMediator( } } - private suspend fun getRemoteKeyForLastItem(state: PagingState): RemoteKeys? { + private suspend fun getRemoteKeyForLastItem(state: PagingState): RemoteKeys? { return state.pages.lastOrNull { it.data.isNotEmpty() }?.data?.lastOrNull() - ?.let { nation -> - dbRemoteKeyRepository.getAllRemoteKeys(nation.uid!!.toInt(), RemoteKeyType.NATION) + ?.let { tank -> + dbRemoteKeyRepository.getAllRemoteKeys(tank.tankId!!.toInt(), RemoteKeyType.NATION) } } - private suspend fun getRemoteKeyForFirstItem(state: PagingState): RemoteKeys? { + private suspend fun getRemoteKeyForFirstItem(state: PagingState): RemoteKeys? { return state.pages.firstOrNull { it.data.isNotEmpty() }?.data?.firstOrNull() - ?.let { nation -> - dbRemoteKeyRepository.getAllRemoteKeys(nation.uid!!.toInt(), RemoteKeyType.NATION) + ?.let { tank -> + dbRemoteKeyRepository.getAllRemoteKeys(tank.tankId!!.toInt(), RemoteKeyType.NATION) } } private suspend fun getRemoteKeyClosestToCurrentPosition( - state: PagingState + state: PagingState ): RemoteKeys? { return state.anchorPosition?.let { position -> - state.closestItemToPosition(position)?.uid?.let { nationUid -> - dbRemoteKeyRepository.getAllRemoteKeys(nationUid.toInt(), RemoteKeyType.NATION) + state.closestItemToPosition(position)?.tankId?.let { tankUid -> + dbRemoteKeyRepository.getAllRemoteKeys(tankUid.toInt(), RemoteKeyType.NATION) } } } diff --git a/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/model/UserTankCrossRefRemote.kt b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/model/UserTankCrossRefRemote.kt index 000f016..08e11bc 100644 --- a/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/model/UserTankCrossRefRemote.kt +++ b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/model/UserTankCrossRefRemote.kt @@ -1,21 +1,27 @@ package ru.ulstu.`is`.pmu.tank.api.model import kotlinx.serialization.Serializable +import ru.ulstu.`is`.pmu.tank.database.DateSerializer import ru.ulstu.`is`.pmu.tank.model.Level import ru.ulstu.`is`.pmu.tank.model.UserTankCrossRef +import java.util.Date @Serializable data class UserTankCrossRefRemote ( val id: Long = 0, - val tankId: Long = 0 + val tankId: Long = 0, + @Serializable(with = DateSerializer::class) + val date: Date = Date() ) fun UserTankCrossRefRemote.toUserTankCrossRef(): UserTankCrossRef = UserTankCrossRef( userId = id, - tankId = tankId + tankId = tankId, + date = date ) fun UserTankCrossRef.toRemote(): UserTankCrossRefRemote = UserTankCrossRefRemote( id = userId, - tankId = tankId + tankId = tankId, + date = date ) \ No newline at end of file diff --git a/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/repository/RestTankRepository.kt b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/repository/RestTankRepository.kt index ab270cf..8efbadc 100644 --- a/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/repository/RestTankRepository.kt +++ b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/api/repository/RestTankRepository.kt @@ -26,6 +26,7 @@ import ru.ulstu.`is`.pmu.tank.repository.OfflineUsersTanksRepository import ru.ulstu.`is`.pmu.tank.repository.TankRepository import ru.ulstu.`is`.pmu.tank.repository.UsersTanksRepository import java.nio.file.Files.find +import java.util.Date class RestTankRepository ( private val service: ServerService, @@ -38,13 +39,13 @@ class RestTankRepository ( override suspend fun getForUserAll(userId: Long): List { val totalList: List = getAll() - val totalUserTankList: List = service.getUserTankCrossRef().map{ it.toUserTankCrossRef() } + val totalUserTankList: List = service.getUserTankCrossRef(100L).map{ it.toUserTankCrossRef() } //спискок, который вернём var supportList = ArrayList() //вспомогательный список для проверки отсутствия танка у пользователя - var notToUser: List = totalList.map{ UserTankCrossRef(userId, it.tankId!!) } + var notToUser: List = totalList.map{ UserTankCrossRef(userId, it.tankId!!, Date()) } if (totalUserTankList.isEmpty()){ return totalList @@ -72,26 +73,31 @@ class RestTankRepository ( val totalNationList: List = service.getAllNations().map { it.toNation() } //все имеющиеся танки у пользователя - val totalUserTankList: List = service.getUserTankCrossRef().map{ it.toUserTankCrossRef() } + val totalUserTankList: List = service.getUserTankCrossRef(100L).map{ it.toUserTankCrossRef() } //спискок, который вернём var supportList = ArrayList() - //вспомогательный список для проверки наличия танка у пользователя - var notToUser: List = totalList.map{ UserTankCrossRef(userId, it.tankId!!) } + //список id-шников танков пользователя + var idList = ArrayList() + + totalUserTankList.forEach(){ tank -> + idList.add(tank.tankId) + } + + //список танков пользователя + var simpleTankList = service.getTanks(idList) if (totalUserTankList.isEmpty()){ return listOf() } else { - notToUser.forEach(){userTank -> - if(totalUserTankList.contains(userTank)){ - val tank = totalList.firstOrNull { it.tankId == userTank.tankId }!! - supportList.add( - TankWithNationAndLevel(tank.tankId, tank.name, tank.price, tank.miniature, - totalLevelList.first { it.uid == tank.levelId }.level, - totalNationList.first { it.uid == tank.nationId }.nationName) - ) - } + simpleTankList.forEach(){userTank -> + val tank = totalList.firstOrNull { it.tankId == userTank.id }!! + supportList.add( + TankWithNationAndLevel(tank.tankId, tank.name, tank.price, tank.miniature, + totalLevelList.first { it.uid == tank.levelId }.level, + totalNationList.first { it.uid == tank.nationId }.nationName) + ) } return supportList } @@ -101,8 +107,8 @@ class RestTankRepository ( service.insertTank(tank.toRemote()) } - override suspend fun buyTank(tankId: Long, userId: Long) { - service.insertUserTankCrossRef(UserTankCrossRefRemote(userId, tankId)) + override suspend fun buyTank(tankId: Long, userId: Long, date: Date) { + service.insertUserTankCrossRef(UserTankCrossRefRemote(userId, tankId, date)) } override suspend fun insertMany(tankList: List) { diff --git a/compose/app/src/main/java/ru/ulstu/is/pmu/tank/database/AppDatabase.kt b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/database/AppDatabase.kt index c37b707..2dc16d3 100644 --- a/compose/app/src/main/java/ru/ulstu/is/pmu/tank/database/AppDatabase.kt +++ b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/database/AppDatabase.kt @@ -25,6 +25,7 @@ import ru.ulstu.`is`.pmu.tank.model.TankImage import ru.ulstu.`is`.pmu.tank.model.User import ru.ulstu.`is`.pmu.tank.model.UserRole import ru.ulstu.`is`.pmu.tank.model.UserTankCrossRef +import java.util.Date //тут, собственно говоря, всё и мутится с БД :))) @Database( @@ -51,7 +52,7 @@ abstract class AppDatabase : RoomDatabase() { abstract fun remoteKeysDao(): RemoteKeysDao companion object { - private const val DB_NAME: String = "22-db" + private const val DB_NAME: String = "23-db" @Volatile private var INSTANCE: AppDatabase? = null @@ -150,11 +151,11 @@ abstract class AppDatabase : RoomDatabase() { userDao.insert(user) - userDao.insert(UserTankCrossRef(user.userId, tank1.tankId ?: 0)) - userDao.insert(UserTankCrossRef(user.userId, tank3.tankId ?: 0)) - userDao.insert(UserTankCrossRef(user.userId, tank5.tankId ?: 0)) - userDao.insert(UserTankCrossRef(user.userId, tank7.tankId ?: 0)) - userDao.insert(UserTankCrossRef(user.userId, tank9.tankId ?: 0)) + userDao.insert(UserTankCrossRef(user.userId, tank1.tankId ?: 0, Date())) + userDao.insert(UserTankCrossRef(user.userId, tank3.tankId ?: 0, Date())) + userDao.insert(UserTankCrossRef(user.userId, tank5.tankId ?: 0, Date())) + userDao.insert(UserTankCrossRef(user.userId, tank7.tankId ?: 0, Date())) + userDao.insert(UserTankCrossRef(user.userId, tank9.tankId ?: 0, Date())) } } diff --git a/compose/app/src/main/java/ru/ulstu/is/pmu/tank/database/DateSerializer.kt b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/database/DateSerializer.kt new file mode 100644 index 0000000..4adac5a --- /dev/null +++ b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/database/DateSerializer.kt @@ -0,0 +1,22 @@ +package ru.ulstu.`is`.pmu.tank.database + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import java.text.SimpleDateFormat +import java.util.Date + +@Serializer(forClass = Date::class) +object DateSerializer : KSerializer { + private val dateFormat = + SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ") // Adjust the format as needed + + override fun serialize(encoder: Encoder, value: Date) { + encoder.encodeString(dateFormat.format(value)) + } + + override fun deserialize(decoder: Decoder): Date { + return dateFormat.parse(decoder.decodeString()) ?: Date() + } +} \ No newline at end of file diff --git a/compose/app/src/main/java/ru/ulstu/is/pmu/tank/model/Tank.kt b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/model/Tank.kt index 0049964..1b934f2 100644 --- a/compose/app/src/main/java/ru/ulstu/is/pmu/tank/model/Tank.kt +++ b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/model/Tank.kt @@ -3,13 +3,9 @@ package ru.ulstu.`is`.pmu.tank.model import android.graphics.Bitmap import androidx.room.ColumnInfo import androidx.room.Entity -import androidx.room.ForeignKey import androidx.room.Ignore import androidx.room.PrimaryKey -import androidx.room.TypeConverters import com.application.ui.getEmptyBitmap -import ru.ulstu.`is`.pmu.R -import ru.ulstu.`is`.pmu.tank.database.Converters @Entity( tableName = "tanks", diff --git a/compose/app/src/main/java/ru/ulstu/is/pmu/tank/model/UserTankCrossRef.kt b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/model/UserTankCrossRef.kt index 57de2bd..52c0810 100644 --- a/compose/app/src/main/java/ru/ulstu/is/pmu/tank/model/UserTankCrossRef.kt +++ b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/model/UserTankCrossRef.kt @@ -1,11 +1,13 @@ package ru.ulstu.`is`.pmu.tank.model +import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.ForeignKey import androidx.room.Ignore import androidx.room.Index import androidx.room.PrimaryKey import org.jetbrains.annotations.NotNull +import java.util.Date //many to many for user and tank @Entity( @@ -14,14 +16,37 @@ import org.jetbrains.annotations.NotNull ) data class UserTankCrossRef( val userId: Long, - val tankId: Long + val tankId: Long, + @ColumnInfo(name = "date") + val date: Date, ){ companion object { fun getEmpty(): UserTankCrossRef { return UserTankCrossRef( userId = 0, - tankId = 0 + tankId = 0, + date = Date() ) } } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as UserTankCrossRef + + if (userId != other.userId) return false + if (tankId != other.tankId) return false + if (date != other.date) return false + + return true + } + + override fun hashCode(): Int { + var result = userId.hashCode() + result = 31 * result + tankId.hashCode() + result = 31 * result + date.hashCode() + return result + } } diff --git a/compose/app/src/main/java/ru/ulstu/is/pmu/tank/repository/OfflineTankRepository.kt b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/repository/OfflineTankRepository.kt index fe98c2a..22de1cb 100644 --- a/compose/app/src/main/java/ru/ulstu/is/pmu/tank/repository/OfflineTankRepository.kt +++ b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/repository/OfflineTankRepository.kt @@ -10,6 +10,7 @@ import ru.ulstu.`is`.pmu.tank.model.TankExtra import ru.ulstu.`is`.pmu.tank.model.TankImage import ru.ulstu.`is`.pmu.tank.model.TankWithNationAndLevel import ru.ulstu.`is`.pmu.tank.model.UserTankCrossRef +import java.util.Date class OfflineTankRepository( private val tankDao: TankDao, @@ -27,8 +28,8 @@ class OfflineTankRepository( tankDao.insert(tank) } - override suspend fun buyTank(tankId: Long, userId: Long) { - usersTanksDao.insert(UserTankCrossRef(userId, tankId)) + override suspend fun buyTank(tankId: Long, userId: Long, date: Date) { + usersTanksDao.insert(UserTankCrossRef(userId, tankId, date)) } override suspend fun insertMany(tankList: List) { diff --git a/compose/app/src/main/java/ru/ulstu/is/pmu/tank/repository/TankRepository.kt b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/repository/TankRepository.kt index 0203dd9..2355a6f 100644 --- a/compose/app/src/main/java/ru/ulstu/is/pmu/tank/repository/TankRepository.kt +++ b/compose/app/src/main/java/ru/ulstu/is/pmu/tank/repository/TankRepository.kt @@ -5,6 +5,7 @@ import kotlinx.coroutines.flow.Flow import ru.ulstu.`is`.pmu.tank.model.Tank import ru.ulstu.`is`.pmu.tank.model.TankExtra import ru.ulstu.`is`.pmu.tank.model.TankWithNationAndLevel +import java.util.Date interface TankRepository { suspend fun getAll(): List @@ -12,7 +13,7 @@ interface TankRepository { suspend fun getTank(uid: Long): Tank suspend fun getUserTanks(uid: Long): List suspend fun insertTank(tank: Tank, image: Bitmap) - suspend fun buyTank(tankId: Long, userId: Long) + suspend fun buyTank(tankId: Long, userId: Long, date: Date) suspend fun insertMany(tankList: List) suspend fun updateTank(tank: Tank, image: Bitmap) suspend fun deleteTank(tank: Tank) diff --git a/compose/server/data.json b/compose/server/data.json index acfd5a2..e4ccda7 100644 --- a/compose/server/data.json +++ b/compose/server/data.json @@ -189,20 +189,59 @@ "password": "Tujh2003", "role": 1, "balance": 12300000 + }, + { + "id": 101, + "nickname": "KorbenDallas", + "email": "korbenDetka@mail.ru", + "password": "Korben2013", + "role": 0, + "balance": 11223300 + }, + { + "id": 102, + "nickname": "Amway921", + "email": "amway@mail.ru", + "password": "Amway2013", + "role": 0, + "balance": 11223300 } ], "users_tanks": [ { "id": 100, - "tankId": 1 + "tankId": 1, + "date": "2023-12-12T12:06:14.720+0000" }, { "id": 100, - "tankId": 5 + "tankId": 5, + "date": "2023-12-13T12:06:14.720+0000" }, { "id": 100, - "tankId": 6 + "tankId": 6, + "date": "2023-12-14T12:06:14.720+0000" + }, + { + "id": 101, + "tankId": 6, + "date": "2023-12-15T12:06:14.720+0000" + }, + { + "id": 101, + "tankId": 11, + "date": "2023-12-16T12:06:14.720+0000" + }, + { + "id": 102, + "tankId": 6, + "date": "2023-12-17T12:06:14.720+0000" + }, + { + "id": 102, + "tankId": 1, + "date": "2023-12-18T12:06:14.720+0000" } ] } \ No newline at end of file diff --git a/compose/server/package-lock.json b/compose/server/package-lock.json index 0203f7f..9d31667 100644 --- a/compose/server/package-lock.json +++ b/compose/server/package-lock.json @@ -1,11 +1,11 @@ { - "name": "fake-db", + "name": "20-db", "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "fake-db", + "name": "20-db", "version": "1.0.0", "devDependencies": { "json-server": "0.17.4"