Some work on opengotha import/export
This commit is contained in:
@@ -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>
|
||||||
|
@@ -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)
|
||||||
|
|
||||||
|
@@ -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)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user