Skip to content

Commit ba4ed82

Browse files
Accuracy information on doc (kyuridenamida#103)
* kyuridenamida#101 Accuracy information on doc * random improvement of layout (still awkward) * remove unused code
1 parent fab8693 commit ba4ed82

File tree

5 files changed

+165
-6
lines changed

5 files changed

+165
-6
lines changed

webapp/copy_ts_model_definition.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import json
2+
3+
4+
def main():
5+
with open("./src/models/QualityResult.ts", 'r') as f:
6+
res = f.read()
7+
res = res[res.find("interface"):]
8+
9+
json_str = json.dumps(res, indent=1)
10+
print("export default {};".format(json_str))
11+
12+
13+
if __name__ == "__main__":
14+
main()

webapp/generate.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,5 @@ copy_file ../README.md ${auto_gen_dir}
1212

1313
echo "Done. Please run \`build_data.sh\` as well"
1414
python3 ./copy_default_templates.py > ${auto_gen_dir}/templateData.js
15-
python3 ./copy_readme_template_section.py > ${auto_gen_dir}/README_TEMPLATE_SECTION.md
15+
python3 ./copy_readme_template_section.py > ${auto_gen_dir}/README_TEMPLATE_SECTION.md
16+
python3 ./copy_ts_model_definition.py > ${auto_gen_dir}/qualityResultDefinition.js

webapp/src/common/Hidable.tsx

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import * as React from 'react';
2+
import { Collapse, Button } from 'reactstrap';
3+
4+
interface ComponentProps {
5+
showButtonText: string,
6+
hideButtonText: string,
7+
visibleByDefault?: boolean,
8+
}
9+
10+
class Hidable extends React.Component<ComponentProps, {collapse: boolean}> {
11+
constructor(props) {
12+
super(props);
13+
this.toggle = this.toggle.bind(this);
14+
this.state = { collapse: !!this.props.visibleByDefault };
15+
}
16+
17+
toggle() {
18+
this.setState({ collapse: !this.state.collapse });
19+
}
20+
21+
render() {
22+
const {showButtonText, hideButtonText} = this.props;
23+
const {collapse} = this.state;
24+
return (
25+
<div>
26+
<Button size="sm" color={!collapse ? "primary" : "secondary"} onClick={this.toggle} style={{ marginBottom: '1rem' }}>{collapse ? hideButtonText : showButtonText}</Button>
27+
<Collapse isOpen={collapse}>
28+
{this.props.children}
29+
</Collapse>
30+
</div>
31+
);
32+
}
33+
}
34+
35+
export default Hidable;

webapp/src/pages/quality/summary/Code.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import SyntaxHighlighter from 'react-syntax-highlighter';
22
import { docco } from 'react-syntax-highlighter/dist/styles/hljs';
33
import * as React from "react";
4-
import Language from "../../../models/Language";
54

65
interface ComponentProps {
76
code: string,
8-
language: Language
7+
language: string,
98
}
109

1110
export default class Code extends React.Component<ComponentProps, {}> {

webapp/src/pages/quality/summary/Summary.tsx

Lines changed: 113 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as React from 'react';
2-
import {Col, Input, Label, Row} from 'reactstrap';
2+
import {Col, Input, Label, Row, Table} from 'reactstrap';
33
import ReactTable from 'react-table'
44
import qualityResultList from "../../../auto_generated/qualityResultList.js"
55
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
@@ -8,18 +8,45 @@ import "./Summary.scss";
88
import Detail from "./Detail";
99
import ProblemLink from "./ProblemLink";
1010
import Scrollable from "../../../common/Scrollable";
11+
import qualityResultDefinition from 'src/auto_generated/qualityResultDefinition.js';
12+
import Hidable from "../../../common/Hidable";
13+
import Code from "./Code";
14+
15+
16+
const filteredQualityResultList = (filterMethod) => {
17+
return qualityResultList.filter(filterMethod);
18+
};
19+
20+
21+
const isSomethingBad = (r) => r.statement_parse.error || r.format_prediction.error;
22+
23+
const getAccuracyData = (contestNameRe: string) => {
24+
const contestFilter = (r) => r.contest.contest_id.match(contestNameRe);
25+
const allContestCount = filteredQualityResultList(contestFilter).length;
26+
const correctContestCount = filteredQualityResultList((r) => !isSomethingBad(r) && contestFilter(r)).length;
27+
return [allContestCount, correctContestCount]
28+
};
29+
30+
const [allRegularContestCount, correctRegularContestCount] = getAccuracyData("(abc|arc|agc)");
31+
const [allAGC, correctAGC] = getAccuracyData("^agc");
32+
const [allARC, correctARC] = getAccuracyData("^arc");
33+
const [allABC, correctABC] = getAccuracyData("^abc");
1134

1235
export default class Summary extends React.Component<{}, {
1336
showingCode: boolean,
1437
detailedSearchMode: boolean,
38+
analysisMode: boolean,
1539
activeQualityResult: QualityResult | null,
40+
analysisQuery: string,
1641
}> {
1742
constructor(props: any) {
1843
super(props);
1944
this.state = {
2045
activeQualityResult: null,
2146
detailedSearchMode: false,
47+
analysisMode: false,
2248
showingCode: false,
49+
analysisQuery: 'r.contest.contest_id.match("(abc|agc|arc)")',
2350
}
2451
}
2552

@@ -34,6 +61,9 @@ export default class Summary extends React.Component<{}, {
3461
return this.state.activeQualityResult && problemId === this.state.activeQualityResult.problem.problem_id
3562
};
3663

64+
onQueryUpdated = (query: string) => {
65+
this.setState({analysisQuery: query});
66+
};
3767

3868
render() {
3969
const {detailedSearchMode} = this.state;
@@ -129,23 +159,103 @@ export default class Summary extends React.Component<{}, {
129159
}
130160
};
131161

162+
const analysisFilterMethod = (r) => {
163+
return eval(this.state.analysisQuery);
164+
};
165+
166+
let failedToParse = false;
167+
168+
let resultsForTable;
169+
if (this.state.analysisMode && this.state.analysisQuery.length > 0) {
170+
try {
171+
resultsForTable = filteredQualityResultList(analysisFilterMethod);
172+
} catch {
173+
resultsForTable = qualityResultList;
174+
failedToParse = true;
175+
}
176+
} else {
177+
resultsForTable = qualityResultList;
178+
}
179+
132180

133181
return <React.Fragment>
134182
<Row>
135-
<h3>各問題毎の解析結果</h3>
136183
<Col sm={12}>
184+
<Row>
185+
<Col sm={6}>
186+
<Hidable
187+
showButtonText={"入力フォーマット解析成功率を表示"}
188+
hideButtonText={"入力フォーマット解析成功率を隠す"}
189+
visibleByDefault
190+
>
191+
<h3 style={{display: "inline-block"}}>入力フォーマット解析成功率</h3>
192+
<Table>
193+
<tbody>
194+
{
195+
[
196+
["AGC", correctAGC, allAGC],
197+
["ARC", correctARC, allARC],
198+
["ABC", correctABC, allABC],
199+
["レギュラーコンテスト全体(AGC,ABC,ARC)", correctRegularContestCount, allRegularContestCount],
200+
].map(([text, correct, all]: [string, number, number]) => {
201+
return <tr key={text}>
202+
<th scope="row">{text}</th>
203+
<td> {correct} / {all} </td>
204+
<td>{Math.round(100 * correct / all)} %</td>
205+
</tr>
206+
})
207+
}
208+
</tbody>
209+
</Table>
210+
</Hidable>
211+
212+
</Col>
213+
</Row>
214+
</Col>
215+
<Col sm={12}>
216+
<h3>各問題毎の解析結果</h3>
217+
</Col>
218+
<Col sm={1}>
137219
<Label>
138220
<Input type="checkbox" checked={this.state.detailedSearchMode}
139221
onChange={() => this.setState({detailedSearchMode: !this.state.detailedSearchMode})}/>
140222
詳細検索モード
141223
</Label>
142224
</Col>
225+
<Col sm={11}>
226+
<Label>
227+
<Input type="checkbox" checked={this.state.analysisMode}
228+
onChange={() => {
229+
this.setState({analysisMode: !this.state.analysisMode})
230+
}}/>
231+
解析モード (開発者向け)
232+
</Label>
233+
</Col>
234+
{this.state.analysisMode && <Col sm={6}>
235+
<Hidable
236+
showButtonText={"QualityResultの定義を表示"}
237+
hideButtonText={"QualityResultの定義を隠す"}
238+
>
239+
<Scrollable height={300}>
240+
<Code code={qualityResultDefinition} language={"typescript"}/>
241+
</Scrollable>
242+
</Hidable>
243+
function filter(r: QualityResult) => {"{ return "}
244+
<Input style={{display: "inline-block"}}
245+
value={this.state.analysisQuery}
246+
onChange={(e) => this.onQueryUpdated(e.target.value)}
247+
placeholder={"javascript condition expression"}
248+
invalid={failedToParse}
249+
/>
250+
{"; }"}
251+
<p> {resultsForTable.length} 件マッチしました。</p>
252+
</Col>}
143253
</Row>
144254
<Row className="page-content">
145255
<Col sm={this.state.detailedSearchMode ? 12 : 6}>
146256
<ReactTable
147257
filterable
148-
data={qualityResultList}
258+
data={resultsForTable}
149259
columns={columns}
150260
defaultFilterMethod={defaultFilterMethod}
151261
pageSize={20}

0 commit comments

Comments
 (0)