omegaup 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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