feat: display solved problems
This commit is contained in:
parent
e57112b7c4
commit
d8ea951492
@ -10,6 +10,7 @@ import com.intellij.openapi.project.Project
|
|||||||
import io.gitlab.jfronny.sdom.actions.SDGetContestsAction
|
import io.gitlab.jfronny.sdom.actions.SDGetContestsAction
|
||||||
import io.gitlab.jfronny.sdom.actions.SDGetProblemsAction
|
import io.gitlab.jfronny.sdom.actions.SDGetProblemsAction
|
||||||
import io.gitlab.jfronny.sdom.model.*
|
import io.gitlab.jfronny.sdom.model.*
|
||||||
|
import io.gitlab.jfronny.sdom.model.scoreboard.Scoreboard
|
||||||
import io.gitlab.jfronny.sdom.util.notify
|
import io.gitlab.jfronny.sdom.util.notify
|
||||||
import io.ktor.client.*
|
import io.ktor.client.*
|
||||||
import io.ktor.client.call.*
|
import io.ktor.client.call.*
|
||||||
@ -29,7 +30,7 @@ import java.util.*
|
|||||||
import java.util.zip.ZipEntry
|
import java.util.zip.ZipEntry
|
||||||
import java.util.zip.ZipOutputStream
|
import java.util.zip.ZipOutputStream
|
||||||
|
|
||||||
typealias ResultFlowListener = (SharedFlow<Result<SDJudgement>>, Contest, Problem, String) -> Unit
|
typealias ResultFlowListener = (SharedFlow<Result<SDJudgement>>, Contest, SDProblem, String) -> Unit
|
||||||
|
|
||||||
object SDom {
|
object SDom {
|
||||||
private const val CONTEST_ID_PROPERTY = "io.gitlab.jfronny.sdom.contestId"
|
private const val CONTEST_ID_PROPERTY = "io.gitlab.jfronny.sdom.contestId"
|
||||||
@ -125,8 +126,9 @@ object SDom {
|
|||||||
field = value
|
field = value
|
||||||
propertiesComponent?.setValue(CONTEST_ID_PROPERTY, value?.id, "")
|
propertiesComponent?.setValue(CONTEST_ID_PROPERTY, value?.id, "")
|
||||||
}
|
}
|
||||||
var problems: List<Problem> = listOf()
|
|
||||||
var currentProblem: Problem? = null
|
var problems: Map<String, SDProblem>? = null
|
||||||
|
var currentProblem: SDProblem? = null
|
||||||
var judgementTypes: Map<String, SDJudgementType>? = null
|
var judgementTypes: Map<String, SDJudgementType>? = null
|
||||||
private var languages: Map<String, SDLanguage>? = null
|
private var languages: Map<String, SDLanguage>? = null
|
||||||
|
|
||||||
@ -154,7 +156,12 @@ object SDom {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun fetchProblems() {
|
suspend fun loadProblems() {
|
||||||
|
fetchProblems()
|
||||||
|
getSolvedProblems()
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun fetchProblems() {
|
||||||
val contest = currentContest ?: return
|
val contest = currentContest ?: return
|
||||||
val result = authenticatedClient.get(SDCredentials.url) {
|
val result = authenticatedClient.get(SDCredentials.url) {
|
||||||
url {
|
url {
|
||||||
@ -163,13 +170,35 @@ object SDom {
|
|||||||
}
|
}
|
||||||
if (result.status.isSuccess()) {
|
if (result.status.isSuccess()) {
|
||||||
problems = result.body<List<Problem>>()
|
problems = result.body<List<Problem>>()
|
||||||
|
.map { SDProblem.of(it, false) }
|
||||||
|
.associateBy { it.id }
|
||||||
|
|
||||||
if (!problems.contains(currentProblem)) {
|
if (problems?.containsValue(currentProblem) != true) {
|
||||||
currentProblem = null
|
currentProblem = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun getSolvedProblems() {
|
||||||
|
val teamId = SDCredentials.teamId ?: return // TODO ??
|
||||||
|
val contest = currentContest ?: return // TODO ??
|
||||||
|
val result = authenticatedClient.get(SDCredentials.url) {
|
||||||
|
url {
|
||||||
|
appendPathSegments("contests", contest.id, "scoreboard")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (result.status.isSuccess()) {
|
||||||
|
val scoreboard = result.body<Scoreboard>()
|
||||||
|
val solvedProblems = scoreboard.rows
|
||||||
|
.firstOrNull { it.teamId == teamId }
|
||||||
|
?.let { row ->
|
||||||
|
row.problems.associateBy { it.problemId }
|
||||||
|
}
|
||||||
|
|
||||||
|
problems?.values?.forEach { it.solved = solvedProblems?.get(it.id)?.solved ?: false }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun selectContest(contest: Contest, context: Project?) {
|
suspend fun selectContest(contest: Contest, context: Project?) {
|
||||||
currentContest = contest
|
currentContest = contest
|
||||||
|
|
||||||
@ -212,7 +241,7 @@ object SDom {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun downloadProblemStatement(contest: Contest, problem: Problem): ByteArray {
|
suspend fun downloadProblemStatement(contest: Contest, problem: SDProblem): ByteArray {
|
||||||
val response: ByteArray = authenticatedClient.get(SDCredentials.url) {
|
val response: ByteArray = authenticatedClient.get(SDCredentials.url) {
|
||||||
url {
|
url {
|
||||||
appendPathSegments("contests", contest.id, "problems", problem.id, "statement")
|
appendPathSegments("contests", contest.id, "problems", problem.id, "statement")
|
||||||
@ -228,7 +257,7 @@ object SDom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
suspend fun submitSolution(
|
suspend fun submitSolution(
|
||||||
contest: Contest, problem: Problem, solution: String, fileName: String, language: SDLanguage
|
contest: Contest, problem: SDProblem, solution: String, fileName: String, language: SDLanguage
|
||||||
): SharedFlow<Result<SDJudgement>> = coroutineScope {
|
): SharedFlow<Result<SDJudgement>> = coroutineScope {
|
||||||
val resultFlow: MutableSharedFlow<Result<SDJudgement>> = MutableSharedFlow()
|
val resultFlow: MutableSharedFlow<Result<SDJudgement>> = MutableSharedFlow()
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ class SDGetProblemsAction : DumbAwareAction() {
|
|||||||
|
|
||||||
override fun actionPerformed(e: AnActionEvent) {
|
override fun actionPerformed(e: AnActionEvent) {
|
||||||
CoroutineScope(Job() + Dispatchers.IO).launch {
|
CoroutineScope(Job() + Dispatchers.IO).launch {
|
||||||
SDom.fetchProblems()
|
SDom.loadProblems()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -11,7 +11,7 @@ import com.intellij.openapi.ui.popup.JBPopupFactory
|
|||||||
import com.intellij.openapi.util.Condition
|
import com.intellij.openapi.util.Condition
|
||||||
import com.intellij.util.ui.ColorIcon
|
import com.intellij.util.ui.ColorIcon
|
||||||
import io.gitlab.jfronny.sdom.SDom
|
import io.gitlab.jfronny.sdom.SDom
|
||||||
import io.gitlab.jfronny.sdom.model.Problem
|
import io.gitlab.jfronny.sdom.model.SDProblem
|
||||||
import java.awt.Color
|
import java.awt.Color
|
||||||
import java.awt.Dimension
|
import java.awt.Dimension
|
||||||
import javax.swing.JComponent
|
import javax.swing.JComponent
|
||||||
@ -28,7 +28,13 @@ class SDProblemSelectionComboBoxAction : ComboBoxAction(), DumbAware {
|
|||||||
override fun createPopupActionGroup(button: JComponent, dataContext: DataContext): DefaultActionGroup {
|
override fun createPopupActionGroup(button: JComponent, dataContext: DataContext): DefaultActionGroup {
|
||||||
val actionGroup = DefaultActionGroup()
|
val actionGroup = DefaultActionGroup()
|
||||||
|
|
||||||
actionGroup.addAll(SDom.problems.map { SelectProblemAction(it, it == SDom.currentProblem) })
|
actionGroup.addAll(
|
||||||
|
SDom.problems
|
||||||
|
?.values
|
||||||
|
?.sorted()
|
||||||
|
?.map { SelectProblemAction(it, it == SDom.currentProblem) }
|
||||||
|
?: emptyList()
|
||||||
|
)
|
||||||
|
|
||||||
return actionGroup
|
return actionGroup
|
||||||
}
|
}
|
||||||
@ -59,11 +65,11 @@ class SDProblemSelectionComboBoxAction : ComboBoxAction(), DumbAware {
|
|||||||
override fun shouldShowDisabledActions(): Boolean = true
|
override fun shouldShowDisabledActions(): Boolean = true
|
||||||
|
|
||||||
private class SelectProblemAction(
|
private class SelectProblemAction(
|
||||||
private val problem: Problem,
|
private val problem: SDProblem,
|
||||||
val isSelected: Boolean
|
val isSelected: Boolean
|
||||||
) : DumbAwareAction() {
|
) : DumbAwareAction() {
|
||||||
init {
|
init {
|
||||||
val name = problem.name
|
val name = (if (problem.solved) "✅ " else "") + problem.name
|
||||||
templatePresentation.setText(name, false)
|
templatePresentation.setText(name, false)
|
||||||
templatePresentation.icon = ColorIcon(13, Color.decode(problem.rgb))
|
templatePresentation.icon = ColorIcon(13, Color.decode(problem.rgb))
|
||||||
}
|
}
|
||||||
|
15
src/main/kotlin/io/gitlab/jfronny/sdom/model/SDProblem.kt
Normal file
15
src/main/kotlin/io/gitlab/jfronny/sdom/model/SDProblem.kt
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package io.gitlab.jfronny.sdom.model
|
||||||
|
|
||||||
|
data class SDProblem(val id: String, val name: String, val rgb: String, var solved: Boolean) : Comparable<SDProblem> {
|
||||||
|
companion object {
|
||||||
|
fun of(problem: Problem, solved: Boolean): SDProblem {
|
||||||
|
return SDProblem(problem.id, problem.name, problem.rgb, solved)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun compareTo(other: SDProblem): Int {
|
||||||
|
if (solved && !other.solved) return 1
|
||||||
|
if (!solved && other.solved) return -1
|
||||||
|
return name.compareTo(other.name)
|
||||||
|
}
|
||||||
|
}
|
@ -7,8 +7,8 @@ import com.intellij.openapi.wm.ToolWindow
|
|||||||
import com.intellij.openapi.wm.ToolWindowFactory
|
import com.intellij.openapi.wm.ToolWindowFactory
|
||||||
import io.gitlab.jfronny.sdom.SDom
|
import io.gitlab.jfronny.sdom.SDom
|
||||||
import io.gitlab.jfronny.sdom.model.Contest
|
import io.gitlab.jfronny.sdom.model.Contest
|
||||||
import io.gitlab.jfronny.sdom.model.Problem
|
|
||||||
import io.gitlab.jfronny.sdom.model.SDJudgement
|
import io.gitlab.jfronny.sdom.model.SDJudgement
|
||||||
|
import io.gitlab.jfronny.sdom.model.SDProblem
|
||||||
import io.gitlab.jfronny.sdom.ui.SDSubmitPanel
|
import io.gitlab.jfronny.sdom.ui.SDSubmitPanel
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@ -37,7 +37,7 @@ class SDToolWindowFactory : ToolWindowFactory, DumbAware {
|
|||||||
contentManager.addContent(loggedOutContent)
|
contentManager.addContent(loggedOutContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun showResultContent(resultFlow: Flow<Result<SDJudgement>>, contest: Contest, problem: Problem, filename: String) {
|
fun showResultContent(resultFlow: Flow<Result<SDJudgement>>, contest: Contest, problem: SDProblem, filename: String) {
|
||||||
submitPanel.logSubmission(contest, problem, filename)
|
submitPanel.logSubmission(contest, problem, filename)
|
||||||
|
|
||||||
CoroutineScope(Job() + Dispatchers.IO).launch {
|
CoroutineScope(Job() + Dispatchers.IO).launch {
|
||||||
|
@ -7,8 +7,8 @@ import com.intellij.openapi.ui.ComponentContainer
|
|||||||
import com.intellij.openapi.util.Disposer
|
import com.intellij.openapi.util.Disposer
|
||||||
import io.gitlab.jfronny.sdom.SDom
|
import io.gitlab.jfronny.sdom.SDom
|
||||||
import io.gitlab.jfronny.sdom.model.Contest
|
import io.gitlab.jfronny.sdom.model.Contest
|
||||||
import io.gitlab.jfronny.sdom.model.Problem
|
|
||||||
import io.gitlab.jfronny.sdom.model.SDJudgement
|
import io.gitlab.jfronny.sdom.model.SDJudgement
|
||||||
|
import io.gitlab.jfronny.sdom.model.SDProblem
|
||||||
import io.gitlab.jfronny.sdom.util.OutputType
|
import io.gitlab.jfronny.sdom.util.OutputType
|
||||||
import io.gitlab.jfronny.sdom.util.println
|
import io.gitlab.jfronny.sdom.util.println
|
||||||
import java.awt.BorderLayout
|
import java.awt.BorderLayout
|
||||||
@ -36,7 +36,7 @@ class SDSubmitPanel (
|
|||||||
panel.isVisible = true
|
panel.isVisible = true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun logSDJudgement(judgement: Result<SDJudgement>, contest: Contest, problem: Problem, filename: String) {
|
fun logSDJudgement(judgement: Result<SDJudgement>, contest: Contest, problem: SDProblem, filename: String) {
|
||||||
judgement.fold(
|
judgement.fold(
|
||||||
onSuccess = { result ->
|
onSuccess = { result ->
|
||||||
val parsedResult =
|
val parsedResult =
|
||||||
@ -48,6 +48,10 @@ class SDSubmitPanel (
|
|||||||
"Submission of \"$filename\" to problem \"${problem.name}\", got result: ${parsedResult.first}",
|
"Submission of \"$filename\" to problem \"${problem.name}\", got result: ${parsedResult.first}",
|
||||||
if (parsedResult.second) OutputType.SUCCESS else OutputType.ERROR
|
if (parsedResult.second) OutputType.SUCCESS else OutputType.ERROR
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (parsedResult.second) {
|
||||||
|
problem.solved = true
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onFailure = { e ->
|
onFailure = { e ->
|
||||||
console.println("Judgement failed: ${e.message}", OutputType.ERROR)
|
console.println("Judgement failed: ${e.message}", OutputType.ERROR)
|
||||||
@ -56,7 +60,7 @@ class SDSubmitPanel (
|
|||||||
panel.revalidate()
|
panel.revalidate()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun logSubmission(contest: Contest, problem: Problem, filename: String) {
|
fun logSubmission(contest: Contest, problem: SDProblem, filename: String) {
|
||||||
console.println("Submitted file \"$filename\" to problem \"${problem.name}\", Waiting for result...", OutputType.OUTPUT)
|
console.println("Submitted file \"$filename\" to problem \"${problem.name}\", Waiting for result...", OutputType.OUTPUT)
|
||||||
panel.revalidate()
|
panel.revalidate()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user