summaryrefslogtreewikicommitdiff
path: root/core/src/db/Database.kt
blob: 50ee4a4ad8072559a8ee0c8302a1111a8a5a7cb6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
package cat.freya.khs.db

import cat.freya.khs.Khs
import java.util.UUID
import org.jetbrains.exposed.v1.core.*
import org.jetbrains.exposed.v1.jdbc.*
import org.jetbrains.exposed.v1.jdbc.Database as Exposed
import org.jetbrains.exposed.v1.jdbc.transactions.transaction

class Database(plugin: Khs) {
    val driver = getDriver(plugin)
    val source = driver.connect()
    val db = Exposed.connect(source)

    init {
        transaction(db) { SchemaUtils.create(Players) }
        migrateLegacy()
    }

    fun getPlayer(uuid: UUID): Player? =
        transaction(db) {
            val id = uuid.toString()
            Players.selectAll().where { Players.uuid eq id }.map { it.toPlayer() }.singleOrNull()
        }

    fun getPlayer(name: String): Player? =
        transaction(db) {
            Players.selectAll().where { Players.name eq name }.map { it.toPlayer() }.singleOrNull()
        }

    fun getPlayers(page: UInt, pageSize: UInt): List<Player> =
        transaction(db) {
            val offset = page * pageSize
            val wins = Players.hiderWins + Players.seekerWins
            Players.selectAll()
                .orderBy(wins to SortOrder.DESC)
                .limit(pageSize.toInt())
                .offset(offset.toLong())
                .map { it.toPlayer() }
        }

    fun getPlayerNames(limit: UInt, startsWith: String): List<String> =
        transaction(db) {
            Players.select(Players.name)
                .where { Players.name like "$startsWith%" }
                .orderBy(Players.name to SortOrder.ASC)
                .limit(limit.toInt())
                .map { it[Players.name] }
                .filterNotNull()
        }

    fun upsertPlayer(player: Player) =
        transaction(db) {
            val id = player.uuid.toString()
            val exists = Players.selectAll().where { Players.uuid eq id }.any()

            if (exists) {
                Players.update({ Players.uuid eq id }) { it.fromPlayer(player) }
            } else {
                Players.insert {
                    it[uuid] = id
                    it.fromPlayer(player)
                }
            }
        }

    fun upsertName(u: UUID, n: String) =
        transaction(db) {
            val id = u.toString()

            val current =
                Players.selectAll()
                    .where { Players.uuid eq id }
                    .map { it.toPlayer() }
                    .singleOrNull()

            if (current == null) {
                Players.insert {
                    it[uuid] = id
                    it[name] = n
                }
                return@transaction
            }

            Players.update({ Players.uuid eq id }) { it[name] = n }
        }

    fun migrateLegacy() =
        transaction(db) {
            if (!LegacyPlayers.exists() || !LegacyNames.exists()) return@transaction

            val legacy =
                LegacyPlayers.join(
                        LegacyNames,
                        JoinType.FULL,
                        onColumn = LegacyPlayers.uuid,
                        otherColumn = LegacyNames.uuid,
                    )
                    .selectAll()
                    .map { it.toLegacyPlayer() }
            Players.insertIgnore { legacy.forEach { player -> it.fromPlayer(player) } }

            SchemaUtils.drop(LegacyPlayers)
            SchemaUtils.drop(LegacyNames)
        }
}