diff --git a/api-webapp/pom.xml b/api-webapp/pom.xml
index f16fb6f..04b8175 100644
--- a/api-webapp/pom.xml
+++ b/api-webapp/pom.xml
@@ -66,6 +66,26 @@
+
+ org.codehaus.mojo
+ jaxb2-maven-plugin
+ 3.1.0
+
+
+ gen-schema
+
+ xjc
+
+
+
+
+ org.jeudego.pairgoth.opengotha
+ XmlSchema
+
+ src/main/resources/xsd
+
+
+
@@ -213,6 +233,17 @@
jgrapht-core
1.5.2
+
+
+ jakarta.xml.bind
+ jakarta.xml.bind-api
+ 4.0.0
+
+
+ org.glassfish.jaxb
+ jaxb-runtime
+ 4.0.3
+
org.junit.jupiter
diff --git a/api-webapp/src/main/kotlin/org/jeudego/pairgoth/ext/OpenGotha.kt b/api-webapp/src/main/kotlin/org/jeudego/pairgoth/ext/OpenGotha.kt
index b5542d4..e9e4bd2 100644
--- a/api-webapp/src/main/kotlin/org/jeudego/pairgoth/ext/OpenGotha.kt
+++ b/api-webapp/src/main/kotlin/org/jeudego/pairgoth/ext/OpenGotha.kt
@@ -1,116 +1,55 @@
package org.jeudego.pairgoth.ext
+import jakarta.xml.bind.JAXBContext
+import jakarta.xml.bind.JAXBElement
+import kotlinx.datetime.LocalDate
import org.jeudego.pairgoth.model.*
+import org.jeudego.pairgoth.opengotha.TournamentType
+import org.jeudego.pairgoth.opengotha.ObjectFactory
import org.jeudego.pairgoth.store.Store
-import org.jeudego.pairgoth.util.XmlFormat
-import org.jeudego.pairgoth.util.booleanAttr
-import org.jeudego.pairgoth.util.arrayOf
-import org.jeudego.pairgoth.util.dateAttr
-import org.jeudego.pairgoth.util.doubleAttr
-import org.jeudego.pairgoth.util.intAttr
-import org.jeudego.pairgoth.util.mutableArrayOf
-import org.jeudego.pairgoth.util.objectOf
-import org.jeudego.pairgoth.util.optBoolean
-import org.jeudego.pairgoth.util.stringAttr
import org.w3c.dom.Element
import java.util.*
+import javax.xml.XMLConstants
+import javax.xml.datatype.XMLGregorianCalendar
+import javax.xml.validation.SchemaFactory
-class OpenGothaFormat(xml: Element): XmlFormat(xml) {
-
- val Players by mutableArrayOf()
- val Games by mutableArrayOf()
- val TournamentParameterSet by objectOf()
-
- class Player(xml: Element): XmlFormat(xml) {
- val agaId by stringAttr()
- val club by stringAttr()
- val country by stringAttr()
- val egfPin by stringAttr()
- val ffgLicence by stringAttr()
- val firstName by stringAttr()
- val name by stringAttr()
- val participating by stringAttr()
- val rank by stringAttr()
- val rating by intAttr()
- }
-
- class Game(xml: Element): XmlFormat(xml) {
- val blackPlayer by stringAttr()
- val whitePlayer by stringAttr()
- val handicap by intAttr()
- val knownColor by booleanAttr()
- val result by stringAttr()
- val roundNumber by intAttr()
- }
-
- class Params(xml: Element): XmlFormat(xml) {
- val GeneralParameterSet by objectOf()
- val HandicapParameterSet by objectOf()
- val PairingParameterSet by objectOf()
- val PlacementParameterSet by objectOf()
-
- class GenParams(xml: Element): XmlFormat(xml) {
- val bInternet by optBoolean()
- val basicTime by intAttr()
- val beginDate by dateAttr()
- val canByoYomiTime by intAttr()
- val complementaryTimeSystem by stringAttr()
- val endDate by dateAttr()
- val fisherTime by intAttr()
- val genCountNotPlayedGamesAsHalfPoint by booleanAttr()
- val genMMBar by stringAttr()
- val genMMFloor by stringAttr()
- val komi by doubleAttr()
- val location by stringAttr()
- val name by stringAttr()
- val nbMovesCanTime by intAttr()
- val numberOfCategories by intAttr()
- val numberOfRounds by intAttr()
- val shortName by stringAttr()
- val size by intAttr()
- val stdByoYomiTime by intAttr()
- }
- class HandicapParams(xml: Element): XmlFormat(xml) {
- val hdBasedOnMMS by booleanAttr()
- val hdCeiling by intAttr()
- val hdCorrection by intAttr()
- val hdNoHdRankThreshold by stringAttr()
- }
- class PairingParams(xml: Element): XmlFormat(xml) {
- val paiMaSeedSystem1 by stringAttr()
- val paiMaSeedSystem2 by stringAttr()
- }
- class Criteria(xml: Element): XmlFormat(xml) {
- val PlacementCriterion by arrayOf()
- }
- class Criterion(xml: Element): XmlFormat(xml) {
- val name by stringAttr()
- }
- }
-}
+private const val MILLISECONDS_PER_DAY = 86400000
+fun XMLGregorianCalendar.toLocalDate() = LocalDate.fromEpochDays((toGregorianCalendar().time.time / MILLISECONDS_PER_DAY).toInt())
object OpenGotha {
fun import(element: Element): Tournament<*> {
- val imported = OpenGothaFormat(element)
- val genParams = imported.TournamentParameterSet.GeneralParameterSet
- val handParams = imported.TournamentParameterSet.HandicapParameterSet
- val pairingParams = imported.TournamentParameterSet.PairingParameterSet
- val placementParams = imported.TournamentParameterSet.PlacementParameterSet
+
+ val context = JAXBContext.newInstance(ObjectFactory::class.java)
+ val parsed = context.createUnmarshaller()/*.also { unmarshaller ->
+ val schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI)
+ val schemaURL = OpenGotha::class.java.getResource("/xsd/opengotha.xsd") ?: throw Error("opengotha.xsd not found")
+ val schema = schemaFactory.newSchema(schemaURL)
+ unmarshaller.schema = schema
+
+ }*/.unmarshal(element) as JAXBElement
+
+ val ogt = parsed.value
+ // import tournament parameters
+
+ val genParams = ogt.tournamentParameterSet.generalParameterSet
+ val handParams = ogt.tournamentParameterSet.handicapParameterSet
+ val placmtParams = ogt.tournamentParameterSet.placementParameterSet
+ val pairParams = ogt.tournamentParameterSet.pairingParameterSet
val tournament = StandardTournament(
id = Store.nextTournamentId,
type = Tournament.Type.INDIVIDUAL, // CB for now, TODO
name = genParams.name,
shortName = genParams.shortName,
- startDate = genParams.beginDate,
- endDate = genParams.endDate,
+ startDate = genParams.beginDate.toLocalDate(),
+ endDate = genParams.endDate.toLocalDate(),
country = "FR", // no country in opengotha format
location = genParams.location,
- online = genParams.bInternet ?: false,
+ online = genParams.isBInternet ?: false,
timeSystem = when (genParams.complementaryTimeSystem) {
"SUDDENDEATH" -> SuddenDeath(genParams.basicTime)
"STDBYOYOMI" -> StandardByoyomi(genParams.basicTime, genParams.stdByoYomiTime, 1) // no periods?
"CANBYOYOMI" -> CanadianByoyomi(genParams.basicTime, genParams.canByoYomiTime, genParams.nbMovesCanTime)
- "FISCHER" -> FischerTime(genParams.basicTime, genParams.fisherTime)
+ "FISCHER" -> FischerTime(genParams.basicTime, genParams.fischerTime)
else -> throw Error("missing byoyomi type")
},
pairing = when (handParams.hdCeiling) {
@@ -119,7 +58,11 @@ object OpenGotha {
),
placementParams = PlacementParams(
- crit = placementParams.PlacementCriterion.map { Criterion.valueOf(it.name) }.toTypedArray()
+ crit = placmtParams.placementCriteria.placementCriterion.filter {
+ it.name != "NULL"
+ }.map {
+ Criterion.valueOf(it.name)
+ }.toTypedArray()
)
) // TODO
else -> MacMahon(
@@ -133,8 +76,10 @@ object OpenGotha {
},
rounds = genParams.numberOfRounds
)
+
val canonicMap = mutableMapOf()
- imported.Players.map { player ->
+ // import players
+ ogt.players.player.map { player ->
Player(
id = Store.nextPlayerId,
name = player.name,
@@ -147,7 +92,7 @@ object OpenGotha {
canonicMap.put("${player.name}${player.firstName}".uppercase(Locale.ENGLISH), it.id)
}
}.associateByTo(tournament.players) { it.id }
- val gamesPerRound = imported.Games.groupBy {
+ val gamesPerRound = ogt.games.game.groupBy {
it.roundNumber
}.values.map {
it.map { game ->
@@ -169,7 +114,7 @@ object OpenGotha {
}.associateBy { it.id }.toMutableMap()
}
gamesPerRound.forEachIndexed { index, games ->
- tournament.games(index).putAll(games)
+ tournament.games(index + 1).putAll(games)
}
return tournament
}
@@ -178,8 +123,9 @@ object OpenGotha {
fun export(tournament: Tournament<*>): String {
// two methods here
// method 1 (advised because it's more error-proof but more complex to set up) is to assign one by one
- // the fields of an OpenGothaFormat instance, then call toPrettyString() on it
- // opengotha = OpenGothaFormat()
+ // the fields of an OGTournamentType instance, then call toPrettyString() on it
+ // val ogt = OGTournamentType()
+ // ...
//
// method 2 (quick and dirty) is to rely on templating:
val xml = """
@@ -281,6 +227,7 @@ object OpenGotha {
""".trimIndent()
+
return xml
}
}
diff --git a/api-webapp/src/main/resources/xsd/opengotha.xsd b/api-webapp/src/main/resources/xsd/opengotha.xsd
new file mode 100644
index 0000000..4ff1eca
--- /dev/null
+++ b/api-webapp/src/main/resources/xsd/opengotha.xsd
@@ -0,0 +1,225 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+