Merge remote-tracking branch 'origin/master' into pairing_theo

This commit is contained in:
Theo Barollet
2023-06-13 18:15:44 +02:00
113 changed files with 87150 additions and 594 deletions

View File

@@ -16,10 +16,6 @@
<description>PairGoth pairing system</description>
<url>TODO</url>
<properties>
<kotlin.version>1.8.21</kotlin.version>
<kotlin.code.style>official</kotlin.code.style>
<kotlin.compiler.jvmTarget>10</kotlin.compiler.jvmTarget>
<kotlin.compiler.incremental>true</kotlin.compiler.incremental>
<pac4j.version>5.7.1</pac4j.version>
</properties>
<build>
@@ -30,7 +26,6 @@
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
@@ -48,33 +43,6 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-resources</id>
<phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/${project.build.finalName}/WEB-INF</outputDirectory>
<resources>
<resource>
<directory>${basedir}/..</directory>
<include>pairgoth.properties</include>
<!-- <filtering>true</filtering> -->
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
@@ -84,6 +52,20 @@
</classpathDependencyExcludes>
</configuration>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>${jetty.version}</version>
<configuration>
<scan>0</scan>
<httpConnector>
<port>8085</port>
</httpConnector>
<webApp>
<contextPath>/api/</contextPath>
</webApp>
</configuration>
</plugin>
</plugins>
</build>
<dependencyManagement>
@@ -161,13 +143,6 @@
<version>${slf4j.version}</version>
<scope>test</scope>
</dependency>
<!--
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
-->
<dependency>
<groupId>com.diogonunes</groupId>
<artifactId>JColor</artifactId>

View File

@@ -1,6 +1,7 @@
package org.jeudego.pairgoth.api
import com.republicate.kson.Json
import com.republicate.kson.toJsonObject
import org.jeudego.pairgoth.api.ApiHandler.Companion.PAYLOAD_KEY
import org.jeudego.pairgoth.api.ApiHandler.Companion.badRequest
import org.jeudego.pairgoth.ext.OpenGotha
@@ -21,7 +22,7 @@ object TournamentHandler: PairgothApiHandler {
override fun get(request: HttpServletRequest, response: HttpServletResponse): Json? {
val accept = request.getHeader("Accept")
return when (val id = getSelector(request)?.toIntOrNull()) {
null -> Json.Array(Store.getTournamentsIDs())
null -> Store.getTournaments().toJsonObject()
else ->
when {
ApiServlet.isJson(accept) -> Store.getTournament(id)?.toJson() ?: badRequest("no tournament with id #${id}")

View File

@@ -1,11 +1,8 @@
package org.jeudego.pairgoth.model
import com.republicate.kson.Json
import com.republicate.kson.toJsonArray
import org.jeudego.pairgoth.api.ApiHandler
import org.jeudego.pairgoth.api.ApiHandler.Companion.badRequest
import org.jeudego.pairgoth.store.Store
import kotlin.math.roundToInt
// Pairable

View File

@@ -22,7 +22,7 @@ private fun Tournament<*>.filename() = "${id.toString().padStart(LEFT_PAD, '0')}
class FileStore(pathStr: String): StoreImplementation {
companion object {
private val filenameRegex = Regex("^(\\d+)-.*\\.tour$")
private val filenameRegex = Regex("^(\\d+)-(.*)\\.tour$")
private val timestampFormat: DateFormat = SimpleDateFormat("yyyyMMddHHmmss")
private val timestamp: String get() = timestampFormat.format(Date())
}
@@ -33,14 +33,15 @@ class FileStore(pathStr: String): StoreImplementation {
}
init {
_nextTournamentId.set(getTournamentsIDs().maxOrNull() ?: 0.toID())
_nextTournamentId.set(getTournaments().keys.maxOrNull() ?: 0.toID())
}
override fun getTournamentsIDs(): Set<ID> {
override fun getTournaments(): Map<ID, String> {
return path.useDirectoryEntries("*.tour") { entries ->
entries.mapNotNull { entry ->
filenameRegex.matchEntire(entry.fileName.toString())?.groupValues?.get(1)?.toID()
}.toSet()
val match = filenameRegex.matchEntire(entry.fileName.toString())
match?.let { Pair(it.groupValues[1].toID(), it.groupValues[2]) }
}.sortedBy { it.first }.toMap()
}
}

View File

@@ -6,7 +6,7 @@ import org.jeudego.pairgoth.model.Tournament
class MemoryStore: StoreImplementation {
private val tournaments = mutableMapOf<ID, Tournament<*>>()
override fun getTournamentsIDs(): Set<ID> = tournaments.keys
override fun getTournaments(): Map<ID, String> = tournaments.mapValues { it.value.shortName }
override fun addTournament(tournament: Tournament<*>) {
if (tournaments.containsKey(tournament.id)) throw Error("tournament id #${tournament.id} already exists")

View File

@@ -14,7 +14,7 @@ interface StoreImplementation {
val nextPlayerId get() = _nextPlayerId.incrementAndGet()
val nextGameId get() = _nextGameId.incrementAndGet()
fun getTournamentsIDs(): Set<ID>
fun getTournaments(): Map<ID, String>
fun addTournament(tournament: Tournament<*>)
fun getTournament(id: ID): Tournament<*>?
fun replaceTournament(tournament: Tournament<*>)

View File

@@ -170,7 +170,7 @@ class ApiServlet : HttpServlet() {
}
// check charset
if (charset != null && EXPECTED_CHARSET != charset) throw ApiException(
if (charset != null && EXPECTED_CHARSET != charset.lowercase(Locale.ROOT).replace("-", "")) throw ApiException(
HttpServletResponse.SC_BAD_REQUEST,
"UTF-8 content expected"
)
@@ -215,6 +215,8 @@ class ApiServlet : HttpServlet() {
HttpServletResponse.SC_BAD_REQUEST,
"Missing 'Accept' header"
)
// CB TODO 1) a reference to a specific API call at this point is a code smell.
// 2) there will e other content types: .tou, .h9, .html
if (!isJson(accept) && (!isXml(accept) || !request.requestURI.matches(Regex("/api/tour/\\d+")))) throw ApiException(
HttpServletResponse.SC_BAD_REQUEST,
"Invalid 'Accept' header"

View File

@@ -51,7 +51,7 @@ class WebappManager : ServletContextListener, ServletContextAttributeListener, H
/* ServletContextListener interface */
override fun contextInitialized(sce: ServletContextEvent) {
context = sce.servletContext
logger.info("---------- Starting Web Application ----------")
logger.info("---------- Starting Pairgoth Server ----------")
context.setAttribute("manager", this)
webappRoot = context.getRealPath("/")
try {