Created
July 23, 2015 18:02
-
-
Save gxespino/298494ec0917ee0c793b to your computer and use it in GitHub Desktop.
Analyzing Shakespeare
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--color | |
--require spec_helper | |
--format documentation |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Analyzer | |
attr_reader :line_hash_array | |
def initialize(line_hash_array) | |
@line_hash_array = line_hash_array | |
@sorted_hash = Hash.new(0) | |
end | |
def analyze | |
hash = line_hash_array.reduce(Hash.new, :merge) | |
@sorted_hash = hash.sort_by { |_key, value| value }.reverse.to_h.each do |k, v| | |
puts "#{v} #{k}" | |
end | |
@sorted_hash | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'spec_helper' | |
describe Analyzer do | |
let(:sample_xml) { File.open("spec/fixtures/sample.xml") } | |
let(:parser) { Parser.new(sample_xml)} | |
it "prints the correct number of lines for characters in an descending fashion" do | |
result = { "Sergeant"=>17, "DUNCAN"=>6, "MALCOLM"=>5 } | |
hashed = parser.speakers_and_lines | |
counter = Counter.new(hashed) | |
counted_lines = counter.line_count_hash | |
analyzer = Analyzer.new(counted_lines).analyze | |
expect(analyzer).to eq result | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Counter | |
attr_reader :parsed_hash | |
def initialize(parsed_hash) | |
@parsed_hash = parsed_hash | |
end | |
def line_count(speaker) | |
consolidate_lines[speaker].count | |
end | |
def consolidate_lines | |
parsed_hash.inject { |speaker, lines| speaker.merge(lines) { |x, val_1, val_2 | val_1 + val_2 }} | |
end | |
def line_count_hash | |
consolidate_lines.map do |speaker, lines_array| | |
{ speaker => consolidate_lines[speaker].count } | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "spec_helper" | |
describe Counter do | |
let(:sample_xml) { File.open("spec/fixtures/sample.xml") } | |
let(:parser) { Parser.new(sample_xml) } | |
it "counts the number of lines for a speaker" do | |
hashed = parser.speakers_and_lines | |
counter = Counter.new(hashed) | |
expect(counter.line_count("DUNCAN")).to eq 6 | |
expect(counter.line_count("MALCOLM")).to eq 5 | |
expect(counter.line_count("Sergeant")).to eq 17 | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'net/http' | |
class Downloader | |
URL = 'http://www.ibiblio.org/xml/examples/shakespeare/macbeth.xml' | |
def download | |
Net::HTTP.get(URI.parse(URL)) | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'spec_helper' | |
describe Downloader do | |
it "downloads the MacBeth file from the internet" do | |
response = "<xml>" | |
stub = stub_request(:get, "http://www.ibiblio.org/xml/examples/shakespeare/macbeth.xml"). | |
to_return(:body => response) | |
file = Downloader.new | |
expect(file.download).to eq response | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
source "https://rubygems.org" | |
gem "nokogiri" | |
gem "rspec" | |
gem "rake" | |
gem "webmock" | |
gem "byebug" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "./lib/analyzer" | |
require "./lib/downloader" | |
require "./lib/parser" | |
require "./lib/counter" | |
xml = Downloader.new.download | |
hashed = Parser.new(xml).speakers_and_lines | |
count = Counter.new(hashed).line_count_hash | |
Analyzer.new(count).analyze |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'nokogiri' | |
class Parser | |
attr_reader :file | |
attr_reader :result | |
def initialize(file) | |
@file = Nokogiri::XML(file) | |
end | |
def speakers_and_lines | |
search_for(file, "SPEECH").map do |speech| | |
speaker = search_for(speech, "SPEAKER").text | |
lines = search_for(speech, "LINE").map(&:text) | |
{ | |
speaker => lines | |
} | |
end | |
end | |
private | |
def search_for(source, text) | |
source.search(text) | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'spec_helper' | |
describe Parser do | |
let(:sample_xml) { File.open("spec/fixtures/sample.xml") } | |
let(:parser) { Parser.new(sample_xml) } | |
it "parses an xml file for speakers and their lines" do | |
duncan_lines = { | |
"DUNCAN" => [ "What bloody man is that? He can report,", | |
"As seemeth by his plight, of the revolt", | |
"The newest state." ] | |
} | |
malcolm_lines = { | |
"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." ] | |
} | |
expect(parser.speakers_and_lines[0]).to eq duncan_lines | |
expect(parser.speakers_and_lines[1]).to eq malcolm_lines | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0"?> | |
<!DOCTYPE PLAY SYSTEM "play.dtd"> | |
<PLAY> | |
<TITLE>The Tragedy of Macbeth</TITLE> | |
<FM> | |
<P>Text placed in the public domain by Moby Lexical Tools, 1992.</P> | |
<P>SGML markup by Jon Bosak, 1992-1994.</P> | |
<P>XML version by Jon Bosak, 1996-1998.</P> | |
<P>This work may be freely copied and distributed worldwide.</P> | |
</FM> | |
<PERSONAE> | |
<TITLE>Dramatis Personae</TITLE> | |
<PERSONA>DUNCAN, king of Scotland.</PERSONA> | |
<PGROUP> | |
<PERSONA>MALCOLM</PERSONA> | |
<PERSONA>DONALBAIN</PERSONA> | |
<GRPDESCR>his sons.</GRPDESCR> | |
</PGROUP> | |
<PGROUP> | |
<PERSONA>MACBETH</PERSONA> | |
<PERSONA>BANQUO</PERSONA> | |
<GRPDESCR>generals of the king's army.</GRPDESCR> | |
</PGROUP> | |
<PGROUP> | |
<PERSONA>MACDUFF</PERSONA> | |
<PERSONA>LENNOX</PERSONA> | |
<PERSONA>ROSS</PERSONA> | |
<PERSONA>MENTEITH</PERSONA> | |
<PERSONA>ANGUS</PERSONA> | |
<PERSONA>CAITHNESS</PERSONA> | |
<GRPDESCR>noblemen of Scotland.</GRPDESCR> | |
</PGROUP> | |
<PERSONA>FLEANCE, son to Banquo.</PERSONA> | |
<PERSONA>SIWARD, Earl of Northumberland, general of the English forces.</PERSONA> | |
<PERSONA>YOUNG SIWARD, his son.</PERSONA> | |
<PERSONA>SEYTON, an officer attending on Macbeth.</PERSONA> | |
<PERSONA>Boy, son to Macduff. </PERSONA> | |
<PERSONA>An English Doctor. </PERSONA> | |
<PERSONA>A Scotch Doctor. </PERSONA> | |
<PERSONA>A Soldier.</PERSONA> | |
<PERSONA>A Porter.</PERSONA> | |
<PERSONA>An Old Man.</PERSONA> | |
<PERSONA>LADY MACBETH</PERSONA> | |
<PERSONA>LADY MACDUFF</PERSONA> | |
<PERSONA>Gentlewoman attending on Lady Macbeth. </PERSONA> | |
<PERSONA>HECATE</PERSONA> | |
<PERSONA>Three Witches.</PERSONA> | |
<PERSONA>Apparitions.</PERSONA> | |
<PERSONA>Lords, Gentlemen, Officers, Soldiers, Murderers, Attendants, and Messengers. </PERSONA> | |
</PERSONAE> | |
<SCNDESCR>SCENE Scotland: England.</SCNDESCR> | |
<PLAYSUBT>MACBETH</PLAYSUBT> | |
<ACT><TITLE>ACT I</TITLE> | |
<SCENE><TITLE>SCENE II. A camp near Forres.</TITLE> | |
<STAGEDIR>Alarum within. Enter DUNCAN, MALCOLM, DONALBAIN, | |
LENNOX, with Attendants, meeting a bleeding Sergeant</STAGEDIR> | |
<SPEECH> | |
<SPEAKER>DUNCAN</SPEAKER> | |
<LINE>What bloody man is that? He can report,</LINE> | |
<LINE>As seemeth by his plight, of the revolt</LINE> | |
<LINE>The newest state.</LINE> | |
</SPEECH> | |
<SPEECH> | |
<SPEAKER>MALCOLM</SPEAKER> | |
<LINE>This is the sergeant</LINE> | |
<LINE>Who like a good and hardy soldier fought</LINE> | |
<LINE>'Gainst my captivity. Hail, brave friend!</LINE> | |
<LINE>Say to the king the knowledge of the broil</LINE> | |
<LINE>As thou didst leave it.</LINE> | |
</SPEECH> | |
<SPEECH> | |
<SPEAKER>Sergeant</SPEAKER> | |
<LINE>Doubtful it stood;</LINE> | |
<LINE>As two spent swimmers, that do cling together</LINE> | |
<LINE>And choke their art. The merciless Macdonwald--</LINE> | |
<LINE>Worthy to be a rebel, for to that</LINE> | |
<LINE>The multiplying villanies of nature</LINE> | |
<LINE>Do swarm upon him--from the western isles</LINE> | |
<LINE>Of kerns and gallowglasses is supplied;</LINE> | |
<LINE>And fortune, on his damned quarrel smiling,</LINE> | |
<LINE>Show'd like a rebel's whore: but all's too weak:</LINE> | |
<LINE>For brave Macbeth--well he deserves that name--</LINE> | |
<LINE>Disdaining fortune, with his brandish'd steel,</LINE> | |
<LINE>Which smoked with bloody execution,</LINE> | |
<LINE>Like valour's minion carved out his passage</LINE> | |
<LINE>Till he faced the slave;</LINE> | |
<LINE>Which ne'er shook hands, nor bade farewell to him,</LINE> | |
<LINE>Till he unseam'd him from the nave to the chaps,</LINE> | |
<LINE>And fix'd his head upon our battlements.</LINE> | |
</SPEECH> | |
<SPEECH> | |
<SPEAKER>DUNCAN</SPEAKER> | |
<LINE>What bloody man is that? He can report,</LINE> | |
<LINE>As seemeth by his plight, of the revolt</LINE> | |
<LINE>The newest state.</LINE> | |
</SPEECH> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$LOAD_PATH << File.dirname(File.dirname(__FILE__)) | |
require "macbeth_analyzer" | |
require "webmock/rspec" | |
WebMock.disable_net_connect!(allow_localhost: true) | |
Dir["spec/support/*.rb"].each { |f| require f } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Well, there are not so many things to talk about:
{}
? And preferinject
overreduce
parsed_result
/expected_result
). Move them tolet
blocks or just rethink your architectureWordCounter
or whatever... (I've seen a project that has aDay
class that was some kind of json serializer, it had only a huge constructor and#to_json
method - almost the same story here). Or move all your classes to some namespace, it will save from conflicts.File.read(path/to/xml)
- move to helperProbably you can also make it more configurable like
require
calls. Read about$LOAD_PATH
andrelative_require
(or, probablyKernel.autoload
, but then you need a namespace module){ key => value }
let
, write some shared helper for fixtures.It seems that you were trying to write everything in a proper OO-way, but Ruby supports multiple paradigms, do not use only OOP. And I don't see any common class that wraps all the functionality (I mean, it would be nice to write it).
I think that's all!