Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,25 @@
# TrialORE

ORE's trial management plugin
ORE's trial management and test plugin

## Test Command Usage

| Command | Alias | Permission | Description |
|-------------------------|---------------|---------------|-------------------------------------------|
| `/test start` | `/starttest` | trialore.test | Start a test |
| `/test history` | | trialore.test | Shows your test history |
| `/test list [user]` | | trialore.list | Lists the passed tests of an individual |
| `/test stop ` | `/stoptest` | trialore.test | Stop your current test run |
| `/test info [id]` | | trialore.list | Show all info of a test with the given ID |
| `/test check [user]` | `/check` | trialore.list | Check if a user passed the test |
| `/test answer [answer]` | `/testanswer` | trialore.test | Answer a question of the test |

## Doing a test
1. Start the test using `/test start`.
2. Once you get asked a question run `/test answer [answer]`. \
The answer should be the answer you think is correct without any prefix. For example it should not be `0b1111` but `1111`.
3. After you finished the test and passed you get a test-id. Paste it in your App. \
Staff are going to use this to verify your test.

## Full Command Usage

Expand Down Expand Up @@ -33,4 +52,4 @@ This "abandonment" period defaults to 5 minutes.
If a Testificate leaves, they will be demoted to Student and given 5 minutes to rejoin.
If they do not rejoin within those 5 minutes, the trial ends.
If a trialer leaves, the trial will automatically end in 5 minutes if they do not rejoin, demoting the Testificate to Student.
The only distinction of an abandoned trial is if the trial ends with an automated abandonment note.
The only distinction of an abandoned trial is if the trial ends with an automated abandonment note.
11 changes: 6 additions & 5 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,16 @@ java {
tasks.shadowJar {
relocate("co.aikar.commands", "trialore.acf")
relocate("co.aikar.locales", "trialore.locales")

relocate("com.fasterxml.jackson", "org.openredstone.lib.jackson")
dependencies {
exclude(
dependency(
"net.luckperms:api:.*"
)
)
exclude(dependency("net.luckperms:api:.*"))
exclude(dependency("io.papermc.paper:paper-api:.*"))
}
archiveClassifier.set("")
}


tasks.build {
dependsOn(tasks.shadowJar)
}
76 changes: 71 additions & 5 deletions src/main/kotlin/org/openredstone/trialore/Storage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package org.openredstone.trialore

import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.selectAll
import org.jetbrains.exposed.sql.transactions.transaction
import java.util.*

Expand All @@ -24,6 +25,16 @@ object Trial : Table("trial") {
override val primaryKey = PrimaryKey(id)
}

object Test : Table("test") {
val id = integer("id").autoIncrement()
val testificate = varchar("testificate", 36).index()
val start = integer("start")
val end = integer("end").nullable()
val passed = bool("passed")
val wrong = integer("wrong")
override val primaryKey = PrimaryKey(id)
}

object UsernameCache : Table("username_cache") {
val uuid = varchar("cache_user", 36).uniqueIndex()
val username = varchar("cache_username", 16).index()
Expand All @@ -41,6 +52,15 @@ data class TrialInfo(
val attempt: Int = 0
)

data class TestInfo(
val testificate: UUID,
val start: Int,
val end: Int,
val passed: Boolean,
val wrong: Int,
val attempt: Int = 0
)

fun now() = System.currentTimeMillis().floorDiv(1000).toInt()

class Storage(
Expand All @@ -55,8 +75,8 @@ class Storage(
}

private fun initTables() = transaction(database) {
SchemaUtils.create(
Note, Trial, UsernameCache
SchemaUtils.createMissingTablesAndColumns(
Note, Trial, UsernameCache, Test
)
}

Expand All @@ -76,14 +96,32 @@ class Storage(
}
}

fun endTest(testificate: UUID, startingtime: Int, passed: Boolean, wrong: Int) = transaction(database) {
Test.insert {
it[Test.testificate] = testificate.toString()
it[start] = startingtime
it[Test.passed] = passed
it[Test.wrong] = wrong
it[end] = now()
}[Test.id]
}

fun getTrials(testificate: UUID): List<Int> = transaction(database) {
Trial.selectAll().where {
Trial.testificate eq testificate.toString()
}.map {
Query(
Trial, Trial.testificate eq testificate.toString()
).map {
it[Trial.id]
}
}

fun getTests(testificate: UUID): List<Int> = transaction(database) {
Query(
Test, Test.testificate eq testificate.toString()
).map {
it[Test.id]
}
}

fun getTrialInfo(trialId: Int): TrialInfo = transaction(database) {
val notes = Note.selectAll().where {
Note.trial_id eq trialId
Expand All @@ -102,12 +140,29 @@ class Storage(
)
}

fun getTestInfo(testId: Int): TestInfo? = transaction(database) {
val resultRow = Test.selectAll().where { Test.id eq testId }.firstOrNull() ?: return@transaction null
TestInfo(
UUID.fromString(resultRow[Test.testificate]),
resultRow[Test.start],
resultRow[Test.end] ?: 0,
resultRow[Test.passed],
resultRow[Test.wrong]
)
}

fun getTrialCount(testificate: UUID): Int = transaction(database) {
Trial.selectAll().where {
Trial.testificate eq testificate.toString()
}.count().toInt()
}

fun getTestCount(testificate: UUID): Int = transaction(database) {
Test.selectAll().where {
Test.testificate eq testificate.toString()
}.count().toInt()
}

fun insertNote(trialId: Int, note: String) = transaction(database) {
Note.insert {
it[trial_id] = trialId
Expand All @@ -133,6 +188,17 @@ class Storage(
}
}

fun didPass(testificate: UUID) : Boolean {
val tests = getTests(testificate)
tests.forEachIndexed { index, testid ->
val testInfo = getTestInfo(testid)
if (testInfo?.passed ?: false) {
return true
}
}
return false
}

fun ensureCachedUsername(user: UUID, username: String) = transaction(database) {
UsernameCache.upsert {
it[this.uuid] = user.toString()
Expand Down
Loading