11import {
22 Button ,
3+ ButtonGroup ,
34 Col ,
45 DropdownItem ,
56 DropdownMenu ,
@@ -15,11 +16,13 @@ import {
1516} from "reactstrap" ;
1617import React , { useState } from "react" ;
1718import {
19+ useContests ,
1820 useMultipleUserSubmissions ,
1921 useProblemModelMap ,
2022 useProblems ,
2123} from "../api/APIClient" ;
2224import Problem from "../interfaces/Problem" ;
25+ import Contest from "../interfaces/Contest" ;
2326import { shuffleArray } from "../utils" ;
2427import {
2528 ExcludeOption ,
@@ -29,6 +32,7 @@ import {
2932 getLastSolvedTimeMap ,
3033 getMaximumExcludeElapsedSecond ,
3134} from "../utils/LastSolvedTime" ;
35+ import { classifyContest } from "../utils/ContestClassifier" ;
3236import { isProblemModelWithDifficultyModel } from "../interfaces/ProblemModel" ;
3337
3438interface Props {
@@ -90,13 +94,30 @@ export const ProblemSetGenerator: React.FC<Props> = (props) => {
9094 ) ;
9195 const [ excludeExperimental , setExcludeExperimental ] = useState ( false ) ;
9296 const [ excludeOption , setExcludeOption ] = useState < ExcludeOption > ( "Exclude" ) ;
97+ const [ contestTypeOption , setContestTypeOption ] = useState ( {
98+ ABC : true ,
99+ ARC : true ,
100+ AGC : true ,
101+ ABC_Like : true ,
102+ ARC_Like : true ,
103+ AGC_Like : true ,
104+ } ) ;
93105 const [ selectedPreset , setSelectedPreset ] = useState ( ABC_PRESET ) ;
94106 const problems = useProblems ( ) ?? [ ] ;
95107 const problemModels = useProblemModelMap ( ) ;
96108 const submissions =
97109 useMultipleUserSubmissions ( props . expectedParticipantUserIds ) . data ?? [ ] ;
98110 const alreadySolvedProblemIds = new Set ( submissions . map ( ( s ) => s . problem_id ) ) ;
99111 const lastSolvedTimeMap = getLastSolvedTimeMap ( submissions ) ;
112+ const { data : contests } = useContests ( ) ;
113+
114+ const contestTypeKeyToDisplayName = ( key : string ) => {
115+ if ( key . includes ( "Like" ) ) {
116+ return key . replace ( "_" , "-" ) ;
117+ } else {
118+ return key ;
119+ }
120+ } ;
100121
101122 return (
102123 < Form className = { "w-100" } >
@@ -142,6 +163,31 @@ export const ProblemSetGenerator: React.FC<Props> = (props) => {
142163 </ InputGroup >
143164 </ Col >
144165 </ FormGroup >
166+ < FormGroup row >
167+ < Col sm = { 6 } >
168+ < Label > Include / Exclude Contest Types</ Label >
169+ < InputGroup >
170+ < ButtonGroup >
171+ { Object . keys ( contestTypeOption ) . map ( ( contestType ) => {
172+ return (
173+ < Button
174+ key = { contestType }
175+ active = { contestTypeOption [ contestType ] as boolean }
176+ onClick = { ( ) : void => {
177+ setContestTypeOption ( {
178+ ...contestTypeOption ,
179+ [ contestType ] : ! contestTypeOption [ contestType ] ,
180+ } ) ;
181+ } }
182+ >
183+ { contestTypeKeyToDisplayName ( contestType ) }
184+ </ Button >
185+ ) ;
186+ } ) }
187+ </ ButtonGroup >
188+ </ InputGroup >
189+ </ Col >
190+ </ FormGroup >
145191 < FormGroup row >
146192 < Col sm = { 6 } >
147193 < Label > Difficulty Adjustment Preset</ Label >
@@ -278,6 +324,26 @@ export const ProblemSetGenerator: React.FC<Props> = (props) => {
278324 } ) ;
279325 }
280326
327+ let candidateContests : Contest [ ] = [ ] ;
328+ Object . keys ( contestTypeOption ) . forEach ( ( contestType ) => {
329+ if ( contestTypeOption [ contestType ] ) {
330+ const filteredContests = contests . filter ( ( contest ) => {
331+ return (
332+ contestTypeKeyToDisplayName ( contestType ) ===
333+ classifyContest ( contest )
334+ ) ;
335+ } ) ;
336+ candidateContests = candidateContests . concat (
337+ filteredContests
338+ ) ;
339+ }
340+ } ) ;
341+ candidateProblems = candidateProblems . filter ( ( p ) => {
342+ return candidateContests
343+ . map ( ( contest ) => contest . id )
344+ . includes ( p . problem . contest_id ) ;
345+ } ) ;
346+
281347 candidateProblems = candidateProblems . filter ( ( p ) => {
282348 if ( excludeOption === "Exclude submitted" ) {
283349 return ! alreadySolvedProblemIds . has ( p . problem . id ) ;
0 commit comments