diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1dde2a4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +coverage +.bundle 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..38c66e8 --- /dev/null +++ b/Gemfile @@ -0,0 +1,4 @@ +source "https://rubygems.org" + +gem "nokogiri" +gem "values" diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..a43c2e8 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,17 @@ +GEM + remote: https://rubygems.org/ + specs: + mini_portile (0.5.3) + nokogiri (1.6.1) + mini_portile (~> 0.5.0) + values (1.5.0) + +PLATFORMS + ruby + +DEPENDENCIES + nokogiri + values + +BUNDLED WITH + 1.10.5 diff --git a/README.md b/README.md index 11daf64..3e79df8 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,56 @@ -***An exercise for Prime subscribers. Visit http://learn.thoughtbot.com/prime to learn more.*** +# Upcase Analyzing Shakespeare -### Difficulty level: intermediate. +One of the many excersizes I take my students through at [Devschool's Online Developer School](https://devschool.rocks) -## Your Task +## Directions -As a Shakespeare buff, statistics junkie, and unix lover, Ben finds himself wanting a command-line tool for analyzing Macbeth. +Take the following XML file: [Macbeth XML](http://www.ibiblio.org/xml/examples/shakespeare/macbeth.xml) -Write a command-line program that prints the number of lines spoken by each character in the play. +Write Ruby code to parse the xml and extract the speakers and their line counts. -Sample usage/output (using made-up numbers): +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*. - $ ruby macbeth_analyzer.rb - 543 Macbeth - 345 Banquo - 220 Duncan - (etc.) +## Running the tests -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. +```bash +rake +``` -Your solution must be tested, preferably via TDD. +Nothing more. You might need to `bundle install` frst. -## Working/Submitting +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. -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. +## How about some help asshole? -## Bounty +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 [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 + +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 + +to print the output to screen: + +```bash +bundle +./bin/print +``` + +or to save the output: + +```bash +bundle +./bin/save +``` -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. diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..2a50202 --- /dev/null +++ b/Rakefile @@ -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/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/lib/shakespeare_analyzer.rb b/lib/shakespeare_analyzer.rb new file mode 100644 index 0000000..fa091ab --- /dev/null +++ b/lib/shakespeare_analyzer.rb @@ -0,0 +1,6 @@ +module ShakespeareAnalyzer + extend self + + def call(xml) + end +end 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..7a2b706 --- /dev/null +++ b/test/integration/line_counts_test.rb @@ -0,0 +1,14 @@ +require 'minitest_helper' +require 'shakespeare_analyzer' + +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 + 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 new file mode 100644 index 0000000..e41d4ee --- /dev/null +++ b/test/minitest_helper.rb @@ -0,0 +1,3 @@ +require 'minitest/autorun' +require 'minitest/pride' +Dir[File.join('./test/support/**/*.rb')].sort.each { |f| require f }