Skip to content

Commit

Permalink
add an option of round point status's points by 100
Browse files Browse the repository at this point in the history
  • Loading branch information
CoCo-Japan-pan committed Sep 15, 2023
1 parent 5737038 commit 8e49403
Showing 1 changed file with 119 additions and 42 deletions.
161 changes: 119 additions & 42 deletions atcoder-problems-frontend/src/pages/ListPage/SmallTable.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from "react";
import { Table } from "reactstrap";
import React, { useState } from "react";
import { Table, Button, ButtonGroup } from "reactstrap";
import { ProblemId } from "../../interfaces/Status";
import { isAccepted } from "../../utils";
import { countBy, groupBy } from "../../utils/GroupBy";
Expand Down Expand Up @@ -47,52 +47,129 @@ export const getUserPointCounts = (
};

export const SmallTable: React.FC<Props> = ({ submissions, setFilterFunc }) => {
const [grouped, setGrouped] = useState(true);
const mergedProblemMap =
useMergedProblemMap().data ?? new Map<ProblemId, MergedProblem>();
const userPointCountMap = getUserPointCounts(mergedProblemMap, submissions);
const totalCount = getTotalCount(mergedProblemMap);
const totalCountBy100 = totalCount.reduce(
(
ret: { point: number; count: number }[],
current: { point: number; count: number }
) => {
const roundedPoint = Math.floor(current.point / 100) * 100;
const prev = ret.find((entry) => entry.point === roundedPoint);
if (prev) {
prev.count += current.count;
} else {
ret.push({ point: roundedPoint, count: current.count });
}
return ret;
},
[]
);

const binarySearch = (
arr: { point: number; count: number }[],
target: number
) => {
let left = 0;
let right = arr.length;
while (right - left > 1) {
const mid = Math.floor((left + right) / 2);
if (arr[mid].point <= target) {
left = mid;
} else {
right = mid;
}
}
return left;
};

const getUserPointCountInArea = (
countByPoint: Map<number | null | undefined, number>,
pointStart: number,
pointEnd: number
) => {
let ret = 0;
for (
let i = binarySearch(totalCount, pointStart);
i < totalCount.length;
i++
) {
if (totalCount[i].point >= pointEnd) {
break;
}
ret += countByPoint.get(totalCount[i].point) ?? 0;
}
return ret;
};

return (
<Table striped bordered hover responsive>
<thead>
<tr>
<th>Point</th>
{totalCount.map(({ point }) => (
<th key={point}>
<a
href={window.location.hash}
onClick={(): void => setFilterFunc(point)}
>
{point}
</a>
</th>
))}
</tr>
<tr>
<th>Total</th>
{totalCount.map(({ point, count }) => (
<th key={point}>{count}</th>
))}
</tr>
</thead>
<tbody>
{userPointCountMap.map(({ userId, countByPoint }) => (
<tr key={userId}>
<td>{userId}</td>
{totalCount.map(({ point, count }) => (
<td
key={point}
className={
countByPoint.get(point) === count
? TableColor.Success
: TableColor.None
}
>
{countByPoint.get(point) ?? 0}
</td>
<>
<ButtonGroup className="mb-2">
<Button onClick={(): void => setGrouped(!grouped)}>
{grouped ? "Grouped" : "All"}
</Button>
</ButtonGroup>
<Table striped bordered hover responsive>
<thead>
<tr>
<th>Point</th>
{(grouped ? totalCountBy100 : totalCount).map(({ point }) => (
<th key={point}>
<a
href={window.location.hash}
onClick={(): void => setFilterFunc(point)}
>
{grouped ? `${point}-` : point}
</a>
</th>
))}
</tr>
))}
</tbody>
</Table>
<tr>
<th>Total</th>
{(grouped ? totalCountBy100 : totalCount).map(
({ point, count }) => (
<th key={point}>{count}</th>
)
)}
</tr>
</thead>
<tbody>
{userPointCountMap.map(({ userId, countByPoint }) => (
<tr key={userId}>
<td>{userId}</td>
{(grouped ? totalCountBy100 : totalCount).map(
({ point, count }) => (
<td
key={point}
className={
(grouped
? getUserPointCountInArea(
countByPoint,
point,
point + 100
)
: countByPoint.get(point)) === count
? TableColor.Success
: TableColor.None
}
>
{(grouped
? getUserPointCountInArea(
countByPoint,
point,
point + 100
)
: countByPoint.get(point)) ?? 0}
</td>
)
)}
</tr>
))}
</tbody>
</Table>
</>
);
};

0 comments on commit 8e49403

Please sign in to comment.