poj_org 0.3.0 → 0.4.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,47 @@
1
+ require 'cgi'
2
+ require 'open-uri'
3
+ require 'nokogiri'
4
+ require 'poj_org/errors'
5
+ require 'poj_org/user'
6
+
7
+ module PojOrg
8
+ class Code
9
+ attr_reader :id, :username, :problem_id, :result, :memory_in_kb, :time_in_ms, :language, :length_in_byte, :submitted_at, :content
10
+
11
+ def initialize(id)
12
+ @id = id
13
+ fetch_details
14
+ end
15
+
16
+ def url
17
+ "http://poj.org/showsource?solution_id=#{id}"
18
+ end
19
+
20
+ def fetch_content(user)
21
+ user.login do |cookie|
22
+ html = Nokogiri::HTML(open(url, 'Cookie' => cookie))
23
+ if html.xpath('/html/head/title').text == 'Error'
24
+ raise PojOrg::Errors::CodeNotFound if html.xpath('/html/body/ul/li').text.include?('No such solution')
25
+ raise PojOrg::Errors::AccessDenied if html.xpath('/html/body/ul/li').text.include?('Source request declined')
26
+ raise PojOrg::Errors::Error
27
+ end
28
+ @content = html.xpath('/html/body/pre').text
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def fetch_details
35
+ html = Nokogiri::HTML(open("http://poj.org/status?top=#{@id+1}"))
36
+ raise PojOrg::Errors::CodeNotFound if html.xpath('/html/body/table[2]/tr[2]/td[1]').text.to_i != @id
37
+ @username = html.xpath('/html/body/table[2]/tr[2]/td[2]').text
38
+ @problem_id = html.xpath('/html/body/table[2]/tr[2]/td[3]').text.to_i
39
+ @result = html.xpath('/html/body/table[2]/tr[2]/td[4]').text
40
+ @memory_in_kb = html.xpath('/html/body/table[2]/tr[2]/td[5]').text.to_i
41
+ @time_in_ms = html.xpath('/html/body/table[2]/tr[2]/td[6]').text.to_i
42
+ @language = html.xpath('/html/body/table[2]/tr[2]/td[7]').text
43
+ @length_in_byte = html.xpath('/html/body/table[2]/tr[2]/td[8]').text.to_i
44
+ @submitted_at = html.xpath('/html/body/table[2]/tr[2]/td[9]').text
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,9 @@
1
+ module PojOrg
2
+ module Errors
3
+ class Error < StandardError; end
4
+ class Unauthorized < StandardError; end
5
+ class ProblemNotFound < StandardError; end
6
+ class CodeNotFound < StandardError; end
7
+ class AccessDenied < StandardError; end
8
+ end
9
+ end
@@ -0,0 +1,22 @@
1
+ require 'open-uri'
2
+ require 'nokogiri'
3
+ require 'poj_org/errors'
4
+
5
+ module PojOrg
6
+ class Problem
7
+ attr_reader :id, :title, :time_limit_in_ms, :memory_limit_in_kb
8
+
9
+ def initialize(id)
10
+ @id = id
11
+ html = Nokogiri::HTML(open(url))
12
+ raise PojOrg::Errors::ProblemNotFound if html.xpath('/html/head/title').text == 'Error'
13
+ @title = html.xpath('/html/body/table[2]/tr/td/div[2]').text
14
+ @time_limit_in_ms = html.xpath('/html/body/table[2]/tr/td/div[3]/table/tr[1]/td[1]').text[/\d+/].to_i
15
+ @memory_limit_in_kb = html.xpath('/html/body/table[2]/tr/td/div[3]/table/tr[1]/td[3]').text[/\d+/].to_i
16
+ end
17
+
18
+ def url
19
+ "http://poj.org/problem?id=#{id}"
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,70 @@
1
+ require 'net/http'
2
+ require 'open-uri'
3
+ require 'poj_org/errors'
4
+
5
+ module PojOrg
6
+ class User
7
+ attr_reader :username
8
+
9
+ def initialize(username, password)
10
+ @username = username
11
+ @password = password
12
+ end
13
+
14
+ def authenticated?
15
+ login
16
+ true
17
+ rescue
18
+ false
19
+ end
20
+
21
+ def login
22
+ response = Net::HTTP.post_form(
23
+ URI('http://poj.org/login'),
24
+ 'user_id1' => username,
25
+ 'password1' => @password
26
+ )
27
+ raise PojOrg::Errors::Unauthorized if response.body['failed']
28
+ yield response['set-cookie'] if block_given?
29
+ open('http://poj.org/login?action=logout')
30
+ end
31
+
32
+ def code(id)
33
+ code = Code.new(id)
34
+ code.fetch_content(self)
35
+ code
36
+ end
37
+
38
+ def code_ids(options = {})
39
+ html = Nokogiri::HTML(open(status_url(options)))
40
+ ids = []
41
+ 2.upto(Float::INFINITY) do |row|
42
+ element = html.xpath("/html/body/table[2]/tr[#{row}]/td[1]").text
43
+ break if element.empty?
44
+ ids << element.to_i
45
+ end
46
+ ids += code_ids(options.merge(top: ids.last)) unless ids.empty?
47
+ ids
48
+ end
49
+
50
+ def codes(options = {})
51
+ code_ids.map do |id|
52
+ code(id)
53
+ end
54
+ end
55
+
56
+ def url
57
+ "http://poj.org/userstatus?user_id=#{@username}"
58
+ end
59
+
60
+ private
61
+
62
+ def status_url(options)
63
+ options.merge!(user_id: @username)
64
+ params = options.map { |key, value|
65
+ "&#{key}=#{value}"
66
+ }.join('&')
67
+ "http://poj.org/status?#{params}"
68
+ end
69
+ end
70
+ end
data/lib/poj_org.rb CHANGED
@@ -1,119 +1,4 @@
1
- require 'net/http'
2
- require 'open-uri'
3
- require 'cgi'
4
-
5
- # This class provides authetication methods
6
- class PojOrg
7
- # Stored user name
8
- @@user = nil
9
-
10
- # Stored password
11
- @@password = nil
12
-
13
- # Status of last authentication
14
- @@authenticated = false
15
-
16
- # Autheticate and store user name and password
17
- #
18
- # @example
19
- # >> PojOrg::authenticate('poj_library', 'secret')
20
- # => true
21
- # >> PojOrg::authenticate('poj_library', 'wrong_password')
22
- # => false
23
- #
24
- # @param [String] user user name of poj.org
25
- # @param [String] password password of poj.org
26
- #
27
- # @return [Boolean] whether authenticated or not
28
- def self.authenticate(user, password)
29
- if login(user, password)
30
- @@user = user
31
- @@password = password
32
- @@authenticated = true
33
- else
34
- @@authenticated = false
35
- end
36
- end
37
-
38
- # Unauthenticate and erase user name and password
39
- def self.unauthenticate
40
- @@user = nil
41
- @@password = nil
42
- @@authenticated = false
43
- end
44
-
45
- # Status of last authentication
46
- #
47
- # @return [Boolean] Whether the last authentication success or not
48
- def self.authenticated?
49
- @@authenticated
50
- end
51
-
52
- # Url of problem
53
- #
54
- # @param [Integer] ID of problem
55
- #
56
- # @return [String] Url of problem
57
- def self.problem_url(id)
58
- "http://poj.org/problem?id=#{id}"
59
- end
60
-
61
- # Details of problem
62
- #
63
- # @param [Integer] ID of problem
64
- #
65
- # @return [Hash] Details of problem or Nil if any error occured
66
- def self.problem(id)
67
- html = open(problem_url(id)).read
68
- return nil if html.include? '<title>Error</title>'
69
- {
70
- id: id,
71
- url: problem_url(id),
72
- title: html[/(?<=<div class="ptt" lang="en-US">).+?(?=<\/div>)/],
73
- time_limit_in_ms: html[/(?<=<b>Time Limit:<\/b>)\s*\d+/].to_i,
74
- memory_limit_in_kb: html[/(?<=<b>Memory Limit:<\/b>)\s*\d+/].to_i
75
- }
76
- end
77
-
78
- # Url of code
79
- #
80
- # @param [Integer] ID of code
81
- #
82
- # @return [String] Url of code
83
- def self.code_url(id)
84
- "http://poj.org/showsource?solution_id=#{id}"
85
- end
86
-
87
- # Details of code
88
- # Need to be autheticated
89
- #
90
- # @param [Integer] ID of code
91
- #
92
- # @return [Hash] Details of code or Nil if any error occured
93
- def self.code(id)
94
- return nil unless authenticated?
95
- html = open(code_url(id), 'Cookie' => login).read
96
- return nil if html.include? '<title>Error</title>'
97
- {
98
- id: id,
99
- url: code_url(id),
100
- problem_id: (/<td><b>Problem:.+?<a.+?>(.+?)<\/a><\/td>/).match(html)[1].to_i,
101
- user: (/<td><b>User:.+?<a.+?>(.+?)<\/a><\/td>/).match(html)[1],
102
- time_in_ms: (/<td><b>Time:.+?(\d+)MS<\/td>/).match(html)[1].to_i,
103
- memory_in_kb: (/<td><b>Memory:.+?(\d+)K<\/td>/).match(html)[1].to_i,
104
- language: (/<td><b>Language:<\/b>\s*(.+?)<\/td>/).match(html)[1],
105
- content: CGI.unescapeHTML((/<pre.+?>(.+)<\/pre>/m).match(html)[1])
106
- }
107
- end
108
-
109
- private
110
-
111
- def self.login(user = nil, password = nil)
112
- login = Net::HTTP.post_form(
113
- URI('http://poj.org/login'),
114
- 'user_id1' => user || @@user,
115
- 'password1' => password || @@password
116
- )
117
- login.body['failed'] ? false : login['set-cookie']
118
- end
119
- end
1
+ require 'poj_org/errors'
2
+ require 'poj_org/problem'
3
+ require 'poj_org/user'
4
+ require 'poj_org/code'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: poj_org
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,15 +9,35 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-25 00:00:00.000000000 Z
13
- dependencies: []
14
- description: Fetch details of problems and codes from poj.org
12
+ date: 2013-03-15 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: nokogiri
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ description: Fetch details of problems, codes and users from poj.org
15
31
  email: pinepara@gmail.com
16
32
  executables: []
17
33
  extensions: []
18
34
  extra_rdoc_files: []
19
35
  files:
20
36
  - ./lib/poj_org.rb
37
+ - ./lib/poj_org/problem.rb
38
+ - ./lib/poj_org/errors.rb
39
+ - ./lib/poj_org/code.rb
40
+ - ./lib/poj_org/user.rb
21
41
  homepage: https://github.com/pinepara/poj_org
22
42
  licenses: []
23
43
  post_install_message: