Add rating date tootip, and avoid registering twice a player
This commit is contained in:
@@ -23,6 +23,9 @@ object PlayerHandler: PairgothApiHandler {
|
|||||||
val tournament = getTournament(request)
|
val tournament = getTournament(request)
|
||||||
val payload = getObjectPayload(request)
|
val payload = getObjectPayload(request)
|
||||||
val player = Player.fromJson(payload)
|
val player = Player.fromJson(payload)
|
||||||
|
player.externalIds.forEach { dbId, pId ->
|
||||||
|
if (tournament.hasPlayer(dbId, pId)) badRequest("player already registered")
|
||||||
|
}
|
||||||
tournament.players[player.id] = player
|
tournament.players[player.id] = player
|
||||||
tournament.dispatchEvent(PlayerAdded, request, player.toJson())
|
tournament.dispatchEvent(PlayerAdded, request, player.toJson())
|
||||||
return Json.Object("success" to true, "id" to player.id)
|
return Json.Object("success" to true, "id" to player.id)
|
||||||
|
@@ -119,6 +119,7 @@ sealed class Tournament <P: Pairable>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun pairedPlayers() = games.flatMap { it.values }.flatMap { listOf(it.black, it.white) }.toSet()
|
fun pairedPlayers() = games.flatMap { it.values }.flatMap { listOf(it.black, it.white) }.toSet()
|
||||||
|
fun hasPlayer(dbId: DatabaseId, pId: String) = players.values.filter { player -> pId == player.externalIds[dbId] }.isNotEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
// standard tournament of individuals
|
// standard tournament of individuals
|
||||||
|
@@ -33,6 +33,10 @@ object EGFRatingsHandler: RatingsHandler(RatingsManager.Ratings.EGF) {
|
|||||||
if ("UK" == player.getString("country")) {
|
if ("UK" == player.getString("country")) {
|
||||||
player["country"] = "GB"
|
player["country"] = "GB"
|
||||||
}
|
}
|
||||||
|
// fix for missing firstnames
|
||||||
|
if (player.getString("firstname") == null) {
|
||||||
|
player["firstname"] = ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -32,7 +32,9 @@ abstract class RatingsHandler(val origin: RatingsManager.Ratings) {
|
|||||||
WebappManager.properties.getProperty("ratings.${origin.name.lowercase(Locale.ROOT)}")?.let { URL(it) } ?: defaultURL
|
WebappManager.properties.getProperty("ratings.${origin.name.lowercase(Locale.ROOT)}")?.let { URL(it) } ?: defaultURL
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun getRatingsFiles() = RatingsManager.path.useDirectoryEntries("${origin.name}-*.json") { entries ->
|
fun activeDate() = ymd.parse(activeRatingsFile.name.substringBefore(".json").substringAfter("${origin.name}-"))
|
||||||
|
|
||||||
|
fun getRatingsFiles() = RatingsManager.path.useDirectoryEntries("${origin.name}-*.json") { entries ->
|
||||||
entries.sortedBy { it.fileName.name }.map {
|
entries.sortedBy { it.fileName.name }.map {
|
||||||
it.toFile()
|
it.toFile()
|
||||||
}.toList()
|
}.toList()
|
||||||
|
@@ -8,6 +8,7 @@ import java.io.BufferedReader
|
|||||||
import java.lang.Exception
|
import java.lang.Exception
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
|
import java.time.format.DateTimeFormatter
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.locks.ReadWriteLock
|
import java.util.concurrent.locks.ReadWriteLock
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||||
@@ -131,10 +132,15 @@ object RatingsManager: Runnable {
|
|||||||
val left = a as Json.Object
|
val left = a as Json.Object
|
||||||
val right = b as Json.Object
|
val right = b as Json.Object
|
||||||
val cmp = left.getString("name")!!.compareTo(right.getString("name")!!)
|
val cmp = left.getString("name")!!.compareTo(right.getString("name")!!)
|
||||||
if (cmp == 0) left.getString("firstname")!!.compareTo(right.getString("firstname")!!)
|
if (cmp == 0) (left.getString("firstname") ?: "").compareTo(right.getString("firstname") ?: "")
|
||||||
else cmp
|
else cmp
|
||||||
}.toCollection(Json.MutableArray())
|
}.toCollection(Json.MutableArray())
|
||||||
}
|
}
|
||||||
|
|
||||||
val index = PlayerIndex()
|
val index = PlayerIndex()
|
||||||
|
|
||||||
|
public fun getRatingsDates() = ratingsHandlers.filter{ it.value.active }.map {
|
||||||
|
Pair(it.key.name.lowercase(),
|
||||||
|
DateTimeFormatter.ISO_LOCAL_DATE.format(it.value.activeDate()))
|
||||||
|
}.toMap()
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
package org.jeudego.pairgoth.view
|
package org.jeudego.pairgoth.view
|
||||||
|
|
||||||
import com.republicate.kson.Json
|
import com.republicate.kson.Json
|
||||||
|
import org.jeudego.pairgoth.ratings.RatingsManager
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
@@ -94,4 +95,6 @@ class PairgothTool {
|
|||||||
companion object {
|
companion object {
|
||||||
const val EXAMPLES_DIRECTORY = "examples"
|
const val EXAMPLES_DIRECTORY = "examples"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getRatingsDates() = RatingsManager.getRatingsDates()
|
||||||
}
|
}
|
@@ -51,7 +51,7 @@ French rules Règles françaises
|
|||||||
Given name Prénom
|
Given name Prénom
|
||||||
Goban Goban
|
Goban Goban
|
||||||
Hd correction Correction hd
|
Hd correction Correction hd
|
||||||
Hd threshold Seuil hd
|
No hd threshold Seuil sans hd
|
||||||
How to use Comment utiliser
|
How to use Comment utiliser
|
||||||
Import Importer
|
Import Importer
|
||||||
Import tournament Importer un tournoi
|
Import tournament Importer un tournoi
|
||||||
@@ -122,6 +122,8 @@ Team of 4 individual players Équipe de 4 joueurs individuels
|
|||||||
Team of 5 individual players Équipe de 5 joueurs individuels
|
Team of 5 individual players Équipe de 5 joueurs individuels
|
||||||
That's the best option if you feel more comfortable when running locally or whenever you want to be able to do the pairing without internet. Pairgoth will launch a local web server to which you can connect using a browser. C’est la meilleure option si vous préférez le faire tourner localement ou quand vous voulez être capable de faire l’appariement sans internet. Pairgoth lancera un serveur web local auquel vous pourrez vous connecter depuis un navigateur.
|
That's the best option if you feel more comfortable when running locally or whenever you want to be able to do the pairing without internet. Pairgoth will launch a local web server to which you can connect using a browser. C’est la meilleure option si vous préférez le faire tourner localement ou quand vous voulez être capable de faire l’appariement sans internet. Pairgoth lancera un serveur web local auquel vous pourrez vous connecter depuis un navigateur.
|
||||||
Time system Temps
|
Time system Temps
|
||||||
|
Tournament director Directeur de tournoi
|
||||||
|
Tournament name Nom du tournoi
|
||||||
Tournament type Type de tournoi
|
Tournament type Type de tournoi
|
||||||
Unpair Désapparier
|
Unpair Désapparier
|
||||||
Unregister Désinscrire
|
Unregister Désinscrire
|
||||||
@@ -137,6 +139,7 @@ Black Noir
|
|||||||
club club
|
club club
|
||||||
country pays
|
country pays
|
||||||
d d
|
d d
|
||||||
|
end date date de fin
|
||||||
first name prénom
|
first name prénom
|
||||||
from du
|
from du
|
||||||
games ) parties )
|
games ) parties )
|
||||||
@@ -163,9 +166,11 @@ sources sources
|
|||||||
sources on FFG's gitlab sur le serveur gitab de la FFG
|
sources on FFG's gitlab sur le serveur gitab de la FFG
|
||||||
standalone, web interface indépendant, interface web
|
standalone, web interface indépendant, interface web
|
||||||
standalone, web interface, via docker indépendant, interface web, via docker
|
standalone, web interface, via docker indépendant, interface web, via docker
|
||||||
|
start date date de début
|
||||||
table table
|
table table
|
||||||
the configuration guide le guide de configuration
|
the configuration guide le guide de configuration
|
||||||
to au
|
to au
|
||||||
|
tournament location lieu du tournoi
|
||||||
unpairable players joueurs non disponibles
|
unpairable players joueurs non disponibles
|
||||||
unpairable, non disponibles,
|
unpairable, non disponibles,
|
||||||
version 0.1 supports the version 0.1 supporte le système d’appariement
|
version 0.1 supports the version 0.1 supporte le système d’appariement
|
||||||
@@ -174,6 +179,7 @@ White Blanc
|
|||||||
white vs. black blanc vs. Noir
|
white vs. black blanc vs. Noir
|
||||||
confirmed. confirmé(s).
|
confirmed. confirmé(s).
|
||||||
Note that login to this instance is reserved to French federation actors plus several external people at our discretion. Send us La connexion à cette instance est réservée aux acteurs de la FFG et à quelques personnes extérieures, à notre discrétion. Envoyez-nous
|
Note that login to this instance is reserved to French federation actors plus several external people at our discretion. Send us La connexion à cette instance est réservée aux acteurs de la FFG et à quelques personnes extérieures, à notre discrétion. Envoyez-nous
|
||||||
|
yyyymmdd-city aaaammjj-ville
|
||||||
an email un email
|
an email un email
|
||||||
to request an access. pour demander un accès.
|
to request an access. pour demander un accès.
|
||||||
(not yet available) (pas encore disponible)
|
(not yet available) (pas encore disponible)
|
||||||
|
@@ -74,12 +74,13 @@ function fillPlayer(player) {
|
|||||||
let form = $('#player-form')[0];
|
let form = $('#player-form')[0];
|
||||||
form.val('name', player.name);
|
form.val('name', player.name);
|
||||||
form.val('firstname', player.firstname);
|
form.val('firstname', player.firstname);
|
||||||
console.log(country);
|
|
||||||
form.val('country', country);
|
form.val('country', country);
|
||||||
form.val('club', player.club);
|
form.val('club', player.club);
|
||||||
form.val('rank', parseRank(player.rank));
|
form.val('rank', parseRank(player.rank));
|
||||||
form.val('rating', player.rating);
|
form.val('rating', player.rating);
|
||||||
form.val('final', false);
|
form.val('final', false);
|
||||||
|
form.val('ffg_id', player.ffg);
|
||||||
|
form.val('egf_id', player.egf);
|
||||||
$('#needle')[0].value = '';
|
$('#needle')[0].value = '';
|
||||||
initSearch();
|
initSearch();
|
||||||
$('#register').focus();
|
$('#register').focus();
|
||||||
@@ -195,6 +196,12 @@ onLoad(() => {
|
|||||||
skip: form.find('input.participation').map((input,i) => [i+1, input.checked]).filter(arr => !arr[1]).map(arr => arr[0]),
|
skip: form.find('input.participation').map((input,i) => [i+1, input.checked]).filter(arr => !arr[1]).map(arr => arr[0]),
|
||||||
final: form.val('final')
|
final: form.val('final')
|
||||||
}
|
}
|
||||||
|
for (let origin of ['egf', 'ffg']) {
|
||||||
|
let value = form.val(`${origin}_id`);
|
||||||
|
if (value) {
|
||||||
|
player[origin] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (form.hasClass('add')) {
|
if (form.hasClass('add')) {
|
||||||
api.postJson(`tour/${tour_id}/part`, player)
|
api.postJson(`tour/${tour_id}/part`, player)
|
||||||
.then(player => {
|
.then(player => {
|
||||||
|
@@ -78,6 +78,9 @@
|
|||||||
<div class="popup-body">
|
<div class="popup-body">
|
||||||
<form id="player-form" class="ui form edit">
|
<form id="player-form" class="ui form edit">
|
||||||
<input type="hidden" name="id"/>
|
<input type="hidden" name="id"/>
|
||||||
|
<input type="hidden" name="egf_id"/>
|
||||||
|
<input type="hidden" name="ffg_id"/>
|
||||||
|
<!-- input type="hidden" name="aga"/> -->
|
||||||
<div class="popup-content">
|
<div class="popup-content">
|
||||||
<div id="search-form" class="five stackable fields">
|
<div id="search-form" class="five stackable fields">
|
||||||
#if($tour.country)
|
#if($tour.country)
|
||||||
@@ -109,7 +112,7 @@
|
|||||||
</div>
|
</div>
|
||||||
*#
|
*#
|
||||||
<div class="two wide field">
|
<div class="two wide field">
|
||||||
<div class="toggle">
|
<div class="toggle" title="$utils.ratingsDates.egf">
|
||||||
<input id="egf" name="egf" type="checkbox" checked value="true"/>
|
<input id="egf" name="egf" type="checkbox" checked value="true"/>
|
||||||
<div class="search-param checkbox">
|
<div class="search-param checkbox">
|
||||||
<div class="circle"></div>
|
<div class="circle"></div>
|
||||||
@@ -118,7 +121,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="two wide field">
|
<div class="two wide field">
|
||||||
<div class="toggle">
|
<div class="toggle" title="$utils.ratingsDates.ffg">
|
||||||
<input id="ffg" name="ffg" type="checkbox" checked value="true"/>
|
<input id="ffg" name="ffg" type="checkbox" checked value="true"/>
|
||||||
<div class="search-param checkbox">
|
<div class="search-param checkbox">
|
||||||
<div class="circle"></div>
|
<div class="circle"></div>
|
||||||
|
Reference in New Issue
Block a user