初步實作出刀紀錄表
This commit is contained in:
+43
@@ -0,0 +1,43 @@
|
|||||||
|
package club.sakunadaisuki.pcrediveclanrecordbackend.database.dto
|
||||||
|
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import org.bson.Document
|
||||||
|
import java.time.Instant
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class BattleRecordDto(
|
||||||
|
val date: String, // yyyy-MM-dd
|
||||||
|
var uid: String,
|
||||||
|
@SerialName("player_name") val playerName: String,
|
||||||
|
@SerialName("discord_name") val discordName: String,
|
||||||
|
@SerialName("discord_id") val discordID: String,
|
||||||
|
@SerialName("attack_detail_list") val attackDetailList: List<AttackDetailDto>
|
||||||
|
) {
|
||||||
|
fun toDocument(): Document = Document.parse(Json.encodeToString(this))
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val json = Json { ignoreUnknownKeys = true }
|
||||||
|
|
||||||
|
fun fromDocument(document: Document): BattleRecordDto = json.decodeFromString(document.toJson())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class AttackDetailDto(
|
||||||
|
@SerialName("boss_round") val bossRound: Int, // 周目
|
||||||
|
@SerialName("boss_index") val bossIndex: Int, // 1~5 號王
|
||||||
|
val damage: Long, // 傷害
|
||||||
|
@SerialName("is_compensation") val isCompensation: Boolean = false, // true: 補償刀, false: 正刀
|
||||||
|
@SerialName("created_at") val createdAt: Long = Instant.now().toEpochMilli(),
|
||||||
|
@SerialName("updated_at") val updatedAt: Long = Instant.now().toEpochMilli()
|
||||||
|
) {
|
||||||
|
fun toDocument(): Document = Document.parse(Json.encodeToString(this))
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val json = Json { ignoreUnknownKeys = true }
|
||||||
|
|
||||||
|
fun fromDocument(document: Document): AttackDetailDto = json.decodeFromString(document.toJson())
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
-5
@@ -1,18 +1,20 @@
|
|||||||
package club.sakunadaisuki.pcrediveclanrecordbackend.database.dto
|
package club.sakunadaisuki.pcrediveclanrecordbackend.database.dto
|
||||||
|
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import org.bson.Document
|
import org.bson.Document
|
||||||
|
import java.time.Instant
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class MemberDto(
|
data class MemberDto(
|
||||||
var uid: String,
|
var uid: String,
|
||||||
val playerName: String,
|
@SerialName("player_name") val playerName: String,
|
||||||
val nickName: String,
|
@SerialName("discord_name") val discordName: String,
|
||||||
val discordID: String,
|
@SerialName("discord_id") val discordID: String,
|
||||||
var leave: Boolean = false,
|
var leave: Boolean = false,
|
||||||
var createAt: Long? = null,
|
@SerialName("created_at") var createAt: Long? = null,
|
||||||
var updatedAt: Long? = null
|
@SerialName("updated_at") var updatedAt: Long? = null
|
||||||
) {
|
) {
|
||||||
fun toDocument(): Document = Document.parse(Json.encodeToString(this))
|
fun toDocument(): Document = Document.parse(Json.encodeToString(this))
|
||||||
|
|
||||||
|
|||||||
+58
@@ -0,0 +1,58 @@
|
|||||||
|
package club.sakunadaisuki.pcrediveclanrecordbackend.database.service
|
||||||
|
|
||||||
|
import club.sakunadaisuki.pcrediveclanrecordbackend.database.dto.BattleRecordDto
|
||||||
|
import com.mongodb.client.MongoCollection
|
||||||
|
import com.mongodb.client.MongoDatabase
|
||||||
|
import com.mongodb.client.model.Filters
|
||||||
|
import com.mongodb.client.model.Filters.and
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import org.bson.Document
|
||||||
|
|
||||||
|
class BattleRecordService(private val database: MongoDatabase) {
|
||||||
|
var collection: MongoCollection<Document>
|
||||||
|
|
||||||
|
init {
|
||||||
|
database.createCollection("battle_records")
|
||||||
|
collection = database.getCollection("battle_records")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create new car
|
||||||
|
suspend fun create(data: BattleRecordDto): String = withContext(Dispatchers.IO) {
|
||||||
|
val doc = data.toDocument()
|
||||||
|
collection.insertOne(doc)
|
||||||
|
doc["uid"].toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read a car
|
||||||
|
suspend fun read(date: String): List<BattleRecordDto> = withContext(Dispatchers.IO) {
|
||||||
|
collection.find(Filters.eq("date", date)).toList().map(BattleRecordDto::fromDocument)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read a car
|
||||||
|
suspend fun read(date: String, uid: String): BattleRecordDto? = withContext(Dispatchers.IO) {
|
||||||
|
val filter = and(
|
||||||
|
Filters.eq("date", date),
|
||||||
|
Filters.eq("uid", uid)
|
||||||
|
)
|
||||||
|
collection.find(filter).first()?.let(BattleRecordDto::fromDocument)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update a car
|
||||||
|
suspend fun update(date: String, data: BattleRecordDto): Document? = withContext(Dispatchers.IO) {
|
||||||
|
val filter = and(
|
||||||
|
Filters.eq("date", date),
|
||||||
|
Filters.eq("uid", data.uid)
|
||||||
|
)
|
||||||
|
collection.findOneAndReplace(filter, data.toDocument())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete a car
|
||||||
|
suspend fun delete(date: String, uid: String): Document? = withContext(Dispatchers.IO) {
|
||||||
|
val filter = and(
|
||||||
|
Filters.eq("date", date),
|
||||||
|
Filters.eq("uid", uid)
|
||||||
|
)
|
||||||
|
collection.findOneAndDelete(filter)
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
-5
@@ -16,7 +16,7 @@ class MemberService(private val database: MongoDatabase) {
|
|||||||
collection = database.getCollection("member")
|
collection = database.getCollection("member")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create new car
|
// Create new member
|
||||||
suspend fun create(data: MemberDto): String = withContext(Dispatchers.IO) {
|
suspend fun create(data: MemberDto): String = withContext(Dispatchers.IO) {
|
||||||
data.createAt = System.currentTimeMillis()
|
data.createAt = System.currentTimeMillis()
|
||||||
data.updatedAt = System.currentTimeMillis()
|
data.updatedAt = System.currentTimeMillis()
|
||||||
@@ -26,22 +26,22 @@ class MemberService(private val database: MongoDatabase) {
|
|||||||
doc["uid"].toString()
|
doc["uid"].toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read a car
|
// Read a member
|
||||||
suspend fun read(): List<MemberDto> = withContext(Dispatchers.IO) {
|
suspend fun read(): List<MemberDto> = withContext(Dispatchers.IO) {
|
||||||
collection.find().toList().map(MemberDto::fromDocument)
|
collection.find().toList().map(MemberDto::fromDocument)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read a car
|
// Read a member
|
||||||
suspend fun read(uid: String): MemberDto? = withContext(Dispatchers.IO) {
|
suspend fun read(uid: String): MemberDto? = withContext(Dispatchers.IO) {
|
||||||
collection.find(Filters.eq("uid", uid)).first()?.let(MemberDto::fromDocument)
|
collection.find(Filters.eq("uid", uid)).first()?.let(MemberDto::fromDocument)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update a car
|
// Update a member
|
||||||
suspend fun update(uid: String, data: MemberDto): Document? = withContext(Dispatchers.IO) {
|
suspend fun update(uid: String, data: MemberDto): Document? = withContext(Dispatchers.IO) {
|
||||||
collection.findOneAndReplace(Filters.eq("uid", uid), data.toDocument())
|
collection.findOneAndReplace(Filters.eq("uid", uid), data.toDocument())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete a car
|
// Delete a member
|
||||||
suspend fun delete(uid: String): Document? = withContext(Dispatchers.IO) {
|
suspend fun delete(uid: String): Document? = withContext(Dispatchers.IO) {
|
||||||
collection.findOneAndDelete(Filters.eq("uid", uid))
|
collection.findOneAndDelete(Filters.eq("uid", uid))
|
||||||
}
|
}
|
||||||
|
|||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
package club.sakunadaisuki.pcrediveclanrecordbackend.mapper
|
||||||
|
|
||||||
|
import club.sakunadaisuki.pcrediveclanrecordbackend.database.dto.AttackDetailDto
|
||||||
|
import club.sakunadaisuki.pcrediveclanrecordbackend.database.dto.BattleRecordDto
|
||||||
|
import club.sakunadaisuki.pcrediveclanrecordbackend.model.AttackDetail
|
||||||
|
import club.sakunadaisuki.pcrediveclanrecordbackend.model.BattleRecord
|
||||||
|
|
||||||
|
fun BattleRecord.toDto(): BattleRecordDto = BattleRecordDto(
|
||||||
|
date = date,
|
||||||
|
uid = uid,
|
||||||
|
playerName = playerName,
|
||||||
|
discordName = discordName,
|
||||||
|
discordID = discordID,
|
||||||
|
attackDetailList = attackDetailList.map { it.toDto() },
|
||||||
|
)
|
||||||
|
|
||||||
|
fun AttackDetail.toDto(): AttackDetailDto = AttackDetailDto(
|
||||||
|
bossRound = bossRound,
|
||||||
|
bossIndex = bossIndex,
|
||||||
|
damage = damage,
|
||||||
|
isCompensation = isCompensation,
|
||||||
|
createdAt = createdAt,
|
||||||
|
updatedAt = updatedAt,
|
||||||
|
)
|
||||||
@@ -7,7 +7,7 @@ fun Member.toDto(): MemberDto {
|
|||||||
return MemberDto(
|
return MemberDto(
|
||||||
uid = uid,
|
uid = uid,
|
||||||
playerName = playerName,
|
playerName = playerName,
|
||||||
nickName = nickName,
|
discordName = discordName,
|
||||||
discordID = discordID,
|
discordID = discordID,
|
||||||
leave = leave,
|
leave = leave,
|
||||||
createAt = createAt,
|
createAt = createAt,
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package club.sakunadaisuki.pcrediveclanrecordbackend.model
|
||||||
|
|
||||||
|
import java.time.Instant
|
||||||
|
|
||||||
|
data class BattleRecord(
|
||||||
|
val date: String, // yyyy-MM-dd
|
||||||
|
var uid: String,
|
||||||
|
val playerName: String,
|
||||||
|
val discordName: String,
|
||||||
|
val discordID: String,
|
||||||
|
val attackDetailList: List<AttackDetail>
|
||||||
|
)
|
||||||
|
|
||||||
|
data class AttackDetail(
|
||||||
|
val bossRound: Int, // 周目
|
||||||
|
val bossIndex: Int, // 1~5 號王
|
||||||
|
val damage: Long, // 傷害
|
||||||
|
val isCompensation: Boolean = false, // true: 補償刀, false: 正刀
|
||||||
|
val createdAt: Long = Instant.now().toEpochMilli(),
|
||||||
|
val updatedAt: Long = Instant.now().toEpochMilli()
|
||||||
|
)
|
||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
package club.sakunadaisuki.pcrediveclanrecordbackend.model
|
||||||
|
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class BattleRecordRequest(
|
||||||
|
val date: String,
|
||||||
|
val uid: String,
|
||||||
|
@SerialName("player_name") val name: String,
|
||||||
|
@SerialName("discord_name") val discordName: String,
|
||||||
|
@SerialName("discord_id") val discordID: String,
|
||||||
|
val round: Int,
|
||||||
|
val boss: Int,
|
||||||
|
val damage: Long,
|
||||||
|
@SerialName("is_compensation") val isCompensation: Boolean = false,
|
||||||
|
)
|
||||||
@@ -3,7 +3,7 @@ package club.sakunadaisuki.pcrediveclanrecordbackend.model
|
|||||||
data class Member(
|
data class Member(
|
||||||
var uid: String,
|
var uid: String,
|
||||||
val playerName: String,
|
val playerName: String,
|
||||||
val nickName: String,
|
val discordName: String,
|
||||||
val discordID: String,
|
val discordID: String,
|
||||||
var leave: Boolean = false,
|
var leave: Boolean = false,
|
||||||
var createAt: Long? = null,
|
var createAt: Long? = null,
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
package club.sakunadaisuki.pcrediveclanrecordbackend.plugins
|
package club.sakunadaisuki.pcrediveclanrecordbackend.plugins
|
||||||
|
|
||||||
|
import club.sakunadaisuki.pcrediveclanrecordbackend.database.dto.BattleRecordDto
|
||||||
|
import club.sakunadaisuki.pcrediveclanrecordbackend.database.service.BattleRecordService
|
||||||
import club.sakunadaisuki.pcrediveclanrecordbackend.model.Member
|
import club.sakunadaisuki.pcrediveclanrecordbackend.model.Member
|
||||||
import club.sakunadaisuki.pcrediveclanrecordbackend.database.service.MemberService
|
import club.sakunadaisuki.pcrediveclanrecordbackend.database.service.MemberService
|
||||||
import club.sakunadaisuki.pcrediveclanrecordbackend.mapper.toDto
|
import club.sakunadaisuki.pcrediveclanrecordbackend.mapper.toDto
|
||||||
|
import club.sakunadaisuki.pcrediveclanrecordbackend.model.AttackDetail
|
||||||
|
import club.sakunadaisuki.pcrediveclanrecordbackend.model.BattleRecordRequest
|
||||||
import com.mongodb.client.*
|
import com.mongodb.client.*
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
import io.ktor.server.application.*
|
import io.ktor.server.application.*
|
||||||
@@ -17,20 +21,23 @@ fun Application.configureMongo() {
|
|||||||
val memberService = runCatching {
|
val memberService = runCatching {
|
||||||
MemberService(mongoDatabase)
|
MemberService(mongoDatabase)
|
||||||
}.getOrNull() ?: return
|
}.getOrNull() ?: return
|
||||||
|
val battleRecordService = runCatching {
|
||||||
|
BattleRecordService(mongoDatabase)
|
||||||
|
}.getOrNull() ?: return
|
||||||
|
|
||||||
routing {
|
routing {
|
||||||
route("/api") {
|
route("/api") {
|
||||||
// Read member
|
// Read member
|
||||||
get("/member") {
|
get("/member") {
|
||||||
memberService.read().let { member ->
|
memberService.read().let { member ->
|
||||||
call.respond(member)
|
call.respond(HttpStatusCode.OK, member)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Read member
|
// Read member
|
||||||
get("/member/{uid}") {
|
get("/member/{uid}") {
|
||||||
val uid = call.parameters["uid"] ?: throw IllegalArgumentException("No ID found")
|
val uid = call.parameters["uid"] ?: throw IllegalArgumentException("No ID found")
|
||||||
memberService.read(uid)?.let { member ->
|
memberService.read(uid)?.let { member ->
|
||||||
call.respond(member)
|
call.respond(HttpStatusCode.OK, member)
|
||||||
} ?: call.respond(HttpStatusCode.NotFound)
|
} ?: call.respond(HttpStatusCode.NotFound)
|
||||||
}
|
}
|
||||||
// Create member
|
// Create member
|
||||||
@@ -56,6 +63,45 @@ fun Application.configureMongo() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO Battle Record
|
// TODO Battle Record
|
||||||
|
get("/battle_record/{date}") {
|
||||||
|
val date = call.parameters["date"] ?: throw IllegalArgumentException("No date")
|
||||||
|
battleRecordService.read(date).let { battleRecord ->
|
||||||
|
call.respond(HttpStatusCode.OK, battleRecord)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
post("/battle_record") {
|
||||||
|
val request = call.receive<BattleRecordRequest>()
|
||||||
|
val newAttackDetail = AttackDetail(
|
||||||
|
bossRound = request.round,
|
||||||
|
bossIndex = request.boss,
|
||||||
|
damage = request.damage,
|
||||||
|
isCompensation = request.isCompensation,
|
||||||
|
)
|
||||||
|
val existData = battleRecordService.read(request.date, request.uid)
|
||||||
|
if (existData != null) {
|
||||||
|
val attackDetails = existData.attackDetailList.toMutableList()
|
||||||
|
attackDetails.add(newAttackDetail.toDto())
|
||||||
|
val newData = existData.copy(
|
||||||
|
attackDetailList = attackDetails
|
||||||
|
)
|
||||||
|
battleRecordService.update(request.date, newData)?.let {
|
||||||
|
call.respond(HttpStatusCode.OK, it)
|
||||||
|
} ?: call.respond(HttpStatusCode.NotFound)
|
||||||
|
} else {
|
||||||
|
val newData = BattleRecordDto(
|
||||||
|
date = request.date,
|
||||||
|
uid = request.uid,
|
||||||
|
playerName = request.name,
|
||||||
|
discordName = request.discordName,
|
||||||
|
discordID = request.discordID,
|
||||||
|
attackDetailList = listOf(newAttackDetail.toDto())
|
||||||
|
)
|
||||||
|
val id = battleRecordService.create(newData)
|
||||||
|
call.respond(HttpStatusCode.Created, id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user