Open Side Menu Go to the Top
Register
Coursera SaaS class (Ruby+Rails) discussion Coursera SaaS class (Ruby+Rails) discussion

03-13-2012 , 06:26 PM
hw1_2

rps.feature:
Code:
Feature: Play RPS

I want to be able to play RPS against one opponent because it's fun.

Scenario Outline: Two player RPS
  Given "<player_one>" threw "<throw_one>"
  When "<player_two>" throws "<throw_two>"
  Then the oputput should be "<output>"
  
Examples:
  |player_one|throw_one|player_two|throw_two|output|
  |Armando|P|Dave|S|Dave,S|
  |Dave|S|Armando|P|Dave,S|
  |Armando|R|Dave|R|Armando,R|
  |Armando|r|Dave|p|Dave,p|
rps_steps.rb:
Code:
require_relative 'hw1_2.rb'

Given /^"([^"]*)" threw "([^"]*)"$/ do |player_one, throw_one|
  @player_one = [player_one, throw_one]
end

When /^"([^"]*)" throws "([^"]*)"$/ do |player_two, throw_two|
  @player_two = [player_two, throw_two]
end

Then /^the oputput should be "([^"]*)"$/ do |winner|
  game = [@player_one, @player_two]
  expected_output = winner.split(',')
  raise "Wrong Output" unless expected_output == rps_game_winner(game)
end
rps_tournament.feature:
Code:
Feature: Play an RPS torunament

I want to be able to play an entire RPS tournament because it's more fun than a single gamefun.

Scenario: RPS tournament [ ["Armando", "P"], ["Kris", "S"] ]
  Given A tournament that looks like [ ["Armando", "P"], ["Kris", "S"] ]
  When The tournament engine is run
  Then the tournament oputput should be ["Kris", "S"]
  
Scenario: RPS tournament [ [ [ "Allen", "P" ], [ "Dave", "S" ] ],[ [ "Richard", "R" ] , [ "Armando", "P" ] ]]
  Given A tournament that looks like [ [ [ "Allen", "P" ], [ "Dave", "S" ] ],[ [ "Richard", "R" ] , [ "Armando", "P" ] ]]
  When The tournament engine is run
  Then the tournament oputput should be ["Dave", "S"]
  
Scenario: RPS tournament [ [ [ "Allen", "p" ], [ "Dave", "P" ] ],[ [ "Richard", "R" ] , [ "Armando", "P" ] ]]
  Given A tournament that looks like [ [ [ "Allen", "p" ], [ "Dave", "P" ] ],[ [ "Richard", "R" ] , [ "Armando", "P" ] ]]
  When The tournament engine is run
  Then the tournament oputput should be ["Allen", "p"]
  
Scenario: RPS tournament [[ [ [ "Allen", "P" ], [ "Dave", "S" ] ],[ [ "Richard", "R" ] , [ "Armando", "P" ] ]], [ [ [ "Omer", "P" ], [ "David", "S" ] ],[ [ "Max", "R" ] , [ "Jonathan", "P" ] ]], ]
  Given A tournament that looks like [[ [ [ "Allen", "P" ], [ "Dave", "S" ] ],[ [ "Richard", "R" ] , [ "Armando", "P" ] ]], [ [ [ "Omer", "P" ], [ "David", "S" ] ],[ [ "Max", "R" ] , [ "Jonathan", "P" ] ]], ]
  When The tournament engine is run
  Then the tournament oputput should be ["Dave", "S"]
rps_tournament_steps.rb:
Code:
require_relative 'hw1_2.rb'

# Some examples of tournaments
tournament_one = [ ["Armando", "P"], ["Dave", "S"] ]
tournament_two = [ 
  [ [ "Allen", "P" ], [ "Dave", "S" ] ],
  [ [ "Richard", "R" ] , [ "Armando", "P" ] ]
]
tournament_three = [
  [ 
     [ [ "Allen", "P" ], [ "Dave", "S" ] ],
     [ [ "Richard", "R" ] , [ "Armando", "P" ] ]
  ], 
  [ 
     [ [ "Omer", "P" ], [ "David", "S" ] ],
     [ [ "Max", "R" ] , [ "Jonathan", "P" ] ]
  ], 
]

Given /^A tournament that looks like (.*)$/ do |tournament|
  @tournament = tournament
end

When /^The tournament engine is run$/ do
  tournament = eval(@tournament)
  @output = rps_tournament_winner(tournament).to_s
end

Then /^the tournament oputput should be (.*)$/ do |expected_output|
  raise "Wrong Output" unless expected_output == @output
end
hw1_2.rb:
Spoiler:

Code:
class WrongNumberOfPlayersError < StandardError ; end
class NoSuchStrategyError < StandardError ; end
def rps_game_winner(game)
  raise WrongNumberOfPlayersError unless game.length == 2
  valid_strategies = ['r','p','s']
  game.each do |name,strategy|
    raise NoSuchStrategyError unless valid_strategies.include? strategy.downcase
  end
  
  # Each game concists of two pairs, each pair looks like this: [player_name,strategy]
  pair_one = game[0]
  strategy_one = pair_one[1].downcase
  pair_two = game[1]
  strategy_two = pair_two[1].downcase
  
  # Ties go to the first player otherwise p>r, s>p, r>s
  if strategy_one == 'r' and strategy_two != 'p'
    return pair_one
  elsif strategy_one == 'p' and strategy_two != 's'
    return pair_one
  elsif strategy_one == 's' and strategy_two != 'r'
    return pair_one
  else
    return pair_two
  end
end

def rps_tournament_winner(tournament)
    # Remove all nesting
    flat_tournament = tournament.flatten
    # Group players with their strategy
    tidy_tournament = flat_tournament.each_slice(2).to_a
    # Group two [player_name,strategy] pairs as a matchup
    matchups = tidy_tournament.each_slice(2).to_a
    
    # Last matchup determines the winner
    if matchups.length == 1
      return rps_game_winner(matchups.first)
    else
      # Build the next round by adding all matchup winners of the current round to next_round
      next_round = Array.new
      matchups.each do |matchup|
        next_round << rps_game_winner(matchup)
      end
      # Run the next round
      rps_tournament_winner(next_round)
    end
end
Coursera SaaS class (Ruby+Rails) discussion Quote
03-13-2012 , 06:29 PM
hw1_3

anagram_spec.rb:
Code:
require_relative '../hw1_3_new.rb'

sample_list = ['cars', 'for', 'potatoes', 'racs', 'four','scar', 'creams',
'scream']

describe "anagram?" do
  it "should return true for equal words" do
    anagram?('house','house').should be_true
  end
  it "should return true for equal words with different capitalization" do
    anagram?('hoUsE','house').should be_true
  end
  it "should return false for different words that aren't anagrams'" do
    anagram?('house','wall').should be_false
  end
  it "should return true for anagrams" do
    anagram?('cars','rcas').should be_true
  end
end

describe "combine anagrams" do
  it "should return a list" do
    combine_anagrams(['cars']).class.should be Array 
  end
  it "should return the same list case sensitive if the count is one" do
    combine_anagrams(['cars']).should == [['cars']]
    combine_anagrams(['Cars']).should == [['Cars']]
  end
  it "should work for simple examples" do
    combine_anagrams(['ab','aa','ba']).sort.should == [['aa'],['ab','ba']].sort
    combine_anagrams(['ab','aa','cc','ba',]).sort.should == [['aa'],['ab','ba'],['cc']].sort
    combine_anagrams(['ab','aa','ba','cc']).sort.should == [['aa'],['ab','ba'],['cc']].sort
  end
  it "should handle a simple case of some repeated single-character inputs" do
    combine_anagrams(['a','a','b','c','d','b']).sort.should == [['a', 'a'], ['b', 'b'], ['c'], ['d']]
  end
  
  it "should work for the testcase ['cars', 'for', 'potatoes', 'racs', 'four','scar', 'creams',
'scream']" do
    combine_anagrams(['cars', 'for', 'potatoes', 'racs', 'four','scar', 'creams',
'scream']).sort.should == [["cars", "racs", "scar"], ["four"], ["for"],
["potatoes"], ["creams", "scream"]].sort
  end
end
hw1_3_new.rb
Spoiler:
Code:
# Create a list of lists of anagrams, repeat words are not removed, case is kept in the output
def combine_anagrams(words)
  final_anagrams = []
  while words.length > 0
    current_item = words.pop
    anagrams = words.find_all{|item| anagram?(current_item,item)}
    # If no anagrams match our current_item we only add it as a list
    if anagrams.empty?
      final_anagrams << [current_item]
    # If we get matches we add those and the current_item as a list and remove all matching items from the original list
    else
      final_anagrams << ([current_item]+anagrams).sort
      anagrams.each do |anagram|
        words.delete(anagram)
      end
    end
  end
  return final_anagrams.sort
end

# Find an anagram given two strings, case does not matter
def anagram?(word_one, word_two)
  a = word_one.downcase.split('').sort.join
  b = word_two.downcase.split('').sort.join
  a == b
end
Coursera SaaS class (Ruby+Rails) discussion Quote
03-13-2012 , 06:31 PM
1_4 is trivial so I'll skip it...1_5:
hw1_5_spec.rb:
Code:
require_relative '../hw1_5.rb'

describe Foo do
  before(:each) do
    @foo = Foo.new
  end
  it "should exist" do
    foo_new = Foo.new
  end
  it "should have a getter for bar" do
    @foo.methods.should include(:bar)
  end
  it "should have getter for bar_history" do
    @foo.methods.should include(:bar_history)
  end
  it "should have a setter for bar" do
    @foo.bar = 3
    @foo.bar.should == 3
  end
  it "should have an empty history at first" do
    @foo.bar_history.should == nil
  end
  it "should remember history" do
    @foo.bar = 3
    @foo.bar = :wowzo
    @foo.bar = 'boo!'
    @foo.bar_history.should == [nil, 3, :wowzo, 'boo!']
  end
  it "should maintain instance variables seperately for each object instance" do
    foo = Foo.new
    foo.bar = 1
    foo.bar = 2
    foo = Foo.new
    foo.bar = 4
    foo.bar_history.should == [nil, 4]
  end
  it "should work for class Baz with methodname lolcat" do
    baz = Baz.new
    baz.lolcat = 'can i'
    baz.lolcat = 'haz'
    baz.lolcat = 'cheesburger?'
    baz.lolcat_history.should == [nil, 'can i', 'haz', 'cheesburger?']
  end
end
hw1_5.rb
Spoiler:

Code:
class Class
  def attr_accessor_with_history(attr_name)
    attr_name = attr_name.to_s # make sure it's a string
    attr_reader attr_name # create the attribute's getter
    attr_reader attr_name+"_history"
    class_eval %Q{
      def #{attr_name}=(value)
	@#{attr_name} = value
	@#{attr_name}_history ||= [nil]
	@#{attr_name}_history << value
      end
    }
  end
end

class Foo
  attr_accessor_with_history :bar
end

class Baz
  attr_accessor_with_history :lolcat
end

f = Foo.new
f.bar = 1
f.bar = 2
#puts f.bar_history.to_s
f.bar_history
Coursera SaaS class (Ruby+Rails) discussion Quote
03-14-2012 , 08:45 PM
My solutions:

1) Almost the same as clowntable's, except I specified a default value of 0 for the hash, which allowed me to omit the conditional inside the loop.

2)
Spoiler:
class WrongNumberOfPlayersError < StandardError ; end
class NoSuchStrategyError < StandardError ; end

def strategy_for_player(player)
strategyHash = {'s'=>:scissors, 'r'=>:rock, 'p'=>aper}
strategy = strategyHash[player[1].downcase]
raise NoSuchStrategyError if strategy == nil

strategy
end

def get_winning_strategy(strategies)

if strategies[0] == strategies[1]
return 0
elsif strategies[0] == :scissors && strategies[1] == aper
return 0
elsif strategies[0] == :scissors && strategies[1] == :rock
return 1
elsif strategies[0] == :rock && strategies[1] == aper
return 1
elsif strategies[0] == :rock && strategies[1] == :scissors
return 0
elsif strategies[0] == aper && strategies[1] == :scissors
return 1
elsif strategies[0] == aper && strategies[1] == :rock
return 0
end
end

def rps_game_winner(game)
raise WrongNumberOfPlayersError unless game.length == 2
strategies = [strategy_for_player(game[0]), strategy_for_player(game[1])]

game[get_winning_strategy(strategies)]
end



def rps_tournament_winner(tournament)
if (tournament[0][0].kind_of?(Array))
return rps_game_winner([rps_tournament_winner(tournament[0]), rps_tournament_winner(tournament[1])])
else
return rps_game_winner(tournament)
end
end


3) I had some trouble finding the string sorting method..
Spoiler:
def sorted_string(word)

sortedString = ""

word.downcase.each_char { |c|
if sortedString != nil
x=0
while x < sortedString.length && c.casecmp(sortedString[x].chr) == 1
x += 1
end

sortedString.insert(x, c)
else
sortedString = c
end
}

sortedString
end


def combine_anagrams(words)

anagramHash = Hash.new
anagramArray = Array.new

words.each { |word|
key = sorted_string(word)

if anagramHash.has_key?(key)
anagramArray[anagramHash[key]] << word
else
anagramArray << [word]
anagramHash[key] = (anagramArray.size - 1)
end
}

anagramArray
end


5) Same as clowntable's
Coursera SaaS class (Ruby+Rails) discussion Quote
03-15-2012 , 01:49 AM
To get good allignment and avoid smilies etc:
put [ code ] [ /code ] around your code in posts (without the spaces in the tags)
Coursera SaaS class (Ruby+Rails) discussion Quote
03-15-2012 , 04:10 PM
HW1 Prob3 can be done slightly simpler relying on more built-in functionality:

Code:
def combine_anagrams(words)
  result_hash = Hash.new { |hash, key| hash[key] = [] }
  words.each do |word|
    hashkey = word.downcase.split(//).sort.join
    result_hash[hashkey] = result_hash[hashkey].push(word)
  end
  result_hash.values
end
Coursera SaaS class (Ruby+Rails) discussion Quote
03-19-2012 , 02:16 AM
Cucumber was kind of fun to learn and somewhat cute but is this really useful? Why use a language whose best feature is resemblance to English to write tests, if you have to use regex to extend/parse the language anyhow?
Coursera SaaS class (Ruby+Rails) discussion Quote
03-19-2012 , 11:30 AM
The entire reason is to tap into more domain expert knowledge/work with customers (imo). If you just work on your own projects I'm pretty sure you could simply stick to rspec.

But if you think about a typical project, Cucumber starts to make way more sense. Just imagine sitting at a table with a customer and collectiong feature, feature, feature, feature then scenarios for the features, then estimate work/feature. You can collect this stuff in Cucumber already and have a decent outline of what you need to do with acceptance criteria etc.
All the customer is ever going to see is the feature files

It probably also helps to clear up stuff etc (and you have some sort of minimalistic documentation of what the system is supposed to do, there's some neat output to pdf and whatnot stuff)
Coursera SaaS class (Ruby+Rails) discussion Quote
03-20-2012 , 02:23 AM
Quote:
Originally Posted by candybar
Cucumber was kind of fun to learn and somewhat cute but is this really useful? Why use a language whose best feature is resemblance to English to write tests, if you have to use regex to extend/parse the language anyhow?
apparently this is a real debate, with DHH taking your side:
http://www.rubyinside.com/dhh-offend...bate-4610.html

i enjoyed this exchange quoted in the article:



Coursera SaaS class (Ruby+Rails) discussion Quote
03-20-2012 , 01:39 PM
"Why would you build a test-specific parser for English" is such a silly question.
Spoiler:
because you can
Coursera SaaS class (Ruby+Rails) discussion Quote
03-20-2012 , 03:13 PM
Quote:
Originally Posted by gaming_mouse
apparently this is a real debate, with DHH taking your side:
http://www.rubyinside.com/dhh-offend...bate-4610.html

i enjoyed this exchange quoted in the article:



LOL. I sort of get it now - feature files can be read and/or written by business folks, whether clients or product managers. And having to parse the feature files to test forces feature documentation to be maintained because tests will fail otherwise. An interesting, fun way to force people who speak different languages to work together. I can see where it may be worth the overhead.
Coursera SaaS class (Ruby+Rails) discussion Quote
03-21-2012 , 01:01 AM
Anyone have some ideas on how to write the rspec tests for this week's homework? Particularly:
-a RESTful route for Find Similar Movies
-handling the sad path of "no director"
I'm still having a hard time wrapping my head around stubbing/isolating functionalities in rspec in general, I think.

Also, it sounds like the hw is saying you should re-use the show.html.haml page for when the user clicks 'Find similar movies'- how are people adding functionality to that page for multiple movies? I implemented it one way but seems kind of clunky.
Coursera SaaS class (Ruby+Rails) discussion Quote
03-30-2012 , 04:26 PM
Quick question on getting setup with Ruby: I downloaded/installed but am a little confused. I can open "Interactive Ruby" and it looks similar to command prompt but think I'm doing something wrong. I'm trying to follow along here:

http://pine.fm/LearnToProgram/?Chapter=00

Not clear how to save the program you write if I'm doing it right. Having said that, I can't write multiple lines of code and then run the program...so I feel like I'm not looking in the right place.

Thanks for the help guys,
Mariogs
Coursera SaaS class (Ruby+Rails) discussion Quote

      
m