Fix country import; fix layout; bump to 0.3

This commit is contained in:
Claude Brisson
2024-02-21 23:19:52 +01:00
parent 999221de9d
commit 816ef24136
19 changed files with 44 additions and 30 deletions

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.jeudego.pairgoth</groupId>
<artifactId>engine-parent</artifactId>
<version>0.2</version>
<version>0.3</version>
</parent>
<artifactId>api-webapp</artifactId>

View File

@@ -124,7 +124,7 @@ object OpenGotha {
shortName = genParams.shortName,
startDate = genParams.beginDate.toLocalDate(),
endDate = genParams.endDate.toLocalDate(),
country = "FR", // no country in opengotha format
country = "fr", // no country in opengotha format
location = genParams.location,
online = genParams.isBInternet ?: false,
timeSystem = when (genParams.complementaryTimeSystem) {

View File

@@ -21,9 +21,10 @@ import kotlin.io.path.useDirectoryEntries
private const val LEFT_PAD = 6 // left padding of IDs with '0' in filename
private fun Tournament<*>.filename() = "${id.toString().padStart(LEFT_PAD, '0')}-${shortName}.tour"
class FileStore(pathStr: String): StoreImplementation {
class FileStore(pathStr: String): IStore {
companion object {
private val filenameRegex = Regex("^(\\d+)-(.*)\\.tour$")
private val displayFormat: DateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
private val timestampFormat: DateFormat = SimpleDateFormat("yyyyMMddHHmmss")
private val timestamp: String get() = timestampFormat.format(Date())
}
@@ -37,11 +38,17 @@ class FileStore(pathStr: String): StoreImplementation {
_nextTournamentId.set(getTournaments().keys.maxOrNull() ?: 0.toID())
}
override fun getTournaments(): Map<ID, String> {
private fun lastModified(path: Path) = displayFormat.format(Date(path.toFile().lastModified()))
override fun getTournaments(): Map<ID, Map<String, String>> {
return path.useDirectoryEntries("*.tour") { entries ->
entries.mapNotNull { entry ->
val match = filenameRegex.matchEntire(entry.fileName.toString())
match?.let { Pair(it.groupValues[1].toID(), it.groupValues[2]) }
match?.let { Pair(it.groupValues[1].toID(), mapOf(
"name" to it.groupValues[2],
"lastModified" to lastModified(entry))
) }
}.sortedBy { it.first }.toMap()
}
}

View File

@@ -8,13 +8,13 @@ internal val _nextTournamentId = AtomicInteger()
internal val _nextPlayerId = AtomicInteger()
internal val _nextGameId = AtomicInteger()
interface StoreImplementation {
interface IStore {
val nextTournamentId get() = _nextTournamentId.incrementAndGet()
val nextPlayerId get() = _nextPlayerId.incrementAndGet()
val nextGameId get() = _nextGameId.incrementAndGet()
fun getTournaments(): Map<ID, String>
fun getTournaments(): Map<ID, Map<String, String>>
fun addTournament(tournament: Tournament<*>)
fun getTournament(id: ID): Tournament<*>?
fun replaceTournament(tournament: Tournament<*>)

View File

@@ -3,10 +3,12 @@ package org.jeudego.pairgoth.store
import org.jeudego.pairgoth.model.ID
import org.jeudego.pairgoth.model.Tournament
class MemoryStore: StoreImplementation {
class MemoryStore: IStore {
private val tournaments = mutableMapOf<ID, Tournament<*>>()
override fun getTournaments(): Map<ID, String> = tournaments.mapValues { it.value.shortName }
override fun getTournaments(): Map<ID, Map<String, String>> = tournaments.mapValues {
mapOf("name" to it.value.shortName)
}
override fun addTournament(tournament: Tournament<*>) {
if (tournaments.containsKey(tournament.id)) throw Error("tournament id #${tournament.id} already exists")

View File

@@ -1,11 +1,8 @@
package org.jeudego.pairgoth.store
import org.jeudego.pairgoth.model.ID
import org.jeudego.pairgoth.model.Tournament
import org.jeudego.pairgoth.server.WebappManager
import java.util.concurrent.atomic.AtomicInteger
private fun createStoreImplementation(): StoreImplementation {
private fun createStoreImplementation(): IStore {
return when (val storeProperty = WebappManager.getProperty("store") ?: "memory") {
"memory" -> MemoryStore()
"file" -> {
@@ -16,4 +13,4 @@ private fun createStoreImplementation(): StoreImplementation {
}
}
object Store: StoreImplementation by createStoreImplementation()
object Store: IStore by createStoreImplementation()

View File

@@ -4,7 +4,7 @@
<parent>
<groupId>org.jeudego.pairgoth</groupId>
<artifactId>engine-parent</artifactId>
<version>0.2</version>
<version>0.3</version>
</parent>
<artifactId>application</artifactId>
<packaging>pom</packaging>

View File

@@ -5,7 +5,7 @@
<groupId>org.jeudego.pairgoth</groupId>
<artifactId>engine-parent</artifactId>
<version>0.2</version>
<version>0.3</version>
<packaging>pom</packaging>
<!-- CB: Temporary add my repository, while waiting for SSE Java server module author to incorporate my PR or for me to fork it -->

View File

@@ -7,7 +7,7 @@
<parent>
<groupId>org.jeudego.pairgoth</groupId>
<artifactId>engine-parent</artifactId>
<version>0.2</version>
<version>0.3</version>
</parent>
<artifactId>view-webapp</artifactId>

View File

@@ -48,7 +48,7 @@ abstract class OAuthHelper {
protected abstract fun getUserInfosURL(accessToken: String): Pair<String, List<NameValuePair>>
@Throws(IOException::class)
fun getUserInfos(accessToken: String): Json {
fun getUserInfos(accessToken: String): Json.Object {
val (url, params) = getUserInfosURL(accessToken)
return JsonApiClient.get(url, *params.toTypedArray()).asObject()
}

View File

@@ -21,7 +21,7 @@ object EGFRatingsHandler: RatingsHandler(RatingsManager.Ratings.EGF) {
player["origin"] = "EGF"
// override rank with rating equivalent
player["rating"]?.toString()?.toIntOrNull()?.let { rating ->
player["rank"] = ((rating - 2050)/100).let { if (rating < 0) "${-it+1}k" else "${it+1}d" }
player["rank"] = ((rating - 2050)/100).let { if (it < 0) "${-it+1}k" else "${it+1}d" }
}
}
}

View File

@@ -10,7 +10,7 @@ object CredentialsChecker {
private const val CREDENTIALS_DB = "pairgoth.db"
private val hasher = MessageDigest.getInstance("SHA-256")
@OptIn(ExperimentalStdlibApi::class)
fun check(email: String, password: String): String? {
fun check(email: String, password: String): Json.Object? {
initDatabase()
val sha256 = hasher.digest(password.toByteArray(StandardCharsets.UTF_8)).toHexString()
DriverManager.getConnection("jdbc:sqlite:$CREDENTIALS_DB").use { conn ->
@@ -19,7 +19,7 @@ object CredentialsChecker {
setString(1, email)
setString(2, password)
}.executeQuery()
return if (rs.next()) email else null
return if (rs.next()) Json.Object("email" to email) else null
}
}

View File

@@ -32,12 +32,12 @@ class LoginServlet: HttpServlet() {
}
}
fun checkSesame(payload: Json.Object): Boolean? {
fun checkSesame(payload: Json.Object): Json.Object? {
val expected = WebappManager.getProperty("auth.sesame") ?: throw Error("sesame wrongly configured")
return if (payload.getString("sesame")?.equals(expected) == true) true else null
return if (payload.getString("sesame")?.equals(expected) == true) Json.Object("logged" to true) else null
}
fun checkLoginPass(payload: Json.Object): String? {
fun checkLoginPass(payload: Json.Object): Json.Object? {
return CredentialsChecker.check(
payload.getString("email") ?: throw Error("Missing login field"),
payload.getString("password") ?: throw Error("missing password field"))

View File

@@ -77,6 +77,10 @@
/* align-items: center; */
margin-left: auto;
margin-right: auto;
> .section {
margin-left: auto;
margin-right: auto;
}
}
}

View File

@@ -3,7 +3,7 @@
, allowing you to tweak it in any possible way. Be sure to contribute back your enhancements! , vous permettant de complètement le modifier. Noubliez pas de partager vos améliorations !
, the well known pairing system software developed by , le logiciel dappariement très connu développé par
, your Go Pairing Engine! , votre logiciel dappariement de Go !
.ui.form input[type=checkbox][name=online] { vertical-align: initial; }
, last modified , dernière modification :
1st round seeding méthode 1è ronde
: If you prefer convenience, you can simply use the : Si vous préférez la commodité, vous pouvez simplement utiliser linstance
: This mode allows you to run : Ce mode vous permet de lancer
@@ -37,6 +37,7 @@ Export Exporter
Export tournament Exporter le tournoi
Family name Nom de famille
Filter Filtrer
Filter... Filtrer…
First name Prénom
Fischer timing Cadence Fischer
French rules Règles françaises
@@ -93,7 +94,7 @@ Results for round Résultats pour la ronde
Round-robin Toutes rondes
Rounds Rondes
Rules Règles
Search... Chercher…
Search... Chercher…
Short name Nom de code
Since the project is still in beta, the sources are only available to FFG actors. If that's your case, you can access the sources here: Comme le projet est encore en beta, les sources sont seulement accessibles aux acteurs FFG. Si cest votre cas, vous pouvez accéder aux sources ici :
Split and fold Couper-plier

View File

@@ -23,9 +23,9 @@
</script>
#else
#foreach($tour in $files.entrySet())
<a href="tour?id=${tour.key}" class="ui open basic secondary white icon floating button">
<a href="tour?id=${tour.key}" class="ui open basic secondary white icon floating button" title="id $tour.key, last modified $tour.value.lastModified">
<i class="fa fa-folder-open-o"></i>
$tour.value
$tour.value.name
</a>
#end
#end

View File

@@ -40,6 +40,7 @@ function search(needle) {
store('searchFormState', searchFormState);
api.postJson('search', search)
.then(result => {
console.log(result)
if (Array.isArray(result)) {
searchResult = result
let html = resultTemplate.render(result);

View File

@@ -4,7 +4,7 @@
<div id="reg-view">
<div id="list-header">
<div id="filter-box" class="ui icon input">
<input type="text" id="filter" placeholder="Search..."/>
<input type="text" id="filter" placeholder="Filter..."/>
<i class="circular times link icon"></i>
</div>
<div>
@@ -73,6 +73,7 @@
<input type="hidden" name="id"/>
<div class="popup-content">
<div id="search-form" class="five stackable fields">
#if($tour.country)
<div class="two wide field">
<div class="toggle">
<input id="countryFilter" name="countryFilter" type="checkbox" value="$tour.country"/>
@@ -82,6 +83,7 @@
<label>$tour.country.toUpperCase()</label>
</div>
</div>
#end
<div class="ten wide field">
<div class="ui icon input">
<input id="needle" name="needle" type="text" placeholder="Search...">

View File

@@ -4,7 +4,7 @@
<parent>
<groupId>org.jeudego.pairgoth</groupId>
<artifactId>engine-parent</artifactId>
<version>0.2</version>
<version>0.3</version>
</parent>
<artifactId>webserver</artifactId>
<packaging>jar</packaging>