-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added Timeline #188
Added Timeline #188
Conversation
e698af6
to
e8b8b80
Compare
TimeLineRunInfo.InProgress(info.time, info.problemId) | ||
} | ||
} | ||
}.filterNotNull() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use mapNotNull instead
|
||
is RunResult.IOI -> { | ||
val ioiResult = info.result as RunResult.IOI | ||
TimeLineRunInfo.IOI(info.time, info.problemId, ioiResult.scoreAfter) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if we should use scoreAfter or score difference here. With score after, maybe we can show only improvements.
is RunResult.ICPC -> { | ||
val icpcResult = info.result as RunResult.ICPC | ||
if (!acceptedProblems.contains(info.problemId)) { | ||
if (icpcResult.verdict == Verdict.Accepted) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's better to use .isAccepted instead of equality check
@@ -28,13 +29,52 @@ fun Route.configureOverlayRouting() { | |||
flowEndpoint("/mainScreen") { DataBus.mainScreenFlow.await() } | |||
flowEndpoint("/contestInfo") { DataBus.currentContestInfoFlow() } | |||
flowEndpoint("/runs") { DataBus.contestStateFlow.await().map { it.runsAfterEvent.values.sortedBy { it.time } } } | |||
webSocket("/teamRuns") { | |||
val teamIdStr = (incoming.receive() as? Frame.Text)?.readText() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we don't want to be able to subscribe to more teams over the existing webSocket, why send this instead of adding to name?
} | ||
val teamId = teamIdStr.toTeamId() | ||
sendJsonFlow(DataBus.contestStateFlow.await().map { state -> | ||
state.runsAfterEvent.values.filter { it.teamId == teamId } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is a bit too time-consuming. Probably we should process events ourselves, ignoring events except known teams.
Something like (didn't run or test to be compilable, just as main idea)
contestStateFlow
.mapNotNull { (it.event as? RunEvent)?.newInfo }
.runningFold(persistentMapOf<RunId, RunInfo>()) { acc, it ->
if (it.teamId == teamId) acc.put(it.id, it) else if (it.runId in acc) acc.remove(it.runId) else acc
}
.distintUntilChanged { a, b -> a === b }
.map { it.value.sortedBy { it.time } }
val acceptedProblems = mutableSetOf<ProblemId>() | ||
val allRuns = mutableMapOf<RunId, RunInfo>() | ||
DataBus.contestStateFlow.await().first().runsAfterEvent.values | ||
.filter { teamId == it.teamId && it.time.toLong(DurationUnit.MILLISECONDS) != 0L } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
!= Duration.ZERO
val teamId = teamIdStr.toTeamId() | ||
val acceptedProblems = mutableSetOf<ProblemId>() | ||
val allRuns = mutableMapOf<RunId, RunInfo>() | ||
DataBus.contestStateFlow.await().first().runsAfterEvent.values |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tbh, I don't like how it ended, but let's proceed with this, I'll rewrite this part later, not sure how exactly.
return ( | ||
<ProblemWrap left={left + "%"}> | ||
<Circle color={getColor(problemResult)}> | ||
<Label darkText={darkText} isBold={problemResult.type === "IN_PROGRESS"}> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's use generated ts constants instead. You can add class into list in build.gradle.kts ins scheme generator, if it is not generated.
const TextWithAnimation = styled.div` | ||
animation: ${ChangeTextAnimation} 10s infinite; | ||
justify-content: center; | ||
position: absolute; | ||
align-items: center; | ||
text-align: center; | ||
`; | ||
|
||
const TextWithAnimation2 = styled.div` | ||
animation: ${ChangeTextAnimation2} 10s infinite; | ||
justify-content: center; | ||
position: absolute; | ||
align-items: center; | ||
text-align: center; | ||
font-size: 12px; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Может, придумать какие-то более разумные названия?
@@ -0,0 +1,182 @@ | |||
import React, { useEffect, useState } from "react"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Может, сразу назвать файл TimeLine.tsx и навесить типы?
const getColor = (problemResult) => { | ||
if (problemResult.type === RunResult.Type.IN_PROGRESS) { | ||
return c.VERDICT_UNKNOWN; | ||
} else if (problemResult.type === RunResult.Type.ICPC) { | ||
if (problemResult.isAccepted) { | ||
return c.VERDICT_OK; | ||
} else { | ||
return c.VERDICT_NOK; | ||
} | ||
} else { | ||
const task = contestInfo.problems.find(info => info.letter === problemResult.problemId); | ||
return getIOIColor(problemResult.score, task?.minScore, task?.maxScore); | ||
} | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Наверное, можно наружу от функции компонента вынести? Ну или useMemo?
useEffect(() => { | ||
const socket = new WebSocket(c.BASE_URL_WS + "/teamRuns/" + teamId); | ||
socket.onopen = function () { | ||
console.log("WebSocket is open"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Здесь и ниже может быь лучше console.debug + добавить какую-то информацию про то, что за вебсокет?
No description provided.