rubedility 0.0.1 → 0.1.1

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
  SHA1:
3
- metadata.gz: 566c5f4ef00e392efdb7b35b5990bcfdaab105e3
4
- data.tar.gz: 533e420f6120eae91221a3b21c393f73edcb741b
3
+ metadata.gz: 8e24c19eb9bf3ce8b7308fa7a0e1ca658cc1600a
4
+ data.tar.gz: 30d4aa32e0d4bd4205e4115d7bbe438cd15ff3f1
5
5
  SHA512:
6
- metadata.gz: 983bf6eadf324614c74c72d50e488bcf45ec518cf1bb25533cbda12cc79ce651132f039f51b6defb678149d22d69e2e9058ebe3e40b6c775bc7a0679cd45adbf
7
- data.tar.gz: a5553306b47ca0c779a6fd015f21def9e9900273afe976040f45345667944cdc63af1c228d3273a32f5d4909432efd6e11159ab648f83d121fb0ec004ddcaf6f
6
+ metadata.gz: 20d46cf961d88b5958b163d519124ff0fd5a3024dc2ebe35a10f73aef9eee091b387df1f198bc954adf1e152117995a61dcde3ed42223e8b6b9dfc07e0ba306f
7
+ data.tar.gz: 372d73efbf9659961cd90005028624e8ef844e0a20cf69dbdc41cd8be7699d78c71665bd07ed3e11a14f2d659c316ee3585668a0f6d7f7eec667dcdcf7c1a652
data/bin/rubedility CHANGED
@@ -2,5 +2,4 @@
2
2
 
3
3
  require 'rubedility'
4
4
 
5
- Rubedility.new
6
- puts "We've started!"
5
+ Rubedility.new.run
@@ -0,0 +1,47 @@
1
+ class Difficulty
2
+ attr_accessor :level
3
+ def initialize(difficulty)
4
+ @level = difficulty
5
+ @@all.push(self)
6
+ @all_tasks = []
7
+ end
8
+
9
+ @@all = []
10
+ @all_tasks = []
11
+
12
+ def self.all
13
+ @@all
14
+ end
15
+
16
+ def all
17
+ @all_tasks
18
+ end
19
+
20
+ def display_tasks
21
+ self.all.each do |task|
22
+ puts task.name
23
+ end
24
+ end
25
+
26
+ def self.display_all
27
+ self.all.each do |diff|
28
+ puts "\n=====#{diff.level}====="
29
+ diff.display_tasks
30
+ puts "=======================\n"
31
+ end
32
+ puts "\n"
33
+ end
34
+
35
+ def self.find_or_create(task_difficulty)
36
+ self.all.each do |d|
37
+ if d.level == task_difficulty
38
+ return d
39
+ end
40
+ end
41
+ return self.new(task_difficulty)
42
+ end
43
+
44
+ def add_task(task)
45
+ self.all.push(task)
46
+ end
47
+ end
@@ -1,5 +1,106 @@
1
1
  class Rubedility::Lesson
2
- def initialize
3
- puts "we've now instantiated a lesson!"
2
+ attr_accessor :name, :number, :lesson_url, :reading_url, :tests_started, :tests_solved
3
+
4
+ @tasks = []
5
+
6
+ def initialize(lesson_hash)
7
+ add_lesson_attributes(lesson_hash)
8
+ @tasks = []
9
+ @@all.push(self)
4
10
  end
11
+
12
+ @@all = []
13
+
14
+ def self.populate_from_scraping(lessons_array)
15
+ lessons_array.each do |lesson|
16
+ self.new(lesson)
17
+ end
18
+ end
19
+
20
+ def self.all
21
+ @@all
22
+ end
23
+
24
+ def self.user_display_one
25
+ self.display_all
26
+ print "Select Lesson Number:"
27
+ input = gets.strip.to_i
28
+ self.all.each do |lesson|
29
+ if lesson.number==input
30
+ lesson.display_lesson
31
+ return nil
32
+ end
33
+ end
34
+ puts "Try selecting a correct number next time."
35
+ end
36
+
37
+ def display_lesson
38
+ self.tasks.each do |task|
39
+ task.display_row
40
+ end
41
+ end
42
+
43
+ def self.display_all
44
+ puts "\nAvailable Lessons: \n"
45
+ self.all.each do |les|
46
+ puts "#{les.number}. #{les.name}"
47
+ end
48
+ puts "\n"
49
+ return nil
50
+ end
51
+
52
+ def self.user_display_stats
53
+ self.display_all
54
+ print "Select Lesson Number for stats:"
55
+ input = gets.strip.to_i
56
+ self.all.each do |lesson|
57
+ if lesson.number==input
58
+ lesson.display_stats
59
+ return nil
60
+ end
61
+ end
62
+ return "Try selecting a correct number next time."
63
+ end
64
+
65
+ def display_stats
66
+ puts "\n#{self.tests_started} tests have been started from this lesson."
67
+ puts "#{self.tests_solved} tests have been solved from this lesson."
68
+ puts "#{self.tasks.length} task(s) gives an average success rate of #{(self.tests_solved.to_f/self.tests_started.to_f).round(3)*100}%"
69
+ end
70
+
71
+ def self.user_open_reading
72
+ self.display_all
73
+ print "Select Lesson Number for reading:"
74
+ input = gets.strip.to_i
75
+ self.all.each do |lesson|
76
+ if lesson.number==input
77
+ #lesson.open_reading
78
+ return lesson.reading_url
79
+ end
80
+ end
81
+ return "Try selecting a correct number next time."
82
+ end
83
+
84
+ def open_reading
85
+ puts "launchy: #{@reading_url}"
86
+ launchy @reading_url
87
+ end
88
+
89
+ def add_tasks(task_array)
90
+ task_array.each do |task_row|
91
+ self.tasks.push(Rubedility::Task.new(task_row))
92
+ end
93
+ end
94
+
95
+ def tasks
96
+ @tasks
97
+ end
98
+
99
+ def add_lesson_attributes(attributes_hash)
100
+ if attributes_hash == nil
101
+ return
102
+ end
103
+ attributes_hash.each{|key, val| self.send(("#{key}="), val)}
104
+ end
105
+
5
106
  end
@@ -0,0 +1,76 @@
1
+ require 'open-uri'
2
+ require 'nokogiri'
3
+ require 'pry'
4
+
5
+ class Scraper
6
+
7
+ def self.scrape_index_page(index_url)
8
+ index = Nokogiri::HTML(open(index_url))
9
+
10
+ lessons = []
11
+ index.css("div.lessons_list a").each do |lesson|
12
+ print "."
13
+ name = lesson.css("div.title").text
14
+ number = lesson.css("div.num").text.delete("Lesson").to_i
15
+ lesson_url = "".concat(index_url).concat(lesson.attr("href").split("/").last)
16
+ lessons.push({:name=>name, :number=>number, :lesson_url=>lesson_url})
17
+ end
18
+
19
+ return lessons
20
+ end
21
+
22
+ def self.scrape_lesson_page(lesson_url)
23
+ begin
24
+ print "."
25
+ lesson = Nokogiri::HTML(open(lesson_url))
26
+ if lesson.css("a#readings").length > 0
27
+ reading_url = lesson.css("a#readings").attr("href").value
28
+ end
29
+ tests_started = lesson.css("span.started span.num").text.to_i
30
+ tests_solved = lesson.css("span.finished span.num").text.to_i
31
+ task_hashes_array = []
32
+ lesson.css("div.task-box").each do |task_row|
33
+ name = task_row.css("h4.title").text.strip
34
+ #url is just the last 'piece' of the task URL
35
+ url = task_row.css("a").attr("href").text
36
+ #have to add that to the end of the 'real' URL, but take off part of it
37
+ task_url = lesson_url.split("/")[0..2].join("/").concat(url)
38
+ difficulty = task_row.css("div.difficulty").text.strip
39
+ tagline = task_row.css("div.synopsis").text.strip
40
+ task_hashes_array.push({:name=>name, :task_url=>task_url, :difficulty=>difficulty, :tagline=>tagline, :task_reading_url=>reading_url})
41
+ end
42
+ lesson_details = {:reading_url=>reading_url, :tests_started=>tests_started, :tests_solved=>tests_solved}
43
+ #return [hash-of-lesson-details, array-of-task-detail-hashes]
44
+ return [lesson_details, task_hashes_array]
45
+ rescue OpenURI::HTTPError => er
46
+ puts "404, Lesson not found"
47
+ puts lesson_url
48
+ puts er
49
+ return nil
50
+ else
51
+ end
52
+ end
53
+
54
+ def self.scrape_task_page(task_url)
55
+ print "."
56
+ begin
57
+ task = Nokogiri::HTML(open(task_url))
58
+ content = task.css("div.desc-rb-en div").first.text
59
+ #the way they have the content is not best for command line display.
60
+ #some '\n' and some '\n\n', command line looks better with '\n\n'
61
+ #substitube singles for doubles
62
+ content.gsub!(/[\n]+/,"\n")
63
+ #substitute doubles for singles
64
+ content.gsub!(/[\n]/,"\n\n")
65
+ return {:content=>content}
66
+ rescue OpenURI::HTTPError => er
67
+ puts "404'd!"
68
+ puts task_url
69
+ puts er
70
+ return nil
71
+ else
72
+ end
73
+ end
74
+
75
+ end
76
+
@@ -1,5 +1,67 @@
1
1
  class Rubedility::Task
2
- def initialize
3
- puts "we've nor instantiated a task!"
2
+ attr_accessor :name, :difficulty, :content, :task_url, :task_reading_url, :tagline
3
+
4
+ def initialize(task_row)
5
+ add_task_attributes(task_row)
6
+ @@all.push(self)
7
+ end
8
+
9
+ @@all = []
10
+
11
+ def self.create_from_collection(task_hash)
12
+ task_hash.each do |task|
13
+ Task.new(task)
14
+ end
15
+ end
16
+
17
+ def add_task_attributes(attributes_hash)
18
+ if attributes_hash == nil
19
+ return
20
+ end
21
+ attributes_hash.each do |key, val|
22
+ self.send(("#{key}="), val)
23
+ if key.to_s == "difficulty"
24
+ d = Difficulty.find_or_create(val)
25
+ d.add_task(self)
26
+ end
27
+ end
28
+ end
29
+
30
+ def self.all
31
+ @@all
32
+ end
33
+
34
+ def self.user_display_one
35
+ print "Enter Task Name:"
36
+ input = gets.strip.downcase
37
+ self.all.each do |task|
38
+ if task.name.downcase==input
39
+ task.display_content
40
+ return nil
41
+ end
42
+ end
43
+ self.display_all
44
+ puts "Try better next time."
45
+ end
46
+
47
+ def display_row
48
+ puts "=#{self.name}= (#{self.difficulty})"
49
+ puts "#{self.tagline}\n\n"
50
+ end
51
+
52
+ def display_content
53
+ puts "========================================="
54
+ puts "==========#{self.name}=========="
55
+ puts "========================================="
56
+ puts "Difficulty: #{self.difficulty}"
57
+ puts @content
58
+ end
59
+
60
+ def self.display_all
61
+ puts "\nAvailable Tasks: \n"
62
+ self.all.each do |task|
63
+ task.display_row
64
+ end
65
+ return nil
4
66
  end
5
67
  end
data/lib/rubedility.rb CHANGED
@@ -1,10 +1,13 @@
1
+ require 'launchy'
2
+
1
3
  class Rubedility
2
4
 
3
5
  def initialize
6
+ scrape_index
4
7
  scrape_lessons
5
8
  scrape_tasks
6
9
  display_greeting
7
- display_menu
10
+ #display_menu (menu will display from the 'while' loop below)
8
11
  end
9
12
 
10
13
  def self.list
@@ -12,27 +15,76 @@ class Rubedility
12
15
  end
13
16
 
14
17
  def run(commands=nil)
15
- puts "we're running"
16
- end
18
+ input = ""
19
+ until input=="exit" || input=="quit" || input=="close"
17
20
 
18
- def display_greeting
19
- puts "Welcome to Rubedility!"
20
- puts "Your command line access point for Ruby-flavored Codility lessons and tasks."
21
+ case input
22
+ when "list lessons"
23
+ Lesson.display_all
24
+
25
+ when "list tasks"
26
+ Task.display_all
27
+
28
+ when "list stats"
29
+ Lesson.user_display_stats
30
+
31
+ when "open lesson"
32
+ Lesson.user_display_one
33
+
34
+ when "open task"
35
+ Task.user_display_one
36
+
37
+ when "list by difficulty"
38
+ Difficulty.display_all
39
+
40
+ when "open reading"
41
+ Launchy.open(Lesson.user_open_reading)
42
+
43
+ else
44
+ display_menu
45
+
46
+ end
47
+ input = gets.strip
48
+ end
21
49
  end
22
50
 
23
- def display_menu
24
- puts "You can 'list <things>'"
51
+ def scrape_index
52
+ print "fetching index ..."
53
+ Lesson.populate_from_scraping(Scraper.scrape_index_page('https://codility.com/programmers/lessons/'))
54
+ puts "\n"
25
55
  end
26
56
 
27
57
  def scrape_lessons
28
- Lesson.new
58
+ #this would be an ideal time for some Asynchronous magical powers of awesome
59
+ print "fetching lessons..."
60
+ Lesson.all.each do |lesson|
61
+ attributes_hash, task_array = Scraper.scrape_lesson_page(lesson.lesson_url)
62
+ lesson.add_lesson_attributes(attributes_hash)
63
+ lesson.add_tasks(task_array)
64
+ end
65
+ puts "\n"
29
66
  end
30
67
 
31
68
  def scrape_tasks
32
- Task.new
69
+ print "fetching tasks ..."
70
+ Task.all.each do |task|
71
+ task.add_task_attributes(Scraper.scrape_task_page(task.task_url))
72
+ end
73
+ end
74
+
75
+ def display_greeting
76
+ puts "\nWelcome to Rubedility!"
77
+ puts "Your command line access point for Ruby-flavored Codility lessons and tasks.\n"
78
+ end
79
+
80
+ def display_menu
81
+ puts "Commands: '<list/open> <lesson(s)/task(s)/stats/reading>', 'list by difficulty', 'exit'"
82
+ #puts "Commands: 'list lessons', 'open lesson', 'list tasks', 'open task', 'list stats', 'open reading', 'exit'"
33
83
  end
34
84
 
35
85
  end
36
86
 
37
87
  require 'rubedility/lesson'
38
88
  require 'rubedility/task'
89
+ require 'rubedility/scraper'
90
+ require 'rubedility/difficulty'
metadata CHANGED
@@ -1,15 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubedility
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Holland
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-29 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2016-03-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: launchy
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
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: nokogiri
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
13
41
  description: Command line access to Codility.com programming lessons and tests
14
42
  email: beehollander@gmail.com
15
43
  executables:
@@ -19,7 +47,9 @@ extra_rdoc_files: []
19
47
  files:
20
48
  - bin/rubedility
21
49
  - lib/rubedility.rb
50
+ - lib/rubedility/difficulty.rb
22
51
  - lib/rubedility/lesson.rb
52
+ - lib/rubedility/scraper.rb
23
53
  - lib/rubedility/task.rb
24
54
  homepage: http://rubygems.org/gems/rubedility
25
55
  licenses: