From f82516cf8ebfba22f739baff2b1b947432e4de8c Mon Sep 17 00:00:00 2001 From: thatrubylove Date: Fri, 4 Apr 2014 12:44:39 -0600 Subject: [PATCH 1/8] boom, problem solved --- .gitignore | 1 + .rubocop.yml | 11 +++ Gemfile | 7 ++ Gemfile.lock | 99 +++++++++++++++++++ Rakefile | 13 +++ lib/shakespeare_analyzer.rb | 15 +++ lib/shakespeare_analyzer/printer.rb | 7 ++ lib/shakespeare_analyzer/speaker.rb | 5 + .../speaker_aggregator.rb | 29 ++++++ .../speaker_counts_from_xml.rb | 23 +++++ lib/tasks/test.rake | 10 ++ output.txt | 41 ++++++++ test/fixtures/story.xml | 23 +++++ test/integration/line_counts_test.rb | 18 ++++ test/minitest_helper.rb | 15 +++ test/support/minitest_reporters.rb | 4 + test/support/mocha.rb | 1 + 17 files changed, 322 insertions(+) create mode 100644 .gitignore create mode 100644 .rubocop.yml create mode 100644 Gemfile create mode 100644 Gemfile.lock create mode 100644 Rakefile create mode 100644 lib/shakespeare_analyzer.rb create mode 100644 lib/shakespeare_analyzer/printer.rb create mode 100644 lib/shakespeare_analyzer/speaker.rb create mode 100644 lib/shakespeare_analyzer/speaker_aggregator.rb create mode 100644 lib/shakespeare_analyzer/speaker_counts_from_xml.rb create mode 100644 lib/tasks/test.rake create mode 100644 output.txt create mode 100644 test/fixtures/story.xml create mode 100644 test/integration/line_counts_test.rb create mode 100644 test/minitest_helper.rb create mode 100644 test/support/minitest_reporters.rb create mode 100644 test/support/mocha.rb diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ed9f9cc --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +coverage \ No newline at end of file diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..ec8e09e --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,11 @@ +Encoding: + Enabled: false + +AccessModifierIndentation: + EnforcedStyle: outdent + +Documentation: + Enabled: false + +ModuleFunction: + Enabled: false diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..8b3f294 --- /dev/null +++ b/Gemfile @@ -0,0 +1,7 @@ +source "https://rubygems.org" + +gem "thincloud-test", group: [:development, :test] +gem "rubocop", group: [:development, :test] + +gem "nokogiri" +gem "values" diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..def5026 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,99 @@ +GEM + remote: https://rubygems.org/ + specs: + ansi (1.4.3) + ast (1.1.0) + builder (3.2.2) + cane (2.5.2) + parallel + celluloid (0.15.2) + timers (~> 1.1.0) + celluloid-io (0.15.0) + celluloid (>= 0.15.0) + nio4r (>= 0.5.0) + coderay (1.1.0) + ffi (1.9.3) + guard (1.6.2) + listen (>= 0.6.0) + lumberjack (>= 1.0.2) + pry (>= 0.9.10) + terminal-table (>= 1.4.3) + thor (>= 0.14.6) + guard-minitest (0.5.0) + guard (>= 0.4) + hashie (2.0.5) + json (1.8.1) + listen (2.7.1) + celluloid (>= 0.15.2) + celluloid-io (>= 0.15.0) + rb-fsevent (>= 0.9.3) + rb-inotify (>= 0.9) + lumberjack (1.0.5) + metaclass (0.0.4) + method_source (0.8.2) + mini_portile (0.5.3) + minitest (4.6.2) + minitest-reporters (0.14.24) + ansi + builder + minitest (>= 2.12, < 5.0) + powerbar + mocha (0.13.3) + metaclass (~> 0.0.1) + multi_json (1.9.2) + nio4r (1.0.0) + nokogiri (1.6.1) + mini_portile (~> 0.5.0) + parallel (1.0.0) + parser (2.1.7) + ast (~> 1.1) + slop (~> 3.4, >= 3.4.5) + powerbar (1.0.11) + ansi (~> 1.4.0) + hashie (>= 1.1.0) + powerpack (0.0.9) + pry (0.9.12.6) + coderay (~> 1.0) + method_source (~> 0.8) + slop (~> 3.4) + rainbow (2.0.0) + rb-fsevent (0.9.4) + rb-inotify (0.9.3) + ffi (>= 0.5.0) + rubocop (0.20.0) + json (>= 1.7.7, < 2) + parser (~> 2.1.7) + powerpack (~> 0.0.6) + rainbow (>= 1.99.1, < 3.0) + ruby-progressbar (~> 1.4) + ruby-progressbar (1.4.2) + simplecov (0.7.1) + multi_json (~> 1.0) + simplecov-html (~> 0.7.1) + simplecov-html (0.7.1) + slop (3.5.0) + terminal-notifier-guard (1.5.3) + terminal-table (1.4.5) + thincloud-test (1.0.0) + cane (~> 2.5.2) + guard (~> 1.6.2) + guard-minitest (~> 0.5.0) + minitest (~> 4.6.2) + minitest-reporters (~> 0.14.7) + mocha (~> 0.13.2) + rb-fsevent (~> 0.9.1) + simplecov (~> 0.7.1) + terminal-notifier-guard (~> 1.5.3) + thor (~> 0.17.0) + thor (0.17.0) + timers (1.1.0) + values (1.5.0) + +PLATFORMS + ruby + +DEPENDENCIES + nokogiri + rubocop + thincloud-test + values diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..69ddec5 --- /dev/null +++ b/Rakefile @@ -0,0 +1,13 @@ +require "rake/testtask" + +require 'rubocop/rake_task' +Rubocop::RakeTask.new + +task default: [:test, :rubocop] + +Rake::TestTask.new(:test) do |t| + t.libs << "lib" + t.libs << "test" + t.pattern = "test/**/*_test.rb" + t.verbose = false +end diff --git a/lib/shakespeare_analyzer.rb b/lib/shakespeare_analyzer.rb new file mode 100644 index 0000000..804d1b4 --- /dev/null +++ b/lib/shakespeare_analyzer.rb @@ -0,0 +1,15 @@ +require 'nokogiri' +require 'values' + +require_relative 'shakespeare_analyzer/speaker_counts_from_xml' +require_relative 'shakespeare_analyzer/speaker_aggregator' + +module ShakespeareAnalyzer + extend self + + def call(printer, xml) + counts = SpeakerCountsFromXml.call(xml) + aggregate = SpeakerAggregator.call(counts) + printer.call(aggregate) + end +end diff --git a/lib/shakespeare_analyzer/printer.rb b/lib/shakespeare_analyzer/printer.rb new file mode 100644 index 0000000..8bdaae4 --- /dev/null +++ b/lib/shakespeare_analyzer/printer.rb @@ -0,0 +1,7 @@ +module Printer + extend self + + def call(counts) + counts.each { |count| puts count.to_s } + end +end diff --git a/lib/shakespeare_analyzer/speaker.rb b/lib/shakespeare_analyzer/speaker.rb new file mode 100644 index 0000000..a95f096 --- /dev/null +++ b/lib/shakespeare_analyzer/speaker.rb @@ -0,0 +1,5 @@ +class Speaker < Value.new(:name, :line_count) + def to_s + "#{@line_count} #{@name.capitalize}" + end +end diff --git a/lib/shakespeare_analyzer/speaker_aggregator.rb b/lib/shakespeare_analyzer/speaker_aggregator.rb new file mode 100644 index 0000000..eed7384 --- /dev/null +++ b/lib/shakespeare_analyzer/speaker_aggregator.rb @@ -0,0 +1,29 @@ +module SpeakerAggregator + extend self + + def call(counts) + sort(aggregate(counts)) + end + +protected + + def speakers(counts) + counts.map(&:name).uniq + end + + def sort(counts) + counts.sort { |a, b| b.line_count <=> a.line_count } + end + + def aggregate(counts) + speakers(counts).reduce([]) do |acc, speaker| + line_counts = sum_lines_by_speaker(counts, speaker) + acc << Speaker.new(speaker, line_counts) + end + end + + def sum_lines_by_speaker(list, speaker) + lc = list.select { |obj| obj.name == speaker }.map(&:line_count) + lc.reduce(:+) + end +end diff --git a/lib/shakespeare_analyzer/speaker_counts_from_xml.rb b/lib/shakespeare_analyzer/speaker_counts_from_xml.rb new file mode 100644 index 0000000..f5af588 --- /dev/null +++ b/lib/shakespeare_analyzer/speaker_counts_from_xml.rb @@ -0,0 +1,23 @@ +require_relative 'speaker' + +module SpeakerCountsFromXml + extend self + + def call(xml) + speaker_line_counts_from(xml) + end + +protected + + def xml_doc(xml) + Nokogiri::XML(xml) + end + + def speaker_line_counts_from(xml) + xml_doc(xml).search('SPEECH').map do |speech| + speaker = speech.at('SPEAKER').text + lines = speech.search('LINE').map(&:text) + Speaker.new(speaker, lines.count) + end + end +end diff --git a/lib/tasks/test.rake b/lib/tasks/test.rake new file mode 100644 index 0000000..2789348 --- /dev/null +++ b/lib/tasks/test.rake @@ -0,0 +1,10 @@ +require "rake/testtask" + +task default: :test + +Rake::TestTask.new(:test) do |t| + t.libs << "lib" + t.libs << "test" + t.pattern = "test/**/*_test.rb" + t.verbose = false +end diff --git a/output.txt b/output.txt new file mode 100644 index 0000000..37ea91e --- /dev/null +++ b/output.txt @@ -0,0 +1,41 @@ +719 Macbeth +265 Lady macbeth +212 Malcolm +180 Macduff +135 Ross +113 Banquo +73 Lennox +70 Duncan +62 First witch +46 Porter +45 Doctor +41 Lady macduff +39 Hecate +35 Sergeant +30 Siward +30 First murderer +27 Third witch +27 Second witch +24 All +23 Gentlewoman +23 Messenger +21 Angus +21 Lord +20 Son +15 Second murderer +12 Menteith +11 Old man +11 Caithness +10 Donalbain +8 Third murderer +7 Young siward +5 Third apparition +5 Seyton +5 Servant +4 Second apparition +3 Lords +2 First apparition +2 Both murderers +2 Fleance +1 Attendant +1 Soldiers diff --git a/test/fixtures/story.xml b/test/fixtures/story.xml new file mode 100644 index 0000000..dfbf267 --- /dev/null +++ b/test/fixtures/story.xml @@ -0,0 +1,23 @@ + + + + DUNCAN + What bloody man is that? He can report, + As seemeth by his plight, of the revolt + The newest state. + + + MALCOLM + This is the sergeant + Who like a good and hardy soldier fought + 'Gainst my captivity. Hail, brave friend! + Say to the king the knowledge of the broil + As thou didst leave it. + + + DUNCAN + What bloody man is that? He can report, + As seemeth by his plight, of the revolt + The newest state. + + diff --git a/test/integration/line_counts_test.rb b/test/integration/line_counts_test.rb new file mode 100644 index 0000000..b697748 --- /dev/null +++ b/test/integration/line_counts_test.rb @@ -0,0 +1,18 @@ +require 'minitest_helper' +require_relative '../../lib/shakespeare_analyzer' +require_relative '../../lib/shakespeare_analyzer/printer' + +describe ShakespeareAnalyzer do + describe 'call' do + subject { ShakespeareAnalyzer } + let(:fixture) { File.expand_path('../../fixtures/story.xml', __FILE__) } + let(:xml) { File.read(fixture) } + + it 'must print a list of speakers and line counts' do + out, _ = capture_io do + subject.call(Printer, xml) + end + out.must_equal "6 Duncan\n5 Malcolm\n" + end + end +end diff --git a/test/minitest_helper.rb b/test/minitest_helper.rb new file mode 100644 index 0000000..69575df --- /dev/null +++ b/test/minitest_helper.rb @@ -0,0 +1,15 @@ +if RUBY_ENGINE == 'ruby' + begin + require 'simplecov' + SimpleCov.start do + add_filter 'test' + add_filter 'config' + command_name 'MiniTest' + end + rescue LoadError + warn 'unable to load SimpleCov' + end +end + +require 'thincloud/test' +Dir[File.join('./test/support/**/*.rb')].sort.each { |f| require f } diff --git a/test/support/minitest_reporters.rb b/test/support/minitest_reporters.rb new file mode 100644 index 0000000..907ebc4 --- /dev/null +++ b/test/support/minitest_reporters.rb @@ -0,0 +1,4 @@ +unless ENV['CI'] + require 'minitest/reporters' + MiniTest::Reporters.use! MiniTest::Reporters::ProgressReporter.new +end diff --git a/test/support/mocha.rb b/test/support/mocha.rb new file mode 100644 index 0000000..2d9ba1b --- /dev/null +++ b/test/support/mocha.rb @@ -0,0 +1 @@ +require 'mocha/setup' From 9943b9f2014230201622fea72a012ec5c09c759e Mon Sep 17 00:00:00 2001 From: "Jim O'Kelly (rubycasts.io)" Date: Sun, 3 May 2015 13:54:12 -0500 Subject: [PATCH 2/8] rubycasts.io --- README.md | 32 ++------------------------------ 1 file changed, 2 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 11daf64..02155b3 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,5 @@ -***An exercise for Prime subscribers. Visit http://learn.thoughtbot.com/prime to learn more.*** +# Brought to you from the people behind www.rubycasts.io -### Difficulty level: intermediate. +Check out these awesome [ruby and rails screencasts](https://www.rubycasts.io)! There is 1 15 minute cast released every week as well as either a 2 Minute Ruby or a 2 Minute Rails screencast! -## Your Task -As a Shakespeare buff, statistics junkie, and unix lover, Ben finds himself wanting a command-line tool for analyzing Macbeth. - -Write a command-line program that prints the number of lines spoken by each character in the play. - -Sample usage/output (using made-up numbers): - - $ ruby macbeth_analyzer.rb - 543 Macbeth - 345 Banquo - 220 Duncan - (etc.) - -You can find an XML-encoded version of Macbeth here: http://www.ibiblio.org/xml/examples/shakespeare/macbeth.xml. Your program should download and parse this file at runtime. - -Your solution must be tested, preferably via TDD. - -## Working/Submitting - -1. To work on this exercise, fork the repo and begin implementing your solution. -2. When you are done, copy the output of your program into a file in this repository. -3. Create a pull request so your code can be reviewed. -4. Perform a code review on at least one other person's solution. Your comments should follow our code review guidelines: https://github.com/thoughtbot/guides/tree/master/code-review. Most important: be friendly. Make suggestions, not demands. -5. Improve your solution based on the comments you've received and approaches you've learned from reviewing others' attempts. - -## Bounty - -While knowledge and skill improvement are their own rewards, the author with the best solution (as judged by thoughtbot) will receive a cool thoughtbot t-shirt. From 60c08695f2348ffa8496e54c023a5600ad295cb8 Mon Sep 17 00:00:00 2001 From: "Jim O'Kelly (rubycasts.io)" Date: Mon, 13 Jul 2015 16:39:31 -0500 Subject: [PATCH 3/8] added some console implementations --- .gitignore | 3 +- Gemfile | 3 -- Gemfile.lock | 88 ++-------------------------------------------------- bin/print | 14 +++++++++ bin/save | 14 +++++++++ output.txt | 2 +- 6 files changed, 34 insertions(+), 90 deletions(-) create mode 100755 bin/print create mode 100755 bin/save diff --git a/.gitignore b/.gitignore index ed9f9cc..1dde2a4 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -coverage \ No newline at end of file +coverage +.bundle diff --git a/Gemfile b/Gemfile index 8b3f294..38c66e8 100644 --- a/Gemfile +++ b/Gemfile @@ -1,7 +1,4 @@ source "https://rubygems.org" -gem "thincloud-test", group: [:development, :test] -gem "rubocop", group: [:development, :test] - gem "nokogiri" gem "values" diff --git a/Gemfile.lock b/Gemfile.lock index def5026..a43c2e8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,92 +1,9 @@ GEM remote: https://rubygems.org/ specs: - ansi (1.4.3) - ast (1.1.0) - builder (3.2.2) - cane (2.5.2) - parallel - celluloid (0.15.2) - timers (~> 1.1.0) - celluloid-io (0.15.0) - celluloid (>= 0.15.0) - nio4r (>= 0.5.0) - coderay (1.1.0) - ffi (1.9.3) - guard (1.6.2) - listen (>= 0.6.0) - lumberjack (>= 1.0.2) - pry (>= 0.9.10) - terminal-table (>= 1.4.3) - thor (>= 0.14.6) - guard-minitest (0.5.0) - guard (>= 0.4) - hashie (2.0.5) - json (1.8.1) - listen (2.7.1) - celluloid (>= 0.15.2) - celluloid-io (>= 0.15.0) - rb-fsevent (>= 0.9.3) - rb-inotify (>= 0.9) - lumberjack (1.0.5) - metaclass (0.0.4) - method_source (0.8.2) mini_portile (0.5.3) - minitest (4.6.2) - minitest-reporters (0.14.24) - ansi - builder - minitest (>= 2.12, < 5.0) - powerbar - mocha (0.13.3) - metaclass (~> 0.0.1) - multi_json (1.9.2) - nio4r (1.0.0) nokogiri (1.6.1) mini_portile (~> 0.5.0) - parallel (1.0.0) - parser (2.1.7) - ast (~> 1.1) - slop (~> 3.4, >= 3.4.5) - powerbar (1.0.11) - ansi (~> 1.4.0) - hashie (>= 1.1.0) - powerpack (0.0.9) - pry (0.9.12.6) - coderay (~> 1.0) - method_source (~> 0.8) - slop (~> 3.4) - rainbow (2.0.0) - rb-fsevent (0.9.4) - rb-inotify (0.9.3) - ffi (>= 0.5.0) - rubocop (0.20.0) - json (>= 1.7.7, < 2) - parser (~> 2.1.7) - powerpack (~> 0.0.6) - rainbow (>= 1.99.1, < 3.0) - ruby-progressbar (~> 1.4) - ruby-progressbar (1.4.2) - simplecov (0.7.1) - multi_json (~> 1.0) - simplecov-html (~> 0.7.1) - simplecov-html (0.7.1) - slop (3.5.0) - terminal-notifier-guard (1.5.3) - terminal-table (1.4.5) - thincloud-test (1.0.0) - cane (~> 2.5.2) - guard (~> 1.6.2) - guard-minitest (~> 0.5.0) - minitest (~> 4.6.2) - minitest-reporters (~> 0.14.7) - mocha (~> 0.13.2) - rb-fsevent (~> 0.9.1) - simplecov (~> 0.7.1) - terminal-notifier-guard (~> 1.5.3) - thor (~> 0.17.0) - thor (0.17.0) - timers (1.1.0) values (1.5.0) PLATFORMS @@ -94,6 +11,7 @@ PLATFORMS DEPENDENCIES nokogiri - rubocop - thincloud-test values + +BUNDLED WITH + 1.10.5 diff --git a/bin/print b/bin/print new file mode 100755 index 0000000..8ad894a --- /dev/null +++ b/bin/print @@ -0,0 +1,14 @@ +#! /usr/bin/env ruby + +$LOAD_PATH.unshift "lib" + +require 'rubygems' +require 'bundler/setup' +require 'nokogiri' +require 'open-uri' +require 'shakespeare_analyzer' + +printer = ->(s) { puts s } + +uri = "http://www.ibiblio.org/xml/examples/shakespeare/macbeth.xml" +ShakespeareAnalyzer.(printer, open(uri)) diff --git a/bin/save b/bin/save new file mode 100755 index 0000000..1012ab0 --- /dev/null +++ b/bin/save @@ -0,0 +1,14 @@ +#! /usr/bin/env ruby + +$LOAD_PATH.unshift "lib" + +require 'rubygems' +require 'bundler/setup' +require 'nokogiri' +require 'open-uri' +require 'shakespeare_analyzer' + +printer = ->(s) { File.write "output.txt", s.map(&:to_s).join("\n") } + +uri = "http://www.ibiblio.org/xml/examples/shakespeare/macbeth.xml" +ShakespeareAnalyzer.(printer, open(uri)) diff --git a/output.txt b/output.txt index 37ea91e..040989e 100644 --- a/output.txt +++ b/output.txt @@ -38,4 +38,4 @@ 2 Both murderers 2 Fleance 1 Attendant -1 Soldiers +1 Soldiers \ No newline at end of file From b806cfda7f9376a457ae417b726edc09eb44d399 Mon Sep 17 00:00:00 2001 From: "Jim O'Kelly (rubycasts.io)" Date: Mon, 13 Jul 2015 16:48:22 -0500 Subject: [PATCH 4/8] readme update --- README.md | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 02155b3..d498574 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,27 @@ -# Brought to you from the people behind www.rubycasts.io +# Thoughtbot (Now Upcase) Shakespeare Analizer -Check out these awesome [ruby and rails screencasts](https://www.rubycasts.io)! There is 1 15 minute cast released every week as well as either a 2 Minute Ruby or a 2 Minute Rails screencast! +## Directions +Take the following XML file: (http://www.ibiblio.org/xml/examples/shakespeare/macbeth.xml)[Macbeth XML] +Write Ruby code to parse the xml and extract the speakers and their line counts. + +## My solution + +In the ./bin folder you will find 2 executable files that implement my solution. One prints out to a screen, the other saves the file to the hard disk as output.txt You could, for instance, write one that saves to a database or whatever floats your boat, all without editing the original software in lib. Al la, the Open/Closed principle bitches. + +## Running my solution + +to print the output to screen: + +```bash +bundle +./bin/print +``` + +or to save the output: + +```bash +bundle +./bin/save +``` From 0f94ad8b07ea63f2d01032520129aad1a53c5a05 Mon Sep 17 00:00:00 2001 From: "Jim O'Kelly (rubycasts.io)" Date: Tue, 14 Jul 2015 23:54:35 -0500 Subject: [PATCH 5/8] cleared the way for others --- Rakefile | 5 +-- lib/shakespeare_analyzer.rb | 11 +---- lib/shakespeare_analyzer/printer.rb | 7 ---- lib/shakespeare_analyzer/speaker.rb | 5 --- .../speaker_aggregator.rb | 29 ------------- .../speaker_counts_from_xml.rb | 23 ----------- lib/tasks/test.rake | 10 ----- output.txt | 41 ------------------- test/integration/line_counts_test.rb | 8 +--- test/minitest_helper.rb | 16 +------- test/support/minitest_reporters.rb | 4 -- test/support/mocha.rb | 1 - 12 files changed, 6 insertions(+), 154 deletions(-) delete mode 100644 lib/shakespeare_analyzer/printer.rb delete mode 100644 lib/shakespeare_analyzer/speaker.rb delete mode 100644 lib/shakespeare_analyzer/speaker_aggregator.rb delete mode 100644 lib/shakespeare_analyzer/speaker_counts_from_xml.rb delete mode 100644 lib/tasks/test.rake delete mode 100644 output.txt delete mode 100644 test/support/minitest_reporters.rb delete mode 100644 test/support/mocha.rb diff --git a/Rakefile b/Rakefile index 69ddec5..2a50202 100644 --- a/Rakefile +++ b/Rakefile @@ -1,9 +1,6 @@ require "rake/testtask" -require 'rubocop/rake_task' -Rubocop::RakeTask.new - -task default: [:test, :rubocop] +task default: [:test] Rake::TestTask.new(:test) do |t| t.libs << "lib" diff --git a/lib/shakespeare_analyzer.rb b/lib/shakespeare_analyzer.rb index 804d1b4..fa091ab 100644 --- a/lib/shakespeare_analyzer.rb +++ b/lib/shakespeare_analyzer.rb @@ -1,15 +1,6 @@ -require 'nokogiri' -require 'values' - -require_relative 'shakespeare_analyzer/speaker_counts_from_xml' -require_relative 'shakespeare_analyzer/speaker_aggregator' - module ShakespeareAnalyzer extend self - def call(printer, xml) - counts = SpeakerCountsFromXml.call(xml) - aggregate = SpeakerAggregator.call(counts) - printer.call(aggregate) + def call(xml) end end diff --git a/lib/shakespeare_analyzer/printer.rb b/lib/shakespeare_analyzer/printer.rb deleted file mode 100644 index 8bdaae4..0000000 --- a/lib/shakespeare_analyzer/printer.rb +++ /dev/null @@ -1,7 +0,0 @@ -module Printer - extend self - - def call(counts) - counts.each { |count| puts count.to_s } - end -end diff --git a/lib/shakespeare_analyzer/speaker.rb b/lib/shakespeare_analyzer/speaker.rb deleted file mode 100644 index a95f096..0000000 --- a/lib/shakespeare_analyzer/speaker.rb +++ /dev/null @@ -1,5 +0,0 @@ -class Speaker < Value.new(:name, :line_count) - def to_s - "#{@line_count} #{@name.capitalize}" - end -end diff --git a/lib/shakespeare_analyzer/speaker_aggregator.rb b/lib/shakespeare_analyzer/speaker_aggregator.rb deleted file mode 100644 index eed7384..0000000 --- a/lib/shakespeare_analyzer/speaker_aggregator.rb +++ /dev/null @@ -1,29 +0,0 @@ -module SpeakerAggregator - extend self - - def call(counts) - sort(aggregate(counts)) - end - -protected - - def speakers(counts) - counts.map(&:name).uniq - end - - def sort(counts) - counts.sort { |a, b| b.line_count <=> a.line_count } - end - - def aggregate(counts) - speakers(counts).reduce([]) do |acc, speaker| - line_counts = sum_lines_by_speaker(counts, speaker) - acc << Speaker.new(speaker, line_counts) - end - end - - def sum_lines_by_speaker(list, speaker) - lc = list.select { |obj| obj.name == speaker }.map(&:line_count) - lc.reduce(:+) - end -end diff --git a/lib/shakespeare_analyzer/speaker_counts_from_xml.rb b/lib/shakespeare_analyzer/speaker_counts_from_xml.rb deleted file mode 100644 index f5af588..0000000 --- a/lib/shakespeare_analyzer/speaker_counts_from_xml.rb +++ /dev/null @@ -1,23 +0,0 @@ -require_relative 'speaker' - -module SpeakerCountsFromXml - extend self - - def call(xml) - speaker_line_counts_from(xml) - end - -protected - - def xml_doc(xml) - Nokogiri::XML(xml) - end - - def speaker_line_counts_from(xml) - xml_doc(xml).search('SPEECH').map do |speech| - speaker = speech.at('SPEAKER').text - lines = speech.search('LINE').map(&:text) - Speaker.new(speaker, lines.count) - end - end -end diff --git a/lib/tasks/test.rake b/lib/tasks/test.rake deleted file mode 100644 index 2789348..0000000 --- a/lib/tasks/test.rake +++ /dev/null @@ -1,10 +0,0 @@ -require "rake/testtask" - -task default: :test - -Rake::TestTask.new(:test) do |t| - t.libs << "lib" - t.libs << "test" - t.pattern = "test/**/*_test.rb" - t.verbose = false -end diff --git a/output.txt b/output.txt deleted file mode 100644 index 040989e..0000000 --- a/output.txt +++ /dev/null @@ -1,41 +0,0 @@ -719 Macbeth -265 Lady macbeth -212 Malcolm -180 Macduff -135 Ross -113 Banquo -73 Lennox -70 Duncan -62 First witch -46 Porter -45 Doctor -41 Lady macduff -39 Hecate -35 Sergeant -30 Siward -30 First murderer -27 Third witch -27 Second witch -24 All -23 Gentlewoman -23 Messenger -21 Angus -21 Lord -20 Son -15 Second murderer -12 Menteith -11 Old man -11 Caithness -10 Donalbain -8 Third murderer -7 Young siward -5 Third apparition -5 Seyton -5 Servant -4 Second apparition -3 Lords -2 First apparition -2 Both murderers -2 Fleance -1 Attendant -1 Soldiers \ No newline at end of file diff --git a/test/integration/line_counts_test.rb b/test/integration/line_counts_test.rb index b697748..7a2b706 100644 --- a/test/integration/line_counts_test.rb +++ b/test/integration/line_counts_test.rb @@ -1,6 +1,5 @@ require 'minitest_helper' -require_relative '../../lib/shakespeare_analyzer' -require_relative '../../lib/shakespeare_analyzer/printer' +require 'shakespeare_analyzer' describe ShakespeareAnalyzer do describe 'call' do @@ -9,10 +8,7 @@ let(:xml) { File.read(fixture) } it 'must print a list of speakers and line counts' do - out, _ = capture_io do - subject.call(Printer, xml) - end - out.must_equal "6 Duncan\n5 Malcolm\n" + subject.call(xml).must_equal "6 Duncan\n5 Malcolm\n" end end end diff --git a/test/minitest_helper.rb b/test/minitest_helper.rb index 69575df..e41d4ee 100644 --- a/test/minitest_helper.rb +++ b/test/minitest_helper.rb @@ -1,15 +1,3 @@ -if RUBY_ENGINE == 'ruby' - begin - require 'simplecov' - SimpleCov.start do - add_filter 'test' - add_filter 'config' - command_name 'MiniTest' - end - rescue LoadError - warn 'unable to load SimpleCov' - end -end - -require 'thincloud/test' +require 'minitest/autorun' +require 'minitest/pride' Dir[File.join('./test/support/**/*.rb')].sort.each { |f| require f } diff --git a/test/support/minitest_reporters.rb b/test/support/minitest_reporters.rb deleted file mode 100644 index 907ebc4..0000000 --- a/test/support/minitest_reporters.rb +++ /dev/null @@ -1,4 +0,0 @@ -unless ENV['CI'] - require 'minitest/reporters' - MiniTest::Reporters.use! MiniTest::Reporters::ProgressReporter.new -end diff --git a/test/support/mocha.rb b/test/support/mocha.rb deleted file mode 100644 index 2d9ba1b..0000000 --- a/test/support/mocha.rb +++ /dev/null @@ -1 +0,0 @@ -require 'mocha/setup' From 43fabb497f143ef8acd742354e65b23745d65744 Mon Sep 17 00:00:00 2001 From: "Jim O'Kelly (rubycasts.io)" Date: Wed, 15 Jul 2015 00:38:40 -0500 Subject: [PATCH 6/8] pontificating in the readme --- README.md | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d498574..18cf9ef 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,37 @@ -# Thoughtbot (Now Upcase) Shakespeare Analizer +# Upcase Analyzing Shakespeare ## Directions -Take the following XML file: (http://www.ibiblio.org/xml/examples/shakespeare/macbeth.xml)[Macbeth XML] +Take the following XML file: [Macbeth XML](http://www.ibiblio.org/xml/examples/shakespeare/macbeth.xml) Write Ruby code to parse the xml and extract the speakers and their line counts. +The main entry-point is the lib/shakespeare_analyzer.rb and it is a stand-alone module, which means it holds no state and it is _not_ meant to be *mixed in*. + +## Running the tests + +```bash +rake +``` + +Nothing more. You might need to `bundle install` frst. + +The tests that are here are very basic top level tests. They are meant to be acceptance tests, meaning when the code 'works' these tests will pass without you changing them at'tall, as my English friend says. + +## How about some help asshole? + +Well, sure. That is only fair. If I gave you no further help I wouldn't be much of a RubyMentor, and that is exactly what I have become and am happy to be. So....... + +## TDDing the Shakespeare Analyzer + +I do this kind of thing much better in video than I do in text. Maybe it is because I curse less in video... Probably not, I think it may just be because I am really too lazy for my own good. Bullshit. I am a good programmer because I am just lazy enough! + +[Watch the video walkthrough here](http://youtu.be/420) + ## My solution +Located [in this branch](https://github.com/therubymentor/shakespeare_analyzer/tree/jimokelly-solution) + In the ./bin folder you will find 2 executable files that implement my solution. One prints out to a screen, the other saves the file to the hard disk as output.txt You could, for instance, write one that saves to a database or whatever floats your boat, all without editing the original software in lib. Al la, the Open/Closed principle bitches. ## Running my solution @@ -25,3 +49,4 @@ or to save the output: bundle ./bin/save ``` + From 64d1804066bd99d759619787537c5756a48dcabf Mon Sep 17 00:00:00 2001 From: "Jim O'Kelly (rubycasts.io)" Date: Sun, 19 Jul 2015 12:56:49 -0500 Subject: [PATCH 7/8] updated readme --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 18cf9ef..262170e 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,9 @@ Well, sure. That is only fair. If I gave you no further help I wouldn't be much I do this kind of thing much better in video than I do in text. Maybe it is because I curse less in video... Probably not, I think it may just be because I am really too lazy for my own good. Bullshit. I am a good programmer because I am just lazy enough! -[Watch the video walkthrough here](http://youtu.be/420) +Watch the [RubyLIVE.tv episode here](https://www.youtube.com/watch?v=lBkau5T1KnA) + +And the code is in [this branch](https://github.com/therubymentor/shakespeare_analyzer/tree/420-live) ## My solution From b4b65e5e0c2ef28c12d22b4a414b3cab53179c19 Mon Sep 17 00:00:00 2001 From: Jim OKelly Date: Wed, 30 Dec 2015 00:29:39 -0600 Subject: [PATCH 8/8] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 262170e..3e79df8 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Upcase Analyzing Shakespeare +One of the many excersizes I take my students through at [Devschool's Online Developer School](https://devschool.rocks) + ## Directions Take the following XML file: [Macbeth XML](http://www.ibiblio.org/xml/examples/shakespeare/macbeth.xml)