First big update :)

This commit is contained in:
ElEgEv 2023-12-22 22:24:57 +04:00
parent 2fdc2d5ba3
commit 2b69f0fc24
13 changed files with 157 additions and 55 deletions

Binary file not shown.

View File

@ -109,6 +109,11 @@ interface ServerService {
@GET(ApiRoutes.TANK)
suspend fun getTanks(): List<TankRemote>
@GET(ApiRoutes.TANK)
suspend fun getTanks(
@Query("id") id: List<Long>
): List<TankRemote>
@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<UserTankCrossRefRemote>
@GET("${ApiRoutes.USER_TANK}")
suspend fun getUserTankCrossRef(
@Query("id") id: Long
): List<UserTankCrossRefRemote>
@POST(ApiRoutes.USER_TANK)
suspend fun insertUserTankCrossRef(

View File

@ -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<Int, Nation>() {
) : RemoteMediator<Int, Tank>() {
override suspend fun initialize(): InitializeAction {
return InitializeAction.LAUNCH_INITIAL_REFRESH
@ -32,7 +30,7 @@ class TankRemoteMediator(
override suspend fun load(
loadType: LoadType,
state: PagingState<Int, Nation>
state: PagingState<Int, Tank>
): MediatorResult {
val page = when (loadType) {
LoadType.REFRESH -> {
@ -85,26 +83,26 @@ class TankRemoteMediator(
}
}
private suspend fun getRemoteKeyForLastItem(state: PagingState<Int, Nation>): RemoteKeys? {
private suspend fun getRemoteKeyForLastItem(state: PagingState<Int, Tank>): 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<Int, Nation>): RemoteKeys? {
private suspend fun getRemoteKeyForFirstItem(state: PagingState<Int, Tank>): 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<Int, Nation>
state: PagingState<Int, Tank>
): 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)
}
}
}

View File

@ -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
)

View File

@ -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<Tank> {
val totalList: List<Tank> = getAll()
val totalUserTankList: List<UserTankCrossRef> = service.getUserTankCrossRef().map{ it.toUserTankCrossRef() }
val totalUserTankList: List<UserTankCrossRef> = service.getUserTankCrossRef(100L).map{ it.toUserTankCrossRef() }
//спискок, который вернём
var supportList = ArrayList<Tank>()
//вспомогательный список для проверки отсутствия танка у пользователя
var notToUser: List<UserTankCrossRef> = totalList.map{ UserTankCrossRef(userId, it.tankId!!) }
var notToUser: List<UserTankCrossRef> = totalList.map{ UserTankCrossRef(userId, it.tankId!!, Date()) }
if (totalUserTankList.isEmpty()){
return totalList
@ -72,26 +73,31 @@ class RestTankRepository (
val totalNationList: List<Nation> = service.getAllNations().map { it.toNation() }
//все имеющиеся танки у пользователя
val totalUserTankList: List<UserTankCrossRef> = service.getUserTankCrossRef().map{ it.toUserTankCrossRef() }
val totalUserTankList: List<UserTankCrossRef> = service.getUserTankCrossRef(100L).map{ it.toUserTankCrossRef() }
//спискок, который вернём
var supportList = ArrayList<TankWithNationAndLevel>()
//вспомогательный список для проверки наличия танка у пользователя
var notToUser: List<UserTankCrossRef> = totalList.map{ UserTankCrossRef(userId, it.tankId!!) }
//список id-шников танков пользователя
var idList = ArrayList<Long>()
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<Tank>) {

View File

@ -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()))
}
}

View File

@ -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<Date> {
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()
}
}

View File

@ -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",

View File

@ -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
}
}

View File

@ -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<Tank>) {

View File

@ -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<Tank>
@ -12,7 +13,7 @@ interface TankRepository {
suspend fun getTank(uid: Long): Tank
suspend fun getUserTanks(uid: Long): List<TankWithNationAndLevel>
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<Tank>)
suspend fun updateTank(tank: Tank, image: Bitmap)
suspend fun deleteTank(tank: Tank)

View File

@ -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"
}
]
}

View File

@ -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"