crowdfund 1.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.
- checksums.yaml +7 -0
- data/LICENSE.txt +19 -0
- data/README.txt +6 -0
- data/bin/EXAMPLE_PROJECTS.csv +3 -0
- data/bin/crowdfund +43 -0
- data/lib/crowdfund/collection.rb +128 -0
- data/lib/crowdfund/collection_turn.rb +24 -0
- data/lib/crowdfund/die.rb +26 -0
- data/lib/crowdfund/pledgepool.rb +21 -0
- data/lib/crowdfund/project.rb +77 -0
- data/spec/crowdfund/collection_spec.rb +77 -0
- data/spec/crowdfund/pledgepool_spec.rb +44 -0
- data/spec/crowdfund/project_spec.rb +129 -0
- metadata +85 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 9fb739ee228a09ceaf54e12d26b32e4879271e0609f64fa33cb67c53168d2ba7
|
|
4
|
+
data.tar.gz: cc8acadf87365152570d23aaa98b1fc805e5262ec98e90ab40000bf31cc0d155
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 75b4e386390daeaf5ca69c98683551c119f8498868542dc0c3aa284e800cde96ef265750a7fadfe9eba7fd62c85e227ecdbd025b5db6c0d086a6ae195a35f065
|
|
7
|
+
data.tar.gz: 5b7dfe49a7a65ed2ca5e593d1b60e5a1046db94f81783b8b0d6c1b379ea58700bc1cef1bf6a1be96ca32e8eae4b5bf8fdd6e10bd5aaa6f9fae573df448375cf0
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Copyright (c) 2022 Jamie Clark / The Pragmatic Studio
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
5
|
+
in the Software without restriction, including without limitation the rights
|
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
8
|
+
furnished to do so, subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
|
11
|
+
copies or substantial portions of the Software.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
19
|
+
SOFTWARE.
|
data/README.txt
ADDED
data/bin/crowdfund
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
#crowdfund (File created 8:43PM on 5/8/22)
|
|
3
|
+
#end of day one is 8:24pm-10:47pm 5/8/22
|
|
4
|
+
#day two is 5:45pm - .... 9pm 5/24/22
|
|
5
|
+
#day three is 9:55pm - .... 11:15pm 6/8/22 (oof)
|
|
6
|
+
#day four is 7:30pm - 8:30pm, resumed at 9:40pm - 1am 6/14/22
|
|
7
|
+
#day five is 12:45pm - 1:30pm before work 6/15/22
|
|
8
|
+
#day six is 12am - 7:05pm 7 hours straight 6/18/22
|
|
9
|
+
#day seven is 4:30pm - 8:15pm and 10pm - 12:30am 6/19/22
|
|
10
|
+
#day eight is 8:55pm - 11:45pm 6/20/22
|
|
11
|
+
#day nine is 11:47pm - 5:34am!! 6/22/22 (night)
|
|
12
|
+
#day ten is 8:08pm - 12:24am and 12:50am - 3:30am 6/22/22 (day)
|
|
13
|
+
|
|
14
|
+
require_relative '../lib/crowdfund/collection' # calls the collection class file
|
|
15
|
+
require_relative '../lib/crowdfund/project' # calls the project class file
|
|
16
|
+
require_relative '../lib/crowdfund/die'
|
|
17
|
+
|
|
18
|
+
my_collection = Crowdfund::Collection.new("Jamie's collection of projects")
|
|
19
|
+
default_player_file = File.join(File.dirname(__FILE__), "EXAMPLE_PROJECTS.csv") #plays an entered file OR the default (WALL.csv)
|
|
20
|
+
my_collection.load_projects(ARGV.shift || default_player_file) #plays an entered file OR the default csv
|
|
21
|
+
|
|
22
|
+
loop do
|
|
23
|
+
puts "\nHow many rounds? ('quit' to exit)"
|
|
24
|
+
ans = gets.chomp.downcase
|
|
25
|
+
|
|
26
|
+
case ans
|
|
27
|
+
when /^\d+$/
|
|
28
|
+
if ans.to_i > 20
|
|
29
|
+
puts "ERROR: Maximum number of rounds allowed: 20." # I will set a limit to 20 rounds
|
|
30
|
+
else
|
|
31
|
+
my_collection.run_projects(ans.to_i) # converts to integer
|
|
32
|
+
end
|
|
33
|
+
when 'quit', 'exit', 'q', 'e', 'ex'
|
|
34
|
+
my_collection.print_stats
|
|
35
|
+
break
|
|
36
|
+
else
|
|
37
|
+
puts "Please enter a number or 'quit'"
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
my_collection.save_output #this goes after the loop
|
|
42
|
+
|
|
43
|
+
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
require_relative 'project'
|
|
2
|
+
require_relative 'die'
|
|
3
|
+
require_relative 'collection_turn'
|
|
4
|
+
require 'csv'
|
|
5
|
+
module Crowdfund
|
|
6
|
+
class Collection
|
|
7
|
+
attr_reader :name, :collection
|
|
8
|
+
def initialize(name) #this method converts a Collection.new specified title to the correct format when created
|
|
9
|
+
@name = name.upcase #upcased all collection titles for now
|
|
10
|
+
@collection = []
|
|
11
|
+
puts "Collection '#{@name}' was created."
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def add_project(project)
|
|
15
|
+
@collection << project
|
|
16
|
+
end
|
|
17
|
+
def show_pledges
|
|
18
|
+
pledges = PledgePool::PLEDGES
|
|
19
|
+
puts "\nThere are #{pledges.size} pledge tiers:"
|
|
20
|
+
pledges.each do |p|
|
|
21
|
+
puts "#{p.name} tier is a donation of $#{p.amount}."
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def print_stats
|
|
26
|
+
puts "\n#{@name}"
|
|
27
|
+
@sorted_list = @collection.sort { |a, b| b.amount <=> a.amount }
|
|
28
|
+
@sorted_list.each do |p|
|
|
29
|
+
p.describe
|
|
30
|
+
puts "Total pledge tier donations for #{p.name}:"
|
|
31
|
+
p.each_pledge_received do |pledge|
|
|
32
|
+
puts "#{pledge.name}: $#{pledge.amount}"
|
|
33
|
+
end
|
|
34
|
+
puts "Other donations: $#{p.amount}"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
met_goal, under_goal = @sorted_list.partition { |project| project.total_amount >= project.target_goal }
|
|
38
|
+
unless met_goal.empty?
|
|
39
|
+
puts "\nProjects at/over goal:"
|
|
40
|
+
met_goal.each do |project|
|
|
41
|
+
puts "#{project.name}: $#{project.total_amount}/#{project.target_goal}" #NOTE: ALWAYS CALL TOTAL_AMOUNT (sum of all pledges + @amount)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
unless under_goal.empty?
|
|
45
|
+
puts "\nProjects under goal:"
|
|
46
|
+
under_goal.each do |project|
|
|
47
|
+
puts "#{project.name}: $#{project.total_amount}/#{project.target_goal}" #NOTE: ALWAYS CALL TOTAL_AMOUNT (sum of all pledges + @amount)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def run_projects(rounds=1) #play one round by default
|
|
54
|
+
puts "\nThere are currently #{@collection.size} projects:" #no sorting called here at first
|
|
55
|
+
@collection.each do |project|
|
|
56
|
+
puts "#{@collection.index(project) + 1}) #{project.name}"
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
show_pledges
|
|
60
|
+
|
|
61
|
+
1.upto(rounds) do |round|
|
|
62
|
+
puts "\nRound #{round}:"
|
|
63
|
+
|
|
64
|
+
@collection.each do |p|
|
|
65
|
+
puts "Start: #{p}"
|
|
66
|
+
CollectionTurn.take_turn(p)
|
|
67
|
+
puts "End: #{p}"
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# after all rounds, this describes each project's funding (similar to print stats method for the playlist project):
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
def load_projects(from_file)
|
|
74
|
+
CSV.foreach(from_file, 'r:bom|utf-8') do |row| #this conditional gets tricky!
|
|
75
|
+
unless row[1].to_i == 0 || row[2].to_i == 0 #unless one of the rows has a nil value...
|
|
76
|
+
project = Project.new(row[0], row[1].to_i, row[2].to_i) #.. then input all values regularly.
|
|
77
|
+
else
|
|
78
|
+
if row[1].to_i == 0 # if amount (second column) is nil >> 0 in csv,
|
|
79
|
+
project = Project.new(row[0], 0, row[2].to_i) # the default gets set to 0. THIS is where default gets assigned.
|
|
80
|
+
end
|
|
81
|
+
if row[2].to_i == 0 # if target_goal (third column) is nil >> 0 in csv,
|
|
82
|
+
project = Project.new(row[0], row[1].to_i, 10000) # the default target gets set to 10000. THIS is where default gets assigned.
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
add_project(project)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
def save_output(to_file="crowdfund_output.txt")
|
|
89
|
+
File.open(to_file, "w") do |file|
|
|
90
|
+
file.puts Time.new.strftime("File updated on %m/%d/%Y at %I:%M %p")
|
|
91
|
+
file.puts "#{@name}"
|
|
92
|
+
file.puts "\nCrowdfund Output:"
|
|
93
|
+
|
|
94
|
+
@collection.each do |project|
|
|
95
|
+
if project.total_amount > project.target_goal
|
|
96
|
+
file.puts "\nProject #{project.name}: $#{project.total_amount}/#{project.target_goal} (over goal)"
|
|
97
|
+
elsif project.total_amount == project.target_goal
|
|
98
|
+
file.puts "\nProject #{project.name}: $#{project.total_amount}/#{project.target_goal} (at goal)"
|
|
99
|
+
else
|
|
100
|
+
file.puts "\nProject #{project.name}: $#{project.total_amount}/#{project.target_goal} (under goal)"
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
file.puts "Total pledge tier donations for #{project.name}:"
|
|
104
|
+
project.each_pledge_received do |pledge|
|
|
105
|
+
file.puts "#{pledge.name}: $#{pledge.amount}"
|
|
106
|
+
end
|
|
107
|
+
file.puts "Other donations: $#{project.amount}"
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
met_goal, under_goal = @collection.partition { |project| project.total_amount >= project.target_goal }
|
|
111
|
+
unless met_goal.empty?
|
|
112
|
+
file.puts "\nProjects at/over goal:"
|
|
113
|
+
met_goal.each do |project|
|
|
114
|
+
file.puts "#{project.name}: $#{project.total_amount}/#{project.target_goal}" #NOTE: ALWAYS CALL TOTAL_AMOUNT (sum of all pledges + @amount)
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
unless under_goal.empty?
|
|
118
|
+
file.puts "\nProjects under goal:"
|
|
119
|
+
under_goal.each do |project|
|
|
120
|
+
file.puts "#{project.name}: $#{project.total_amount}/#{project.target_goal}" #NOTE: ALWAYS CALL TOTAL_AMOUNT (sum of all pledges + @amount)
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require_relative 'project'
|
|
2
|
+
require_relative 'die'
|
|
3
|
+
require_relative 'pledgepool'
|
|
4
|
+
module Crowdfund
|
|
5
|
+
module CollectionTurn
|
|
6
|
+
|
|
7
|
+
def self.take_turn(p)
|
|
8
|
+
die = Die.new
|
|
9
|
+
number_rolled = die.roll
|
|
10
|
+
case number_rolled
|
|
11
|
+
when 5..6
|
|
12
|
+
p.fund(15)
|
|
13
|
+
when 3..4
|
|
14
|
+
puts "#{p.name} was skipped."
|
|
15
|
+
when 1..2
|
|
16
|
+
p.defund(10)
|
|
17
|
+
else # (nothing is added if die roll is 3 or 4... or 0 etc.)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
tier = PledgePool.random
|
|
21
|
+
p.pledge_received(tier)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module Crowdfund #you can delete one of these modules (based on..) once/how you split up your projects
|
|
2
|
+
class Die
|
|
3
|
+
attr_reader :number
|
|
4
|
+
|
|
5
|
+
def roll
|
|
6
|
+
@number = rand(1..6)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def initialize
|
|
10
|
+
roll #the new die object now initializes as soon as "roll" is called anywhere.
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
module Songfile #you can delete one of these once you split up your projects
|
|
15
|
+
class Die
|
|
16
|
+
attr_reader :number
|
|
17
|
+
|
|
18
|
+
def roll
|
|
19
|
+
@number = rand(1..6)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def initialize
|
|
23
|
+
roll #the new die object now initializes as soon as "roll" is called anywhere.
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
Pledge = Struct.new(:name, :amount) #bigger number means more influence (I use them as multiplier values)
|
|
2
|
+
module Crowdfund
|
|
3
|
+
module PledgePool
|
|
4
|
+
|
|
5
|
+
PLEDGES = [
|
|
6
|
+
Pledge.new(:Gold, 100),
|
|
7
|
+
Pledge.new(:Silver, 75),
|
|
8
|
+
Pledge.new(:Bronze, 50),
|
|
9
|
+
]
|
|
10
|
+
|
|
11
|
+
def self.random
|
|
12
|
+
PLEDGES.sample
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
if __FILE__ == $0
|
|
17
|
+
p PledgePool::PLEDGES.map(&:name)
|
|
18
|
+
tier = PledgePool.random
|
|
19
|
+
puts "#{tier.name} tier is a donation of $#{tier.amount}."
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
require_relative 'collection'
|
|
2
|
+
require_relative 'die'
|
|
3
|
+
require_relative 'pledgepool'
|
|
4
|
+
module Crowdfund
|
|
5
|
+
class Project
|
|
6
|
+
attr_accessor :name, :amount #you can now write to amount for project to update it
|
|
7
|
+
attr_reader :target_goal
|
|
8
|
+
|
|
9
|
+
def initialize(name, amount=0, target_goal=10000)
|
|
10
|
+
@name = name
|
|
11
|
+
@amount = amount.abs() #no negative initial amount
|
|
12
|
+
@target_goal = target_goal.abs() #no negative target value
|
|
13
|
+
puts "New project '#{@name}' ($#{@amount}) is initialized. Target goal is #{@target_goal}."
|
|
14
|
+
@pledges_received = Hash.new(0)
|
|
15
|
+
end
|
|
16
|
+
def pledge_received(pledge)
|
|
17
|
+
@pledges_received[pledge.name] += pledge.amount #was missing the "s" on @pledges_received which is for the hash
|
|
18
|
+
puts "#{@name} received a #{pledge.name} pledge worth $#{pledge.amount}."
|
|
19
|
+
puts "#{@name}'s pledge amounts: #{@pledges_received}"
|
|
20
|
+
end
|
|
21
|
+
def total_amount
|
|
22
|
+
@pledges_received.values.reduce(0, :+) + @amount
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def fund(value=0)
|
|
26
|
+
@amount += value
|
|
27
|
+
puts "'#{@name}' received $#{value} in funding!"
|
|
28
|
+
#puts "'#{@name}' now has $#{total_amount} in funding." #NOTE: ALWAYS CALL TOTAL_AMOUNT (sum of all pledges + @amount)
|
|
29
|
+
end
|
|
30
|
+
def defund(value=0)
|
|
31
|
+
@amount -= value
|
|
32
|
+
puts "'#{@name}' has lost $#{value} in funding!"
|
|
33
|
+
#puts "'#{@name}' now has $#{total_amount} in funding." #NOTE: ALWAYS CALL TOTAL_AMOUNT (sum of all pledges + @amount)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def empty?
|
|
37
|
+
total_amount <= 0
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def target_goal_met?
|
|
41
|
+
total_amount >= @target_goal
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def status
|
|
45
|
+
"(No funds!)" if empty?
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def to_s #defines what happens when you use puts on an object of class "Song"
|
|
49
|
+
if empty?
|
|
50
|
+
"#{@name} ($#{total_amount}) #{status}"
|
|
51
|
+
else
|
|
52
|
+
"#{@name} ($#{total_amount})"
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def describe
|
|
57
|
+
@current_time = Time.new.strftime("%-I:%M %p %-m/%-d/%-y")
|
|
58
|
+
if total_amount > @target_goal #NOTE: ALWAYS CALL TOTAL_AMOUNT (sum of all pledges + @amount)
|
|
59
|
+
puts "\nProject #{@name}: $#{total_amount}/#{@target_goal} (over goal) as of #{@current_time}."
|
|
60
|
+
elsif total_amount < @target_goal
|
|
61
|
+
puts "\nProject #{@name}: $#{total_amount}/#{@target_goal} (under goal) as of #{@current_time}."
|
|
62
|
+
else
|
|
63
|
+
puts "\nProject #{@name}: $#{total_amount}/#{@target_goal} (at goal) as of #{@current_time}."
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def each_pledge_received
|
|
68
|
+
@pledges_received.each do |name, amount| # (@pledges_received is the hash)
|
|
69
|
+
yield Pledge.new(name, amount)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
#the default for the amount of funding is 100
|
|
74
|
+
#therefore, $100 gets printed out for the "describe" method.
|
|
75
|
+
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#require_relative "collection"
|
|
2
|
+
require 'crowdfund/collection'
|
|
3
|
+
#require_relative "die"
|
|
4
|
+
require 'crowdfund/die'
|
|
5
|
+
|
|
6
|
+
module Crowdfund
|
|
7
|
+
describe Collection do
|
|
8
|
+
|
|
9
|
+
before do
|
|
10
|
+
@collection = Collection.new("test collection")
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
context "single project collection" do
|
|
14
|
+
before do
|
|
15
|
+
@collection = Collection.new("Jamie's collection of projects")
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
before do
|
|
19
|
+
@initial_amount = -500
|
|
20
|
+
@project = Project.new('ABC', @initial_amount, -3000)
|
|
21
|
+
@initial_amount = @project.amount #this line had to be added to update the @inital amount
|
|
22
|
+
#variable in the test file so that it is updated to reflect the initialization of the "amount" attribute
|
|
23
|
+
#of the project (which changes negative values to their absolute value versions!)
|
|
24
|
+
@collection.add_project(@project)
|
|
25
|
+
@round_amount = 3
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "FUNDS on a high number (5-6)" do
|
|
29
|
+
Die.any_instance.stub(:roll).and_return(5)
|
|
30
|
+
@collection.run_projects(@round_amount)
|
|
31
|
+
expect(@project.amount).to eq(@initial_amount + (15 * (@round_amount)))
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "no change on medium number (3-4)" do
|
|
35
|
+
Die.any_instance.stub(:roll).and_return(3)
|
|
36
|
+
@collection.run_projects(@round_amount)
|
|
37
|
+
expect(@project.amount).to eq(@initial_amount)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "DEFUNDS on a low number (1-2)" do
|
|
41
|
+
Die.any_instance.stub(:roll).and_return(1)
|
|
42
|
+
@collection.run_projects(@round_amount)
|
|
43
|
+
expect(@project.amount).to eq(@initial_amount - (10 * (@round_amount)))
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "assigns a pledge tier and amount to tally during a project's turn" do
|
|
48
|
+
collection = Collection.new("Test List")
|
|
49
|
+
project = Project.new("ABC", 100, 200)
|
|
50
|
+
|
|
51
|
+
collection.add_project(project)
|
|
52
|
+
|
|
53
|
+
collection.run_projects(1) #runs 1 round
|
|
54
|
+
|
|
55
|
+
project.amount.should_not be_zero
|
|
56
|
+
|
|
57
|
+
# or use alternate expectation syntax:
|
|
58
|
+
# expect(player.points).not_to be_zero
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
context "default values replacing nils (with default project file)" do
|
|
62
|
+
before do
|
|
63
|
+
@my_collection = Collection.new("Test collection")
|
|
64
|
+
default_player_file = File.join(File.dirname(__FILE__), "../../bin/EXAMPLE_PROJECTS.csv") #plays an entered file OR the default (WALL.csv)
|
|
65
|
+
@my_collection.load_projects(ARGV.shift || default_player_file)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "replaces nil amount values with default value of amount=0" do
|
|
69
|
+
expect(@my_collection.collection[2].amount).to eq(0) # "XYZ,,300" gets filled in with "XYZ,0,300"
|
|
70
|
+
end
|
|
71
|
+
it "replaces nil target_goal values with default value of target_goal=10000" do
|
|
72
|
+
expect(@my_collection.collection[1].target_goal).to eq(10000) # "LMN,800," gets filled in with "LMN,800,1000"
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#require_relative "pledgepool"
|
|
2
|
+
require 'crowdfund/pledgepool'
|
|
3
|
+
|
|
4
|
+
module Crowdfund
|
|
5
|
+
describe Pledge do
|
|
6
|
+
before do
|
|
7
|
+
@pledge = Pledge.new(:Gold, 100)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it "has correct name attribute" do
|
|
11
|
+
@pledge.name.should == :Gold
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "has a correct amount attribute" do
|
|
15
|
+
@pledge.amount.should == 100
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
describe PledgePool do
|
|
21
|
+
|
|
22
|
+
it "returns a random pledge tier from the pledgepool" do
|
|
23
|
+
pledge = PledgePool.random
|
|
24
|
+
PledgePool::PLEDGES.should include(pledge)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "has three pledge tiers" do
|
|
28
|
+
PledgePool::PLEDGES.size.should == 3
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "includes Gold ($100)" do
|
|
32
|
+
PledgePool::PLEDGES[0].should == Pledge.new(:Gold, 100)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "includes Silver ($75)" do
|
|
36
|
+
PledgePool::PLEDGES[1].should == Pledge.new(:Silver, 75)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "includes Bronze ($50)" do
|
|
40
|
+
PledgePool::PLEDGES[2].should == Pledge.new(:Bronze, 50)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# ***** SONG TEST FILE *******
|
|
2
|
+
#require_relative 'project' # calls the project class file
|
|
3
|
+
require 'crowdfund/project'
|
|
4
|
+
#require_relative 'pledgepool' # calls the project class file
|
|
5
|
+
require 'crowdfund/pledgepool'
|
|
6
|
+
module Crowdfund
|
|
7
|
+
describe Project do
|
|
8
|
+
|
|
9
|
+
context "song with a NEGATIVE funding and target goal" do
|
|
10
|
+
before do
|
|
11
|
+
@project = Project.new("CVS", -10, -1000) # a user types in a negative rank (not ok)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "automatically gets a negative rank # assigned to a positive rank #" do
|
|
15
|
+
expect(@project.amount).to eq(10) #rather than -10
|
|
16
|
+
expect(@project.target_goal).to eq(1000) #rather than -1000
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
context "project description conditionals" do
|
|
21
|
+
before do
|
|
22
|
+
@initial_amount = 10
|
|
23
|
+
@target_goal = 100
|
|
24
|
+
@project = Project.new("CVS", @initial_amount, @target_goal)
|
|
25
|
+
@time = Time.new.strftime("%-I:%M %p %-m/%-d/%-y")
|
|
26
|
+
end
|
|
27
|
+
it "correctly displays under goal" do
|
|
28
|
+
expect do
|
|
29
|
+
@project.describe
|
|
30
|
+
end.to output("\nProject CVS: $10/100 (under goal) as of #{@time}.\n").to_stdout
|
|
31
|
+
end
|
|
32
|
+
it "correctly displays over goal" do
|
|
33
|
+
@project.amount = 200
|
|
34
|
+
expect do
|
|
35
|
+
@project.describe
|
|
36
|
+
end.to output("\nProject CVS: $200/100 (over goal) as of #{@time}.\n").to_stdout
|
|
37
|
+
end
|
|
38
|
+
it "correctly displays at goal" do
|
|
39
|
+
@project.amount = 100
|
|
40
|
+
expect do
|
|
41
|
+
@project.describe
|
|
42
|
+
end.to output("\nProject CVS: $100/100 (at goal) as of #{@time}.\n").to_stdout
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
context "project w/o amount or target goal defined" do
|
|
47
|
+
before do
|
|
48
|
+
@project = Project.new("CVS") # a user types in a negative rank (not ok)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "has default amount of 0, and default target goal of 10000" do
|
|
52
|
+
expect(@project.amount).to eq(0)
|
|
53
|
+
expect(@project.target_goal).to eq(10000) #rather than -1000
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
before do
|
|
58
|
+
@initial_amount = 10
|
|
59
|
+
@project = Project.new("CVS", @initial_amount, 1000)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "has a correct initial value" do
|
|
63
|
+
expect(@project.amount).to eq(@initial_amount) #better, new syntax
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it "has correct display with 'to_s' (Song)" do
|
|
67
|
+
expect(@project.to_s).to eq("CVS ($#{@initial_amount})")
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it "has correct amount after fund(100)" do
|
|
71
|
+
@project.fund(100)
|
|
72
|
+
expect(@project.amount).to eq(@initial_amount + 100)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it "has correct amount after defund(100)" do
|
|
76
|
+
@project.defund(100)
|
|
77
|
+
expect(@project.amount).to eq(@initial_amount - 100)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it "has correct default of 0 for 'fund' method" do
|
|
81
|
+
@project.fund
|
|
82
|
+
expect(@project.amount).to eq(@initial_amount)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it "has correct default of 0 for 'defund' method" do
|
|
86
|
+
@project.defund
|
|
87
|
+
expect(@project.amount).to eq(@initial_amount)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it "computes the sum of all pledge donations" do
|
|
91
|
+
@project.total_amount.should == 0 + @initial_amount
|
|
92
|
+
|
|
93
|
+
@project.pledge_received(Pledge.new(:gold, 100))
|
|
94
|
+
|
|
95
|
+
@project.total_amount.should == 100 + @initial_amount
|
|
96
|
+
|
|
97
|
+
@project.pledge_received(Pledge.new(:silver, 75))
|
|
98
|
+
|
|
99
|
+
@project.total_amount.should == 175 + @initial_amount # 100 + 75 @initial amount (10 for now)
|
|
100
|
+
|
|
101
|
+
@project.pledge_received(Pledge.new(:bronze, 50))
|
|
102
|
+
|
|
103
|
+
@project.total_amount.should == 225 + @initial_amount # 175 + 50 + @initial amount (10 for now)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it "yields each pledge donation and its total contribution" do
|
|
107
|
+
@project.pledge_received(Pledge.new(:bronze, 50))
|
|
108
|
+
@project.pledge_received(Pledge.new(:bronze, 50))
|
|
109
|
+
@project.pledge_received(Pledge.new(:silver, 75))
|
|
110
|
+
@project.pledge_received(Pledge.new(:silver, 75))
|
|
111
|
+
@project.pledge_received(Pledge.new(:silver, 75))
|
|
112
|
+
@project.pledge_received(Pledge.new(:silver, 75))
|
|
113
|
+
@project.pledge_received(Pledge.new(:gold, 100))
|
|
114
|
+
@project.pledge_received(Pledge.new(:gold, 100))
|
|
115
|
+
|
|
116
|
+
yielded = []
|
|
117
|
+
@project.each_pledge_received do |pledge|
|
|
118
|
+
yielded << pledge
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
yielded.should == [
|
|
122
|
+
Pledge.new(:bronze, 100),
|
|
123
|
+
Pledge.new(:silver, 300),
|
|
124
|
+
Pledge.new(:gold, 200)
|
|
125
|
+
]
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
end
|
|
129
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: crowdfund
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Jamie Clark
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2022-06-24 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: rspec
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '2.8'
|
|
20
|
+
- - ">="
|
|
21
|
+
- !ruby/object:Gem::Version
|
|
22
|
+
version: 2.8.0
|
|
23
|
+
type: :development
|
|
24
|
+
prerelease: false
|
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
26
|
+
requirements:
|
|
27
|
+
- - "~>"
|
|
28
|
+
- !ruby/object:Gem::Version
|
|
29
|
+
version: '2.8'
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: 2.8.0
|
|
33
|
+
description: |
|
|
34
|
+
********* BASIC INSTRUCTIONS ********
|
|
35
|
+
TO RUN DEFAULT CSV SHEET PROJECTS):
|
|
36
|
+
crowdfund
|
|
37
|
+
|
|
38
|
+
TO RUN SPECS:
|
|
39
|
+
rspec (not "rspec .")
|
|
40
|
+
email: clarkcjamie@gmail.com
|
|
41
|
+
executables:
|
|
42
|
+
- crowdfund
|
|
43
|
+
extensions: []
|
|
44
|
+
extra_rdoc_files: []
|
|
45
|
+
files:
|
|
46
|
+
- LICENSE.txt
|
|
47
|
+
- README.txt
|
|
48
|
+
- bin/EXAMPLE_PROJECTS.csv
|
|
49
|
+
- bin/crowdfund
|
|
50
|
+
- lib/crowdfund/collection.rb
|
|
51
|
+
- lib/crowdfund/collection_turn.rb
|
|
52
|
+
- lib/crowdfund/die.rb
|
|
53
|
+
- lib/crowdfund/pledgepool.rb
|
|
54
|
+
- lib/crowdfund/project.rb
|
|
55
|
+
- spec/crowdfund/collection_spec.rb
|
|
56
|
+
- spec/crowdfund/pledgepool_spec.rb
|
|
57
|
+
- spec/crowdfund/project_spec.rb
|
|
58
|
+
homepage: http://pragmaticstudio.com
|
|
59
|
+
licenses:
|
|
60
|
+
- MIT
|
|
61
|
+
metadata: {}
|
|
62
|
+
post_install_message:
|
|
63
|
+
rdoc_options: []
|
|
64
|
+
require_paths:
|
|
65
|
+
- lib
|
|
66
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
67
|
+
requirements:
|
|
68
|
+
- - ">="
|
|
69
|
+
- !ruby/object:Gem::Version
|
|
70
|
+
version: '1.9'
|
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - ">="
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '0'
|
|
76
|
+
requirements: []
|
|
77
|
+
rubygems_version: 3.3.7
|
|
78
|
+
signing_key:
|
|
79
|
+
specification_version: 4
|
|
80
|
+
summary: Text based game for fundraising projects featuring rounds, donation pledge
|
|
81
|
+
tiers, and fundraising statistics
|
|
82
|
+
test_files:
|
|
83
|
+
- spec/crowdfund/collection_spec.rb
|
|
84
|
+
- spec/crowdfund/pledgepool_spec.rb
|
|
85
|
+
- spec/crowdfund/project_spec.rb
|