]>
Commit | Line | Data |
---|---|---|
014ee8a6 MG |
1 | #!/usr/bin/perl -w |
2 | use v5.14; | |
3 | ||
4 | use Gruntmaster::Data; | |
014ee8a6 MG |
5 | |
6 | use IO::Prompter [ -style => 'bold', '-stdio', '-verbatim' ]; | |
7 | use File::Slurp qw/read_file/; | |
8 | use Term::ANSIColor qw/RED RESET/; | |
0d2f8987 | 9 | use Getopt::Long qw/:config require_order/; |
014ee8a6 MG |
10 | |
11 | ################################################## | |
12 | ||
13 | my $contest; | |
14 | ||
15 | sub cmd_help{ | |
16 | exec perldoc => $0 | |
17 | } | |
18 | ||
19 | sub prompt_file{ | |
20 | my ($meta, $name, $prefix) = @_; | |
21 | my $filename = prompt '$prefix filename', -complete => 'filenames'; | |
22 | $meta->{files}{$name}{content} = read_file $filename; | |
f1e0b2b2 | 23 | $meta->{files}{$name}{format} = prompt '$prefix format', -menu => [qw/C CPP MONO JAVA PASCAL PERL PYTHON/]; |
014ee8a6 MG |
24 | $meta->{files}{$name}{name} = prompt "$prefix filename [$filename]", -default => $filename; |
25 | } | |
26 | ||
27 | sub cmd_add{ | |
28 | my $id = shift; | |
29 | my $name = prompt 'Problem name'; | |
646feed4 | 30 | my $private = prompt('Private?', '-yn') eq 'y'; |
014ee8a6 MG |
31 | my $author = prompt 'Problem author (full name)'; |
32 | my $owner = prompt 'Problem owner (username)'; | |
33 | my $level = prompt 'Problem level', -menu => "beginner\neasy\nmedium\nhard"; | |
34 | my $statement = read_file prompt 'File with problem statement', -complete => 'filenames'; | |
35 | my %meta; | |
cd25d613 MG |
36 | my $generator = prompt 'Generator', -menu => "File\nRun\nUndef"; |
37 | my $runner = prompt 'Runner', -menu => "File\nVerifier\nInteractive"; | |
38 | my $judge = prompt 'Judge', -menu => "Absolute\nPoints"; | |
39 | my $testcnt = prompt 'Test count', '-i'; | |
014ee8a6 | 40 | |
cd25d613 MG |
41 | my $timeout = prompt 'Time limit (seconds)', '-n'; |
42 | my $olimit = prompt 'Output limit (bytes)', '-i'; | |
014ee8a6 MG |
43 | say 'Memory limits are broken, so I won\'t ask you for one'; |
44 | ||
cd25d613 | 45 | prompt_file \%meta, gen => '[Generator::Run] Generator' if $generator eq 'Run'; |
014ee8a6 | 46 | |
cd25d613 MG |
47 | if ($runner eq 'File') { |
48 | $meta{tests}[$_ - 1] = prompt "[Runner::File] Score for test ${_} [10]", '-i', -default => 10 for 1 .. $testcnt; | |
014ee8a6 MG |
49 | } |
50 | ||
cd25d613 | 51 | prompt_file \%meta, ver => '[Runner::Verifier] Verifier' if $runner eq 'Verifier'; |
014ee8a6 | 52 | |
cd25d613 | 53 | if ($runner eq 'Interactive') { |
014ee8a6 | 54 | say RED, 'WARNING: Runner::Interactive is experimental', RESET; |
cd25d613 | 55 | prompt_file \%meta, int => '[Runner::Interactive] Interactive verifier'; |
014ee8a6 MG |
56 | } |
57 | ||
646feed4 MG |
58 | insert_problem $id => ( |
59 | name => $name, | |
60 | level => $level, | |
61 | statement => $statement, | |
62 | author => $author, | |
63 | owner => $owner, | |
64 | generator => $generator, | |
65 | runner => $runner, | |
66 | judge => $judge, | |
67 | testcnt => $testcnt, | |
68 | ($private ? (private => $private) : ()), | |
69 | (defined $timeout ? (timeout => $timeout) : ()), | |
70 | (defined $olimit ? (olimit => $olimit) : ())); | |
014ee8a6 MG |
71 | set_problem_meta $id => \%meta; |
72 | PUBLISH genpage => $contest ? "ct/$contest/pb/index.html" : 'pb/index.html'; | |
73 | PUBLISH genpage => $contest ? "ct/$contest/pb/$id.html" : "pb/$id.html"; | |
74 | } | |
75 | ||
76 | sub cmd_set{ | |
77 | my $file; | |
78 | GetOptions ( 'file!' => \$file ); | |
79 | my ($id, %values) = @ARGV; | |
80 | %values = map { $_ => scalar read_file $values{$_} } keys %values if $file; | |
81 | edit_problem $id => %values; | |
82 | PUBLISH genpage => 'pb/index.html'; | |
83 | PUBLISH genpage => "pb/$id.html"; | |
84 | } | |
85 | ||
86 | sub cmd_list{ | |
87 | local $, = "\n"; | |
88 | say problems; | |
89 | } | |
90 | ||
91 | sub cmd_rm{ | |
92 | remove_problem shift; | |
93 | PUBLISH genpage => $contest ? "ct/$contest/pb/index.html" : 'pb/index.html'; | |
94 | } | |
95 | ||
96 | sub cmd_show{ | |
97 | local $_ = shift or goto &cmd_list; | |
98 | } | |
99 | ||
100 | ################################################## | |
101 | ||
102 | GetOptions ( 'contest=s' => \$contest ); | |
103 | local $Gruntmaster::Data::contest = $contest; | |
104 | my $cmd = 'cmd_' . shift; | |
105 | cmd_help unless exists $main::{$cmd}; | |
106 | no strict 'refs'; | |
107 | $cmd->(@ARGV) if exists $main::{$cmd}; | |
108 | ||
109 | 1; | |
110 | __END__ | |
111 | ||
112 | =encoding utf-8 | |
113 | ||
114 | =head1 NAME | |
115 | ||
116 | gruntmaster-problem - shell interface to Gruntmaster 6000 problems | |
117 | ||
118 | =head1 SYNOPSIS | |
119 | ||
e90402be MG |
120 | gruntmaster-problem [--contest=mycontest] add problem_id |
121 | gruntmaster-problem [--contest=mycontest] list | |
122 | gruntmaster-problem [--contest=mycontest] rm problem_id | |
123 | gruntmaster-problem [--contest=mycontest] show problem_id | |
124 | gruntmaster-problem [--contest=mycontest] set [--file] problem_id key value | |
014ee8a6 MG |
125 | |
126 | =head1 DESCRIPTION | |
127 | ||
e90402be MG |
128 | gruntmaster-problem is a tool for managing problems. |
129 | ||
130 | Select the contest with the optional argument I<--contest>. | |
131 | ||
132 | =over | |
133 | ||
134 | =item B<list> | |
135 | ||
136 | Prints the list of problems in the selected contest. | |
137 | ||
138 | =item B<show> I<id> | |
139 | ||
140 | Prints detailed information about problem I<id>. | |
141 | ||
142 | =item B<add> I<id> | |
143 | ||
144 | Adds a new problem with id I<id>. | |
145 | ||
146 | =item B<rm> I<id> | |
147 | ||
148 | Removes the problem with id I<id>. | |
149 | ||
150 | =item B<set> I<id> I<key> I<value> | |
151 | ||
152 | Sets the I<key> configuration option of problem I<id> to I<value>. | |
153 | ||
154 | =item B<set> --file I<id> I<key> I<file> | |
155 | ||
156 | Sets the I<key> configuration option of problem I<id> to the contents of the file I<file>. | |
157 | ||
158 | =back | |
159 | ||
160 | =head1 AUTHOR | |
161 | ||
162 | Marius Gavrilescu E<lt>marius@ieval.roE<gt> | |
163 | ||
164 | =head1 COPYRIGHT AND LICENSE | |
165 | ||
166 | Copyright (C) 2014 by Marius Gavrilescu | |
167 | ||
168 | This library is free software: you can redistribute it and/or modify | |
169 | it under the terms of the GNU Affero General Public License as published by | |
170 | the Free Software Foundation, either version 3 of the License, or | |
171 | (at your option) any later version. | |
014ee8a6 MG |
172 | |
173 | ||
174 | =cut |