Skip to content

Commit

Permalink
feat: org rank
Browse files Browse the repository at this point in the history
  • Loading branch information
GZTimeWalker committed Aug 28, 2022
1 parent 3d57b36 commit bde5d38
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 15 deletions.
11 changes: 9 additions & 2 deletions GZCTF/ClientApp/src/components/ChallengeDetailModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -188,9 +188,16 @@ const ChallengeDetailModal: FC<ChallengeDetailModalProps> = (props) => {
setFlag('')
checkDataFlag(res.data)
clearInterval(polling)
setDisabled(false)
}
})
.catch(showErrorNotification)
.catch((err) => {
setOnSubmitting(false)
setFlag('')
showErrorNotification(err)
clearInterval(polling)
setDisabled(false)
})
}, 500)
return () => clearInterval(polling)
}, [submitId])
Expand Down Expand Up @@ -219,7 +226,7 @@ const ChallengeDetailModal: FC<ChallengeDetailModalProps> = (props) => {
updateNotification({
id: 'flag-submitted',
color: 'yellow',
message: 'Flag 状态未知,后续请求还没写……',
message: 'Flag 状态未知',
icon: <Icon path={mdiLoading} size={1} />,
disallowClose: true,
})
Expand Down
47 changes: 38 additions & 9 deletions GZCTF/ClientApp/src/components/ScoreboardTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
Stack,
Pagination,
Title,
Select,
} from '@mantine/core'
import { Icon } from '@mdi/react'
import api, { ChallengeInfo, ChallengeTag, ScoreboardItem, SubmissionType } from '@Api'
Expand Down Expand Up @@ -54,16 +55,16 @@ const useStyles = createStyles((theme) => ({
},
}))

const Lefts = [0, 40, 190, 260, 315]
const Widths = Array(4).fill(0)
const Lefts = [0, 40, 80, 230, 300, 355]
const Widths = Array(5).fill(0)
Lefts.forEach((val, idx) => {
Widths[idx - 1 || 0] = val - Lefts[idx - 1 || 0]
})

const TableHeader = (table: Record<string, ChallengeInfo[]>) => {
const { classes, cx, theme } = useStyles()

const hiddenCol = [...Array(4).keys()].map((i) => (
const hiddenCol = [...Array(5).keys()].map((i) => (
<th
key={i}
className={cx(classes.theadFixLeft, classes.noBorder)}
Expand Down Expand Up @@ -103,7 +104,7 @@ const TableHeader = (table: Record<string, ChallengeInfo[]>) => {
</tr>
{/* Headers & Score */}
<tr>
{['排名', '战队', '解题数量', '总分'].map((header, idx) => (
{['总排名', '排名', '战队', '解题数量', '总分'].map((header, idx) => (
<th
key={idx}
className={cx(classes.theadFixLeft, classes.theadHeader)}
Expand All @@ -126,18 +127,22 @@ const TableHeader = (table: Record<string, ChallengeInfo[]>) => {

const TableRow: FC<{
item: ScoreboardItem
orgRank: number
onOpenDetail: () => void
iconMap: Map<SubmissionType, React.ReactNode>
challenges?: Record<string, ChallengeInfo[]>
}> = ({ item, challenges, onOpenDetail, iconMap }) => {
}> = ({ item, challenges, onOpenDetail, iconMap, orgRank }) => {
const { classes, cx } = useStyles()
const solved = item.challenges?.filter((c) => c.type !== SubmissionType.Unaccepted)
return (
<tr>
<td className={cx(classes.theadMono, classes.theadFixLeft)} style={{ left: Lefts[0] }}>
{item.rank}
</td>
<td className={cx(classes.theadFixLeft)} style={{ left: Lefts[1] }}>
<td className={cx(classes.theadMono, classes.theadFixLeft)} style={{ left: Lefts[1] }}>
{orgRank}
</td>
<td className={cx(classes.theadFixLeft)} style={{ left: Lefts[2] }}>
<Group position="left" spacing={5} noWrap onClick={onOpenDetail}>
<Avatar
src={item.avatar}
Expand Down Expand Up @@ -168,10 +173,10 @@ const TableRow: FC<{
</Text>
</Group>
</td>
<td className={cx(classes.theadMono, classes.theadFixLeft)} style={{ left: Lefts[2] }}>
<td className={cx(classes.theadMono, classes.theadFixLeft)} style={{ left: Lefts[3] }}>
{solved?.length}
</td>
<td className={cx(classes.theadMono, classes.theadFixLeft)} style={{ left: Lefts[3] }}>
<td className={cx(classes.theadMono, classes.theadFixLeft)} style={{ left: Lefts[4] }}>
{solved?.reduce((acc, cur) => acc + (cur?.score ?? 0), 0)}
</td>
{challenges &&
Expand Down Expand Up @@ -205,16 +210,39 @@ const ScoreboardTable: FC = () => {
})
const { iconMap } = SubmissionTypeIconMap(1)
const [activePage, setPage] = useState(1)
const [organization, setOrganization] = useState<string | null>('')

const filtered = !organization
? scoreboard?.items
: scoreboard?.items?.filter((s) => s.organization === organization)

const base = (activePage - 1) * ITEM_COUNT_PER_PAGE
const currentItems = scoreboard?.items?.slice(base, base + ITEM_COUNT_PER_PAGE)
const currentItems = filtered?.slice(base, base + ITEM_COUNT_PER_PAGE)

const [currentItem, setCurrentItem] = useState<ScoreboardItem | null>(null)
const [itemDetailOpened, setItemDetailOpened] = useState(false)

return (
<Paper shadow="md" p="md">
<Stack spacing="xs">
{scoreboard?.organizations && scoreboard.organizations.length > 0 && (
<Group>
<Select
defaultValue=""
data={[
{ value: '', label: '总排行' },
...scoreboard.organizations.map((o) => ({ value: o, label: o })),
]}
value={organization}
onChange={setOrganization}
styles={{
input: {
width: 300,
},
}}
/>
</Group>
)}
<Box style={{ position: 'relative' }}>
<Box style={{ maxWidth: '100%', overflow: 'scroll' }}>
<Table className={classes.table}>
Expand All @@ -224,6 +252,7 @@ const ScoreboardTable: FC = () => {
currentItems?.map((item, idx) => (
<TableRow
key={base + idx}
orgRank={base + idx + 1}
item={item}
onOpenDetail={() => {
setCurrentItem(item)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ const GameChallengeEdit: FC = () => {
nothingFound="没有找到标签"
clearButtonLabel="显示全部"
value={category}
onChange={(value) => setCategory(value as ChallengeTag)}
onChange={(value: ChallengeTag) => setCategory(value)}
itemComponent={ChallengeTagItem}
data={Object.entries(ChallengeTag).map((tag) => {
const data = ChallengeTagLabelMap.get(tag[1])
Expand Down
14 changes: 13 additions & 1 deletion GZCTF/Controllers/GameController.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using CTFServer.Middlewares;
using CTFServer.Models;
using CTFServer.Models.Request.Admin;
using CTFServer.Models.Request.Edit;
using CTFServer.Models.Request.Game;
Expand Down Expand Up @@ -155,6 +156,7 @@ public async Task<IActionResult> JoinGame(int id, [FromBody] GameJoinModel model
else
{
part.Status = ParticipationStatus.Pending;
part.Organization = model.Organization;
await participationRepository.SaveAsync(token);

return Ok();
Expand All @@ -167,7 +169,17 @@ public async Task<IActionResult> JoinGame(int id, [FromBody] GameJoinModel model
if (await participationRepository.CheckRepeatParticipation(team!, game, token))
return BadRequest(new RequestResponse("队伍中有成员重复报名"));

await participationRepository.CreateParticipation(team!, game, model.Organization, token);
part = await participationRepository.CreateParticipation(team!, game, model.Organization, token);

if (part is not null && game.AcceptWithoutReview)
{
part.Status = ParticipationStatus.Accepted;

// will also update participation status
if (await participationRepository.EnsureInstances(part, game, token))
// flush scoreboard when instances are updated
gameRepository.FlushScoreboard(game.Id);
}

logger.Log($"[{team!.Name}] 成功报名了比赛 [{game.Title}]", user, TaskStatus.Success);

Expand Down
3 changes: 1 addition & 2 deletions GZCTF/Repositories/ParticipationRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ public async Task<Participation> CreateParticipation(Team team, Game game, strin
{
Game = game,
Team = team,
Organization = organization,
Status = game.AcceptWithoutReview ? ParticipationStatus.Accepted : ParticipationStatus.Pending
Organization = organization
};

await context.AddAsync(participation, token);
Expand Down

0 comments on commit bde5d38

Please sign in to comment.