實作CRUD

This commit is contained in:
Raymond Yang 2023-06-26 13:52:28 +08:00
parent f288fb7c4b
commit 3e92de1609
13 changed files with 446 additions and 7 deletions

View File

@ -0,0 +1,40 @@
package com.ray650128.pcredive.database.dto
import com.ray650128.pcredive.database.model.Member
import kotlinx.serialization.Serializable
@Serializable
data class MemberDto(
var _id: String? = null,
var playerName: String,
var nickName: String,
var discordID: String,
var uid: String,
var leave: Boolean = false,
var createAt: Long? = null,
var updatedAt: Long? = null
)
fun Member.toDto(): MemberDto {
return MemberDto(
_id = this._id.toString(),
playerName = this.playerName,
nickName = this.nickName,
discordID = this.discordID,
uid = this.uid,
leave = this.leave,
createAt = this.createAt,
updatedAt = this.updatedAt
)
}
fun MemberDto.toMember(): Member =
Member(
playerName = this.playerName,
nickName = this.nickName,
discordID = this.discordID,
uid = this.uid,
leave = this.leave,
createAt = this.createAt,
updatedAt = this.updatedAt
)

View File

@ -0,0 +1,49 @@
package com.ray650128.pcredive.database.dto
import com.ray650128.pcredive.database.model.Member
import com.ray650128.pcredive.database.model.MemberRecord
import com.ray650128.pcredive.database.model.Record
import com.ray650128.pcredive.database.service.MemberService
import kotlinx.serialization.Serializable
@Serializable
data class MemberRecordDto(
var _id: String? = null,
var member: Member? = null,
var record1: Record,
var record1c: Record,
var record2: Record,
var record2c: Record,
var record3: Record,
var record3c: Record,
var createdAt: Long?,
var updatedAt: Long?
)
fun MemberRecord.toDto(): MemberRecordDto {
return MemberRecordDto(
_id = this._id.toString(),
member = MemberService.findById(this.memberId.toString()),
record1 = this.record1,
record1c = this.record1c,
record2 = this.record2,
record2c = this.record2c,
record3 = this.record3,
record3c = this.record3c,
createdAt = this.createdAt,
updatedAt = this.updatedAt
)
}
fun MemberRecordDto.toMemberRecord(): MemberRecord =
MemberRecord(
memberId = this.member?._id,
record1 = this.record1,
record1c = this.record1c,
record2 = this.record2,
record2c = this.record2c,
record3 = this.record3,
record3c = this.record3c,
createdAt = this.createdAt,
updatedAt = this.updatedAt
)

View File

@ -0,0 +1,18 @@
package com.ray650128.pcredive.database.model
import kotlinx.serialization.Contextual
import kotlinx.serialization.Serializable
import org.litote.kmongo.Id
import org.litote.kmongo.newId
@Serializable
data class Member(
@Contextual var _id: Id<Member> = newId(),
var playerName: String,
var nickName: String,
var discordID: String,
var uid: String,
var leave: Boolean = false,
var createAt: Long? = null,
var updatedAt: Long? = null
)

View File

@ -0,0 +1,26 @@
package com.ray650128.pcredive.database.model
import kotlinx.serialization.Contextual
import kotlinx.serialization.Serializable
import org.litote.kmongo.Id
import org.litote.kmongo.newId
@Serializable
data class MemberRecord(
@Contextual var _id: Id<MemberRecord> = newId(),
@Contextual var memberId: Id<Member>? = null,
var record1: Record = Record("未出"),
var record1c: Record = Record("未出"),
var record2: Record = Record("未出"),
var record2c: Record = Record("未出"),
var record3: Record = Record("未出"),
var record3c: Record = Record("未出"),
var createdAt: Long? = null,
var updatedAt: Long? = null
)
@Serializable
data class Record(
var boss: String,
var damage: Int? = null
)

View File

@ -0,0 +1,9 @@
package com.ray650128.pcredive.database.model
import kotlinx.serialization.Serializable
@Serializable
data class RecordData(
val member: Member,
var record: MemberRecord
)

View File

@ -0,0 +1,16 @@
package com.ray650128.pcredive.database.model
import kotlinx.serialization.Serializable
@Serializable
data class UpdateMemberRecord(
var memberId: String,
var record1: Record = Record("未出"),
var record1c: Record = Record("未出"),
var record2: Record = Record("未出"),
var record2c: Record = Record("未出"),
var record3: Record = Record("未出"),
var record3c: Record = Record("未出"),
var createdAt: Long? = null,
var updatedAt: Long? = null
)

View File

@ -0,0 +1,53 @@
package com.ray650128.pcredive.database.service
import com.ray650128.pcredive.database.model.Member
import com.ray650128.pcredive.database.model.MemberRecord
import org.bson.types.ObjectId
import org.litote.kmongo.*
import org.litote.kmongo.id.toId
object MemberRecordService {
private val client = KMongo.createClient("mongodb://ray650128:Zx650128!@www.ray650128.com:27017")
private val database = client.getDatabase("pc_re_dive_clan_battle")
private val recordCollection = database.getCollection<MemberRecord>()
fun create(record: MemberRecord): Id<MemberRecord> {
recordCollection.insertOne(record)
return record._id
}
fun findById(id: String): MemberRecord? {
val bsonId: Id<MemberRecord> = ObjectId(id).toId()
return recordCollection.findOne(MemberRecord::_id eq bsonId)
}
fun findByTimeBetween(start: Long, end: Long): List<MemberRecord> {
return recordCollection.find(MemberRecord::createdAt gte start, MemberRecord::createdAt lt end).toList()
}
fun findByOwnerId(id: String): List<MemberRecord> {
val bsonId: Id<Member> = ObjectId(id).toId()
return recordCollection.find(MemberRecord::memberId eq bsonId).toList()
}
fun updateById(id: String, request: MemberRecord): Boolean =
findById(id)?.let { record ->
val updateResult = recordCollection.replaceOne(
record.copy(
record1 = request.record1,
record1c = request.record1c,
record2 = request.record2,
record2c = request.record2c,
record3 = request.record3,
record3c = request.record3c,
updatedAt = System.currentTimeMillis()
)
)
updateResult.modifiedCount == 1L
} ?: false
fun deleteById(id: String): Boolean {
val deleteResult = recordCollection.deleteOneById(ObjectId(id))
return deleteResult.deletedCount == 1L
}
}

View File

@ -0,0 +1,52 @@
package com.ray650128.pcredive.database.service
import com.ray650128.pcredive.database.model.Member
import org.bson.types.ObjectId
import org.litote.kmongo.*
import org.litote.kmongo.id.toId
object MemberService {
private val client = KMongo.createClient("mongodb://ray650128:Zx650128!@www.ray650128.com:27017")
private val database = client.getDatabase("pc_re_dive_clan_battle")
private val memberCollection = database.getCollection<Member>()
fun create(member: Member): Id<Member> {
memberCollection.insertOne(member)
return member._id
}
//fun findAll(): List<Member> = memberCollection.find().toList()
fun findAll(isLeave: Boolean? = null): List<Member> {
return if (isLeave == null) {
memberCollection.find().toList()
} else {
memberCollection.find(Member::leave eq isLeave).toList()
}
}
fun findById(id: String): Member? {
val bsonId: Id<Member> = ObjectId(id).toId()
return memberCollection.findOne(Member::_id eq bsonId)
}
fun updateById(id: String, request: Member): Boolean =
findById(id)?.let { member ->
val updateResult = memberCollection.replaceOne(
member.copy(
playerName = request.playerName,
nickName = request.nickName,
discordID = request.discordID,
uid = request.uid,
leave = request.leave,
updatedAt = request.updatedAt
)
)
updateResult.modifiedCount == 1L
} ?: false
fun deleteById(id: String): Boolean {
val deleteResult = memberCollection.deleteOneById(ObjectId(id))
return deleteResult.deletedCount == 1L
}
}

View File

@ -1,15 +1,119 @@
package com.ray650128.pcredive.plugins
import com.ray650128.pcredive.database.dto.toDto
import com.ray650128.pcredive.database.model.MemberRecord
import com.ray650128.pcredive.database.model.Record
import com.ray650128.pcredive.database.model.RecordData
import com.ray650128.pcredive.database.model.UpdateMemberRecord
import com.ray650128.pcredive.database.service.MemberRecordService
import com.ray650128.pcredive.database.service.MemberService
import io.ktor.http.*
import io.ktor.serialization.kotlinx.json.*
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.server.response.*
import io.ktor.server.application.*
import io.ktor.server.request.*
import io.ktor.server.routing.*
import io.ktor.server.util.*
import kotlinx.coroutines.coroutineScope
import org.litote.kmongo.toId
import java.util.*
fun Application.configureMemberRecordRouting() {
routing {
get("/json/kotlinx-serialization") {
call.respond(mapOf("hello" to "world"))
route("/api") {
route("/record") {
get {
val calendar = Calendar.getInstance().apply {
timeInMillis = System.currentTimeMillis() - (5 * 60 * 60 * 1000) // 由於公連換日為每日早上5:00因此減去時差
}
val records = getData(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH))
call.respond(HttpStatusCode.OK, records)
}
post("/{id}") {
val id = call.parameters.getOrFail<String>("id")
val record = call.receive<MemberRecord>()
val member = MemberService.findById(id) ?: run {
call.respond(HttpStatusCode.NotFound)
return@post
}
record.apply {
memberId = member._id
createdAt = System.currentTimeMillis()
updatedAt = System.currentTimeMillis()
}
MemberRecordService.create(record).let {
call.respond(HttpStatusCode.OK, record)
}
}
get("/{year}/{month}/{day}") {
val year = call.parameters.getOrFail<Int>("year").toInt()
val month = call.parameters.getOrFail<Int>("month").toInt() - 1
val day = call.parameters.getOrFail<Int>("day").toInt()
val records = getData(year, month, day)
call.respond(HttpStatusCode.OK, records)
}
get("/{id}") {
// Show an article with a specific id
val id = call.parameters.getOrFail<String>("id")
val record = MemberRecordService.findById(id)?.toDto() ?: run {
call.respond(HttpStatusCode.NotFound)
return@get
}
call.respond(HttpStatusCode.OK, record)
}
put("/{id}") {
val id = call.parameters.getOrFail<String>("id")
val record = call.receive<UpdateMemberRecord>()
val oldData = MemberRecordService.findById(id) ?: run {
call.respond(HttpStatusCode.NotFound)
return@put
}
oldData.apply {
record1 = record.record1
record1c = record.record1c
record2 = record.record2
record2c = record.record2c
record3 = record.record3
record3c = record.record3c
createdAt = System.currentTimeMillis()
updatedAt = System.currentTimeMillis()
}
MemberRecordService.updateById(id, oldData)
call.respond(HttpStatusCode.OK, record)
}
}
}
}
}
fun getData(year: Int, month: Int, day: Int): List<RecordData> {
val calendar = Calendar.getInstance().apply {
set(Calendar.YEAR, year)
set(Calendar.MONTH, month)
set(Calendar.DAY_OF_MONTH, day)
}
val startTime = calendar.apply {
set(Calendar.HOUR_OF_DAY, 5)
set(Calendar.MINUTE, 0)
set(Calendar.SECOND, 0)
set(Calendar.MILLISECOND, 0)
}.timeInMillis
val endTime = startTime + 86399000L
// Show a list of articles
val records = ArrayList<RecordData>()
val memberList = MemberService.findAll()
memberList.forEach { member ->
records.add(
RecordData(member = member, MemberRecord())
)
}
val recordList = MemberRecordService.findByTimeBetween(startTime, endTime)
recordList.forEach { record ->
val player = MemberService.findById(record.memberId.toString())
records.firstOrNull { it.member == player }?.let { playerRecord ->
playerRecord.record = record
}
}
return records
}

View File

@ -1,15 +1,80 @@
package com.ray650128.pcredive.plugins
import com.ray650128.pcredive.database.dto.toDto
import com.ray650128.pcredive.database.model.Member
import com.ray650128.pcredive.database.service.MemberService
import io.ktor.http.*
import io.ktor.serialization.kotlinx.json.*
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.server.response.*
import io.ktor.server.application.*
import io.ktor.server.request.*
import io.ktor.server.routing.*
import io.ktor.server.util.*
import kotlinx.coroutines.coroutineScope
fun Application.configureMemberRouting() {
routing {
get("/json/kotlinx-serialization") {
call.respond(mapOf("hello" to "world"))
route("/api") {
route("/member") {
get("/all") {
// 顯示所有登錄的成員資料
coroutineScope {
val memberList = MemberService.findAll()
call.respond(HttpStatusCode.OK, memberList)
}
}
get("/{id}") {
val id = call.parameters.getOrFail<String>("id")
val member = MemberService.findById(id) ?: run {
call.respond(HttpStatusCode.NotFound)
return@get
}
call.respond(HttpStatusCode.OK, member)
}
post("/new") {
// Save an article
val formParameters = call.receiveParameters()
val _playerName = formParameters.getOrFail("playerName")
val _nickName = formParameters.getOrFail("nickName")
val _discordID = formParameters.getOrFail("discordID")
val _uid = formParameters.getOrFail("uid")
val _createAt = System.currentTimeMillis()
val member = Member(
playerName = _playerName,
nickName = _nickName,
discordID = _discordID,
uid = _uid,
createAt = _createAt,
)
MemberService.create(member).let { memberId ->
call.respond(HttpStatusCode.OK, member)
}
}
put("/{id}") {
val id = call.parameters.getOrFail<String>("id")
val formParameters = call.receiveParameters()
coroutineScope {
val _playerName = formParameters.getOrFail("playerName")
val _nickName = formParameters.getOrFail("nickName")
val _discordID = formParameters.getOrFail("discordID")
val _uid = formParameters.getOrFail("uid")
val _leave = (formParameters.getOrFail("leave") == "2")
val _updatedAt = System.currentTimeMillis()
val member = Member(
playerName = _playerName,
nickName = _nickName,
discordID = _discordID,
uid = _uid,
leave = _leave,
updatedAt = _updatedAt,
)
MemberService.updateById(id, member)
call.respondRedirect("/memberList/$id")
}
}
}
}
}
}

View File

@ -5,9 +5,13 @@ import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.server.response.*
import io.ktor.server.application.*
import io.ktor.server.routing.*
import kotlinx.serialization.json.Json
import org.litote.kmongo.id.serialization.IdKotlinXSerializationModule
fun Application.configureSerialization() {
install(ContentNegotiation) {
json()
json(
Json { serializersModule = IdKotlinXSerializationModule }
)
}
}

View File

@ -1,6 +1,6 @@
ktor {
deployment {
port = 8080
port = 10001
port = ${?PORT}
}
application {

View File

@ -11,7 +11,10 @@ class ApplicationTest {
@Test
fun testRoot() = testApplication {
application {
configureRouting()
configureHTTP()
configureSerialization()
configureMemberRouting()
configureMemberRecordRouting()
}
client.get("/").apply {
assertEquals(HttpStatusCode.OK, status)