From 0b68db0d72435fd7382f26d6916be2b85eae190a Mon Sep 17 00:00:00 2001 From: Pavel Kunyavskiy Date: Tue, 29 Aug 2023 20:01:10 +0200 Subject: [PATCH] Add the ability to override problem name in advanced.json --- config/_examples/_cms/advanced.json | 22 +++++++++++++++++++ schemas/advanced.schema.json | 5 ++++- .../service/analytics/AnalyticsGenerator.kt | 4 ++-- .../icpclive/export/clics/ClicsExporter.kt | 4 ++-- .../org/icpclive/export/pcms/PCMSExporter.kt | 7 +++--- .../kotlin/org/icpclive/api/ContestInfo.kt | 4 ++-- .../org/icpclive/api/tunning/Advanced.kt | 14 +++++++----- .../cds/adapters/AdvancedPropertiesAdapter.kt | 6 ++--- .../icpclive/cds/atcoder/AtcoderDataSource.kt | 5 ++--- .../org/icpclive/cds/cats/CATSDataSource.kt | 4 ++-- .../org/icpclive/cds/clics/ClicsModel.kt | 4 ++-- .../org/icpclive/cds/cms/CmsDataSoruce.kt | 4 ++-- .../cds/codedrills/CodeDrillsDataSoruce.kt | 4 ++-- .../icpclive/cds/codeforces/CFContestInfo.kt | 10 ++++----- .../icpclive/cds/ejudge/EjudgeDataSource.kt | 4 ++-- .../org/icpclive/cds/krsu/KRSUDataSource.kt | 4 ++-- .../org/icpclive/cds/pcms/PCMSDataSource.kt | 4 ++-- .../icpclive/cds/testsys/TestSysDataSource.kt | 4 ++-- .../icpclive/cds/yandex/YandexContestInfo.kt | 6 ++--- .../main/kotlin/org/icpclive/reacbot/Bot.kt | 2 +- 20 files changed, 74 insertions(+), 47 deletions(-) create mode 100644 config/_examples/_cms/advanced.json diff --git a/config/_examples/_cms/advanced.json b/config/_examples/_cms/advanced.json new file mode 100644 index 000000000..778c08f8f --- /dev/null +++ b/config/_examples/_cms/advanced.json @@ -0,0 +1,22 @@ +{ + "problemOverrides": { + "SC2022CEOI13prize": { + "displayName": "A1" + }, + "SC2022CEOI11abracadabra": { + "displayName": "B1" + }, + "SC2022CEOI12homework": { + "displayName": "C1" + }, + "SC2022CEOI22measures": { + "displayName": "A2" + }, + "SC2022CEOI21drawing": { + "displayName": "B2" + }, + "SC2022CEOI23parking": { + "displayName": "C2" + } + } +} \ No newline at end of file diff --git a/schemas/advanced.schema.json b/schemas/advanced.schema.json index e78b67e7a..183265bb6 100644 --- a/schemas/advanced.schema.json +++ b/schemas/advanced.schema.json @@ -2552,7 +2552,10 @@ ".*": { "type": "object", "properties": { - "name": { + "displayName": { + "type": "string" + }, + "fullName": { "type": "string" }, "color": { diff --git a/src/backend/src/main/kotlin/org/icpclive/service/analytics/AnalyticsGenerator.kt b/src/backend/src/main/kotlin/org/icpclive/service/analytics/AnalyticsGenerator.kt index d8c5a9e1b..20ce8955d 100644 --- a/src/backend/src/main/kotlin/org/icpclive/service/analytics/AnalyticsGenerator.kt +++ b/src/backend/src/main/kotlin/org/icpclive/service/analytics/AnalyticsGenerator.kt @@ -47,8 +47,8 @@ class AnalyticsGenerator(jsonTemplatePath: Path) { private fun getMessage(analyse: RunAnalyse, team: TeamInfo, problem: ProblemInfo): String { val substitute = mapOf( "{team.shortName}" to team.displayName, - "{problem.letter}" to problem.letter, - "{problem.name}" to problem.name, + "{problem.letter}" to problem.displayName, + "{problem.name}" to problem.fullName, "{run.result}" to (analyse.run.result as? ICPCRunResult)?.verdict?.shortName.orEmpty(), "{result.rank}" to analyse.result.rank.toString(), "{result.solvedProblems}" to analyse.solvedProblems?.takeIf { it > 0 }?.toString().orEmpty(), diff --git a/src/cds-converter/src/main/kotlin/org/icpclive/export/clics/ClicsExporter.kt b/src/cds-converter/src/main/kotlin/org/icpclive/export/clics/ClicsExporter.kt index be75c8c93..6899dee0f 100644 --- a/src/cds-converter/src/main/kotlin/org/icpclive/export/clics/ClicsExporter.kt +++ b/src/cds-converter/src/main/kotlin/org/icpclive/export/clics/ClicsExporter.kt @@ -28,8 +28,8 @@ typealias EventProducer = (String) -> Event private fun ProblemInfo.toClicsProblem() = Problem( id = contestSystemId, ordinal = ordinal, - label = letter, - name = name, + label = displayName, + name = fullName, rgb = color, test_data_count = 1, ) diff --git a/src/cds-converter/src/main/kotlin/org/icpclive/export/pcms/PCMSExporter.kt b/src/cds-converter/src/main/kotlin/org/icpclive/export/pcms/PCMSExporter.kt index c599d630b..c5b40c8ba 100644 --- a/src/cds-converter/src/main/kotlin/org/icpclive/export/pcms/PCMSExporter.kt +++ b/src/cds-converter/src/main/kotlin/org/icpclive/export/pcms/PCMSExporter.kt @@ -11,7 +11,6 @@ import org.icpclive.cds.ContestUpdate import org.icpclive.cds.adapters.* import org.icpclive.scoreboard.getScoreboardCalculator import org.icpclive.util.createChild -import org.icpclive.util.getLogger import org.w3c.dom.Element import java.io.StringWriter import javax.xml.parsers.DocumentBuilderFactory @@ -58,8 +57,8 @@ object PCMSExporter { private fun Element.buildChallengeNode(info: ContestInfo) { info.scoreboardProblems.forEach { problem -> createChild("problem").also { - it.setAttribute("alias", problem.letter) - it.setAttribute("name", problem.name) + it.setAttribute("alias", problem.displayName) + it.setAttribute("name", problem.fullName) } } } @@ -87,7 +86,7 @@ object PCMSExporter { probNode.setAttribute("accepted", isAcceptedInt.toString()) probNode.setAttribute("attempts", (probResult.wrongAttempts + isAcceptedInt).toString()) probNode.setAttribute("id", info.scoreboardProblems[index].contestSystemId) - probNode.setAttribute("alias", info.scoreboardProblems[index].letter) + probNode.setAttribute("alias", info.scoreboardProblems[index].displayName) probNode.setAttribute("time", (probResult.lastSubmitTime ?: Duration.ZERO).inWholeMilliseconds.toString()) probNode.setAttribute("penalty", (if (probResult.isSolved) { (probResult.lastSubmitTime!! + info.penaltyPerWrongAttempt * probResult.wrongAttempts).inWholeMinutes diff --git a/src/cds/src/main/kotlin/org/icpclive/api/ContestInfo.kt b/src/cds/src/main/kotlin/org/icpclive/api/ContestInfo.kt index 9bbbb3a3f..e7f9a8302 100644 --- a/src/cds/src/main/kotlin/org/icpclive/api/ContestInfo.kt +++ b/src/cds/src/main/kotlin/org/icpclive/api/ContestInfo.kt @@ -56,8 +56,8 @@ enum class ScoreMergeMode { @Serializable data class ProblemInfo( - val letter: String, - val name: String, + @SerialName("letter") val displayName: String, + @SerialName("name") val fullName: String, val id: Int, val ordinal: Int, val contestSystemId: String, diff --git a/src/cds/src/main/kotlin/org/icpclive/api/tunning/Advanced.kt b/src/cds/src/main/kotlin/org/icpclive/api/tunning/Advanced.kt index 34ba15641..a6fd26ce1 100644 --- a/src/cds/src/main/kotlin/org/icpclive/api/tunning/Advanced.kt +++ b/src/cds/src/main/kotlin/org/icpclive/api/tunning/Advanced.kt @@ -35,16 +35,19 @@ data class TeamInfoOverride( ) /** - * @param name Problem name. + * @param displayName Name to show in scoreboard and queue. + * @param fullName Problem name. * @param color Color of a problem balloon. It would be shown in queue and scoreboard in places related to the problem * @param ordinal Number to sort problems in the scoreboard * @param minScore In ioi mode minimal possible value of points in this problem * @param maxScore In ioi mode maximal possible value of points in this problem - * @param scoreMergeMode In ioi mode, select the ruleset to calculate final score based on the scores for each submission. + * @param scoreMergeMode In ioi mode, select the ruleset to calculate the final score based on the scores for each submission. */ +@OptIn(ExperimentalSerializationApi::class) @Serializable data class ProblemInfoOverride( - val name: String? = null, + val displayName: String? = null, + val fullName: String? = null, @Serializable(ColorSerializer::class) val color: Color? = null, val ordinal: Int? = null, val minScore: Double? = null, @@ -208,8 +211,9 @@ fun ContestInfo.toAdvancedProperties(fields: Set) : AdvancedProperties { ) }, problemOverrides = problemList.associate { - it.letter to ProblemInfoOverride( - name = it.name.takeIfAsked("problemName"), + it.contestSystemId to ProblemInfoOverride( + displayName = it.displayName.takeIfAsked("problemDisplayName"), + fullName = it.fullName.takeIfAsked("problemFullName"), color = it.color.takeIfAsked("color"), ordinal = it.ordinal.takeIfAsked("ordinal"), minScore = it.minScore.takeIfAsked("minScore"), diff --git a/src/cds/src/main/kotlin/org/icpclive/cds/adapters/AdvancedPropertiesAdapter.kt b/src/cds/src/main/kotlin/org/icpclive/cds/adapters/AdvancedPropertiesAdapter.kt index 6b59daa96..0767497a1 100644 --- a/src/cds/src/main/kotlin/org/icpclive/cds/adapters/AdvancedPropertiesAdapter.kt +++ b/src/cds/src/main/kotlin/org/icpclive/cds/adapters/AdvancedPropertiesAdapter.kt @@ -303,12 +303,12 @@ private fun mergeProblems( ) = mergeOverrides( problems, overrides, - ProblemInfo::letter, + ProblemInfo::contestSystemId, unusedMessage = { "No problem for override: $it" } ) { problem, override -> ProblemInfo( - letter = problem.letter, - name = override.name ?: problem.name, + displayName = override.displayName ?: problem.displayName, + fullName = override.fullName ?: problem.fullName, id = problem.id, ordinal = override.ordinal ?: problem.ordinal, contestSystemId = problem.contestSystemId, diff --git a/src/cds/src/main/kotlin/org/icpclive/cds/atcoder/AtcoderDataSource.kt b/src/cds/src/main/kotlin/org/icpclive/cds/atcoder/AtcoderDataSource.kt index 0e749c275..b110fae73 100644 --- a/src/cds/src/main/kotlin/org/icpclive/cds/atcoder/AtcoderDataSource.kt +++ b/src/cds/src/main/kotlin/org/icpclive/cds/atcoder/AtcoderDataSource.kt @@ -9,7 +9,6 @@ import org.icpclive.cds.common.FullReloadContestDataSource import org.icpclive.cds.common.jsonLoader import org.icpclive.cds.settings.AtcoderSettings import org.icpclive.util.* -import kotlin.time.Duration import kotlin.time.Duration.Companion.ZERO import kotlin.time.Duration.Companion.minutes import kotlin.time.Duration.Companion.nanoseconds @@ -86,8 +85,8 @@ internal class AtcoderDataSource(val settings: AtcoderSettings) : FullReloadCont val data = loader.load() val problems = data.TaskInfo.mapIndexed { index, task -> ProblemInfo( - letter = task.Assignment, - name = task.TaskName, + displayName = task.Assignment, + fullName = task.TaskName, id = problemIds[task.TaskScreenName], ordinal = index, contestSystemId = task.TaskScreenName, diff --git a/src/cds/src/main/kotlin/org/icpclive/cds/cats/CATSDataSource.kt b/src/cds/src/main/kotlin/org/icpclive/cds/cats/CATSDataSource.kt index 46f9243a1..fbad739c1 100644 --- a/src/cds/src/main/kotlin/org/icpclive/cds/cats/CATSDataSource.kt +++ b/src/cds/src/main/kotlin/org/icpclive/cds/cats/CATSDataSource.kt @@ -134,8 +134,8 @@ internal class CATSDataSource(val settings: CatsSettings, creds: Map ProblemInfo( - letter = problem.code, - name = problem.name, + displayName = problem.code, + fullName = problem.name, color = null, id = problem.id, ordinal = index, diff --git a/src/cds/src/main/kotlin/org/icpclive/cds/clics/ClicsModel.kt b/src/cds/src/main/kotlin/org/icpclive/cds/clics/ClicsModel.kt index 869e34a27..a31f643c1 100644 --- a/src/cds/src/main/kotlin/org/icpclive/cds/clics/ClicsModel.kt +++ b/src/cds/src/main/kotlin/org/icpclive/cds/clics/ClicsModel.kt @@ -86,8 +86,8 @@ internal class ClicsModel( } private fun Problem.toApi() = ProblemInfo( - letter = label, - name = name, + displayName = label, + fullName = name, id = problemToId[id], ordinal = ordinal, contestSystemId = id, diff --git a/src/cds/src/main/kotlin/org/icpclive/cds/cms/CmsDataSoruce.kt b/src/cds/src/main/kotlin/org/icpclive/cds/cms/CmsDataSoruce.kt index 9babd010f..9d3bc607d 100644 --- a/src/cds/src/main/kotlin/org/icpclive/cds/cms/CmsDataSoruce.kt +++ b/src/cds/src/main/kotlin/org/icpclive/cds/cms/CmsDataSoruce.kt @@ -30,8 +30,8 @@ internal class CmsDataSource(val settings: CmsSettings) : FullReloadContestDataS val problems = tasksLoader.load().entries.groupBy { it.value.contest }.mapValues { it.value.map { (k, v) -> ProblemInfo( - letter = v.short_name, - name = v.name, + displayName = v.short_name, + fullName = v.name, id = problemId[k], contestSystemId = k, ordinal = 0, diff --git a/src/cds/src/main/kotlin/org/icpclive/cds/codedrills/CodeDrillsDataSoruce.kt b/src/cds/src/main/kotlin/org/icpclive/cds/codedrills/CodeDrillsDataSoruce.kt index 85a24f2cf..6808b4dc4 100644 --- a/src/cds/src/main/kotlin/org/icpclive/cds/codedrills/CodeDrillsDataSoruce.kt +++ b/src/cds/src/main/kotlin/org/icpclive/cds/codedrills/CodeDrillsDataSoruce.kt @@ -87,8 +87,8 @@ internal class CodeDrillsDataSource(val settings: CodeDrillsSettings, creds: Map val contest = scoreboard.scoreboard.contest val problems = scoreboard.scoreboard.problemList.mapIndexed { index, problem -> ProblemInfo( - letter = problem.index, - name = problem.title, + displayName = problem.index, + fullName = problem.title, id = problem.id, contestSystemId = problem.id.toString(), ordinal = index diff --git a/src/cds/src/main/kotlin/org/icpclive/cds/codeforces/CFContestInfo.kt b/src/cds/src/main/kotlin/org/icpclive/cds/codeforces/CFContestInfo.kt index a0c29ebdb..00bfef0e6 100644 --- a/src/cds/src/main/kotlin/org/icpclive/cds/codeforces/CFContestInfo.kt +++ b/src/cds/src/main/kotlin/org/icpclive/cds/codeforces/CFContestInfo.kt @@ -41,8 +41,8 @@ internal class CFContestInfo { if (problemsMap.isEmpty() && standings.problems.isNotEmpty()) { for ((id, problem) in standings.problems.withIndex()) { val problemInfo = ProblemInfo( - letter = problem.index, - name = problem.name!!, + displayName = problem.index, + fullName = problem.name!!, id = id, ordinal = id, contestSystemId = id.toString(), @@ -59,8 +59,8 @@ internal class CFContestInfo { } if (contestType == CFContestType.CF) { val hacksInfo = ProblemInfo( - letter = "*", - name = "Hacks", + displayName = "*", + fullName = "Hacks", id = -1, ordinal = -1, contestSystemId = "hacks", @@ -68,7 +68,7 @@ internal class CFContestInfo { maxScore = null, scoreMergeMode = ScoreMergeMode.SUM, ) - problemsMap[hacksInfo.letter] = hacksInfo + problemsMap[hacksInfo.displayName] = hacksInfo problems.add(hacksInfo) } } diff --git a/src/cds/src/main/kotlin/org/icpclive/cds/ejudge/EjudgeDataSource.kt b/src/cds/src/main/kotlin/org/icpclive/cds/ejudge/EjudgeDataSource.kt index 1e33a44cf..d90d4f809 100644 --- a/src/cds/src/main/kotlin/org/icpclive/cds/ejudge/EjudgeDataSource.kt +++ b/src/cds/src/main/kotlin/org/icpclive/cds/ejudge/EjudgeDataSource.kt @@ -21,8 +21,8 @@ internal class EjudgeDataSource(val settings: EjudgeSettings) : FullReloadContes .child("problems") .children().mapIndexed { index, element -> ProblemInfo( - letter = element.getAttribute("short_name"), - name = element.getAttribute("long_name"), + displayName = element.getAttribute("short_name"), + fullName = element.getAttribute("long_name"), id = element.getAttribute("id").toInt(), ordinal = index, contestSystemId = element.getAttribute("id"), diff --git a/src/cds/src/main/kotlin/org/icpclive/cds/krsu/KRSUDataSource.kt b/src/cds/src/main/kotlin/org/icpclive/cds/krsu/KRSUDataSource.kt index a9e989bf3..209eef59a 100644 --- a/src/cds/src/main/kotlin/org/icpclive/cds/krsu/KRSUDataSource.kt +++ b/src/cds/src/main/kotlin/org/icpclive/cds/krsu/KRSUDataSource.kt @@ -22,8 +22,8 @@ internal class KRSUDataSource(val settings: KRSUSettings) : FullReloadContestDat val problemsList = contest.ProblemSet.mapIndexed { index, it -> ProblemInfo( - letter = "" + ('A' + index), - name = "" + ('A' + index), + displayName = "" + ('A' + index), + fullName = "" + ('A' + index), id = it.Problem, ordinal = index, contestSystemId = index.toString(), diff --git a/src/cds/src/main/kotlin/org/icpclive/cds/pcms/PCMSDataSource.kt b/src/cds/src/main/kotlin/org/icpclive/cds/pcms/PCMSDataSource.kt index 9df70d613..1a5cc87c1 100644 --- a/src/cds/src/main/kotlin/org/icpclive/cds/pcms/PCMSDataSource.kt +++ b/src/cds/src/main/kotlin/org/icpclive/cds/pcms/PCMSDataSource.kt @@ -55,8 +55,8 @@ internal class PCMSDataSource(val settings: PCMSSettings, creds: Map ProblemInfo( - letter = it.getAttribute("alias"), - name = it.getAttribute("name"), + displayName = it.getAttribute("alias"), + fullName = it.getAttribute("name"), id = problemIds[it.getAttribute("alias")], ordinal = index, contestSystemId = it.getAttribute("id").takeIf { it.isNotEmpty() } ?: it.getAttribute("alias"), diff --git a/src/cds/src/main/kotlin/org/icpclive/cds/testsys/TestSysDataSource.kt b/src/cds/src/main/kotlin/org/icpclive/cds/testsys/TestSysDataSource.kt index 49bf2252a..77534e62d 100644 --- a/src/cds/src/main/kotlin/org/icpclive/cds/testsys/TestSysDataSource.kt +++ b/src/cds/src/main/kotlin/org/icpclive/cds/testsys/TestSysDataSource.kt @@ -32,8 +32,8 @@ internal class TestSysDataSource(val settings: TestSysSettings) : FullReloadCont val problemsWithPenalty = (data["@p"] ?: emptyList()).mapIndexed { index, prob -> val (letter, name, penalty) = prob.splitCommas() ProblemInfo( - letter = letter, - name = name, + displayName = letter, + fullName = name, id = index, ordinal = index, contestSystemId = letter, diff --git a/src/cds/src/main/kotlin/org/icpclive/cds/yandex/YandexContestInfo.kt b/src/cds/src/main/kotlin/org/icpclive/cds/yandex/YandexContestInfo.kt index 7bdcc6073..980bcb79c 100644 --- a/src/cds/src/main/kotlin/org/icpclive/cds/yandex/YandexContestInfo.kt +++ b/src/cds/src/main/kotlin/org/icpclive/cds/yandex/YandexContestInfo.kt @@ -7,8 +7,8 @@ import kotlin.time.Duration import kotlin.time.Duration.Companion.seconds private fun Problem.toApi(index:Int, resultType: ContestResultType) = ProblemInfo( - letter = alias, - name = name, + displayName = alias, + fullName = name, id = index, ordinal = index, contestSystemId = id, @@ -46,7 +46,7 @@ internal class YandexContestInfo private constructor( ) fun submissionToRun(submission: Submission): RunInfo { - val problemId = problems.indexOfFirst { it.letter == submission.problemAlias } + val problemId = problems.indexOfFirst { it.displayName == submission.problemAlias } if (problemId == -1) { throw IllegalStateException("Problem not found: ${submission.problemAlias}") } diff --git a/src/reactions-bot/src/main/kotlin/org/icpclive/reacbot/Bot.kt b/src/reactions-bot/src/main/kotlin/org/icpclive/reacbot/Bot.kt index 50b0dc427..88d79ae81 100644 --- a/src/reactions-bot/src/main/kotlin/org/icpclive/reacbot/Bot.kt +++ b/src/reactions-bot/src/main/kotlin/org/icpclive/reacbot/Bot.kt @@ -67,7 +67,7 @@ class Bot(private val config: Config) { val ci = runBlocking { contestInfo.await().value } ci.teams[reaction.teamId]?.let { team -> ci.problems[reaction.problemId]?.let { problem -> - caption = "${team.fullName}, problem ${problem.letter}" + caption = "${team.fullName}, problem ${problem.displayName}" } } }