Some work on opengotha import/export

This commit is contained in:
Claude Brisson
2023-06-22 07:48:59 +02:00
parent 6cd363b13d
commit c6157d687c
3 changed files with 45 additions and 32 deletions

View File

@@ -4,12 +4,11 @@ import org.jeudego.pairgoth.model.*
import org.jeudego.pairgoth.store.Store import org.jeudego.pairgoth.store.Store
import org.jeudego.pairgoth.util.XmlFormat import org.jeudego.pairgoth.util.XmlFormat
import org.jeudego.pairgoth.util.booleanAttr import org.jeudego.pairgoth.util.booleanAttr
import org.jeudego.pairgoth.util.childrenArrayOf import org.jeudego.pairgoth.util.arrayOf
import org.jeudego.pairgoth.util.dateAttr import org.jeudego.pairgoth.util.dateAttr
import org.jeudego.pairgoth.util.doubleAttr import org.jeudego.pairgoth.util.doubleAttr
import org.jeudego.pairgoth.util.find
import org.jeudego.pairgoth.util.get
import org.jeudego.pairgoth.util.intAttr import org.jeudego.pairgoth.util.intAttr
import org.jeudego.pairgoth.util.mutableArrayOf
import org.jeudego.pairgoth.util.objectOf import org.jeudego.pairgoth.util.objectOf
import org.jeudego.pairgoth.util.optBoolean import org.jeudego.pairgoth.util.optBoolean
import org.jeudego.pairgoth.util.stringAttr import org.jeudego.pairgoth.util.stringAttr
@@ -18,8 +17,8 @@ import java.util.*
class OpenGothaFormat(xml: Element): XmlFormat(xml) { class OpenGothaFormat(xml: Element): XmlFormat(xml) {
val Players by childrenArrayOf<Player>() val Players by mutableArrayOf<Player>()
val Games by childrenArrayOf<Game>() val Games by mutableArrayOf<Game>()
val TournamentParameterSet by objectOf<Params>() val TournamentParameterSet by objectOf<Params>()
class Player(xml: Element): XmlFormat(xml) { class Player(xml: Element): XmlFormat(xml) {
@@ -48,6 +47,7 @@ class OpenGothaFormat(xml: Element): XmlFormat(xml) {
val GeneralParameterSet by objectOf<GenParams>() val GeneralParameterSet by objectOf<GenParams>()
val HandicapParameterSet by objectOf<HandicapParams>() val HandicapParameterSet by objectOf<HandicapParams>()
val PairingParameterSet by objectOf<PairingParams>() val PairingParameterSet by objectOf<PairingParams>()
val PlacementParameterSet by objectOf<Criteria>()
class GenParams(xml: Element): XmlFormat(xml) { class GenParams(xml: Element): XmlFormat(xml) {
val bInternet by optBoolean() val bInternet by optBoolean()
@@ -80,6 +80,12 @@ class OpenGothaFormat(xml: Element): XmlFormat(xml) {
val paiMaSeedSystem1 by stringAttr() val paiMaSeedSystem1 by stringAttr()
val paiMaSeedSystem2 by stringAttr() val paiMaSeedSystem2 by stringAttr()
} }
class Criteria(xml: Element): XmlFormat(xml) {
val PlacementCriterion by arrayOf<Criterion>()
}
class Criterion(xml: Element): XmlFormat(xml) {
val name by stringAttr()
}
} }
} }
@@ -89,6 +95,7 @@ object OpenGotha {
val genParams = imported.TournamentParameterSet.GeneralParameterSet val genParams = imported.TournamentParameterSet.GeneralParameterSet
val handParams = imported.TournamentParameterSet.HandicapParameterSet val handParams = imported.TournamentParameterSet.HandicapParameterSet
val pairingParams = imported.TournamentParameterSet.PairingParameterSet val pairingParams = imported.TournamentParameterSet.PairingParameterSet
val placementParams = imported.TournamentParameterSet.PlacementParameterSet
val tournament = StandardTournament( val tournament = StandardTournament(
id = Store.nextTournamentId, id = Store.nextTournamentId,
type = Tournament.Type.INDIVIDUAL, // CB for now, TODO type = Tournament.Type.INDIVIDUAL, // CB for now, TODO
@@ -107,22 +114,22 @@ object OpenGotha {
else -> throw Error("missing byoyomi type") else -> throw Error("missing byoyomi type")
}, },
pairing = when (handParams.hdCeiling) { pairing = when (handParams.hdCeiling) {
/* 0 -> Swiss(
when (pairingParams.paiMaSeedSystem1) { pairingParams = PairingParams(
"SPLITANDFOLD" -> SeedMethod.SPLIT_AND_FOLD
"SPLITANDRANDOM" -> SeedMethod.SPLIT_AND_RANDOM ),
"SPLITANDSLIP" -> SeedMethod.SPLIT_AND_SLIP placementParams = PlacementParams(
else -> throw Error("unknown swiss pairing method") crit = placementParams.PlacementCriterion.map { Criterion.valueOf(it.name) }.toTypedArray()
}, )
when (pairingParams.paiMaSeedSystem2) { ) // TODO
"SPLITANDFOLD" -> SeedMethod.SPLIT_AND_FOLD else -> MacMahon(
"SPLITANDRANDOM" -> SeedMethod.SPLIT_AND_RANDOM pairingParams = PairingParams(
"SPLITANDSLIP" -> SeedMethod.SPLIT_AND_SLIP
else -> throw Error("unknown swiss pairing method") ),
} placementParams = PlacementParams(
*/
0 -> Swiss() // TODO )
else -> MacMahon() // TODO ) // TODO
}, },
rounds = genParams.numberOfRounds rounds = genParams.numberOfRounds
) )
@@ -169,6 +176,12 @@ object OpenGotha {
// TODO - bye player(s) // TODO - bye player(s)
fun export(tournament: Tournament<*>): String { 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()
//
// method 2 (quick and dirty) is to rely on templating:
val xml = """ val xml = """
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Tournament dataVersion="201" externalIPAddress="88.122.144.219" fullVersionNumber="3.51" runningMode="SAL" saveDT="20210111180800"> <Tournament dataVersion="201" externalIPAddress="88.122.144.219" fullVersionNumber="3.51" runningMode="SAL" saveDT="20210111180800">
@@ -238,18 +251,17 @@ object OpenGotha {
TimeSystem.TimeSystemType.CANADIAN -> "CANBYOYOMI" TimeSystem.TimeSystemType.CANADIAN -> "CANBYOYOMI"
TimeSystem.TimeSystemType.FISCHER -> "FISCHER" TimeSystem.TimeSystemType.FISCHER -> "FISCHER"
} }" director="" endDate="${tournament.endDate}" fischerTime="${tournament.timeSystem.increment}" genCountNotPlayedGamesAsHalfPoint="false" genMMBar="9D" genMMFloor="30K" genMMS2ValueAbsent="1" genMMS2ValueBye="2" genMMZero="30K" genNBW2ValueAbsent="0" genNBW2ValueBye="2" genRoundDownNBWMMS="true" komi="${tournament.komi}" location="${tournament.location}" name="${tournament.name}" nbMovesCanTime="${tournament.timeSystem.stones}" numberOfCategories="1" numberOfRounds="${tournament.rounds}" shortName="${tournament.shortName}" size="${tournament.gobanSize}" stdByoYomiTime="${tournament.timeSystem.byoyomi}"/> } }" director="" endDate="${tournament.endDate}" fischerTime="${tournament.timeSystem.increment}" genCountNotPlayedGamesAsHalfPoint="false" genMMBar="9D" genMMFloor="30K" genMMS2ValueAbsent="1" genMMS2ValueBye="2" genMMZero="30K" genNBW2ValueAbsent="0" genNBW2ValueBye="2" genRoundDownNBWMMS="true" komi="${tournament.komi}" location="${tournament.location}" name="${tournament.name}" nbMovesCanTime="${tournament.timeSystem.stones}" numberOfCategories="1" numberOfRounds="${tournament.rounds}" shortName="${tournament.shortName}" size="${tournament.gobanSize}" stdByoYomiTime="${tournament.timeSystem.byoyomi}"/>
<HandicapParameterSet hdBasedOnMMS="false" hdCeiling="0" hdCorrection="0" hdNoHdRankThreshold="30K"/> <HandicapParameterSet hdBasedOnMMS="${tournament.pairing.pairingParams.handicap.useMMS}" hdCeiling="${tournament.pairing.pairingParams.handicap.ceiling}" hdCorrection="${tournament.pairing.pairingParams.handicap.correction}" hdNoHdRankThreshold="${displayRank(tournament.pairing.pairingParams.handicap.rankThreshold)}"/>
<PlacementParameterSet> <PlacementParameterSet>
<PlacementCriteria> <PlacementCriteria>
<PlacementCriterion name="NBW" number="1"/> ${
<PlacementCriterion name="SOSW" number="2"/> (0..5).map {
<PlacementCriterion name="SOSOSW" number="3"/> """<PlacementCriterion name="${tournament.pairing.placementParams.criteria.getOrNull(it)?.name ?: "NULL"}" number="${it + 1}"/>"""
<PlacementCriterion name="NULL" number="4"/> }
<PlacementCriterion name="NULL" number="5"/> }
<PlacementCriterion name="NULL" number="6"/>
</PlacementCriteria> </PlacementCriteria>
</PlacementParameterSet> </PlacementParameterSet>
<PairingParameterSet paiBaAvoidDuplGame="500000000000000" paiBaBalanceWB="1000000" paiBaDeterministic="true" paiBaRandom="0" paiMaAdditionalPlacementCritSystem1="Rating" paiMaAdditionalPlacementCritSystem2="Rating" paiMaAvoidMixingCategories="0" paiMaCompensateDUDD="true" paiMaDUDDLowerMode="MID" paiMaDUDDUpperMode="MID" paiMaDUDDWeight="100000000" paiMaLastRoundForSeedSystem1="2" paiMaMaximizeSeeding="5000000" paiMaMinimizeScoreDifference="100000000000" paiMaSeedSystem1="SPLITANDSLIP" paiMaSeedSystem2="SPLITANDSLIP" paiSeAvoidSameGeo="0" paiSeBarThresholdActive="true" paiSeDefSecCrit="20000000000000" paiSeMinimizeHandicap="0" paiSeNbWinsThresholdActive="true" paiSePreferMMSDiffRatherThanSameClub="0" paiSePreferMMSDiffRatherThanSameCountry="0" paiSeRankThreshold="30K" paiStandardNX1Factor="0.5"/> <PairingParameterSet paiBaAvoidDuplGame="${tournament.pairing.pairingParams.base.dupWeight.toInt()}" paiBaBalanceWB="${tournament.pairing.pairingParams.base.colorBalanceWeight.toInt()}" paiBaDeterministic="${tournament.pairing.pairingParams.base.deterministic}" paiBaRandom="${tournament.pairing.pairingParams.base.random.toInt()}" paiMaAdditionalPlacementCritSystem1="Rating" paiMaAdditionalPlacementCritSystem2="Rating" paiMaAvoidMixingCategories="0" paiMaCompensateDUDD="true" paiMaDUDDLowerMode="MID" paiMaDUDDUpperMode="MID" paiMaDUDDWeight="100000000" paiMaLastRoundForSeedSystem1="2" paiMaMaximizeSeeding="5000000" paiMaMinimizeScoreDifference="100000000000" paiMaSeedSystem1="SPLITANDSLIP" paiMaSeedSystem2="SPLITANDSLIP" paiSeAvoidSameGeo="0" paiSeBarThresholdActive="true" paiSeDefSecCrit="20000000000000" paiSeMinimizeHandicap="0" paiSeNbWinsThresholdActive="true" paiSePreferMMSDiffRatherThanSameClub="0" paiSePreferMMSDiffRatherThanSameCountry="0" paiSeRankThreshold="30K" paiStandardNX1Factor="0.5"/>
<DPParameterSet displayClCol="true" displayCoCol="true" displayIndGamesInMatches="true" displayNPPlayers="false" displayNumCol="true" displayPlCol="true" gameFormat="short" playerSortType="name" showByePlayer="true" showNotFinallyRegisteredPlayers="true" showNotPairedPlayers="true" showNotParticipatingPlayers="false" showPlayerClub="true" showPlayerCountry="false" showPlayerGrade="true"/> <DPParameterSet displayClCol="true" displayCoCol="true" displayIndGamesInMatches="true" displayNPPlayers="false" displayNumCol="true" displayPlCol="true" gameFormat="short" playerSortType="name" showByePlayer="true" showNotFinallyRegisteredPlayers="true" showNotPairedPlayers="true" showNotParticipatingPlayers="false" showPlayerClub="true" showPlayerCountry="false" showPlayerGrade="true"/>
<PublishParameterSet exportToLocalFile="true" htmlAutoScroll="false" print="false"/> <PublishParameterSet exportToLocalFile="true" htmlAutoScroll="false" print="false"/>
</TournamentParameterSet> </TournamentParameterSet>

View File

@@ -28,7 +28,8 @@ object ByePlayer: Pairable(0, "bye", 0, Int.MIN_VALUE) {
override val country = "none" override val country = "none"
} }
fun Pairable.displayRank() = if (rank < 0) "${-rank}k" else "${rank + 1}d" fun displayRank(rank: Int) = if (rank < 0) "${-rank}k" else "${rank + 1}d"
fun Pairable.displayRank() = displayRank(rank)
private val rankRegex = Regex("(\\d+)([kd])", RegexOption.IGNORE_CASE) private val rankRegex = Regex("(\\d+)([kd])", RegexOption.IGNORE_CASE)

View File

@@ -34,8 +34,8 @@ fun XmlFormat.double() = DoubleXmlDelegate(xml.element())
inline fun <reified E: Enum<*>> XmlFormat.enum() = EnumXmlDelegate<E>(xml.element(), E::class) inline fun <reified E: Enum<*>> XmlFormat.enum() = EnumXmlDelegate<E>(xml.element(), E::class)
fun XmlFormat.date(format: String = ISO_LOCAL_DATE_FORMAT) = DateXmlDelegate(xml.element(), format) fun XmlFormat.date(format: String = ISO_LOCAL_DATE_FORMAT) = DateXmlDelegate(xml.element(), format)
fun XmlFormat.datetime(format: String = ISO_LOCAL_DATETIME_FORMAT) = DateTimeXmlDelegate(xml.element(), format) fun XmlFormat.datetime(format: String = ISO_LOCAL_DATETIME_FORMAT) = DateTimeXmlDelegate(xml.element(), format)
inline fun <reified T: XmlFormat> XmlFormat.childrenArrayOf() = ArrayXmlDelegate(xml, T::class) inline fun <reified T: XmlFormat> XmlFormat.arrayOf() = ArrayXmlDelegate(xml, T::class)
inline fun <reified T: XmlFormat> XmlFormat.childrenArrayOf(tagName: String) = ChildrenArrayXmlDelegate(xml, tagName, T::class) inline fun <reified T: XmlFormat> XmlFormat.arrayOf(tagName: String) = ChildrenArrayXmlDelegate(xml, tagName, T::class)
inline fun <reified T: XmlFormat> XmlFormat.mutableArrayOf() = MutableArrayXmlDelegate(xml, T::class) inline fun <reified T: XmlFormat> XmlFormat.mutableArrayOf() = MutableArrayXmlDelegate(xml, T::class)
inline fun <reified T: XmlFormat> XmlFormat.objectOf() = ObjectXmlDelegate(xml, T::class) inline fun <reified T: XmlFormat> XmlFormat.objectOf() = ObjectXmlDelegate(xml, T::class)