lemonade_stand 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c1ecb99f0138e24b5b9ca28aef726dc42b0f6b1d
4
+ data.tar.gz: a0a0705fa35b14de53523ce412d860f1689668f2
5
+ SHA512:
6
+ metadata.gz: c6e07276f41ac1834b58cf7a6ff56415a38bb0a7833211c1a466fc091da7893ce90cc70afde2bda7ef2036fd05e04837b0d86f99cb00920146e9f93e2d00d446
7
+ data.tar.gz: ab982138ef987760161cf980b286a08e683550b20d12c2c010b4254054f86ea9addba4b51b3748c830d70ee3e1ecf83c80c77b0c2f86bbc6606c21dbffa23f95
@@ -0,0 +1,16 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+
16
+ .DS_Store
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in lemonade_stand.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Darren Cauthon
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,31 @@
1
+ # LemonadeStand
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'lemonade_stand'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install lemonade_stand
20
+
21
+ ## Usage
22
+
23
+ TODO: Write usage instructions here
24
+
25
+ ## Contributing
26
+
27
+ 1. Fork it ( https://github.com/[my-github-username]/lemonade_stand/fork )
28
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
29
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
30
+ 4. Push to the branch (`git push origin my-new-feature`)
31
+ 5. Create a new Pull Request
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'lemonade_stand'
4
+
5
+ if ARGV.include?('-v')
6
+ puts LemonadeStand::VERSION
7
+ exit
8
+ end
9
+
10
+ puts 'How many players are playing?'
11
+ number_of_players = gets.chomp.to_i
12
+
13
+ puts 'How many days will this game last?'
14
+ number_of_days = gets.chomp.to_i
15
+
16
+ game = LemonadeStand::Game.new number_of_players
17
+
18
+ (1..number_of_days).each do |day|
19
+
20
+ game.start_a_new_day
21
+
22
+ game.players.each do |player|
23
+ puts "Player #{player.index} is up!!!"
24
+
25
+ puts "You have #{player.assets} pennies."
26
+
27
+ choice = LemonadeStand::Choice.new
28
+
29
+ puts "How many glasses of lemonade do you want to make?"
30
+ choice.glasses_made = gets.chomp.to_i
31
+
32
+ puts "How much will you charge per glass?"
33
+ choice.price_per_glass = gets.chomp.to_i
34
+
35
+ player.choose choice
36
+
37
+ end
38
+
39
+ game.players.each do |player|
40
+ puts "Player #{player.index} ended the day with: #{player.assets}"
41
+ end
42
+
43
+ end
44
+
45
+ puts "The game is over!"
46
+ winner = game.players.sort_by { |x| x.assets }[-1]
47
+
48
+ puts "The winner is: Player #{winner.index}"
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'lemonade_stand/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "lemonade_stand"
8
+ spec.version = LemonadeStand::VERSION
9
+ spec.authors = ["Darren Cauthon"]
10
+ spec.email = ["darren@cauthon.com"]
11
+ spec.summary = %q{The Lemonade Stand game.}
12
+ spec.description = %q{This is a ruby implementation of the old Lemonade Stand game.}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_runtime_dependency 'money'
22
+ spec.add_development_dependency "bundler", "~> 1.7"
23
+ spec.add_development_dependency "rake", "~> 10.0"
24
+ spec.add_development_dependency "mocha"
25
+ end
@@ -0,0 +1,7 @@
1
+ require "lemonade_stand/version"
2
+ Dir[File.dirname(__FILE__) + '/lemonade_stand/*.rb'].each { |f| require f }
3
+ Dir[File.dirname(__FILE__) + '/lemonade_stand/events/*.rb'].each {|f| require f }
4
+
5
+ module LemonadeStand
6
+ # Your code goes here...
7
+ end
@@ -0,0 +1,43 @@
1
+ module LemonadeStand
2
+ class Choice
3
+
4
+ HIGH_PRICE = 10.0
5
+ DEMAND = 30.0
6
+
7
+ attr_accessor :signs
8
+ attr_accessor :price_per_glass
9
+ attr_accessor :glasses_made
10
+
11
+ def max_sales
12
+ sales_factor + (sales_factor * signs_factor)
13
+ end
14
+
15
+ def signs
16
+ @signs.to_i
17
+ end
18
+
19
+ def price_per_glass
20
+ @price_per_glass.to_i
21
+ end
22
+
23
+ def glasses_made
24
+ @glasses_made.to_i
25
+ end
26
+
27
+ private
28
+
29
+ def sales_factor
30
+ result = if price_per_glass < 10
31
+ (HIGH_PRICE - price_per_glass) / HIGH_PRICE * 0.8 * DEMAND + DEMAND
32
+ else
33
+ (HIGH_PRICE * HIGH_PRICE) * DEMAND / (price_per_glass * price_per_glass)
34
+ end
35
+ result
36
+ end
37
+
38
+ def signs_factor
39
+ 1.0 - Math.exp((-1.0 * signs) * 0.5)
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,39 @@
1
+ module LemonadeStand
2
+
3
+ class Day
4
+
5
+ attr_accessor :number
6
+
7
+ def weather
8
+ @weather ||= LemonadeStand::Weather.weather_for self
9
+ end
10
+
11
+ def sales_for choice
12
+ data = {
13
+ glasses_sold: calculate_glasses_sold(choice),
14
+ choice: choice,
15
+ day: self,
16
+ }
17
+ LemonadeStand::Result.new data
18
+ end
19
+
20
+ def cost_per_glass
21
+ case number
22
+ when (1..2) then 2
23
+ when (3..4) then 4
24
+ else 5
25
+ end
26
+ end
27
+
28
+ def calculate_glasses_sold choice
29
+ max_sales = [choice.max_sales, event.modify(choice)].max
30
+ [choice.glasses_made, max_sales].min.round
31
+ end
32
+
33
+ def event
34
+ @event ||= Event.for(self)
35
+ end
36
+
37
+ end
38
+
39
+ end
@@ -0,0 +1,10 @@
1
+ require 'money'
2
+
3
+ module LemonadeStand
4
+ module Display
5
+ def self.money input
6
+ Money.use_i18n = false
7
+ "$" + Money.new(input).to_s
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,36 @@
1
+ module LemonadeStand
2
+
3
+ class Event
4
+
5
+ DAY_TYPES = [:sunny, :hot_and_dry, :cloudy]
6
+
7
+ def self.for day
8
+ type = DAY_TYPES.select { |x| day.weather.send("#{x}?".to_sym) }.first
9
+ send("#{type}_event_for".to_sym, day)
10
+ end
11
+
12
+ def self.sunny_event_for day
13
+ if day.number > 2 && rand(100) < 25
14
+ return build(:street_work)
15
+ end
16
+ return build(:normal)
17
+ end
18
+
19
+ def self.cloudy_event_for _
20
+ if rand(100) < 25
21
+ return build(:storm)
22
+ end
23
+ return build(:rain)
24
+ end
25
+
26
+ def self.hot_and_dry_event_for _
27
+ build(:heat_wave)
28
+ end
29
+
30
+ def self.build type
31
+ eval("LemonadeStand::#{type.to_s.split('_').map { |x| x.capitalize }.join('')}Event").new
32
+ end
33
+
34
+ end
35
+
36
+ end
@@ -0,0 +1,11 @@
1
+ module LemonadeStand
2
+
3
+ class HeatWaveEvent < Event;
4
+
5
+ def modify choice
6
+ choice.max_sales * 2
7
+ end
8
+
9
+ end
10
+
11
+ end
@@ -0,0 +1,11 @@
1
+ module LemonadeStand
2
+
3
+ class NormalEvent < Event
4
+
5
+ def modify choice
6
+ choice.max_sales
7
+ end
8
+
9
+ end
10
+
11
+ end
@@ -0,0 +1,15 @@
1
+ module LemonadeStand
2
+
3
+ class RainEvent < Event
4
+
5
+ def chance_of_rain
6
+ (rand * 0.5 + 0.3).round(2)
7
+ end
8
+
9
+ def modify choice
10
+ ((1 - chance_of_rain) * choice.max_sales).round
11
+ end
12
+
13
+ end
14
+
15
+ end
@@ -0,0 +1,11 @@
1
+ module LemonadeStand
2
+
3
+ class StormEvent < Event
4
+
5
+ def modify _
6
+ 0
7
+ end
8
+
9
+ end
10
+
11
+ end
@@ -0,0 +1,11 @@
1
+ module LemonadeStand
2
+
3
+ class StreetWorkEvent < Event
4
+
5
+ def modify choice
6
+ rand(4) == 3 ? choice.glasses_made : 0
7
+ end
8
+
9
+ end
10
+
11
+ end
@@ -0,0 +1,52 @@
1
+ module LemonadeStand
2
+
3
+ class Game
4
+
5
+ def initialize number_of_players
6
+ @number_of_players = number_of_players
7
+ end
8
+
9
+ def make_choice choice, options
10
+ player = options[:player]
11
+ day = options[:day] || days.last
12
+ results = day.sales_for choice
13
+ player.assets += results.profit
14
+ store_sales_results_for results, player, day
15
+ end
16
+
17
+ def days
18
+ @days ||= []
19
+ end
20
+
21
+ def start_a_new_day
22
+ @days ||= []
23
+ day = LemonadeStand::Day.new
24
+ @days << day
25
+ day.number = @days.count
26
+ day
27
+ end
28
+
29
+ def store_sales_results_for results, player, day
30
+ @sales_results ||= []
31
+ @sales_results << { player: player, day: day, results: results }
32
+ end
33
+
34
+ def sales_results_for player, day
35
+ @sales_results ||= []
36
+ @sales_results.select do |record|
37
+ return record[:results] if record[:player].object_id == player.object_id && record[:day].object_id == day.object_id
38
+ end
39
+ end
40
+
41
+ def players
42
+ @players ||= (0...@number_of_players).map do |i|
43
+ p = LemonadeStand::Player.new
44
+ p.index = i
45
+ p.game = self
46
+ p
47
+ end
48
+ end
49
+
50
+ end
51
+
52
+ end
@@ -0,0 +1,18 @@
1
+ module LemonadeStand
2
+
3
+ class Player
4
+ attr_accessor :index
5
+ attr_accessor :game
6
+ attr_accessor :assets
7
+
8
+ def initialize
9
+ @assets = 200
10
+ end
11
+
12
+ def choose choice
13
+ game.make_choice choice, { player: self }
14
+ end
15
+
16
+ end
17
+
18
+ end