Resummit my solution to the Madlabs Quiz and the unit tests.
Best Regards,
Steve Li.
···
--------------------------------------------------------------------------------------------------------------------
Madlibs.rb
class Story
attr_accessor :placeholders
def initialize(base)
@placeholders = []
story_parts = []
match = Placeholder.getPattern().match(base)
reuseMap = {}
while(match != nil)
story_parts << match.pre_match
placeholderString = match[1]
placeholder = Placeholder.new(placeholderString, story_parts.size)
# if name is reused
if reuseMap[placeholder.name] == nil
@placeholders << placeholder
# if the name is reusable, add it to the reuse table
if placeholder.reusable()
reuseMap[placeholder.name] = placeholder
end
# replace the placeholder with the system generated position
string
story_parts << get_position_string(story_parts.size.to_s)
else
# for reuse placeholder,
# replace the placeholder with the system generated position
string for the referenced placeholder
story_parts <<
get_position_string(reuseMap[placeholder.name].position.to_s)
end
remaind = match.post_match
match = Placeholder.getPattern().match(match.post_match)
if (match == nil)
story_parts << remaind
end
end
@base = story_parts.join("")
end
def to_s
result = @base
@placeholders.each do |placeholder|
result.gsub!(Regexp.new(get_position_string(placeholder.position.to_s)),
placeholder.value)
end
return result
end
def get_position_string(position)
"%%" + position.to_s + "%%"
end
end
class Placeholder
attr_accessor :name, :display_name, :position, :value
def initialize(placeholderString, position)
@value = ""
@position = position
if placeholderString.include?(":")
@name = placeholderString.split(":")[0]
@display_name = placeholderString.split(":")[1]
else
@name = placeholderString
@display_name = placeholderString
end
end
def getTemplate()
Regexp.new(
"\\(\\(\\s*(#{name}|#{name}\\s*:\\s*#{display_name})\\s*\\)\\)")
end
def Placeholder.getPattern()
/\(\(([^)]*)\)\)/
end
def getValueQuestion()
"Give me #{display_name}: "
end
def reusable()
name != display_name
end
end
if $0 == __FILE__
# read story from standard input
story_string = ""
ARGF.each_line do |line|
story_string += line
end
# create story
story = Story.new(story_string)
# request uesr to enter the corresponding value for each placeholder
print "There are #{story.placeholders.size} placeholders.\n"
story.placeholders.each do |placeholder|
print placeholder.getValueQuestion()
placeholder.value = gets().chop()
end
# display the story
print story.to_s, "\n"
end
--------------------------------------------------------------------------------------------------------------------
UnitTest;
MadlibsTest.rb
require 'runit/testcase'
require 'Madlibs'
class TestMadlibs < RUNIT::TestCase
def testStoryTemplate()
# parse simple story
# e.g. "Our favorite language is ((a gemstone))."
template = "Our favorite language is ((a gemstone))."
story = Story.new(template)
# should return a Story with a symbol name='a gemstome' and alias=nil
assert_equals(1, story.placeholders.size)
assert_not_nil(story.placeholders[0])
assert_equals("a gemstone", story.placeholders[0].display_name)
end
def testStoryTemplateWithAlias()
# parse story with name alias
# e.g. "Our favorite language is ((gem:a gemstone)). We think ((gem))
is
# better than ((a gemstone))."
template = "Our favorite language is ((gem:a gemstone)). "
template += "We think ((gem)) is better then ((a gemstone))."
story = Story.new(template)
# should return a Story with 2 symbole
# Symbol 1: name = 'gem' alias='a gemstome'
# Symbol 2: name = 'a gemstome'
assert_equals(2, story.placeholders.size)
assert_not_nil(story.placeholders[0])
assert_equals("gem", story.placeholders[0].name)
assert_equals("a gemstone", story.placeholders[0].display_name)
assert_not_nil(story.placeholders[1])
assert_equals("a gemstone", story.placeholders[1].name)
assert_equals("a gemstone", story.placeholders[1].display_name)
end
def testStoryGeneration()
# give: "Our favorite language is ((a gemstone))."
# input: gemstone = Ruby
# result: Our favorite language is Ruby."
String template = "Our favorite language is ((a gemstone))."
story = Story.new(template)
story.placeholders[0].value = "Ruby"
assert_equals("Our favorite language is Ruby.", story.to_s())
end
def testStoryGenerationWithAlias()
# given: "Our favorite language is ((gem:a gemstone)).
# We think ((gem)) is better than ((a gemstone))."
# input: a gemstone = Ruby, a genstone = Emerald
# given: "Our favorite language is Ruby.
# We think Ruby is better than Emerald."
template = "Our favorite language is ((gem:a gemstone)). "
template += "We think ((gem)) is better then ((a gemstone))."
story = Story.new(template)
story.placeholders[0].value = "Ruby"
story.placeholders[1].value = "Emerald"
assert_equals("Our favorite language is Ruby. We think Ruby is better
then Emerald.", story.to_s())
end
end
if $0 == __FILE__
require 'runit/cui/testrunner'
RUNIT::CUI::TestRunner.run(TestMadlibs.suite)
end