omegaup 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: de5fc0741a09e56d1c27cb5af631d3b966d7e2141e412174ec1975dbf8c87cf9
4
- data.tar.gz: a70008f5e26bc8927b00fa925188c2e76e3a8497835021731dd0d54d02d8506c
3
+ metadata.gz: 767e4b440acdf0d4b4f07d2fa568b0c05e78a8e066e1280765d49c6d62b23c46
4
+ data.tar.gz: 4151f5ade0af99d594d81e7cb1dae1259532d0627cc1c02f0499e1db03c4cec3
5
5
  SHA512:
6
- metadata.gz: 6f970627e3fcf17db767d1dd7613f4e566b879a644bbb589815614cae11496afd1bff06664a0bb6b1f91c1fecb0bda023b9c8ea0d6daf3d665c132f780792e9f
7
- data.tar.gz: dae56c4d719e2af83459fee4510a73dce522f272540e1f43b98b7cc40378fd4532f205f4f621c97f74e704bcb01f0d884c4de610e46336cb3af90bfa05568a5c
6
+ metadata.gz: 2511e42ce423bb7530f9e696e2a8f436fe547a9526731e3fc119952d63a014c0ef151b2ed78087b033009ee3420fe5bfee6495fe0b35f33a92aff90d62ee1488
7
+ data.tar.gz: b0816baf5e9fb16c43a9dbdb2e00b8c1462fd0f77ae33ce843c9fc03d42f6491e75d492a4d3847591cd9cf225589a6b2b23601ce333ee90c23873814cce80e90
data/.rubocop.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  AllCops:
2
- TargetRubyVersion: 2.7
2
+ TargetRubyVersion: 3.1
3
3
  NewCops: enable
4
4
  Gemspec/RequiredRubyVersion:
5
5
  Enabled: false
data/Gemfile CHANGED
File without changes
data/lib/omega/base.rb CHANGED
File without changes
@@ -51,6 +51,23 @@ module Omega
51
51
  puts "#{contest_name}: #{e.message}"
52
52
  end
53
53
 
54
+ def add_problem(contest_name, problem_name)
55
+ contest = omega.contest(contest_name)
56
+ contest.add_problem(problem_name)
57
+ rescue StandardError => e
58
+ puts "Error adding #{problem_name}: #{e.message}"
59
+ end
60
+
61
+ def copy_problems(contest_name, from)
62
+ contest = omega.contest(contest_name)
63
+ source = omega.contest(from)
64
+ source.problems.each do |problem|
65
+ contest.add_problem(problem[:alias])
66
+ rescue StandardError => e
67
+ puts "Error adding #{problem[:alias]}: #{e.message}"
68
+ end
69
+ end
70
+
54
71
  def download_sources(contest_name, path)
55
72
  Dir.mkdir(path) unless File.directory?(path)
56
73
  contest = omega.contest(contest_name)
data/lib/omega/cli.rb CHANGED
@@ -24,6 +24,7 @@ OmegaUp CLI. Developed by OMIJal https://github.com/omijal/omegaup-cli.
24
24
  Tool for interacting with omegaup from CLI and available throug ruby gems.
25
25
  Commands:
26
26
  - register-users Add a user or a bunch of users to the a contest.
27
+ - copy-problems Adds prob from another contest
27
28
  - user Generates a dump of the user data in yml format.
28
29
  - scoreboard Gets contest scoreboard with users and score.
29
30
  - clarifications Gets contest clarifications.
@@ -51,6 +52,16 @@ OMEGAUP_PASS *Required* Your OmegaUp Password
51
52
  @cmd = ARGV.shift
52
53
 
53
54
  @cmd_opts = case @cmd
55
+ when 'copy-problems'
56
+ Optimist.options do
57
+ opt :contest, 'Contest ShortName or identifier', type: :string
58
+ opt :from, 'Another constest that allows to clone users from another contest', type: :string
59
+ end
60
+ when 'add-problem'
61
+ Optimist.options do
62
+ opt :contest, 'Contest ShortName or identifier', type: :string
63
+ opt :problem, 'Problem name', type: :string
64
+ end
54
65
  when 'register-users'
55
66
  Optimist.options do
56
67
  opt :contest, 'Contest ShortName or identifier', type: :string
@@ -95,8 +106,8 @@ OMEGAUP_PASS *Required* Your OmegaUp Password
95
106
  config = {
96
107
  'omega' => {
97
108
  'endpoint' => ENV['OMEGAUP_URL'] || 'https://omegaup.com',
98
- 'user' => ENV['OMEGAUP_USER'],
99
- 'pass' => ENV['OMEGAUP_PASS']
109
+ 'user' => ENV.fetch('OMEGAUP_USER', nil),
110
+ 'pass' => ENV.fetch('OMEGAUP_PASS', nil)
100
111
  }
101
112
  }
102
113
 
@@ -119,6 +130,10 @@ OMEGAUP_PASS *Required* Your OmegaUp Password
119
130
  clarifications(@cmd_opts[:contest], @cmd_opts[:open])
120
131
  when 'sources'
121
132
  download_sources(@cmd_opts[:contest], @cmd_opts[:path])
133
+ when 'copy-problems'
134
+ copy_problems(@cmd_opts[:contest], @cmd_opts[:from])
135
+ when 'add-problem'
136
+ add_problem(@cmd_opts[:contest], @cmd_opts[:problem])
122
137
  end
123
138
  end
124
139
  end
data/lib/omega/client.rb CHANGED
@@ -4,10 +4,16 @@ require_relative 'contest'
4
4
  require_relative 'scoreboard'
5
5
  require_relative 'user'
6
6
  require_relative 'contest_run'
7
+ require 'json'
8
+ require 'nokogiri'
7
9
 
8
10
  require 'httparty'
9
11
 
10
12
  module Omega
13
+ KAREL_LANGS = 'kp,kj'
14
+ OMI_LANGS = 'c11-gcc,c11-clang,cpp11-gcc,cpp11-clang,cpp17-gcc,cpp17-clang,cpp20-gcc,cpp20-clang'
15
+ ALL_LANGS = 'kp,kj,c11-gcc,c11-clang,cpp11-gcc,cpp11-clang,cpp17-gcc,cpp17-clang,cpp20-gcc,cpp20-clang,java,kt,py2,py3,rb,cs,pas,cat,hs,lua,go,rs,js'
16
+
11
17
  class OmegaError < StandardError
12
18
  attr_reader :data
13
19
 
@@ -18,6 +24,14 @@ module Omega
18
24
  def message
19
25
  "#{@data[:errorname]}::#{@data[:errorcode]} >> #{@data[:error]}"
20
26
  end
27
+
28
+ def errorname
29
+ @data[:errorname]
30
+ end
31
+
32
+ def errorcode
33
+ @data[:errorcode]
34
+ end
21
35
  end
22
36
 
23
37
  class Client
@@ -30,7 +44,7 @@ module Omega
30
44
  def perform_request(method, endpoint, data, retried = false)
31
45
  url = "#{@config['endpoint']}#{endpoint}"
32
46
  response = self.class.send(method, url, body: data)
33
- body = JSON.parse(response.body, symbolize_names: true)
47
+ body = ::JSON.parse(response.body, symbolize_names: true)
34
48
 
35
49
  if body[:errorcode] == 401 && !retried
36
50
  login
@@ -67,6 +81,58 @@ module Omega
67
81
  retry
68
82
  end
69
83
 
84
+ def problem_details(problem_alias)
85
+ post('/api/problem/details', { problem_alias: })
86
+ end
87
+
88
+ def create_group(name, description: nil, alias: nil)
89
+ post('/api/group/create', name:, alias:, description:)
90
+ end
91
+
92
+ def create_contest(name:, short_name:, description:, start_time:, finish_time:,
93
+ public: false, penalty_calc_policy: 'sum', show_penalty: true,
94
+ points_decay_factor: '0', submissions_gap: '60', languages: ALL_LANGS, feedback: 'none',
95
+ penalty: '0', scoreboard: '100', penalty_type: 'none',
96
+ default_show_all_contestants_in_scoreboard: false,
97
+ show_scoreboard_after: true,
98
+ score_mode: 'partial',
99
+ needs_basic_information: false,
100
+ requests_user_information: 'no',
101
+ contest_for_teams: false)
102
+ post('/api/contest/create/', {
103
+ admin: true,
104
+ admission_mode: (public ? 'public' : 'private'),
105
+ alias: short_name,
106
+ archived: false,
107
+ opened: false,
108
+ penalty_calc_policy:,
109
+ show_penalty:,
110
+ title: name,
111
+ description:,
112
+ has_submissions: false,
113
+ start_time: start_time.to_time.to_i,
114
+ finish_time: finish_time.to_time.to_i,
115
+ points_decay_factor:,
116
+ submissions_gap:,
117
+ languages:,
118
+ feedback:,
119
+ penalty:,
120
+ scoreboard:,
121
+ penalty_type:,
122
+ default_show_all_contestants_in_scoreboard:,
123
+ show_scoreboard_after:,
124
+ score_mode:,
125
+ needs_basic_information:,
126
+ requests_user_information:,
127
+ contest_for_teams:
128
+ })
129
+ contest(short_name)
130
+ rescue OmegaError => e
131
+ raise e unless e.errorname == 'aliasInUse'
132
+
133
+ contest(short_name)
134
+ end
135
+
70
136
  def scoreboard(name)
71
137
  data = post('/api/contest/scoreboard/', { contest_alias: name })
72
138
  Scoreboard.new(self, data)
@@ -86,6 +152,12 @@ module Omega
86
152
  User.new(self, data)
87
153
  end
88
154
 
155
+ def add_admin_group(contest, group)
156
+ post('/api/contest/addGroupAdmin', { contest_alias: contest, group: })
157
+ rescue OmegaError
158
+ # Omega seems to have a bug
159
+ end
160
+
89
161
  def add_user_to_contest(user, contest)
90
162
  post('/api/contest/addUser', { contest_alias: contest, usernameOrEmail: user })
91
163
  end
@@ -99,8 +171,50 @@ module Omega
99
171
  end
100
172
 
101
173
  def contest_runs(contest, offset, page_size)
102
- data = post('/api/contest/runs/', { contest_alias: contest, offset: offset, rowcount: page_size })
174
+ data = post('/api/contest/runs/', { contest_alias: contest, offset:, rowcount: page_size })
103
175
  data[:runs].map { |run| ContestRun.new(self, run) }
104
176
  end
177
+
178
+ def add_problem_to_contest(contest, problem, points = 100)
179
+ post('/api/contest/addProblem', contest_alias: contest, problem_alias: problem, points:)
180
+ end
181
+
182
+ def add_user_to_group(group_name, username)
183
+ post('/api/group/addUser', group_alias: group_name, usernameOrEmail: username)
184
+ rescue OmegaError => e
185
+ raise if e.errorname != 'identityInGroup'
186
+ end
187
+
188
+ def get_payload_from_response_by_id(response_body, id)
189
+ page = Nokogiri::HTML(response_body)
190
+ script = page.at_css("script##{id}")
191
+ unless script
192
+ raise OmegaError.new(errorname: 'ScrapingError', errorcode: 404,
193
+ error: "Script with id #{id} not found")
194
+ end
195
+
196
+ script_content = script.content
197
+ # Extrayendo el contenido JSON del script
198
+ begin
199
+ ::JSON.parse(script_content, symbolize_names: true)
200
+ rescue JSON::ParserError
201
+ raise OmegaError.new(errorname: 'ScrapingError', errorcode: 500, error: 'Unable to parse JSON data')
202
+ end
203
+ end
204
+
205
+ def scrap_get(endpoint, id = 'payload')
206
+ url = "#{@config['endpoint']}#{endpoint}"
207
+ response = self.class.get(url)
208
+ unless response.success?
209
+ raise OmegaError.new(errorname: 'HttpError', errorcode: response.code,
210
+ error: response.message)
211
+ end
212
+
213
+ body = get_payload_from_response_by_id(response.body, id)
214
+
215
+ raise OmegaError, body if body[:error]
216
+
217
+ body
218
+ end
105
219
  end
106
220
  end
data/lib/omega/contest.rb CHANGED
@@ -9,6 +9,10 @@ module Omega
9
9
  @client.scoreboard(data[:alias])
10
10
  end
11
11
 
12
+ def problems
13
+ @data[:problems]
14
+ end
15
+
12
16
  def runs(offset = 0, page_size = 100)
13
17
  @client.contest_runs(data[:alias], offset, page_size)
14
18
  end
@@ -27,6 +31,14 @@ module Omega
27
31
  sources
28
32
  end
29
33
 
34
+ def full_details
35
+ @full_details ||= @client.scrap_get("/contest/#{data[:alias]}/edit/")
36
+ end
37
+
38
+ def group_admin?(group_name)
39
+ full_details[:group_admins].any? { |group| group[:alias].casecmp(group_name).zero? }
40
+ end
41
+
30
42
  def add_user(user)
31
43
  if user.is_a?(String)
32
44
  @client.add_user_to_contest(user, data[:alias])
@@ -43,6 +55,18 @@ module Omega
43
55
  scoreboard.users
44
56
  end
45
57
 
58
+ def alias
59
+ @data[:alias].downcase
60
+ end
61
+
62
+ def add_problem(name)
63
+ @client.add_problem_to_contest(data[:alias], name)
64
+ end
65
+
66
+ def add_admin_group(group)
67
+ @client.add_admin_group(data[:alias], group)
68
+ end
69
+
46
70
  def observe(score_notifier, clar_noritifer)
47
71
  last = current = scoreboard
48
72
  sleep(5)
@@ -13,7 +13,7 @@ module Omega
13
13
  end
14
14
 
15
15
  def save_at(path)
16
- File.write("#{path}/#{@data[:guid]}.yaml", { details: details, data: @data }.to_yaml)
16
+ File.write("#{path}/#{@data[:guid]}.yaml", { details:, data: @data }.to_yaml)
17
17
  end
18
18
  end
19
19
  end
@@ -10,7 +10,7 @@ module Omega
10
10
  def initialize(client, entry)
11
11
  @username = entry[:username]
12
12
  @problems = entry[:problems] || []
13
- super(client, entry)
13
+ super
14
14
  end
15
15
 
16
16
  def merge(score)
@@ -37,6 +37,10 @@ module Omega
37
37
  end
38
38
  nil
39
39
  end
40
+
41
+ def to_h
42
+ @data[:problems]
43
+ end
40
44
  end
41
45
 
42
46
  class Scoreboard < Base
@@ -49,6 +53,10 @@ module Omega
49
53
  end
50
54
  end
51
55
 
56
+ def to_h
57
+ @data[:ranking].map { |username, entry| { username:, score: entry.to_h } }
58
+ end
59
+
52
60
  def merge(board)
53
61
  result = clone
54
62
  board.data[:ranking].each do |user, score|
data/lib/omega/user.rb CHANGED
@@ -7,7 +7,7 @@ module Omega
7
7
  def full_data
8
8
  {
9
9
  data: @data,
10
- problems_solved: problems_solved,
10
+ problems_solved:,
11
11
  resume: report
12
12
  }
13
13
  end
@@ -16,6 +16,10 @@ module Omega
16
16
  @client.problems_solved(data[:username])[:problems]
17
17
  end
18
18
 
19
+ def username
20
+ @data[:username]
21
+ end
22
+
19
23
  def report
20
24
  data = { score: 0, count: 0 }
21
25
  problems_solved.each do |p|
data/lib/omega/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Omega
4
- VERSION = '0.4.0'
4
+ VERSION = '0.5.0'
5
5
  end
data/lib/omega.rb CHANGED
File without changes
data/omega.gemspec CHANGED
@@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
8
8
  spec.name = 'omegaup'
9
9
  spec.version = Omega::VERSION
10
10
  spec.authors = ['Gilberto Vargas']
11
- spec.email = ['tachoguitar@gmail.com']
11
+ spec.email = ['tachomexgems@gmail.com']
12
12
 
13
13
  spec.summary = 'File created for encrypting files using ssh keys'
14
14
  spec.description = 'Allows to encrypt files using ssh keys'
@@ -25,10 +25,11 @@ Gem::Specification.new do |spec|
25
25
  spec.add_development_dependency 'amazing_print'
26
26
  spec.add_development_dependency 'httparty'
27
27
  spec.add_development_dependency 'minitest', '~> 5'
28
+ spec.add_development_dependency 'mocha'
28
29
  spec.add_development_dependency 'optimist'
29
30
  spec.add_development_dependency 'rack-minitest'
30
- spec.add_development_dependency 'webmock'
31
- spec.add_development_dependency 'mocha'
32
- spec.add_development_dependency 'simplecov'
33
31
  spec.add_development_dependency 'rake', '~> 10.0'
32
+ spec.add_development_dependency 'simplecov'
33
+ spec.add_development_dependency 'webmock'
34
+ spec.metadata['rubygems_mfa_required'] = 'true'
34
35
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omegaup
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gilberto Vargas
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-06-15 00:00:00.000000000 Z
11
+ date: 2024-07-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: amazing_print
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '5'
55
55
  - !ruby/object:Gem::Dependency
56
- name: optimist
56
+ name: mocha
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
@@ -67,7 +67,7 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: rack-minitest
70
+ name: optimist
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - ">="
@@ -81,7 +81,7 @@ dependencies:
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: webmock
84
+ name: rack-minitest
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - ">="
@@ -95,19 +95,19 @@ dependencies:
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
- name: mocha
98
+ name: rake
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - ">="
101
+ - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '0'
103
+ version: '10.0'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - ">="
108
+ - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '0'
110
+ version: '10.0'
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: simplecov
113
113
  requirement: !ruby/object:Gem::Requirement
@@ -123,22 +123,22 @@ dependencies:
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
125
  - !ruby/object:Gem::Dependency
126
- name: rake
126
+ name: webmock
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
- - - "~>"
129
+ - - ">="
130
130
  - !ruby/object:Gem::Version
131
- version: '10.0'
131
+ version: '0'
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
- - - "~>"
136
+ - - ">="
137
137
  - !ruby/object:Gem::Version
138
- version: '10.0'
138
+ version: '0'
139
139
  description: Allows to encrypt files using ssh keys
140
140
  email:
141
- - tachoguitar@gmail.com
141
+ - tachomexgems@gmail.com
142
142
  executables:
143
143
  - omega
144
144
  extensions: []
@@ -161,7 +161,8 @@ files:
161
161
  homepage: https://github.com/omijal/omegaup-cli
162
162
  licenses:
163
163
  - MIT
164
- metadata: {}
164
+ metadata:
165
+ rubygems_mfa_required: 'true'
165
166
  post_install_message:
166
167
  rdoc_options: []
167
168
  require_paths:
@@ -177,7 +178,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
177
178
  - !ruby/object:Gem::Version
178
179
  version: '0'
179
180
  requirements: []
180
- rubygems_version: 3.1.4
181
+ rubygems_version: 3.5.14
181
182
  signing_key:
182
183
  specification_version: 4
183
184
  summary: File created for encrypting files using ssh keys