project_euler_cli 1.2.0 → 1.3.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: d24479bc8b7da8a9224cd9fbed31f5719d55f8470631661ef1854aa4f72456c7
4
- data.tar.gz: 1c2019b22c5b6f7dbac1f4831b51ffc1d16961a4294f20bf70965307e238ace7
3
+ metadata.gz: c66d200a7ebd8baa0a733e1ad106595280b60a1dace740083df802b6b2c6cfb0
4
+ data.tar.gz: 19437da2e5cf758d9a7f5476672e6889e8e25f46d3e8fab0902de80d70f39497
5
5
  SHA512:
6
- metadata.gz: 9b407f362003ada505414c27c933abd6d92a2e60569e97eac901349a9d09a5751401f6ec8d936391a36b389b8019725638d190ff64b0fe9d0d59c84ddc93d7c7
7
- data.tar.gz: 3f920320f2902c8e232c79fef65a3a03c90050600d3815e8c7c354740d44b066fa36ac7c47a70ac1d55f35339eff74f3074d6ee5434989a0102037789b93f50e
6
+ metadata.gz: 6c2fd76b1c7fee6762f642d980358a95a45190e39996886046bfd191b2002c074f2f633164f85d3b789d1afa8184957ef856c650452ad00f0740b23a75918d93
7
+ data.tar.gz: ce9fe335d2d88c0def96b18b85e0ffd8f9a4735f8ce85125eab05eff9643114a1811c1dbc1423c55a4879906ae9a86da2c14185c595a6f045b0f72a894a94ebf
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- project_euler_cli (1.2.0)
4
+ project_euler_cli (1.3.0)
5
5
  nokogiri (~> 1.8)
6
6
 
7
7
  GEM
@@ -4,10 +4,9 @@ require 'nokogiri'
4
4
  require 'pry'
5
5
 
6
6
  require "project_euler_cli/version"
7
- require "project_euler_cli/problem"
8
7
  require "project_euler_cli/page"
8
+ require "project_euler_cli/problem"
9
9
  require "project_euler_cli/concerns/scraper"
10
- require "project_euler_cli/archive_controller"
11
10
  require "project_euler_cli/archive_viewer"
12
11
  require "project_euler_cli/archive_searcher"
13
12
  require "project_euler_cli/cli"
@@ -9,9 +9,7 @@ class ArchiveSearcher
9
9
  # Tracks whether there is an active search
10
10
  attr_accessor :searching
11
11
 
12
- def initialize(problems)
13
- @problems = problems
14
-
12
+ def initialize
15
13
  @results = []
16
14
  @searching = false
17
15
  @initial_search = true
@@ -21,27 +19,27 @@ class ArchiveSearcher
21
19
  def load_keywords
22
20
  puts "updating keywords..."
23
21
 
24
- 0.upto(Page.total) { |page| load_page(page, @problems) }
22
+ 0.upto(Page.total) { |page| load_page(page) }
25
23
  end
26
24
 
27
25
  # Performs a simple search of the problems. It accepts multiple terms and
28
26
  # recognizes quoted phrases. Results will contain *all* of the search terms.
29
27
  #
30
28
  # * +terms+ - String of search terms
31
- def search(terms_string)
29
+ def search(search_string)
32
30
  load_keywords if Page.visited != (0..Page.total).to_a
33
31
 
34
32
  puts "searching..."
35
33
  @searching = true
36
34
 
37
- terms_string.downcase!
38
- terms = terms_string.scan(/"[^"]*"/)
39
- terms.each { |term| terms_string.slice!(term) }
35
+ search_string.downcase!
36
+ terms = search_string.scan(/"[^"]*"/)
37
+ terms.each { |term| search_string.slice!(term) }
40
38
  terms.collect! { |term| term.gsub("\"", '') }
41
- terms += terms_string.split(' ')
39
+ terms += search_string.split(' ')
42
40
 
43
41
  @results = (1..Problem.total).select do |i|
44
- terms.all? { |term| @problems[i].title.downcase.include?(term) }
42
+ terms.all? { |term| Problem[i].title.downcase.include?(term) }
45
43
  end
46
44
  end
47
45
 
@@ -4,31 +4,31 @@ module ProjectEulerCli
4
4
  class ArchiveViewer
5
5
  include Scraper
6
6
 
7
- def initialize(problems)
8
- @problems = problems
7
+ def initialize
8
+ lookup_totals
9
9
  end
10
10
 
11
11
  # Displays the 10 most recently added problems.
12
12
  def display_recent
13
- load_recent(@problems)
13
+ load_recent
14
14
 
15
15
  puts
16
16
 
17
17
  (Problem.total).downto(Problem.total - 9) do |i|
18
- puts "#{i} - #{@problems[i].title}"
18
+ puts "#{i} - #{Problem[i].title}"
19
19
  end
20
20
  end
21
21
 
22
22
  # Displays the problem numbers and titles for an individual page of the
23
23
  # archive.
24
24
  def display_page(page)
25
- load_page(page, @problems)
25
+ load_page(page)
26
26
 
27
27
  puts
28
28
 
29
29
  start = (page - 1) * Page::LENGTH + 1
30
30
  start.upto(start + Page::LENGTH - 1) do |i|
31
- puts "#{i} - #{@problems[i].title}" unless i >= Problem.total - 9
31
+ puts "#{i} - #{Problem[i].title}" unless i >= Problem.total - 9
32
32
  end
33
33
  end
34
34
 
@@ -36,17 +36,17 @@ class ArchiveViewer
36
36
  #
37
37
  # * +id+ - ID of the problem to be displayed
38
38
  def display_problem(id)
39
- load_problem_details(id, @problems)
39
+ load_problem_details(id)
40
40
 
41
41
  puts
42
42
  puts "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-="
43
43
  puts
44
- puts "#{@problems[id].title}".upcase
44
+ puts Problem[id].title.upcase
45
45
  puts "Problem #{id}"
46
46
  puts
47
- puts @problems[id].published
48
- puts @problems[id].solved_by
49
- puts @problems[id].difficulty if id < Problem.total - 9
47
+ puts Problem[id].published
48
+ puts Problem[id].solved_by
49
+ puts Problem[id].difficulty if id < Problem.total - 9
50
50
  puts
51
51
  puts "https://projecteuler.net/problem=#{id}"
52
52
  puts
@@ -58,7 +58,7 @@ class ArchiveViewer
58
58
  # * +list+ - Array of problem IDs
59
59
  def display_custom_page(list)
60
60
  puts
61
- list.each { |id| puts "#{id} - #{@problems[id].title}" }
61
+ list.each { |id| puts "#{id} - #{Problem[id].title}" }
62
62
  end
63
63
 
64
64
  end
@@ -1,11 +1,11 @@
1
1
  module ProjectEulerCli #:nodoc:
2
2
 
3
- # Manages the command line interface for the program. It uses the
4
- # ArchiveController to access the site data.
3
+ # Manages the command line interface for the program.
5
4
  class CLI
6
5
 
7
6
  def initialize
8
- @ac = ArchiveController.new
7
+ @av = ArchiveViewer.new
8
+ @as = ArchiveSearcher.new
9
9
  end
10
10
 
11
11
  def start
@@ -51,7 +51,7 @@ class CLI
51
51
  end
52
52
 
53
53
  def recent_menu
54
- @ac.display_recent
54
+ @av.display_recent
55
55
 
56
56
  puts
57
57
  puts "e(x)it"
@@ -69,7 +69,7 @@ class CLI
69
69
 
70
70
  def page_menu(page)
71
71
  page = [1, page, Page.total].sort[1] #clamp
72
- @ac.display_page(page)
72
+ @av.display_page(page)
73
73
 
74
74
  puts
75
75
  puts "[#{page}/#{Page.total}] (n)ext (p)rev (g)oto e(x)it"
@@ -95,7 +95,7 @@ class CLI
95
95
  end
96
96
 
97
97
  def problem_menu(id)
98
- @ac.display_problem(id)
98
+ @av.display_problem(id)
99
99
 
100
100
  puts
101
101
  puts "(b)ack e(x)it"
@@ -103,10 +103,10 @@ class CLI
103
103
  input = prompt
104
104
 
105
105
  if input == 'b'
106
- if @ac.searching
106
+ if @as.searching
107
107
  search_results_menu
108
108
  else
109
- page = @ac.get_page(id)
109
+ page = Problem.page(id)
110
110
  page == 0 ? recent_menu : page_menu(page)
111
111
  end
112
112
  elsif input == 'x'
@@ -120,24 +120,24 @@ class CLI
120
120
  print "search: "
121
121
 
122
122
  search_terms = gets.strip
123
- @ac.search(search_terms)
123
+ @as.search(search_terms)
124
124
  search_results_menu
125
125
  end
126
126
 
127
127
  def search_results_menu
128
- @ac.display_results
128
+ @av.display_custom_page(@as.results)
129
129
 
130
130
  puts
131
131
  puts "(s)earch e(x)it"
132
132
 
133
133
  input = prompt
134
134
 
135
- if @ac.results_include?(input.to_i)
135
+ if @as.results.include?(input.to_i)
136
136
  problem_menu(input.to_i)
137
137
  elsif input == 's'
138
138
  search_menu
139
139
  elsif input == 'x'
140
- @ac.searching = false
140
+ @as.searching = false
141
141
  return
142
142
  else
143
143
  search_results_menu
@@ -15,12 +15,10 @@ module Scraper
15
15
 
16
16
  # The newest problem is the first one listed on the recent page. The ID
17
17
  # of this problem will always equal the total number of problems.
18
- Problem.total = id_col.first.text.to_i
18
+ id_col.first.text.to_i.times { Problem.new }
19
19
  # There are ten problems on the recent page, so the last archive problem
20
- # can be found by subtracting 10 from the total number of problems. This
21
- # is used to calculate the total number of pages.
22
- last_archive_id = Problem.total - 10
23
- Page.total = (last_archive_id - 1) / Page::LENGTH + 1
20
+ # can be found by subtracting 10 from the total number of problems.
21
+ Page.total = Problem.page(Problem.total - 10)
24
22
  end
25
23
  rescue Timeout::Error
26
24
  puts "Project Euler is not responding."
@@ -30,7 +28,7 @@ module Scraper
30
28
  end
31
29
 
32
30
  # Loads in all of the problem numbers and titles from the recent page.
33
- def load_recent(problems)
31
+ def load_recent
34
32
  return if Page.visited.include?(0)
35
33
 
36
34
  html = open("https://projecteuler.net/recent")
@@ -40,7 +38,7 @@ module Scraper
40
38
 
41
39
  i = Problem.total
42
40
  problem_links.each do |link|
43
- problems[i].title = link.text
41
+ Problem[i].title = link.text
44
42
  i -= 1
45
43
  end
46
44
 
@@ -48,7 +46,7 @@ module Scraper
48
46
  end
49
47
 
50
48
  # Loads the problem numbers and titles for an individual page of the archive.
51
- def load_page(page, problems)
49
+ def load_page(page)
52
50
  return if Page.visited.include?(page)
53
51
 
54
52
  html = open("https://projecteuler.net/archives;page=#{page}")
@@ -58,7 +56,7 @@ module Scraper
58
56
 
59
57
  i = (page - 1) * Page::LENGTH + 1
60
58
  problem_links.each do |link|
61
- problems[i].title = link.text
59
+ Problem[i].title = link.text
62
60
  i += 1
63
61
  end
64
62
 
@@ -66,8 +64,8 @@ module Scraper
66
64
  end
67
65
 
68
66
  # Loads the details of an individual problem.
69
- def load_problem_details(id, problems)
70
- return unless problems[id].published.nil?
67
+ def load_problem_details(id)
68
+ return unless Problem[id].published.nil?
71
69
 
72
70
  html = open("https://projecteuler.net/problem=#{id}")
73
71
  fragment = Nokogiri::HTML(html)
@@ -75,11 +73,11 @@ module Scraper
75
73
  problem_info = fragment.css('div#problem_info span span')
76
74
 
77
75
  details = problem_info.text.split(';')
78
- problems[id].published = details[0].strip
79
- problems[id].solved_by = details[1].strip
76
+ Problem[id].published = details[0].strip
77
+ Problem[id].solved_by = details[1].strip
80
78
 
81
79
  # recent problems do not have a difficult rating
82
- problems[id].difficulty = details[2].strip if id < Problem.total - 9
80
+ Problem[id].difficulty = details[2].strip if id <= Problem.total - 10
83
81
  end
84
82
 
85
83
  end
@@ -3,14 +3,31 @@ module ProjectEulerCli
3
3
  class Problem
4
4
  attr_accessor :title, :published, :solved_by, :difficulty
5
5
 
6
- @@total = 0
6
+ @@all = []
7
+
8
+ def initialize
9
+ @@all << self
10
+ end
11
+
12
+ def self.[](id)
13
+ @@all[id - 1]
14
+ end
15
+
16
+ def self.[]=(id, value)
17
+ @@all[id - 1] = value
18
+ end
7
19
 
8
20
  def self.total
9
- @@total
21
+ @@all.size
10
22
  end
11
23
 
12
- def self.total=(total)
13
- @@total = total
24
+ # call-seq:
25
+ # get_page(id) => page
26
+ #
27
+ # Returns page number based on the ID of the problem. The recent page is
28
+ # considered page 0.
29
+ def self.page(id)
30
+ id.between?(1, total - 10) ? (id - 1) / Page::LENGTH + 1 : 0
14
31
  end
15
32
 
16
33
  end
@@ -1,3 +1,3 @@
1
1
  module ProjectEulerCli
2
- VERSION = "1.2.0"
2
+ VERSION = "1.3.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: project_euler_cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ecssiah
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-04-23 00:00:00.000000000 Z
11
+ date: 2018-04-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -102,7 +102,6 @@ files:
102
102
  - bin/project-euler-cli
103
103
  - bin/setup
104
104
  - lib/project_euler_cli.rb
105
- - lib/project_euler_cli/archive_controller.rb
106
105
  - lib/project_euler_cli/archive_searcher.rb
107
106
  - lib/project_euler_cli/archive_viewer.rb
108
107
  - lib/project_euler_cli/cli.rb
@@ -1,60 +0,0 @@
1
- module ProjectEulerCli
2
-
3
- # Controller class that manages the archive system. It holds the archive data
4
- # used by ArchiveViewer and ArchiveSearcher.
5
- class ArchiveController
6
- include Scraper
7
-
8
- def initialize
9
- lookup_totals
10
-
11
- @problems = Array.new(Problem.total + 1) { Problem.new }
12
-
13
- @av = ArchiveViewer.new(@problems)
14
- @as = ArchiveSearcher.new(@problems)
15
- end
16
-
17
- def searching=(searching)
18
- @as.searching = searching
19
- end
20
-
21
- def searching
22
- @as.searching
23
- end
24
-
25
- def search(terms)
26
- @as.search(terms)
27
- end
28
-
29
- def results_include?(id)
30
- @as.results.include?(id)
31
- end
32
-
33
- def display_recent
34
- @av.display_recent
35
- end
36
-
37
- def display_page(page)
38
- @av.display_page(page)
39
- end
40
-
41
- def display_results
42
- @av.display_custom_page(@as.results)
43
- end
44
-
45
- def display_problem(id)
46
- @av.display_problem(id)
47
- end
48
-
49
- # call-seq:
50
- # get_page(id) => page
51
- #
52
- # Returns page number based on the ID of the problem. The recent page is
53
- # considered page 0.
54
- def get_page(id)
55
- id.between?(1, Problem.total - 10) ? (id - 1) / Page::LENGTH + 1 : 0
56
- end
57
-
58
- end
59
-
60
- end