contestify 2.0.1 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
data/lib/contestify/contest.rb
CHANGED
@@ -9,6 +9,13 @@ module Contestify
|
|
9
9
|
clean_dir! contest.working_root_path
|
10
10
|
end
|
11
11
|
|
12
|
+
desc "local PROBLEMS_DIRECTORY JUDGE_UPLOAD_URL JUDGE_PASSWORD", "Setups a contest based on a local problemset"
|
13
|
+
def local(problems_path, judge_url, judge_password)
|
14
|
+
contest = Contestify::Judge::Local.new problems_path
|
15
|
+
Contestify::Uploader.upload!(judge_url, judge_password, contest.problems_paths)
|
16
|
+
clean_dir! contest.working_root_path
|
17
|
+
end
|
18
|
+
|
12
19
|
desc "check", "Checks that the user has the required OS software installed"
|
13
20
|
def check
|
14
21
|
check_dependencies
|
data/lib/contestify/judges.rb
CHANGED
@@ -1 +1,2 @@
|
|
1
|
-
require 'contestify/judges/coci/coci'
|
1
|
+
require 'contestify/judges/coci/coci'
|
2
|
+
require 'contestify/judges/local/local'
|
@@ -0,0 +1,19 @@
|
|
1
|
+
Contestify::Local
|
2
|
+
===
|
3
|
+
|
4
|
+
This strategy will upload the problems from a local directory to the server. Usage:
|
5
|
+
|
6
|
+
contestify local problem_url judge_upload_url judge_admin_password
|
7
|
+
|
8
|
+
Note that the Judge URL is the actual **upload** URL, which is normally `http://you-dom-judge.com/jury/problem.php`.
|
9
|
+
|
10
|
+
Here's an example of usage with _real_ data:
|
11
|
+
|
12
|
+
contestify /tmp/my_test_data http://domjudge.factorcomun.org/jury/problem.php p4ssw0rd
|
13
|
+
|
14
|
+
This will get the problems in `/tmp/my_test_data` and add them to DOMjudge on the server.
|
15
|
+
|
16
|
+
`/tmp/my_test_data` should contain a directory for every problem and each directory should
|
17
|
+
contain the input and output files for the problem. The files should be named `something.in`
|
18
|
+
and `something.out`, respectively. So if you want to add several test files for a problem
|
19
|
+
named `Example` the files inside `/tmp/my_test_data/example` would look like this: `example.1.in, example.1.out, example.2.in, example.2.out`.
|
@@ -0,0 +1,106 @@
|
|
1
|
+
module Contestify
|
2
|
+
module Local
|
3
|
+
# <tt>Local::Configuration</tt> holds all the logic to configure a contest
|
4
|
+
# from a local directory. This class **must** implement the `self.configure!`
|
5
|
+
# method.
|
6
|
+
class Configuration
|
7
|
+
|
8
|
+
# <tt>Contestify::Configuration.configure!</tt> is *the only* method you
|
9
|
+
# should call from the contest interface. All the other methods should be
|
10
|
+
# called from here. This is the only method needed for future strategies
|
11
|
+
# for other judges.
|
12
|
+
#
|
13
|
+
# This should be called in a directory structure such that you have a
|
14
|
+
# `base_folder` with one folder for each problem you want to upload to the
|
15
|
+
# server. Each of these problems folders should have all the input/output
|
16
|
+
# files you want to use as test cases.
|
17
|
+
#
|
18
|
+
# This method **must** return the absolute paths of the problem folders in
|
19
|
+
# an array. This return value will be used in Contestify::Uploader.upload!
|
20
|
+
#
|
21
|
+
# ==== Parameters
|
22
|
+
# base_folder<String>:: The base folder where all the problems folders are
|
23
|
+
# stored.
|
24
|
+
#
|
25
|
+
def self.configure!(base_folder)
|
26
|
+
puts green "=> Configuring problems (#{base_folder})"
|
27
|
+
problem_index = 0
|
28
|
+
Dir.glob("*").select { |f| File.directory?(f) }.map do |dir|
|
29
|
+
Dir.chdir File.join(base_folder, dir)
|
30
|
+
dirid = Dir.pwd.split('/').last[0...8]
|
31
|
+
puts green "==> #{dirid.upcase}"
|
32
|
+
rename_data_files
|
33
|
+
convert_to_unix_format
|
34
|
+
add_problem_config(dirid, problem_index)
|
35
|
+
problem_index += 1
|
36
|
+
puts green "==> All the work for #{dirid.upcase} is done"
|
37
|
+
# Return the absolute path for this problem
|
38
|
+
Dir.pwd
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
#########################################################################
|
43
|
+
private #################################################################
|
44
|
+
|
45
|
+
# <tt>Local::Configuration.rename_data_files</tt> is in charge of
|
46
|
+
# giving each input/output file a standard name that DOMJudge understands.
|
47
|
+
#
|
48
|
+
# This method should be overriden in future strategies.
|
49
|
+
#
|
50
|
+
# After this method is called, every different input/output file **must**
|
51
|
+
# have the following structure:
|
52
|
+
#
|
53
|
+
# `problemid`.`number`.in
|
54
|
+
# `problemid`.`number`.out
|
55
|
+
#
|
56
|
+
# where:
|
57
|
+
#
|
58
|
+
# `problemid` is at most 8 letters long and it's the id for the judge and
|
59
|
+
# `number` is the test case number. The .in and .out will determine the
|
60
|
+
# input and compare file the judge will run/diff.
|
61
|
+
def self.rename_data_files
|
62
|
+
puts blue "===> Renaming input/output files"
|
63
|
+
Dir.glob("*").select { |f| f =~ /\.in.[0-9]+/ }.each do |f|
|
64
|
+
|
65
|
+
parts = f.gsub(".dummy", "-dummy").split(".")
|
66
|
+
new_name = [parts[0], parts[2], parts[1]].join(".")
|
67
|
+
File.rename f, new_name
|
68
|
+
|
69
|
+
f.gsub!(".in", ".out")
|
70
|
+
parts = f.gsub(".dummy", "-dummy").split(".")
|
71
|
+
new_name = [parts[0], parts[2], parts[1]].join(".")
|
72
|
+
File.rename f, new_name
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
# <tt>Local::Configuration.add_problem_config</tt> will add the
|
78
|
+
# configuration file needed for DOMJudge to understand the problem.
|
79
|
+
#
|
80
|
+
# ==== Parameters
|
81
|
+
# probid<String>:: The problem id for DOMJudge. This **must** be at most
|
82
|
+
# 8 letters long.
|
83
|
+
#
|
84
|
+
# problem_index<Integer>:: This is the problem number. This is only used
|
85
|
+
# to choose the problem ballon color.
|
86
|
+
#
|
87
|
+
def self.add_problem_config(probid, problem_index)
|
88
|
+
puts blue "===> Adding DOM Judge configuration #{probid}"
|
89
|
+
file_content = <<-TEXT
|
90
|
+
probid = #{probid}
|
91
|
+
name = #{probid}
|
92
|
+
allow_submit = true
|
93
|
+
color = #{Contestify::PROBLEM_COLORS[problem_index]}
|
94
|
+
timelimit = 1
|
95
|
+
TEXT
|
96
|
+
File.open(File.join(Dir.pwd, "domjudge-problem.ini"), 'w') {|f| f.write(file_content) }
|
97
|
+
end
|
98
|
+
|
99
|
+
def self.convert_to_unix_format
|
100
|
+
puts blue "===> Converting to UNIX file format"
|
101
|
+
system "dos2unix *"
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'contestify/judges/local/configuration'
|
2
|
+
|
3
|
+
module Contestify
|
4
|
+
module Judge
|
5
|
+
class Local
|
6
|
+
attr_accessor :problems_path, :working_root_path, :problems_paths
|
7
|
+
|
8
|
+
def initialize(problems_path)
|
9
|
+
@problems_path = problems_path
|
10
|
+
@working_root_path = File.join(Dir.pwd, "contestify")
|
11
|
+
FileUtils.mkdir_p @working_root_path
|
12
|
+
copy_problems
|
13
|
+
@problems_paths = Contestify::Local::Configuration.configure!(@working_root_path)
|
14
|
+
end
|
15
|
+
|
16
|
+
private ################################################ PRIVATE
|
17
|
+
|
18
|
+
def copy_problems
|
19
|
+
puts green "=> Copying problems from #{@problems_path}"
|
20
|
+
if not File.directory?(@problems_path)
|
21
|
+
raise Exception.new(red "#{@problems_path} is not a valid directory. Did you mistype something?")
|
22
|
+
end
|
23
|
+
Dir.chdir @problems_path
|
24
|
+
FileUtils.cp_r Dir.glob("*"), @working_root_path
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/contestify/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: contestify
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0
|
4
|
+
version: 2.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-12-
|
12
|
+
date: 2011-12-22 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: thor
|
16
|
-
requirement: &
|
16
|
+
requirement: &70361113068320 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 0.14.6
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70361113068320
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rake
|
27
|
-
requirement: &
|
27
|
+
requirement: &70361113065580 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,7 +32,7 @@ dependencies:
|
|
32
32
|
version: 0.9.2
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70361113065580
|
36
36
|
description: Gem to prepare internal programming contests taking problems from the
|
37
37
|
COCI contests.
|
38
38
|
email:
|
@@ -56,6 +56,9 @@ files:
|
|
56
56
|
- lib/contestify/judges/coci/README.md
|
57
57
|
- lib/contestify/judges/coci/coci.rb
|
58
58
|
- lib/contestify/judges/coci/configuration.rb
|
59
|
+
- lib/contestify/judges/local/README.md
|
60
|
+
- lib/contestify/judges/local/configuration.rb
|
61
|
+
- lib/contestify/judges/local/local.rb
|
59
62
|
- lib/contestify/messages.rb
|
60
63
|
- lib/contestify/uploader.rb
|
61
64
|
- lib/contestify/util.rb
|
@@ -74,7 +77,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
74
77
|
version: '0'
|
75
78
|
segments:
|
76
79
|
- 0
|
77
|
-
hash:
|
80
|
+
hash: 2690431504346224305
|
78
81
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
79
82
|
none: false
|
80
83
|
requirements:
|
@@ -83,7 +86,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
83
86
|
version: '0'
|
84
87
|
segments:
|
85
88
|
- 0
|
86
|
-
hash:
|
89
|
+
hash: 2690431504346224305
|
87
90
|
requirements: []
|
88
91
|
rubyforge_project:
|
89
92
|
rubygems_version: 1.8.10
|