Ragequit.
This commit is contained in:
@@ -20,6 +20,11 @@ shadowJar {
|
||||
}
|
||||
}
|
||||
|
||||
task DMkt(type: JavaExec) {
|
||||
classpath = sourceSets.main.runtimeClasspath
|
||||
mainClass = 'database.DatabaseManagerKt'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation 'org.jetbrains.kotlin:kotlin-test'
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.10.0'
|
||||
@@ -28,6 +33,7 @@ dependencies {
|
||||
implementation "io.github.oshai:kotlin-logging-jvm:7.0.3"
|
||||
implementation "org.slf4j:slf4j-api:2.0.13"
|
||||
implementation "ch.qos.logback:logback-classic:1.5.20"
|
||||
implementation "io.fusionauth:fusionauth-jwt:6.0.0"
|
||||
|
||||
// oh my gawd
|
||||
implementation "org.jetbrains.exposed:exposed-core:1.2.0"
|
||||
@@ -38,6 +44,7 @@ dependencies {
|
||||
implementation "com.zaxxer:HikariCP:4.0.3"
|
||||
|
||||
implementation project(':common')
|
||||
implementation "org.jetbrains.kotlin:kotlin-test:2.2.0"
|
||||
}
|
||||
|
||||
kotlin {
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
2026-05-13 20:52:27.910 [main] DEBUG Exposed -
|
||||
DO $$ BEGIN
|
||||
CREATE TYPE weapontype AS ENUM ('hammer', 'shotgun', 'bat');
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN null;
|
||||
END $$;
|
||||
|
||||
2026-05-13 20:52:29.769 [main] DEBUG Exposed - CREATE TABLE IF NOT EXISTS "User" (id uuid PRIMARY KEY, username TEXT NOT NULL, "password" TEXT NOT NULL, email TEXT NOT NULL)
|
||||
2026-05-13 20:52:30.071 [main] DEBUG Exposed - SELECT humanbeing.id, humanbeing."name", humanbeing.coordinates, humanbeing.creation_date, humanbeing.real_hero, humanbeing.has_toothpick, humanbeing.impact_speed, humanbeing.soundtrack_name, humanbeing.minutes_of_waiting, humanbeing.car, humanbeing.weapon_type FROM humanbeing
|
||||
2026-05-13 20:53:16.919 [main] DEBUG Exposed -
|
||||
DO $$ BEGIN
|
||||
CREATE TYPE weapontype AS ENUM ('hammer', 'shotgun', 'bat');
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN null;
|
||||
END $$;
|
||||
|
||||
2026-05-13 20:53:18.805 [main] DEBUG Exposed - SELECT humanbeing.id, humanbeing."name", humanbeing.coordinates, humanbeing.creation_date, humanbeing.real_hero, humanbeing.has_toothpick, humanbeing.impact_speed, humanbeing.soundtrack_name, humanbeing.minutes_of_waiting, humanbeing.car, humanbeing.weapon_type FROM humanbeing
|
||||
@@ -1,4 +1,4 @@
|
||||
import database.Repository
|
||||
import collection.CollectionManager
|
||||
import commands.*
|
||||
import file.FileManager
|
||||
import mu.KotlinLogging
|
||||
@@ -17,7 +17,7 @@ fun main(args: Array<String>) {
|
||||
logger.info{ "[startup] Starting server on port $port with $args args" }
|
||||
|
||||
val fileManager = FileManager(filePath)
|
||||
val manager = Repository()
|
||||
val manager = CollectionManager()
|
||||
val invoker = CommandInvoker()
|
||||
|
||||
// Загружаем коллекцию из файла
|
||||
@@ -29,8 +29,7 @@ fun main(args: Array<String>) {
|
||||
// Сохранение при завершении (Ctrl+C или kill)
|
||||
val server = NetworkManager(port = port, invoker = invoker)
|
||||
Runtime.getRuntime().addShutdownHook(Thread {
|
||||
logger.info{ "Saving collection before exit..." }
|
||||
fileManager.write(manager.getAll())
|
||||
logger.info{ "Exit..." }
|
||||
server.stop()
|
||||
})
|
||||
|
||||
@@ -40,10 +39,6 @@ fun main(args: Array<String>) {
|
||||
logger.info{ "[Server-console] Server-side commands: save, exit" }
|
||||
while (scanner.hasNextLine()) {
|
||||
when (scanner.nextLine().trim().lowercase()) {
|
||||
"save" -> {
|
||||
fileManager.write(manager.getAll())
|
||||
logger.info{ "[Server-console] Collection is saved" }
|
||||
}
|
||||
"exit" -> {
|
||||
logger.info{ "[Server-console] Shutting down..." }
|
||||
exitProcess(0)
|
||||
@@ -58,7 +53,7 @@ fun main(args: Array<String>) {
|
||||
|
||||
fun registerServerCommands(
|
||||
invoker: CommandInvoker,
|
||||
manager: Repository,
|
||||
manager: CollectionManager,
|
||||
fileManager: FileManager
|
||||
) {
|
||||
listOf(
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package auth
|
||||
|
||||
import io.fusionauth.jwt.Signer
|
||||
import io.fusionauth.jwt.Verifier
|
||||
import io.fusionauth.jwt.domain.JWT
|
||||
import io.fusionauth.jwt.hmac.HMACSigner
|
||||
import io.fusionauth.jwt.hmac.HMACVerifier
|
||||
import java.time.ZoneOffset
|
||||
import java.time.ZonedDateTime
|
||||
|
||||
class JWTManager (
|
||||
private val jwtSecret: String = "random",
|
||||
private val issuer: String = "aklivtsov.tech",
|
||||
private val subject: String = "f1e33ab3-027f-47c5-bb07-8dd8ab37a2d3"
|
||||
) {
|
||||
private val signer: Signer = HMACSigner.newSHA256Signer(jwtSecret)
|
||||
private val verifier: Verifier = HMACVerifier.newVerifier(jwtSecret)
|
||||
|
||||
fun createJWT(expiredAfterMinutes: Long): String {
|
||||
val jwt: JWT = JWT()
|
||||
.setIssuer(issuer)
|
||||
.setIssuedAt(ZonedDateTime.now(ZoneOffset.UTC))
|
||||
.setSubject(subject)
|
||||
.setExpiration(ZonedDateTime.now(ZoneOffset.UTC).plusMinutes(expiredAfterMinutes))
|
||||
|
||||
return JWT.getEncoder().encode(jwt, signer)
|
||||
}
|
||||
|
||||
fun validateJWT(jwt: String): Boolean {
|
||||
// check if it validates expired tokens
|
||||
val jwt = JWT.getDecoder().decode(jwt, verifier)
|
||||
return jwt.subject == subject
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package collection
|
||||
|
||||
import models.HumanBeing
|
||||
import mu.KotlinLogging
|
||||
import java.time.LocalDate
|
||||
import java.util.TreeSet
|
||||
import java.util.UUID
|
||||
|
||||
private val logger = KotlinLogging.logger {}
|
||||
|
||||
|
||||
class CollectionManager {
|
||||
|
||||
private val collection: TreeSet<HumanBeing> = TreeSet()
|
||||
val initDate: LocalDate = LocalDate.now()
|
||||
|
||||
fun add(humanBeing: HumanBeing): Boolean {
|
||||
logger.info { "[ADD] Element created ${humanBeing.id}" }
|
||||
return collection.add(humanBeing)
|
||||
}
|
||||
|
||||
fun update(id: UUID, updated: HumanBeing): Boolean {
|
||||
val old = getById(id) ?: return false
|
||||
collection.remove(old)
|
||||
val replaced = updated.copy(id = old.id, creationDate = old.creationDate)
|
||||
logger.info { "[UPDATE] Element updated ${old.id}" }
|
||||
return collection.add(replaced)
|
||||
}
|
||||
|
||||
fun removeById(id: UUID): Boolean {
|
||||
val target = getById(id) ?: return false
|
||||
logger.info { "[REMOVE] Element deleted ${target.id}" }
|
||||
return collection.remove(target)
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
collection.clear()
|
||||
logger.info { "[CLEAR] Collection cleared" }
|
||||
}
|
||||
|
||||
fun getAll(): TreeSet<HumanBeing> = TreeSet(collection)
|
||||
|
||||
fun getById(id: UUID): HumanBeing? =
|
||||
collection.stream()
|
||||
.filter { it.id == id }
|
||||
.findFirst()
|
||||
.orElse(null)
|
||||
|
||||
fun size(): Int = collection.size
|
||||
|
||||
fun isEmpty(): Boolean = collection.isEmpty()
|
||||
|
||||
fun getMax(): HumanBeing? =
|
||||
collection.stream()
|
||||
.max(Comparator.naturalOrder())
|
||||
.orElse(null)
|
||||
|
||||
fun getMin(): HumanBeing? =
|
||||
collection.stream()
|
||||
.min(Comparator.naturalOrder())
|
||||
.orElse(null)
|
||||
|
||||
fun sumOfMinutesOfWaiting(): Double =
|
||||
collection.stream()
|
||||
.mapToDouble { it.minutesOfWaiting.toDouble() }
|
||||
.sum()
|
||||
|
||||
fun minByName(): HumanBeing? =
|
||||
collection.stream()
|
||||
.min(Comparator.comparing { it.name })
|
||||
.orElse(null)
|
||||
|
||||
fun getMinutesOfWaitingDescending(): List<Float> =
|
||||
collection.stream()
|
||||
.map { it.minutesOfWaiting }
|
||||
.sorted(Comparator.reverseOrder())
|
||||
.toList()
|
||||
|
||||
fun loadFromFile(items: List<HumanBeing>) {
|
||||
collection.clear()
|
||||
items.stream().forEach { collection.add(it) }
|
||||
logger.info { "[LOAD] loaded ${items.size} elements" }
|
||||
}
|
||||
|
||||
fun getInfo(): String =
|
||||
"""
|
||||
|Тип коллекции : ${collection::class.simpleName}
|
||||
|Тип элементов : ${HumanBeing::class.simpleName}
|
||||
|Дата инициал. : $initDate
|
||||
|Кол-во элемен.: ${collection.size}
|
||||
""".trimMargin()
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
package commands
|
||||
|
||||
import database.Repository
|
||||
import collection.CollectionManager
|
||||
import kotlinx.serialization.Contextual
|
||||
import kotlinx.serialization.Serializable
|
||||
import models.HumanBeing
|
||||
import network.Response
|
||||
|
||||
@Serializable
|
||||
class AddCommand(@Contextual private val manager: Repository) : Command {
|
||||
class AddCommand(@Contextual private val manager: CollectionManager) : Command {
|
||||
override val name = "add"
|
||||
override val description = "добавить новый элемент в коллекцию"
|
||||
override val args = listOf(CommandArgType.NONE)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package commands
|
||||
|
||||
import database.Repository
|
||||
import collection.CollectionManager
|
||||
import models.HumanBeing
|
||||
import network.Response
|
||||
|
||||
class AddIfMaxCommand(private val manager: Repository) : Command {
|
||||
class AddIfMaxCommand(private val manager: CollectionManager) : Command {
|
||||
override val name = "add_if_max"
|
||||
override val description = "добавить элемент, если он больше максимального"
|
||||
override val type = CommandType.MODEL
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package commands
|
||||
|
||||
import database.Repository
|
||||
import collection.CollectionManager
|
||||
import models.HumanBeing
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.Contextual
|
||||
import network.Response
|
||||
|
||||
@Serializable
|
||||
class AddIfMinCommand(@Contextual private val manager: Repository) : Command {
|
||||
class AddIfMinCommand(@Contextual private val manager: CollectionManager) : Command {
|
||||
override val name = "add_if_min"
|
||||
override val description = "добавить элемент, если он меньше минимального"
|
||||
override val type = CommandType.MODEL
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package commands
|
||||
|
||||
import database.Repository
|
||||
import collection.CollectionManager
|
||||
import kotlinx.serialization.Contextual
|
||||
import kotlinx.serialization.Serializable
|
||||
import models.HumanBeing
|
||||
import network.Response
|
||||
|
||||
@Serializable
|
||||
class ClearCommand(@Contextual private val manager: Repository) : Command {
|
||||
class ClearCommand(@Contextual private val manager: CollectionManager) : Command {
|
||||
override val name = "clear"
|
||||
override val description = "очистить коллекцию"
|
||||
override val args = listOf(CommandArgType.NONE)
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package commands
|
||||
|
||||
import database.Repository
|
||||
import collection.CollectionManager
|
||||
import kotlinx.serialization.Contextual
|
||||
import kotlinx.serialization.Serializable
|
||||
import models.HumanBeing
|
||||
import network.Response
|
||||
|
||||
@Serializable
|
||||
class InfoCommand(@Contextual private val manager: Repository) : Command {
|
||||
class InfoCommand(@Contextual private val manager: CollectionManager) : Command {
|
||||
override val name = "info"
|
||||
override val description = "вывести информацию о коллекции"
|
||||
override val type = CommandType.SIMPLE
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package commands
|
||||
|
||||
import database.Repository
|
||||
import collection.CollectionManager
|
||||
import kotlinx.serialization.Contextual
|
||||
import kotlinx.serialization.Serializable
|
||||
import models.HumanBeing
|
||||
@@ -10,7 +10,7 @@ import network.Response
|
||||
* Выводит любой элемент с минимальным значением поля [HumanBeing.name].
|
||||
*/
|
||||
@Serializable
|
||||
class MinByNameCommand(@Contextual private val manager: Repository) : Command {
|
||||
class MinByNameCommand(@Contextual private val manager: CollectionManager) : Command {
|
||||
override val name = "min_by_name"
|
||||
override val description = "вывести элемент с минимальным именем"
|
||||
override val type = CommandType.SIMPLE
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package commands
|
||||
|
||||
import database.Repository
|
||||
import collection.CollectionManager
|
||||
import kotlinx.serialization.Contextual
|
||||
import kotlinx.serialization.Serializable
|
||||
import models.HumanBeing
|
||||
@@ -10,7 +10,7 @@ import network.Response
|
||||
* Выводит значения поля [models.HumanBeing.minutesOfWaiting] в порядке убывания.
|
||||
*/
|
||||
@Serializable
|
||||
class PrintDescendingMinutesCommand(@Contextual private val manager: Repository) : Command {
|
||||
class PrintDescendingMinutesCommand(@Contextual private val manager: CollectionManager) : Command {
|
||||
override val name = "print_field_descending_minutes_of_waiting"
|
||||
override val description = "вывести minutesOfWaiting в порядке убывания"
|
||||
override val type = CommandType.SIMPLE
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package commands
|
||||
|
||||
import database.Repository
|
||||
import collection.CollectionManager
|
||||
import kotlinx.serialization.Contextual
|
||||
import kotlinx.serialization.Serializable
|
||||
import java.util.UUID
|
||||
@@ -8,7 +8,7 @@ import models.HumanBeing
|
||||
import network.Response
|
||||
|
||||
@Serializable
|
||||
class RemoveByIdCommand(@Contextual private val manager: Repository) : Command {
|
||||
class RemoveByIdCommand(@Contextual private val manager: CollectionManager) : Command {
|
||||
override val name = "remove_by_id"
|
||||
override val description = "удалить элемент по id: remove_by_id <uuid>"
|
||||
override val type = CommandType.MODEL
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
package commands
|
||||
|
||||
import database.Repository
|
||||
import collection.CollectionManager
|
||||
import file.FileManager
|
||||
import kotlinx.serialization.Contextual
|
||||
import kotlinx.serialization.Serializable
|
||||
import models.HumanBeing
|
||||
import network.Response
|
||||
import java.util.UUID
|
||||
|
||||
@Serializable
|
||||
class SaveCommand(
|
||||
@Contextual private val manager: Repository,
|
||||
@Contextual private val manager: CollectionManager,
|
||||
@Contextual private val fileManager: FileManager
|
||||
) : Command {
|
||||
override val name = "save"
|
||||
@@ -18,7 +19,8 @@ class SaveCommand(
|
||||
override val args = listOf(CommandArgType.NONE)
|
||||
|
||||
override fun execute(args: List<String>, humanBeing: HumanBeing?): Response {
|
||||
return if (fileManager.write(manager.getAll())) Response(true, "Коллекция сохранена.")
|
||||
val dummyUser: UUID = UUID.fromString("68db6bf5-65ce-46c7-881d-c85b23254f92")
|
||||
return if (fileManager.write(manager.getAll(), dummyUser)) Response(true, "Коллекция сохранена.")
|
||||
else Response(false, "[Ошибка] Не удалось сохранить коллекцию.")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package commands
|
||||
|
||||
import database.Repository
|
||||
import collection.CollectionManager
|
||||
import kotlinx.serialization.Contextual
|
||||
import kotlinx.serialization.Serializable
|
||||
import models.HumanBeing
|
||||
import network.Response
|
||||
|
||||
@Serializable
|
||||
class ShowCommand(@Contextual private val manager: Repository) : Command {
|
||||
class ShowCommand(@Contextual private val manager: CollectionManager) : Command {
|
||||
override val name = "show"
|
||||
override val description = "вывести все элементы коллекции"
|
||||
override val type = CommandType.SIMPLE
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package commands
|
||||
|
||||
import database.Repository
|
||||
import collection.CollectionManager
|
||||
import kotlinx.serialization.Contextual
|
||||
import kotlinx.serialization.Serializable
|
||||
import models.HumanBeing
|
||||
@@ -10,7 +10,7 @@ import network.Response
|
||||
* Выводит сумму значений поля [models.HumanBeing.minutesOfWaiting].
|
||||
*/
|
||||
@Serializable
|
||||
class SumOfMinutesCommand(@Contextual private val manager: Repository) : Command {
|
||||
class SumOfMinutesCommand(@Contextual private val manager: CollectionManager) : Command {
|
||||
override val name = "sum_of_minutes_of_waiting"
|
||||
override val description = "вывести сумму minutesOfWaiting всех элементов"
|
||||
override val type = CommandType.SIMPLE
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package commands
|
||||
|
||||
import database.Repository
|
||||
import collection.CollectionManager
|
||||
import kotlinx.serialization.Contextual
|
||||
import kotlinx.serialization.Serializable
|
||||
import models.HumanBeing
|
||||
@@ -8,7 +8,7 @@ import network.Response
|
||||
import java.util.UUID
|
||||
|
||||
@Serializable
|
||||
class UpdateCommand(@Contextual private val manager: Repository) : Command {
|
||||
class UpdateCommand(@Contextual private val manager: CollectionManager) : Command {
|
||||
override val name = "update"
|
||||
override val description = "обновить элемент по id: update <uuid>"
|
||||
override val type = CommandType.MODEL
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package database
|
||||
|
||||
import com.zaxxer.hikari.*
|
||||
import database.tables.CarTable
|
||||
import database.tables.CoordinatesTable
|
||||
import database.tables.HumanBeingTable
|
||||
import models.Coordinates
|
||||
import database.tables.UserTable
|
||||
import org.jetbrains.exposed.v1.jdbc.*
|
||||
import org.jetbrains.exposed.v1.jdbc.transactions.transaction
|
||||
|
||||
@@ -24,16 +25,19 @@ class DatabaseManager {
|
||||
Database.connect(dataSource)
|
||||
|
||||
transaction {
|
||||
exec("""
|
||||
exec(
|
||||
"""
|
||||
DO ${'$'}${'$'} BEGIN
|
||||
CREATE TYPE weapontype AS ENUM ('hammer', 'shotgun', 'bat');
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN null;
|
||||
END ${'$'}${'$'};
|
||||
""")
|
||||
"""
|
||||
)
|
||||
SchemaUtils.create(CoordinatesTable)
|
||||
SchemaUtils.create(CarTable)
|
||||
SchemaUtils.create(HumanBeingTable)
|
||||
SchemaUtils.create(UserTable)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,20 +45,19 @@ class DatabaseManager {
|
||||
val smth = mutableListOf<String>()
|
||||
|
||||
transaction {
|
||||
val rows = HumanBeingTable.selectAll().toList()
|
||||
val rows = HumanBeingTable.selectAll()
|
||||
rows.forEach { row ->
|
||||
smth.add(row[HumanBeingTable.name])
|
||||
}
|
||||
}
|
||||
|
||||
return smth
|
||||
}
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val manager = DatabaseManager()
|
||||
print("here we go!")
|
||||
println("here we go!")
|
||||
manager.start()
|
||||
print(manager.test())
|
||||
print("here we don't go!")
|
||||
}
|
||||
println(manager.test())
|
||||
println("here we don't go!")
|
||||
}
|
||||
|
||||
@@ -2,128 +2,58 @@ package database
|
||||
|
||||
import database.tables.CarTable
|
||||
import database.tables.CoordinatesTable
|
||||
import models.HumanBeing
|
||||
import models.Car
|
||||
import database.tables.HumanBeingTable
|
||||
import mu.KotlinLogging
|
||||
import database.tables.UserTable
|
||||
import io.github.oshai.kotlinlogging.KotlinLogging
|
||||
import models.HumanBeing
|
||||
import org.jetbrains.exposed.v1.core.*
|
||||
import org.jetbrains.exposed.v1.jdbc.*
|
||||
import org.jetbrains.exposed.v1.jdbc.transactions.transaction
|
||||
import org.jetbrains.exposed.v1.jdbc.insert
|
||||
import java.time.LocalDate
|
||||
import java.util.TreeSet
|
||||
import java.util.UUID
|
||||
import kotlin.uuid.ExperimentalUuidApi
|
||||
import kotlin.uuid.Uuid
|
||||
|
||||
private val logger = KotlinLogging.logger {}
|
||||
|
||||
class Repository(private val filePath: String) {
|
||||
|
||||
class Repository {
|
||||
//fun read(): List<HumanBeing> {}
|
||||
|
||||
private val collection: TreeSet<HumanBeing> = TreeSet()
|
||||
val initDate: LocalDate = LocalDate.now()
|
||||
|
||||
fun add(humanBeing: HumanBeing): Boolean {
|
||||
var allGood = true
|
||||
@OptIn(ExperimentalUuidApi::class)
|
||||
fun write(items: Collection<HumanBeing>, userId: UUID): Boolean {
|
||||
transaction {
|
||||
try {
|
||||
val cords = CoordinatesTable.insert {
|
||||
it[x] = humanBeing.coordinates.x
|
||||
it[y] = humanBeing.coordinates.y
|
||||
} get CoordinatesTable.id
|
||||
|
||||
val theCar = CarTable.insert {
|
||||
it[cool] = humanBeing.car.cool
|
||||
} get CarTable.id
|
||||
|
||||
HumanBeingTable.insert {
|
||||
it[name] = humanBeing.name
|
||||
it[coordinates] = cords
|
||||
it[creationDate] = humanBeing.creationDate
|
||||
it[realHero] = humanBeing.realHero
|
||||
it[hasToothpick] = humanBeing.hasToothpick
|
||||
it[impactSpeed] = humanBeing.impactSpeed
|
||||
it[soundtrackName] = humanBeing.soundtrackName
|
||||
it[minutesOfWaiting] = humanBeing.minutesOfWaiting
|
||||
it[car] = theCar
|
||||
it[weaponType] = humanBeing.weaponType
|
||||
for (item in items) {
|
||||
val cords = CoordinatesTable.insertAndGetId {
|
||||
it[x] = item.coordinates.x
|
||||
it[y] = item.coordinates.y
|
||||
}
|
||||
|
||||
val cars = CarTable.insertAndGetId {
|
||||
it[cool] = item.car.cool
|
||||
}
|
||||
|
||||
val user = UserTable
|
||||
.select(UserTable.id)
|
||||
.where { UserTable.id eq userId }
|
||||
.first()
|
||||
|
||||
HumanBeingTable.insert {
|
||||
it[owner_id] = userId
|
||||
it[name] = item.name
|
||||
it[id] = user[UserTable.id] // it fucking autoincrements (check perplexity)
|
||||
it[coordinates] = cords
|
||||
it[creationDate] = item.creationDate
|
||||
it[realHero] = item.realHero
|
||||
it[hasToothpick] = item.hasToothpick
|
||||
it[impactSpeed] = item.impactSpeed
|
||||
it[soundtrackName] = item.soundtrackName
|
||||
it[minutesOfWaiting] = item.minutesOfWaiting
|
||||
it[car] = cars
|
||||
it[weaponType] = item.weaponType
|
||||
}
|
||||
|
||||
logger.info { "[ADD] Element created ${humanBeing.id}" }
|
||||
allGood = true
|
||||
} catch (e: Exception) {
|
||||
logger.error(e) { "[ADD] Error during inserting: $e" }
|
||||
allGood = false
|
||||
}
|
||||
}
|
||||
return allGood
|
||||
}
|
||||
|
||||
fun update(id: UUID, updated: HumanBeing): Boolean {
|
||||
val old = getById(id) ?: return false
|
||||
collection.remove(old)
|
||||
val replaced = updated.copy(id = old.id, creationDate = old.creationDate)
|
||||
logger.info { "[UPDATE] Element updated ${old.id}" }
|
||||
return collection.add(replaced)
|
||||
}
|
||||
|
||||
fun removeById(id: UUID): Boolean {
|
||||
val target = getById(id) ?: return false
|
||||
logger.info { "[REMOVE] Element deleted ${target.id}" }
|
||||
return collection.remove(target)
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
collection.clear()
|
||||
logger.info { "[CLEAR] Collection cleared" }
|
||||
}
|
||||
|
||||
fun getAll(): TreeSet<HumanBeing> = TreeSet(collection)
|
||||
|
||||
fun getById(id: UUID): HumanBeing? =
|
||||
collection.stream()
|
||||
.filter { it.id == id }
|
||||
.findFirst()
|
||||
.orElse(null)
|
||||
|
||||
fun size(): Int = collection.size
|
||||
|
||||
fun isEmpty(): Boolean = collection.isEmpty()
|
||||
|
||||
fun getMax(): HumanBeing? =
|
||||
collection.stream()
|
||||
.max(Comparator.naturalOrder())
|
||||
.orElse(null)
|
||||
|
||||
fun getMin(): HumanBeing? =
|
||||
collection.stream()
|
||||
.min(Comparator.naturalOrder())
|
||||
.orElse(null)
|
||||
|
||||
fun sumOfMinutesOfWaiting(): Double =
|
||||
collection.stream()
|
||||
.mapToDouble { it.minutesOfWaiting.toDouble() }
|
||||
.sum()
|
||||
|
||||
fun minByName(): HumanBeing? =
|
||||
collection.stream()
|
||||
.min(Comparator.comparing { it.name })
|
||||
.orElse(null)
|
||||
|
||||
fun getMinutesOfWaitingDescending(): List<Float> =
|
||||
collection.stream()
|
||||
.map { it.minutesOfWaiting }
|
||||
.sorted(Comparator.reverseOrder())
|
||||
.toList()
|
||||
|
||||
fun loadFromFile(items: List<HumanBeing>) {
|
||||
collection.clear()
|
||||
items.stream().forEach { collection.add(it) }
|
||||
logger.info { "[LOAD] loaded ${items.size} elements" }
|
||||
}
|
||||
|
||||
fun getInfo(): String =
|
||||
"""
|
||||
|Тип коллекции : ${collection::class.simpleName}
|
||||
|Тип элементов : ${HumanBeing::class.simpleName}
|
||||
|Дата инициал. : $initDate
|
||||
|Кол-во элемен.: ${collection.size}
|
||||
""".trimMargin()
|
||||
}
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
package database.tables
|
||||
|
||||
import models.WeaponType
|
||||
import org.jetbrains.exposed.v1.core.dao.id.java.UUIDTable
|
||||
import org.jetbrains.exposed.v1.core.Table
|
||||
import org.jetbrains.exposed.v1.javatime.date
|
||||
import org.postgresql.util.PGobject
|
||||
import kotlin.uuid.ExperimentalUuidApi
|
||||
|
||||
|
||||
object HumanBeingTable : UUIDTable("humanBeing") {
|
||||
object HumanBeingTable : Table("humanBeing") {
|
||||
@OptIn(ExperimentalUuidApi::class)
|
||||
val id = uuid("id")
|
||||
val owner_id = reference("owner_id", UserTable.id)
|
||||
val name = text("name")
|
||||
val coordinates = reference("coordinates", CoordinatesTable.id)
|
||||
val creationDate = date("creation_date")
|
||||
@@ -31,4 +35,7 @@ object HumanBeingTable : UUIDTable("humanBeing") {
|
||||
}
|
||||
}
|
||||
).nullable().default(null)
|
||||
|
||||
@OptIn(ExperimentalUuidApi::class)
|
||||
override val primaryKey = PrimaryKey(id)
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package database.tables
|
||||
|
||||
import org.jetbrains.exposed.v1.core.dao.id.java.UUIDTable
|
||||
|
||||
object UserTable: UUIDTable("user") {
|
||||
val username = text("username")
|
||||
val password = text("password") // change
|
||||
val email = text("email") // ask that or username when logging-in
|
||||
}
|
||||
@@ -137,7 +137,7 @@ class FileManager(private val filePath: String) {
|
||||
* @param items коллекция объектов [HumanBeing] для записи
|
||||
* @return true если запись прошла успешно
|
||||
*/
|
||||
fun write(items: Collection<HumanBeing>): Boolean {
|
||||
fun write(items: Collection<HumanBeing>, user: UUID): Boolean {
|
||||
val file = File(filePath)
|
||||
|
||||
if (file.exists() && !file.canWrite()) {
|
||||
|
||||
Reference in New Issue
Block a user