omegaup 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rubocop.yml +3 -0
- data/Gemfile +4 -0
- data/bin/omega +6 -0
- data/lib/omega.rb +7 -0
- data/lib/omega/base.rb +12 -0
- data/lib/omega/cli.rb +102 -0
- data/lib/omega/cli/contest.rb +39 -0
- data/lib/omega/client.rb +82 -0
- data/lib/omega/contest.rb +42 -0
- data/lib/omega/scoreboard.rb +74 -0
- data/lib/omega/user.rb +28 -0
- data/lib/omega/version.rb +5 -0
- data/omega.gemspec +29 -0
- metadata +113 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d68043d4f4131c6b4d11b1607e6d38b0ba05e74621bab4c08cf1bcc0e1c7a948
|
4
|
+
data.tar.gz: cefb8c9d26da0a24d6d720fcd22fbcdc8a4aedc57f5a8b28d1e2b7ceedad9226
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 84ee8b49d4c2d380b03b9dbbe6c67ae0af343a89b09b7fe5c95ac639a8be46478d484bb9c2e4328eff7e2705303ffaf807c7636418825b7995d5e0ef3fe50509
|
7
|
+
data.tar.gz: 93c3a835cbbca8134b4ef626eb14c53061fc495c5cd7fc716a5333b8e209035e2beea10c840f0385f16a41d2632159a3b5367a7e36c4adb564f2433dfa26e99e
|
data/.rubocop.yml
ADDED
data/Gemfile
ADDED
data/bin/omega
ADDED
data/lib/omega.rb
ADDED
data/lib/omega/base.rb
ADDED
data/lib/omega/cli.rb
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../omega'
|
4
|
+
require_relative 'cli/contest'
|
5
|
+
require 'optimist'
|
6
|
+
|
7
|
+
module Omega
|
8
|
+
class CLI
|
9
|
+
attr_reader :omega
|
10
|
+
|
11
|
+
include Omega::CLI::Contest
|
12
|
+
SUB_COMMANDS = %w[
|
13
|
+
register-users
|
14
|
+
user
|
15
|
+
scoreboard
|
16
|
+
create-contest
|
17
|
+
add-problem
|
18
|
+
help
|
19
|
+
].freeze
|
20
|
+
|
21
|
+
def print_help
|
22
|
+
puts %(
|
23
|
+
OmegaUp CLI. Developed by OMIJal https://github.com/omijal/omegaup-cli.
|
24
|
+
Tool for interacting with omegaup from CLI and available throug ruby gems.
|
25
|
+
Commands:
|
26
|
+
- register_users Add a user or a bunch of users to the a contest.
|
27
|
+
- user Generates a dump of the user data in yml format.
|
28
|
+
- scoreboard Gets contest scoreboard with users and score.
|
29
|
+
Parametes:
|
30
|
+
--contest Contest name
|
31
|
+
--user Username or email
|
32
|
+
--user_file A file path containing a list of user one per line without
|
33
|
+
header
|
34
|
+
Setup:
|
35
|
+
You need to add two env variables with your omegaup credentials.
|
36
|
+
OMEGAUP_URL *Optional* This is intended for development purpose, it will target
|
37
|
+
to https://omegau.com by default.
|
38
|
+
OMEGAUP_USER *Required* Your OmegaUp Username or Email
|
39
|
+
OMEGAUP_PASS *Required* Your OmegaUp Password
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
43
|
+
def initialize(_)
|
44
|
+
@cmd = ARGV.shift
|
45
|
+
|
46
|
+
@cmd_opts = case @cmd
|
47
|
+
when 'register-users'
|
48
|
+
Optimist.options do
|
49
|
+
opt :contest, 'Contest ShortName or identifier', type: :string
|
50
|
+
opt :user, 'Username or email', type: :string
|
51
|
+
opt :user_file, 'A file containing the users list one per line and without header', type: :string
|
52
|
+
end
|
53
|
+
when 'user'
|
54
|
+
Optimist.options do
|
55
|
+
opt :user, 'Username or email', type: :string
|
56
|
+
end
|
57
|
+
when 'scoreboard'
|
58
|
+
Optimist.options do
|
59
|
+
opt :contest, 'Contest ShortName or identifier', type: :string
|
60
|
+
end
|
61
|
+
# when 'create-contest'
|
62
|
+
# Optimist.options do
|
63
|
+
# opt :contest, 'Contest ShortName or identifier', type: :string
|
64
|
+
# end
|
65
|
+
# when 'add-problem'
|
66
|
+
# Optimist.options do
|
67
|
+
# opt :contest, 'Contest ShortName or identifier', type: :string
|
68
|
+
# opt :problem, type: :string
|
69
|
+
# end
|
70
|
+
else
|
71
|
+
print_help
|
72
|
+
exit(0)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def login
|
77
|
+
config = {
|
78
|
+
'omega' => {
|
79
|
+
'endpoint' => ENV['OMEGAUP_URL'] || 'https://omegaup.com',
|
80
|
+
'user' => ENV['OMEGAUP_USER'],
|
81
|
+
'pass' => ENV['OMEGAUP_PASS']
|
82
|
+
}
|
83
|
+
}
|
84
|
+
|
85
|
+
@omega = Omega::Client.new(config['omega'])
|
86
|
+
@omega.login
|
87
|
+
end
|
88
|
+
|
89
|
+
def execute
|
90
|
+
login
|
91
|
+
case @cmd
|
92
|
+
when 'register-users'
|
93
|
+
register_user(@cmd_opts[:contest], @cmd_opts[:user]) if @cmd_opts[:user]
|
94
|
+
register_users(@cmd_opts[:contest], @cmd_opts[:user_file]) if @cmd_opts[:user_file]
|
95
|
+
when 'user'
|
96
|
+
user_data(@cmd_opts[:user])
|
97
|
+
when 'scoreboard'
|
98
|
+
scoreboard(@cmd_opts[:contest])
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Omega
|
4
|
+
class CLI
|
5
|
+
module Contest
|
6
|
+
def register_user(contest_name, user)
|
7
|
+
contest = omega.contest(contest_name)
|
8
|
+
puts contest.add_user(user)[:status]
|
9
|
+
rescue StandardError => e
|
10
|
+
puts "Error adding #{user}: #{e.message}"
|
11
|
+
end
|
12
|
+
|
13
|
+
def register_users(contest_name, user_file)
|
14
|
+
users = File.readlines(user_file).map(&:strip)
|
15
|
+
contest = omega.contest(contest_name)
|
16
|
+
failed = []
|
17
|
+
users.each do |user|
|
18
|
+
puts "Adding #{user}..."
|
19
|
+
contest.add_user(user)
|
20
|
+
rescue StandardError => e
|
21
|
+
puts "Error adding #{user}: #{e.message}"
|
22
|
+
failed << user
|
23
|
+
end
|
24
|
+
puts "Failed users: \n- #{failed.join("\n- ")}"
|
25
|
+
end
|
26
|
+
|
27
|
+
def user_data(user)
|
28
|
+
puts omega.user(user).full_data.to_yaml
|
29
|
+
end
|
30
|
+
|
31
|
+
def scoreboard(contest_name)
|
32
|
+
score = omega.scoreboard(contest_name)
|
33
|
+
score.simple_display.each_with_index { |s, i| puts "#{i + 1}.- #{s.values.join(': ')}" }
|
34
|
+
rescue StandardError => e
|
35
|
+
puts "#{contest_name}: #{e.message}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/omega/client.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'contest'
|
4
|
+
require_relative 'scoreboard'
|
5
|
+
require_relative 'user'
|
6
|
+
|
7
|
+
require 'httparty'
|
8
|
+
|
9
|
+
module Omega
|
10
|
+
class OmegaError < StandardError
|
11
|
+
attr_reader :data
|
12
|
+
|
13
|
+
def initialize(data)
|
14
|
+
@data = data
|
15
|
+
end
|
16
|
+
|
17
|
+
def message
|
18
|
+
"#{@data[:errorname]}::#{@data[:errorcode]} >> #{@data[:error]}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class Client
|
23
|
+
include HTTParty
|
24
|
+
|
25
|
+
def initialize(conf)
|
26
|
+
@config = conf
|
27
|
+
end
|
28
|
+
|
29
|
+
def perform_request(method, endpoint, data)
|
30
|
+
url = "#{@config['endpoint']}#{endpoint}"
|
31
|
+
response = self.class.send(method, url, body: data)
|
32
|
+
body = JSON.parse(response.body, symbolize_names: true)
|
33
|
+
raise OmegaError, body if body[:error]
|
34
|
+
|
35
|
+
body
|
36
|
+
end
|
37
|
+
|
38
|
+
def post(endpoint, data)
|
39
|
+
perform_request(:post, endpoint, data)
|
40
|
+
end
|
41
|
+
|
42
|
+
def login
|
43
|
+
data = post('/api/user/login',
|
44
|
+
usernameOrEmail: @config['user'],
|
45
|
+
password: @config['pass'])
|
46
|
+
@token = data[:auth_token]
|
47
|
+
self.class.default_cookies.add_cookies('ouat' => data[:auth_token])
|
48
|
+
end
|
49
|
+
|
50
|
+
def open_contest(name)
|
51
|
+
post('/api/contest/open/', { contest_alias: name })
|
52
|
+
end
|
53
|
+
|
54
|
+
def contest(name)
|
55
|
+
data = post('/api/contest/details/', { contest_alias: name })
|
56
|
+
Contest.new(self, data)
|
57
|
+
rescue OmegaError => e
|
58
|
+
raise unless e.data[:errorname] == 'userNotAllowed'
|
59
|
+
|
60
|
+
open_contest(name)
|
61
|
+
retry
|
62
|
+
end
|
63
|
+
|
64
|
+
def scoreboard(name)
|
65
|
+
data = post('/api/contest/scoreboard/', { contest_alias: name })
|
66
|
+
Scoreboard.new(self, data)
|
67
|
+
end
|
68
|
+
|
69
|
+
def user(user)
|
70
|
+
data = post('/api/user/profile/', { username: user })
|
71
|
+
User.new(self, data)
|
72
|
+
end
|
73
|
+
|
74
|
+
def add_user_to_contest(user, contest)
|
75
|
+
post('/api/contest/addUser', { contest_alias: contest, usernameOrEmail: user })
|
76
|
+
end
|
77
|
+
|
78
|
+
def problems_solved(user)
|
79
|
+
post('/api/user/problemsSolved/', { username: user })
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base'
|
4
|
+
|
5
|
+
module Omega
|
6
|
+
class Contest < Base
|
7
|
+
def scoreboard
|
8
|
+
@client.scoreboard(data[:alias])
|
9
|
+
end
|
10
|
+
|
11
|
+
def add_user(user)
|
12
|
+
if user.is_a?(String)
|
13
|
+
@client.add_user_to_contest(user, data[:alias])
|
14
|
+
else
|
15
|
+
@client.add_user_to_contest(user.data[:username], data[:alias])
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def observe
|
20
|
+
last = current = scoreboard
|
21
|
+
sleep(5)
|
22
|
+
loop do
|
23
|
+
current = scoreboard
|
24
|
+
last.users.each do |score|
|
25
|
+
puts score.username
|
26
|
+
current_score = current.score_for(score.username)
|
27
|
+
score.problems.each do |problem|
|
28
|
+
name = problem[:alias]
|
29
|
+
current_problem = current_score.score_for(name)
|
30
|
+
last_points = problem[:points]
|
31
|
+
current_points = current_problem[:points]
|
32
|
+
puts " #{name}::#{last_points} >> #{current_points}"
|
33
|
+
yield(contest_name, score.username, name, current_points, last_points) if current_points != last_points
|
34
|
+
end
|
35
|
+
puts '-' * 60
|
36
|
+
end
|
37
|
+
last = current
|
38
|
+
sleep(15)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base'
|
4
|
+
|
5
|
+
module Omega
|
6
|
+
class ScoreboardEntry < Base
|
7
|
+
attr_accessor :problems
|
8
|
+
attr_reader :username
|
9
|
+
|
10
|
+
def initialize(client, entry)
|
11
|
+
@username = entry[:username]
|
12
|
+
@client = client
|
13
|
+
@problems = entry[:problems] || []
|
14
|
+
@data = entry
|
15
|
+
end
|
16
|
+
|
17
|
+
def merge(score)
|
18
|
+
result = clone
|
19
|
+
result.problems += score.problems
|
20
|
+
result.data[:total][:points] += score.data[:total][:points]
|
21
|
+
result
|
22
|
+
end
|
23
|
+
|
24
|
+
def simple_display
|
25
|
+
{
|
26
|
+
username: @data[:username],
|
27
|
+
score: @data[:total][:points]
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
def <=>(other)
|
32
|
+
other.data[:total][:points] <=> @data[:total][:points]
|
33
|
+
end
|
34
|
+
|
35
|
+
def score_for(name)
|
36
|
+
problems.each do |problem|
|
37
|
+
return problem if problem[:alias] == name
|
38
|
+
end
|
39
|
+
nil
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class Scoreboard < Base
|
44
|
+
def initialize(client, data)
|
45
|
+
@client = client
|
46
|
+
@data = data.dup
|
47
|
+
@data[:ranking] = {}
|
48
|
+
data[:ranking].each do |entry|
|
49
|
+
@data[:ranking][entry[:username]] = ScoreboardEntry.new(client, entry)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def merge(board)
|
54
|
+
result = clone
|
55
|
+
board.data[:ranking].each do |user, score|
|
56
|
+
result.data[:ranking][user] =
|
57
|
+
result.data[:ranking][user].nil? ? score : result.data[:ranking][user].merge(score)
|
58
|
+
end
|
59
|
+
result
|
60
|
+
end
|
61
|
+
|
62
|
+
def simple_display
|
63
|
+
users.map(&:simple_display)
|
64
|
+
end
|
65
|
+
|
66
|
+
def score_for(user)
|
67
|
+
@data[:ranking][user]
|
68
|
+
end
|
69
|
+
|
70
|
+
def users
|
71
|
+
@data[:ranking].values.sort
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
data/lib/omega/user.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base'
|
4
|
+
|
5
|
+
module Omega
|
6
|
+
class User < Base
|
7
|
+
def full_data
|
8
|
+
{
|
9
|
+
data: @data,
|
10
|
+
problems_solved: problems_solved,
|
11
|
+
resume: report
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
def problems_solved
|
16
|
+
@client.problems_solved(data[:username])[:problems]
|
17
|
+
end
|
18
|
+
|
19
|
+
def report
|
20
|
+
data = { score: 0, count: 0 }
|
21
|
+
problems_solved.each do |p|
|
22
|
+
data[:score] += p[:difficulty] || 0
|
23
|
+
data[:count] += 1
|
24
|
+
end
|
25
|
+
data
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/omega.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require 'omega/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = 'omegaup'
|
9
|
+
spec.version = Omega::VERSION
|
10
|
+
spec.authors = ['Gilberto Vargas']
|
11
|
+
spec.email = ['tachoguitar@gmail.com']
|
12
|
+
|
13
|
+
spec.summary = 'File created for encrypting files using ssh keys'
|
14
|
+
spec.description = 'Allows to encrypt files using ssh keys'
|
15
|
+
spec.homepage = 'https://github.com/omijal/omegaup-cli'
|
16
|
+
spec.license = 'MIT'
|
17
|
+
|
18
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
19
|
+
f.match(%r{^(test|spec|features)/})
|
20
|
+
end
|
21
|
+
spec.bindir = 'bin'
|
22
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
23
|
+
spec.require_paths = ['lib']
|
24
|
+
|
25
|
+
spec.add_development_dependency 'amazing_print'
|
26
|
+
spec.add_development_dependency 'minitest', '~> 5'
|
27
|
+
spec.add_development_dependency 'optimist'
|
28
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: omegaup
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Gilberto Vargas
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-03-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: amazing_print
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: minitest
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '5'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '5'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: optimist
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '10.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '10.0'
|
69
|
+
description: Allows to encrypt files using ssh keys
|
70
|
+
email:
|
71
|
+
- tachoguitar@gmail.com
|
72
|
+
executables:
|
73
|
+
- omega
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- ".rubocop.yml"
|
78
|
+
- Gemfile
|
79
|
+
- bin/omega
|
80
|
+
- lib/omega.rb
|
81
|
+
- lib/omega/base.rb
|
82
|
+
- lib/omega/cli.rb
|
83
|
+
- lib/omega/cli/contest.rb
|
84
|
+
- lib/omega/client.rb
|
85
|
+
- lib/omega/contest.rb
|
86
|
+
- lib/omega/scoreboard.rb
|
87
|
+
- lib/omega/user.rb
|
88
|
+
- lib/omega/version.rb
|
89
|
+
- omega.gemspec
|
90
|
+
homepage: https://github.com/omijal/omegaup-cli
|
91
|
+
licenses:
|
92
|
+
- MIT
|
93
|
+
metadata: {}
|
94
|
+
post_install_message:
|
95
|
+
rdoc_options: []
|
96
|
+
require_paths:
|
97
|
+
- lib
|
98
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '0'
|
108
|
+
requirements: []
|
109
|
+
rubygems_version: 3.1.4
|
110
|
+
signing_key:
|
111
|
+
specification_version: 4
|
112
|
+
summary: File created for encrypting files using ssh keys
|
113
|
+
test_files: []
|