rubedility 0.0.1 → 0.1.1

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
  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: