crowdfund_sergio_silva 1.0.0

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: f504e5608564e2e76a9b02c6a93b438e6fed955a
4
+ data.tar.gz: ebb8b1ea04b6891bcb8f9cc98aefddbe6759f768
5
+ SHA512:
6
+ metadata.gz: fd3dd8a2773fd9bbdd4136f66b0835b4913f6df03795c941dbe35e2924c757e222c2f2b566e3765d9a8d0c842ed097d8f268889498068c89bb79a418af085526
7
+ data.tar.gz: d5bc9de9151d96a9d3172e27f370532788d9b62b4f37c0b55deb6ea013657d386a599685c8eb68b6f97c256cebf3efa8d870e0170e9076b7fdf73f974cd15eb6
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2012 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
+ - You may not use this Software in other training contexts.
11
+
12
+ - The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,6 @@
1
+ This is an example application used in The Pragmatic Studio's
2
+ Ruby Programming course, as described at
3
+
4
+ http://pragmaticstudio.com
5
+
6
+ This code is Copyright 2012 The Pragmatic Studio. See the LICENSE file.
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative '../lib/crowdfund/project'
4
+ require_relative '../lib/crowdfund/fundrequest'
5
+ require_relative '../lib/crowdfund/grant_project'
6
+ require_relative '../lib/crowdfund/matching_project'
7
+
8
+ #create a fundrequest
9
+ projects = Crowdfund::FundRequest.new("Ruby course Crowdfunding App")
10
+ puts "#{ projects.title }\n\n"
11
+
12
+ default_player_file = File.join(File.dirname(__FILE__), 'projects.csv')
13
+ projects.load_projects(ARGV.shift || default_player_file)
14
+
15
+ #Create other projects
16
+ project4 = Crowdfund::MatchingProject.new("Match", 200)
17
+ project5 = Crowdfund::GrantProject.new("Grant", 1_000, 300)
18
+
19
+ #Adds these projects
20
+ projects.add_project(project4)
21
+ projects.add_project(project5)
22
+
23
+ #Running
24
+ loop do
25
+ puts "\nHow many rounds of funding? ('quit' to exit)"
26
+ answer = gets.chomp.downcase
27
+ case answer
28
+ when /^\d+$/
29
+ projects.request_funding(answer.to_i)
30
+ when 'quit', 'exit'
31
+ projects.print_stats
32
+ break
33
+ else
34
+ puts "Please enter a number or 'quit'"
35
+ end
36
+ end
37
+
38
+ #project1 = Crowdfund::Project.new("ABC", 1_000, 500)
39
+ #project2 = Crowdfund::Project.new("LMN", 500, 3_000)
40
+ #project3 = Crowdfund::Project.new("XYZ", 25, 75)
41
+
42
+
43
+ #projects.add_project(project1)
44
+ #projects.add_project(project2)
45
+ #projects.add_project(project3)
46
+
47
+
48
+ #projects.request_funding(4)
49
+
50
+ #projects.print_stats
@@ -0,0 +1,3 @@
1
+ ABC,10000,5000
2
+ LMN,3000,1500
3
+ XYZ,300,500
@@ -0,0 +1,3 @@
1
+ Projects needing some donation:
2
+ Grant............... $300 under
3
+ ABC................. $245 under
@@ -0,0 +1,20 @@
1
+ module Crowdfund
2
+ class Die
3
+
4
+ attr_reader :number
5
+
6
+ def initialize
7
+ @number = 0
8
+ end
9
+
10
+ def roll
11
+ @number = 1 +rand(6)
12
+ end
13
+
14
+ end
15
+ end
16
+
17
+ if __FILE__ == $0
18
+ die = Die.new()
19
+ puts die.roll
20
+ end
@@ -0,0 +1,23 @@
1
+ module Crowdfund
2
+ module Fundable
3
+
4
+ def remove_funds
5
+ @funding -= 15
6
+ puts "#{ @name } lost some funds!"
7
+ end
8
+
9
+ def add_funds
10
+ @funding += 25
11
+ puts "#{ @name } got more funds!"
12
+ end
13
+
14
+ def total_funding_outstanding
15
+ @target - total_funds
16
+ end
17
+
18
+ def fully_funded?
19
+ total_funding_outstanding <= 0
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ require_relative 'die'
2
+ require_relative 'project'
3
+
4
+ module Crowdfund
5
+ module FundingRound
6
+
7
+ @die = Die.new
8
+
9
+ def self.round(project)
10
+ number_rolled = @die.roll
11
+
12
+ if number_rolled.odd?
13
+ project.remove_funds
14
+ else
15
+ project.add_funds
16
+ end
17
+
18
+ pledge = PledgePool.random
19
+ project.received_pledge(pledge)
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,114 @@
1
+ require_relative 'project'
2
+ require_relative 'die'
3
+ require_relative 'funding_round'
4
+ require_relative 'pledge_pool'
5
+
6
+ module Crowdfund
7
+ class FundRequest
8
+
9
+ attr_reader :title
10
+
11
+ def initialize(title)
12
+ @title = title
13
+ @projects = []
14
+ end
15
+
16
+ def add_project(project)
17
+ @projects.push(project)
18
+ end
19
+
20
+ def request_funding(rounds)
21
+ puts"There are #{ @projects.size } projects that you could fund"
22
+
23
+ @projects.each do |project|
24
+ puts project
25
+ end
26
+
27
+ pledges = PledgePool::PLEDGES
28
+ puts "\nThere are #{ pledges.size } possible pledge amounts:"
29
+ pledges.each do |pledge|
30
+ puts "A #{ pledge.name } pledge is worth $#{ pledge.amount }."
31
+ end
32
+ puts"\n"
33
+
34
+ 1.upto(rounds) do |round|
35
+ puts"Round: #{ round }"
36
+ @projects.each do |project|
37
+ FundingRound.round(project)
38
+ puts "#{ project }\n\n"
39
+ end
40
+ end
41
+ end
42
+
43
+ def print_name_and_funding(project)
44
+ puts "#{ project.name } - #{ project.funding }"
45
+ end
46
+
47
+ def print_name(project)
48
+ puts "Project #{ project.name }"
49
+ end
50
+
51
+ def print_stats
52
+ puts"\n#{ fully_funded_projects.size } Fully funded projects"
53
+ fully_funded_projects.each do |f|
54
+ print_name(f)
55
+ end
56
+
57
+ puts"\n#{ under_funded_projects.size } Under funded projects"
58
+ under_funded_projects.each do |u|
59
+ print_name(u)
60
+ end
61
+
62
+ sorted = sorted_under_funded_projects
63
+ puts"\nProjects needing some donation"
64
+ sorted.each do |s|
65
+ puts under_funded_entry(s)
66
+ end
67
+
68
+ @projects.each do |project|
69
+ puts"\n#{ project.name }'s pledges:"
70
+ project.each_received_pledge do |pledge|
71
+ puts "$#{ pledge.amount } in #{ pledge.name } pledges"
72
+ end
73
+ puts "#{ project.pledges } in total pledges"
74
+ end
75
+
76
+ save_under_funded_projects
77
+ end
78
+
79
+ def sorted_under_funded_projects
80
+ under_funded_projects.sort { |a, b| b.total_funding_outstanding <=> a.total_funding_outstanding}
81
+ end
82
+
83
+ def fully_funded_projects
84
+ @projects.select { |project| project.fully_funded? }
85
+ end
86
+
87
+ def under_funded_projects
88
+ @projects.reject { |project| project.fully_funded? }
89
+ end
90
+
91
+ def under_funded_entry(project)
92
+ formatted_name = project.name.ljust(20, '.')
93
+ "#{ formatted_name } $#{ project.total_funding_outstanding } under"
94
+ end
95
+
96
+ def load_projects(from_file)
97
+ File.readlines(from_file).each do |line|
98
+ name, target_funding_amount, funding = line.split(',')
99
+ project = Project.new(name, Integer(target_funding_amount), Integer(funding))
100
+ add_project(project)
101
+ end
102
+ end
103
+
104
+ def save_under_funded_projects(to_file="results.txt")
105
+ File.open(to_file, "w") do |file|
106
+ file.puts "Projects needing some donation:"
107
+ sorted_under_funded_projects.each do |project|
108
+ file.puts(under_funded_entry(project))
109
+ end
110
+ end
111
+ end
112
+
113
+ end
114
+ end
@@ -0,0 +1,19 @@
1
+ require_relative 'project'
2
+
3
+ module Crowdfund
4
+ class GrantProject < Project
5
+
6
+ def remove_funds
7
+ puts"No funds can be removed from a grant project"
8
+ end
9
+
10
+ end
11
+ end
12
+
13
+ if __FILE__ == $0
14
+ grant = GrantProject.new("Grant", 1_000, 300)
15
+
16
+ puts "#{grant.name} has $#{grant.total_funds} in funding towards a goal of $#{grant.target}."
17
+ grant.remove_funds
18
+ puts "#{grant.name} has $#{grant.total_funds} in funding towards a goal of $#{grant.target}."
19
+ end
@@ -0,0 +1,31 @@
1
+ require_relative 'project'
2
+
3
+ module Crowdfund
4
+ class MatchingProject < Project
5
+
6
+ def initialize(name, target_funding_amount, funding = 0)
7
+ super(name, target_funding_amount, funding)
8
+ @half_amount = target_funding_amount / 2
9
+ end
10
+
11
+ def half_amount?
12
+ @half_amount <= funding
13
+ end
14
+
15
+ def add_funds
16
+ if half_amount?
17
+ @funding += (25 * 2)
18
+ puts "#{ name } has received at least half of its target amount"
19
+ else
20
+ super
21
+ end
22
+ end
23
+
24
+ end
25
+ end
26
+
27
+ if __FILE__ == $0
28
+ matching = MatchingProject.new("Matching 123", 200, 0)
29
+ 6.times { matching.add_funds }
30
+ puts matching.funding
31
+ end
@@ -0,0 +1,22 @@
1
+ module Crowdfund
2
+ Pledge = Struct.new(:name, :amount)
3
+
4
+ module PledgePool
5
+ PLEDGES = [
6
+ Pledge.new(:bronze, 50),
7
+ Pledge.new(:silver, 75),
8
+ Pledge.new(:gold, 100)
9
+ ]
10
+
11
+ def self.random
12
+ PLEDGES.sample
13
+ end
14
+
15
+ end
16
+ end
17
+
18
+ if __FILE__ == $0
19
+ puts PledgePool::PLEDGES
20
+ treasure = PledgePool.random
21
+ puts "You have received a #{pledge.name} pledge. It values $#{plege.points}"
22
+ end
@@ -0,0 +1,54 @@
1
+ require_relative 'pledge_pool'
2
+ require_relative 'fundable'
3
+
4
+ module Crowdfund
5
+ class Project
6
+ include Fundable
7
+
8
+ attr_accessor :name
9
+ attr_reader :target, :funding
10
+
11
+ def initialize(name, target_funding_amount, funding = 0)
12
+ @name = name
13
+ @target = target_funding_amount
14
+ @funding = funding
15
+ @pledges_container = Hash.new(0)
16
+ end
17
+
18
+ def to_s
19
+ "#{ @name } has $#{ total_funds } in funding towards a goal of $#{ @target }."
20
+ end
21
+
22
+ def received_pledge(pledge)
23
+ @pledges_container[pledge.name] += pledge.amount
24
+ puts "#{ @name } received a #{ pledge.name } pledge worth $#{ pledge.amount }."
25
+ puts "#{ @name }'s pledges: #{ @pledges_container }"
26
+ end
27
+
28
+ def pledges
29
+ @pledges_container.values.reduce(0, :+)
30
+ end
31
+
32
+ def total_funds
33
+ @funding + pledges
34
+ end
35
+
36
+ def each_received_pledge
37
+ @pledges_container.each do|key, value|
38
+ pledge = Pledge.new(key, value)
39
+ yield(pledge)
40
+ end
41
+ end
42
+
43
+ end
44
+ end
45
+
46
+ if __FILE__ == $0
47
+ project = Project.new("LMN", 500, 3_000)
48
+ puts project
49
+ puts project.target
50
+ project.add_funds
51
+ puts project.funding
52
+ project.remove_funds
53
+ puts project.funding
54
+ end
@@ -0,0 +1,42 @@
1
+ require 'crowdfund/fundrequest'
2
+
3
+ module Crowdfund
4
+ describe FundRequest do
5
+
6
+ before do
7
+ @fundrequest = FundRequest.new("Ruby course Crowdfunding App")
8
+
9
+ @initial_funds = 1_000
10
+ @project = Project.new("ABC", 5_000, @initial_funds)
11
+
12
+ @fundrequest.add_project(@project)
13
+ end
14
+
15
+ it "adds funds to a project if an even number is rolled" do
16
+ allow_any_instance_of(Die).to receive(:roll).and_return(2)
17
+
18
+ @fundrequest.request_funding(1)
19
+
20
+ expect(@project.funding).to eq(@initial_funds + 25)
21
+ end
22
+
23
+ it "remove funds to a project if an odd number is rolled" do
24
+ allow_any_instance_of(Die).to receive(:roll).and_return(1)
25
+
26
+ @fundrequest.request_funding(1)
27
+
28
+ expect(@project.funding).to eq(@initial_funds - 15)
29
+ end
30
+
31
+ it "assigns a pledge for amount during a project's funding round" do
32
+ fundrequest = FundRequest.new("Ruby course Crowdfunding App")
33
+ project = Project.new("ABC", 5_000, @initial_funds)
34
+
35
+ fundrequest.add_project(project)
36
+ fundrequest.request_funding(1)
37
+
38
+ expect(project.pledges).to_not eq 0
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,20 @@
1
+ require 'crowdfund/grant_project'
2
+
3
+ module Crowdfund
4
+ describe GrantProject do
5
+
6
+ before do
7
+ @initial_funds = 1_000
8
+ @grant = GrantProject.new("Grant", 5_000, @initial_funds)
9
+ end
10
+
11
+ it "can not have its funds removed" do
12
+ expect(@grant.funding).to eq 1_000
13
+
14
+ @grant.remove_funds
15
+
16
+ expect(@grant.funding).to eq @initial_funds
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,30 @@
1
+ require 'crowdfund/matching_project'
2
+
3
+ module Crowdfund
4
+ describe MatchingProject do
5
+
6
+ before do
7
+ @initial_funds = 0
8
+ @matching = MatchingProject.new("Match", 200, @initial_funds)
9
+ end
10
+
11
+ it "does not match additional funds when the project is not halfway funded" do
12
+ 3.times { @matching.add_funds }
13
+
14
+ expect(@matching.half_amount?).to be false
15
+ end
16
+
17
+ it "is halfway funded when it has received half of its target funding amount" do
18
+ 4.times { @matching.add_funds }
19
+
20
+ expect(@matching.half_amount?).to be true
21
+ end
22
+
23
+ it "receives twice as much added funds when it is halfway funded" do
24
+ 7.times { @matching.add_funds }
25
+
26
+ expect(@matching.funding).to eq(@initial_funds + (4 * 25)+(3 * 25 * 2))
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,45 @@
1
+ require 'crowdfund/pledge_pool'
2
+
3
+ module Crowdfund
4
+ describe Pledge do
5
+
6
+ before do
7
+ @pledge = Pledge.new(:bronze, 50)
8
+ end
9
+
10
+ it "has a name attribute" do
11
+ expect(@pledge.name).to be(:bronze)
12
+ end
13
+
14
+ it "has an amount attribute" do
15
+ expect(@pledge.amount).to eq 50
16
+ end
17
+
18
+ end
19
+ end
20
+
21
+ module Crowdfund
22
+ describe PledgePool do
23
+
24
+ it "has three pledges" do
25
+ expect(PledgePool::PLEDGES.size).to eq 3
26
+ end
27
+
28
+ it "has a bronze pledge worth $50" do
29
+ expect(PledgePool::PLEDGES[0]).to eq (Pledge.new(:bronze, 50))
30
+ end
31
+
32
+ it "has a silver pledge worth 75 points" do
33
+ expect(PledgePool::PLEDGES[1]).to eq(Pledge.new(:silver, 75))
34
+ end
35
+
36
+ it "has a gold pledge worth 100 points" do
37
+ expect(PledgePool::PLEDGES[2]).to eq(Pledge.new(:gold, 100))
38
+ end
39
+
40
+ it "returns a random pledge" do
41
+ expect(PledgePool.random).to be_an_instance_of(Pledge)
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,100 @@
1
+ require 'crowdfund/project'
2
+
3
+ module Crowdfund
4
+ describe Project do
5
+ before do
6
+ @initial_founds = 1_000
7
+ @project = Project.new("ABC", 5_000, @initial_founds)
8
+ end
9
+
10
+ it "has an initial target funding amount" do
11
+ expect(@project.target).to eq 5_000
12
+ end
13
+
14
+ it "computes the total funding outstantind as the target amount minus the funding amount" do
15
+ expect(@project.total_funding_outstanding).to eq (5_000 - 1_000)
16
+ end
17
+
18
+ it "increases funds by 25 when funds are added" do
19
+ @project.add_funds
20
+
21
+ expect(@project.funding).to eq(@initial_founds.to_i + 25)
22
+ end
23
+
24
+ it "decreases funds by 15 when funds are removed" do
25
+ @project.remove_funds
26
+
27
+ expect(@project.funding).to eq(@initial_founds.to_i - 15)
28
+ end
29
+
30
+ context "when a project is initialized with no initial funding amount" do
31
+ before do
32
+ @project = Project.new("LMN", 5_000)
33
+ end
34
+
35
+ it "has default value of 0 for funding amount" do
36
+ expect(@project.funding).to eq 0
37
+ end
38
+ end
39
+
40
+ context "when total funding outstanding is less than or equals zero" do
41
+ before do
42
+ @project = Project.new("LMN", 5_000, 5_000)
43
+ end
44
+
45
+ it "is fully funded" do
46
+ expect(@project).to be_fully_funded
47
+ end
48
+ end
49
+
50
+ context "when total funding outstanding is greater than zero" do
51
+ before do
52
+ @project = Project.new("LMN", 5_000, 1_000)
53
+ end
54
+
55
+ it "is not fully funded" do
56
+ expect(@project).to_not be_fully_funded
57
+ end
58
+ end
59
+
60
+ it "computes pledges as the sum of all pledges" do
61
+ expect(@project.pledges).to eq 0
62
+
63
+ @project.received_pledge(Pledge.new(:silver, 75))
64
+
65
+ expect(@project.pledges).to eq 75
66
+
67
+ @project.received_pledge(Pledge.new(:gold, 100))
68
+
69
+ expect(@project.pledges).to eq 175
70
+
71
+ @project.received_pledge(Pledge.new(:gold, 100))
72
+
73
+ expect(@project.pledges).to eq 275
74
+
75
+ end
76
+
77
+ it "computes total funds as the sum of a projects funding and pledges" do
78
+ @project.received_pledge(Pledge.new(:gold, 100))
79
+ @project.received_pledge(Pledge.new(:gold, 100))
80
+
81
+ expect(@project.total_funds).to eq 1_200
82
+ end
83
+
84
+ it "yields each pledge received and its value" do
85
+ @project.received_pledge(Pledge.new(:bronze, 50))
86
+ @project.received_pledge(Pledge.new(:silver, 75))
87
+ @project.received_pledge(Pledge.new(:gold, 100))
88
+
89
+ yielded = []
90
+ @project.each_received_pledge do |pledge|
91
+ yielded << pledge
92
+ end
93
+
94
+ expect(yielded).to eq([Pledge.new(:bronze, 50),
95
+ Pledge.new(:silver, 75),
96
+ Pledge.new(:gold, 100)])
97
+ end
98
+
99
+ end
100
+ end
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: crowdfund_sergio_silva
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Sérgio Vitarelli Silva
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-07-01 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: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description: |-
28
+ This is an example application used in The Pragmatic Studio's
29
+ Ruby Programming course, as described at
30
+
31
+ http://pragmaticstudio.com
32
+
33
+ This code is Copyright 2012 The Pragmatic Studio. See the LICENSE file.
34
+ email: sergio.silva@dito.com.br
35
+ executables:
36
+ - crowdfund
37
+ extensions: []
38
+ extra_rdoc_files: []
39
+ files:
40
+ - LICENSE
41
+ - README
42
+ - bin/crowdfund
43
+ - bin/projects.csv
44
+ - bin/results.txt
45
+ - lib/crowdfund/die.rb
46
+ - lib/crowdfund/fundable.rb
47
+ - lib/crowdfund/funding_round.rb
48
+ - lib/crowdfund/fundrequest.rb
49
+ - lib/crowdfund/grant_project.rb
50
+ - lib/crowdfund/matching_project.rb
51
+ - lib/crowdfund/pledge_pool.rb
52
+ - lib/crowdfund/project.rb
53
+ - spec/crowdfund/fundrequest_spec.rb
54
+ - spec/crowdfund/grant_project_spec.rb
55
+ - spec/crowdfund/matching_project_spec.rb
56
+ - spec/crowdfund/pledge_pool_spec.rb
57
+ - spec/crowdfund/project_spec.rb
58
+ homepage: https://github.com/
59
+ licenses: []
60
+ metadata: {}
61
+ post_install_message:
62
+ rdoc_options: []
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '1.9'
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ requirements: []
76
+ rubyforge_project:
77
+ rubygems_version: 2.4.5
78
+ signing_key:
79
+ specification_version: 4
80
+ summary: Crowdfund application gem
81
+ test_files: []