Skip to content

Commit

Permalink
Revert "Try to support scoreboard diff"
Browse files Browse the repository at this point in the history
This reverts commit 8bea34e.
  • Loading branch information
irdkwmnsb committed Apr 15, 2024
1 parent 52c7e4c commit 9705e42
Show file tree
Hide file tree
Showing 11 changed files with 84 additions and 97 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { ShrinkingBox } from "../../atoms/ShrinkingBox";
import { RankLabel } from "../../atoms/ContestLabels";
import { formatScore, useFormatPenalty } from "@/services/displayUtils";
import { useAppSelector } from "@/redux/hooks";
import { Award } from "@shared/api";


const ContestantInfoLabel = styled(RankLabel)`
Expand Down Expand Up @@ -49,12 +48,10 @@ const ContestantInfoScoreLabel = styled(ShrinkingBox)`
export const ContestantInfo = ({ teamId, roundBR= true, className = null }) => {
const contestInfo = useAppSelector((state) => state.contestInfo.info);
const scoreboardData = useAppSelector((state) => state.scoreboard[SCOREBOARD_TYPES.normal].ids[teamId]);
const awards = useAppSelector((state) => state.scoreboard[SCOREBOARD_TYPES.normal].idAwards[teamId]);
const medal = awards.find((award) => award.type == Award.Type.medal) as Award.medal;
const teamData = useAppSelector((state) => state.contestInfo.info?.teamsId[teamId]);
const formatPenalty = useFormatPenalty();
return <ContestantInfoWrap round={roundBR} className={className}>
<ContestantInfoLabel rank={scoreboardData?.rank} medal={medal?.medalColor}/>
<ContestantInfoLabel rank={scoreboardData?.rank} medal={scoreboardData?.medalType}/>
<ContestantInfoTeamNameLabel text={teamData?.shortName ?? "??"}/>
<ContestantInfoScoreLabel align={"right"}
text={scoreboardData === null ? "??" : formatScore(scoreboardData?.totalScore ?? 0.0, 1)}/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ interface ContestantViewLineProps {
}

export const ContestantViewLine = ({ teamId, isSmall, className, isTop }: ContestantViewLineProps) => {
const scoreboardData = useAppSelector((state) => state.scoreboard[SCOREBOARD_TYPES.normal]?.ids[teamId]);
const scoreboardData: LegacyScoreboardRow = useAppSelector((state) => state.scoreboard[SCOREBOARD_TYPES.normal]?.ids[teamId]);
// for (let i = 0; i < scoreboardData?.problemResults.length; i++) {
// scoreboardData.problemResults[i]["index"] = i;
// }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ const TickerScoreboardContestantInfo = styled(ContestantInfo)`
export const Scoreboard = ({ tickerSettings, state }) => {
const { from, to, periodMs } = tickerSettings;
const [row, setRow] = useState(0);
const order = useAppSelector((state) => state.scoreboard[SCOREBOARD_TYPES.normal].order.slice(from-1, to));
const nrows = Math.ceil(order.length / 4);
const rows = useAppSelector((state) => state.scoreboard[SCOREBOARD_TYPES.normal].rows.slice(from-1, to));
const nrows = Math.ceil(rows.length / 4);
useEffect(() => {
if(state !== "entering" && order.length > 0) {
if(state !== "entering" && rows.length > 0) {
const interval = setInterval(() => {
if (state !== "exiting") {
setRow((row) => {
Expand All @@ -48,13 +48,13 @@ export const Scoreboard = ({ tickerSettings, state }) => {
}, (periodMs - c.TICKER_SCROLL_TRANSITION_TIME) / nrows / c.TICKER_SCOREBOARD_REPEATS + 1);
return () => clearInterval(interval);
}
}, [nrows, periodMs, state, order.length]);
}, [nrows, periodMs, state, rows.length]);

// This fugliness is needed to scroll the scoreboard
return (
<ScoreboardWrap nrows={nrows*2} top={`calc(${-row * 100 }% - ${row * 2}px)`}>
{order.map((teamId) => (
<TickerScoreboardContestantInfo key={teamId} teamId={teamId}/>
{rows.map((row) => (
<TickerScoreboardContestantInfo key={row.teamId} teamId={row.teamId}/>
))}
</ScoreboardWrap>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import star from "../../../assets/icons/star.svg";
import star_mask from "../../../assets/icons/star_mask.svg";
import { formatScore } from "@/services/displayUtils";
import { useAppSelector } from "@/redux/hooks";
import { Award, RunInfo, Widget } from "@shared/api";
import { RunInfo, Widget } from "@shared/api";
import { isFTS } from "@/utils/statusInfo";

// const MAX_QUEUE_ROWS_COUNT = 20;
Expand Down Expand Up @@ -297,13 +297,12 @@ export const QueueRow = ({ runInfo,
const scoreboardData = useAppSelector((state) => state.scoreboard[SCOREBOARD_TYPES.normal].ids[runInfo.teamId]);
const teamData = useAppSelector((state) => state.contestInfo.info?.teamsId[runInfo.teamId]);
const probData = useAppSelector((state) => state.contestInfo.info?.problemsId[runInfo.problemId]);
const awards = useAppSelector((state) => state.scoreboard[SCOREBOARD_TYPES.normal].idAwards[runInfo.teamId]);
const medal = awards?.find((award) => award.type == Award.Type.medal) as Award.medal;
const isFTSRun = runInfo?.result?.type === "ICPC" && runInfo.result.isFirstToSolveRun || runInfo?.result?.type === "IOI" && runInfo.result.isFirstBestRun;

return <StyledQueueRow
// flashing={flashing}
>
<QueueRankLabel rank={scoreboardData?.rank} medal={medal?.medalColor}/>
<QueueRankLabel rank={scoreboardData?.rank} medal={scoreboardData?.medalType}/>
<QueueTeamNameLabel text={teamData?.shortName ?? "??"}/>
<QueueScoreLabel align={"right"}
text={scoreboardData === null ? "??" : formatScore(scoreboardData?.totalScore ?? 0.0, 1)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@ import { ShrinkingBox } from "../../atoms/ShrinkingBox";
import { formatScore, useFormatPenalty, useNeedPenalty } from "@/services/displayUtils";
import { useElementSize } from "usehooks-ts";
import { useAppSelector } from "@/redux/hooks";
import { Award, LegacyScoreboardRow, OptimismLevel, ScoreboardSettings } from "@shared/api";
import { LegacyScoreboardRow, OptimismLevel, ScoreboardSettings } from "@shared/api";
import { ScoreboardData } from "@/redux/contest/scoreboard";
import { SCOREBOARD_TYPES } from "@/consts";


const ScoreboardWrap = styled.div`
Expand Down Expand Up @@ -127,12 +126,10 @@ export const ScoreboardRow = ({ teamId,
const scoreboardData = useAppSelector((state) => state.scoreboard[optimismLevel].ids[teamId]);
const contestData = useAppSelector((state) => state.contestInfo.info);
const teamData = useAppSelector((state) => state.contestInfo.info?.teamsId[teamId]);
const awards = useAppSelector((state) => state.scoreboard[SCOREBOARD_TYPES.normal].idAwards[teamId]);
const medal = awards?.find((award) => award.type == Award.Type.medal) as Award.medal;
const needPenalty = useNeedPenalty();
const formatPenalty = useFormatPenalty();
return <ScoreboardRowWrap nProblems={contestData?.problems?.length ?? 1} needPenalty={needPenalty}>
<ScoreboardRankLabel rank={scoreboardData?.rank} medal={medal?.medalColor}/>
<ScoreboardRankLabel rank={scoreboardData?.rank} medal={scoreboardData?.medalType}/>
<ScoreboardRowName align={c.SCOREBOARD_CELL_TEAMNANE_ALIGN} text={teamData?.shortName ?? "??"}/>
<ShrinkingBox align={c.SCOREBOARD_CELL_POINTS_ALIGN}
text={scoreboardData === null ? "??" : formatScore(scoreboardData?.totalScore ?? 0.0, 1)}/>
Expand Down Expand Up @@ -177,16 +174,8 @@ const ScoreboardRowsWrap = styled.div<{maxHeight: number}>`
max-height: ${({ maxHeight }) => `${maxHeight}px`};
`;

export const useScoreboardRows = (optimismLevel: OptimismLevel, selectedGroup: string) => {
const order = useAppSelector((state) => state.scoreboard[optimismLevel]?.orderById);
const teamsId = useAppSelector((state) => state.contestInfo.info?.teamsId);
if (teamsId === undefined || order === undefined) {
return [];
}
return Object.entries(order)
.filter(([k]) =>
selectedGroup === "all" || (teamsId[k]?.groups ?? []).includes(selectedGroup));
};
export const extractScoreboardRows = (data: ScoreboardData, selectedGroup) =>
data.rows.filter(t => selectedGroup === "all" || (t?.teamGroups ?? []).includes(selectedGroup));

/**
* Scollbar for scoreboard
Expand Down Expand Up @@ -225,13 +214,21 @@ interface ScoreboardRowsProps {
}

export const ScoreboardRows = ({ settings, onPage }: ScoreboardRowsProps) => {
const rows = useScoreboardRows(settings.optimismLevel, settings.group);
const rows = extractScoreboardRows(
useAppSelector((state) => state.scoreboard[settings.optimismLevel]),
settings.group);
const teams = _(rows)
.map((el, i): [number, LegacyScoreboardRow] => [i, el])
.sortBy("[1].teamId")
.value();
const rowHeight = c.SCOREBOARD_ROW_HEIGHT + c.SCOREBOARD_ROW_PADDING;
const scrollPos = useScroller(rows.length, onPage, c.SCOREBOARD_SCROLL_INTERVAL, settings.startFromRow - 1, settings.numRows);
return <ScoreboardRowsWrap maxHeight={onPage * rowHeight}>
{rows.map(([teamId, position]) =>
<PositionedScoreboardRow key={teamId} zIndex={rows.length-position} pos={(position - scrollPos) * rowHeight - c.SCOREBOARD_ROW_PADDING}>
<ScoreboardRow teamId={teamId} optimismLevel={settings.optimismLevel}/>
{teams.map(([index, teamData]) =>
<PositionedScoreboardRow key={teamData.teamId} zIndex={rows.length-index} pos={(index - scrollPos) * rowHeight - c.SCOREBOARD_ROW_PADDING}>
<ScoreboardRow teamId={teamData.teamId} optimismLevel={settings.optimismLevel}
// hideTasks={settings} // I currently have no idea what hidetasks was so..
/>
</PositionedScoreboardRow>
)}
</ScoreboardRowsWrap>;
Expand Down
6 changes: 3 additions & 3 deletions src/frontend/overlay/src/consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ export const WEBSOCKETS = {
queue: "queue",
statistics: "statistics",
ticker: "ticker",
scoreboardNormal: "scoreboard/v2/normal",
scoreboardOptimistic: "scoreboard/v2/optimistic",
scoreboardPessimistic: "scoreboard/v2/pessimistic",
scoreboardNormal: "scoreboard/normal",
scoreboardOptimistic: "scoreboard/optimistic",
scoreboardPessimistic: "scoreboard/pessimistic",
...WEBSOCKETS_OVERRIDE
};

Expand Down
2 changes: 1 addition & 1 deletion src/frontend/overlay/src/redux/contest/contestInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const ActionTypes = {
type ContestState = {
info: (ContestInfo & {
teamsId: Record<TeamInfo["id"], TeamInfo>,
problemsId: Record<ProblemInfo["id"], ProblemInfo>,
problemsId: Record<ProblemInfo["id"], ProblemInfo>
}) | undefined
}

Expand Down
93 changes: 44 additions & 49 deletions src/frontend/overlay/src/redux/contest/scoreboard.ts
Original file line number Diff line number Diff line change
@@ -1,62 +1,57 @@
import _ from "lodash";
import { Award, OptimismLevel, ScoreboardDiff, ScoreboardRow, TeamId } from "@shared/api";
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { LegacyScoreboardRow, OptimismLevel } from "@shared/api";

const ActionTypes = {
SCOREBOARD_SET: "SCOREBOARD_SET",
};

export type ScoreboardData = {
ids: Record<TeamId, ScoreboardRow & {rank: number}>, // maybe stable?
idAwards: Record<TeamId, undefined | Exclude<Award, "teams">[]>,
order: TeamId[],
orderById: Record<TeamId, number>,
ranks: number[],
awards: Award[]
rows: LegacyScoreboardRow[],
ids: Record<LegacyScoreboardRow["teamId"], LegacyScoreboardRow>
};

export type ScoreboardState = {
[key in OptimismLevel]: ScoreboardData
}

const initialState: ScoreboardState = Object.fromEntries(
Object.keys(OptimismLevel).map((key) => [key, {
ids: {},
idAwards: {},
order: [],
ranks: [],
awards: []
}])
) as ScoreboardState;
const initialState: ScoreboardState = {
[OptimismLevel.normal]: {
rows: [],
ids: {}
},
[OptimismLevel.optimistic]: {
rows: [],
ids: {}
},
[OptimismLevel.pessimistic]: {
rows: [],
ids: {}
}
};

const scoreboardSlice = createSlice({
name: "scoreboard",
initialState,
reducers: {
handleScoreboardDiff(state, action: PayloadAction<{ optimism: OptimismLevel, diff: ScoreboardDiff }>) {
const { optimism, diff } = action.payload;
state[optimism].awards = diff.awards;
state[optimism].order = diff.order;
state[optimism].ranks = diff.ranks;
const rankMap = Object.fromEntries(_.zip(diff.order, diff.ranks));
for (const [id, newData] of Object.entries(diff.rows)) {
state[optimism].ids[id] = {
...newData,
rank: rankMap[id]
};
export const setScoreboard = (scoreboardType, rows) => {
return async dispatch => {
dispatch({
type: ActionTypes.SCOREBOARD_SET,
payload: {
type: scoreboardType,
rows: rows
}
state[optimism].orderById = Object.fromEntries(
diff.order.map((teamId, index) => [teamId, index])
);
state[optimism].idAwards = {};
for (const award of diff.awards) {
for (const teamId of award.teams) {
if(state[optimism].idAwards[teamId] === undefined) {
state[optimism].idAwards[teamId] = [];
}
state[optimism].idAwards[teamId].push({ ...award, teams: undefined });
}
});
};
};

export function scoreboardReducer(state = initialState, action): ScoreboardState {
switch (action.type) {
case ActionTypes.SCOREBOARD_SET:
return {
...state,
[action.payload.type]: {
rows: action.payload.rows,
ids: _.keyBy(action.payload.rows, "teamId")
}
}
};
default:
return state;
}
});

export const { handleScoreboardDiff } = scoreboardSlice.actions;

export default scoreboardSlice.reducer;
}
2 changes: 1 addition & 1 deletion src/frontend/overlay/src/redux/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// import thunkMiddleware from "redux-thunk";
import { contestInfoReducer } from "./contest/contestInfo";
import { queueReducer } from "./contest/queue";
import scoreboardReducer from "./contest/scoreboard";
import { scoreboardReducer } from "./contest/scoreboard";
import debugReducer from "./debug";
import statusReducer from "./status";
import { widgetsReducer } from "./widgets";
Expand Down
10 changes: 5 additions & 5 deletions src/frontend/overlay/src/services/ws/scoreboard.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { handleScoreboardDiff } from "../../redux/contest/scoreboard";
import { OptimismLevel, ScoreboardDiff } from "@shared/api";
import { setScoreboard } from "../../redux/contest/scoreboard";
import { LegacyScoreboard } from "@shared/api";

export const handleMessage = (optimism: OptimismLevel) => (dispatch, e) => {
const diff = JSON.parse(e.data) as ScoreboardDiff;
dispatch(handleScoreboardDiff({ optimism, diff }));
export const handleMessage = (type) => (dispatch, e) => {
const message = JSON.parse(e.data) as LegacyScoreboard;
dispatch(setScoreboard(type, message.rows));
};
7 changes: 3 additions & 4 deletions src/frontend/overlay/src/services/ws/ws.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { handleMessage as queueHandler } from "./queue";
import { handleMessage as scoreboardHandler } from "./scoreboard";
import { handleMessage as statisticsHandler } from "./statistics";
import { handleMessage as tickerHandler } from "./ticker";
import { OptimismLevel } from "@shared/api";


const handler = {
Expand All @@ -33,9 +32,9 @@ const handler = {
export const WEBSOCKET_HANDLERS = new Proxy({
mainScreen: mainScreenHandler,
queue: queueHandler,
scoreboardOptimistic: scoreboardHandler(OptimismLevel.optimistic),
scoreboardNormal: scoreboardHandler(OptimismLevel.normal),
scoreboardPessimistic: scoreboardHandler(OptimismLevel.pessimistic),
scoreboardOptimistic: scoreboardHandler(SCOREBOARD_TYPES.optimistic),
scoreboardNormal: scoreboardHandler(SCOREBOARD_TYPES.normal),
scoreboardPessimistic: scoreboardHandler(SCOREBOARD_TYPES.pessimistic),
contestInfo: contestInfoHandler,
ticker: tickerHandler,
statistics: statisticsHandler,
Expand Down

0 comments on commit 9705e42

Please sign in to comment.