owemegod 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.
- data/.gitignore +6 -0
- data/.rvmrc +1 -0
- data/Gemfile +12 -0
- data/Guardfile +12 -0
- data/Rakefile +14 -0
- data/Readme.md +53 -0
- data/features/debt_distribution.feature +27 -0
- data/features/steps/debt_distribution.rb +75 -0
- data/features/support/env.rb +10 -0
- data/lib/owemegod.rb +5 -0
- data/lib/owemegod/debt.rb +6 -0
- data/lib/owemegod/debt_distribution.rb +81 -0
- data/lib/owemegod/expense.rb +11 -0
- data/lib/owemegod/expense_collection.rb +25 -0
- data/lib/owemegod/group.rb +26 -0
- data/lib/owemegod/person.rb +25 -0
- data/lib/owemegod/version.rb +3 -0
- data/owemegod.gemspec +25 -0
- data/spec/owemegod/debt_distribution_spec.rb +95 -0
- data/spec/owemegod/expense_collection_spec.rb +55 -0
- data/spec/owemegod/expense_spec.rb +11 -0
- data/spec/owemegod/group_spec.rb +16 -0
- data/spec/owemegod/person_spec.rb +19 -0
- data/spec/spec_helper.rb +14 -0
- metadata +122 -0
data/.gitignore
ADDED
data/.rvmrc
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
rvm use --create 1.9.3@owemegod
|
data/Gemfile
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
source "http://rubygems.org"
|
|
2
|
+
|
|
3
|
+
# Specify your gem's dependencies in owemegod.gemspec
|
|
4
|
+
gemspec
|
|
5
|
+
|
|
6
|
+
group :development do
|
|
7
|
+
gem 'growl'
|
|
8
|
+
gem 'guard'
|
|
9
|
+
gem 'guard-minitest', :git => 'git://github.com/aspiers/guard-minitest.git'
|
|
10
|
+
gem 'guard-spinach'
|
|
11
|
+
gem 'simplecov'
|
|
12
|
+
end
|
data/Guardfile
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
guard 'minitest' do
|
|
2
|
+
watch(%r|^spec/(.*)_spec\.rb|)
|
|
3
|
+
watch(%r|^lib/(.*)\.rb|) { |m| "spec/#{m[1]}_spec.rb" }
|
|
4
|
+
watch(%r|^spec/spec_helper\.rb|) { "spec" }
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
guard 'spinach' do
|
|
8
|
+
watch(%r|^features/(.*)\.feature|)
|
|
9
|
+
watch(%r|^features/steps/(.*)([^/]+)\.rb|) do |m|
|
|
10
|
+
"features/#{m[1]}#{m[2]}.feature"
|
|
11
|
+
end
|
|
12
|
+
end
|
data/Rakefile
ADDED
data/Readme.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Owemegod
|
|
2
|
+
|
|
3
|
+
Owemegod is a tool made for distributing costs of events or parties among a bunch of people.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
### Set up a bunch of people
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
me = Owemegod::Person.new(name: "Josep Jaume")
|
|
11
|
+
petula = Owemegod::Person.new(name: "Petula Clark")
|
|
12
|
+
chaplin = Owemegod::Person.new(name: "Charles Chaplin")
|
|
13
|
+
napoleon = Owemegod::Person.new(name: "Napoleon Dynamite")
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### Assign them a bunch of expenses
|
|
17
|
+
|
|
18
|
+
```ruby
|
|
19
|
+
me.add_expense("Food", 50)
|
|
20
|
+
me.add_expense("Bitches", 100)
|
|
21
|
+
petula.add_expense("Drinks", 40)
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Create a group
|
|
25
|
+
|
|
26
|
+
```ruby
|
|
27
|
+
group = Owemegod::Group.new [me, petula, chaplin]
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Distribute the costs
|
|
31
|
+
|
|
32
|
+
```ruby
|
|
33
|
+
distribution = group.distribute
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Inspect the results
|
|
37
|
+
|
|
38
|
+
```ruby
|
|
39
|
+
puts distribution.debts.inspect
|
|
40
|
+
=> [[#<Owemegod::Person name="Petula Clark">, #<Owemegod::Person name="Josep Jaume">, 7.5], [#<Owemegod::Person name="Napoleon Dynamite">, #<Owemegod::Person name="Josep Jaume">, 47.5], [#<Owemegod::Person name="Charles Chaplin">, #<Owemegod::Person name="Josep Jaume">, 47.5]]
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Todo
|
|
44
|
+
|
|
45
|
+
* Create a prettier API
|
|
46
|
+
* Create prettier output
|
|
47
|
+
* Simplify internals (refactoring)
|
|
48
|
+
* Add documentation
|
|
49
|
+
* Create a web interface
|
|
50
|
+
|
|
51
|
+
## License
|
|
52
|
+
|
|
53
|
+
MIT License. Copyright 2011 Josep Jaume
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
Feature: Debt distribution
|
|
2
|
+
In order to distribute the cost of an event among friends
|
|
3
|
+
As the organizer
|
|
4
|
+
I want Owemegod to suggest a debt distribution
|
|
5
|
+
|
|
6
|
+
Scenario: I organize a party and pay for all
|
|
7
|
+
Given I'm organizing a party
|
|
8
|
+
And I invited 5 of my friends
|
|
9
|
+
And I paid for all for an amount of 120eur
|
|
10
|
+
When I use Owemegod to distribute the costs
|
|
11
|
+
Then everyone should pay me 20eur
|
|
12
|
+
And I should not pay a thing
|
|
13
|
+
|
|
14
|
+
Scenario: Someone organizes a party and each one pays the same amount
|
|
15
|
+
Given I'm organizing a party
|
|
16
|
+
And I invited 5 of my friends
|
|
17
|
+
And each one of us paid 15eur
|
|
18
|
+
When I use Owemegod to distribute the costs
|
|
19
|
+
Then no one should pay a thing
|
|
20
|
+
|
|
21
|
+
Scenario: Someone organizes a party and someone didn't pay for anything
|
|
22
|
+
Given I'm organizing a party
|
|
23
|
+
And I invited 5 of my friends
|
|
24
|
+
And each one of us paid 15eur except me
|
|
25
|
+
When I use Owemegod to distribute the costs
|
|
26
|
+
Then I should pay 2.5eur to everyone
|
|
27
|
+
And no one else should pay anything
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
class DebtDistribution < Spinach::FeatureSteps
|
|
2
|
+
feature 'Debt distribution'
|
|
3
|
+
Given 'I\'m organizing a party' do
|
|
4
|
+
@me = Owemegod::Person.new(name: 'John Doe')
|
|
5
|
+
@group = Owemegod::Group.new
|
|
6
|
+
@group.add_person @me
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
And 'I invited 5 of my friends' do
|
|
10
|
+
@friends = []
|
|
11
|
+
5.times do |i|
|
|
12
|
+
friend = Owemegod::Person.new(name: "Friend #{i}")
|
|
13
|
+
@group.add_person friend
|
|
14
|
+
@friends << friend
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
And 'I paid for all for an amount of 120eur' do
|
|
19
|
+
@me.add_expense("Food", 50)
|
|
20
|
+
@me.add_expense("Equipment", 50)
|
|
21
|
+
@me.add_expense("Other", 20)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
When 'I use Owemegod to distribute the costs' do
|
|
25
|
+
@distribution = @group.distribute
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
Then 'everyone should pay me 20eur' do
|
|
29
|
+
@friends.each do |friend|
|
|
30
|
+
debts = @distribution.outgoing_debts(friend)
|
|
31
|
+
debts.length.must_equal 1
|
|
32
|
+
debt = debts.first
|
|
33
|
+
debt[1].name.must_equal "John Doe"
|
|
34
|
+
debt[2].must_equal 20
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
And 'I should not pay a thing' do
|
|
39
|
+
@distribution.outgoing_debts(@me).length.must_equal 0
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
And 'each one of us paid 15eur' do
|
|
43
|
+
(@friends + [@me]).each do |person|
|
|
44
|
+
person.add_expense("Food", 10)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
And 'no one should pay a thing' do
|
|
49
|
+
(@friends + [@me]).each do |person|
|
|
50
|
+
@distribution.outgoing_debts(person).length.must_equal 0
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
And 'each one of us paid 15eur except me' do
|
|
55
|
+
@friends.each do |person|
|
|
56
|
+
person.add_expense("Food", 15)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
Then 'I should pay 2.5eur to everyone' do
|
|
61
|
+
debts = @distribution.outgoing_debts(@me)
|
|
62
|
+
debts.length.must_equal 5
|
|
63
|
+
@friends.each do |friend|
|
|
64
|
+
friend_debts = debts.select{|d| d[1] == friend}
|
|
65
|
+
friend_debts.length.must_equal 1
|
|
66
|
+
friend_debts.first[2].must_equal 2.5
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
And 'no one else should pay anything' do
|
|
71
|
+
@friends.each do |friend|
|
|
72
|
+
@distribution.outgoing_debts(friend).length.must_equal 0
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
data/lib/owemegod.rb
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
module Owemegod
|
|
2
|
+
class DebtDistribution
|
|
3
|
+
attr_accessor :people, :debts
|
|
4
|
+
|
|
5
|
+
def initialize(people)
|
|
6
|
+
self.people = people
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def average_expenses
|
|
10
|
+
total_amount = people.reduce(0.0) do |sum, person|
|
|
11
|
+
sum += person.total_expenses
|
|
12
|
+
end
|
|
13
|
+
total_amount / people.length
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def debts
|
|
17
|
+
@debts ||= []
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def add_debt(from, to, amount)
|
|
21
|
+
debts << [from, to, amount]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def outgoing_debts(person)
|
|
25
|
+
debts.select do |debt|
|
|
26
|
+
debt[0] == person
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def outgoing_debts_amount(person)
|
|
31
|
+
outgoing_debts(person).inject(0.0) do |sum, debt|
|
|
32
|
+
sum += debt[2]
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def incoming_debts(person)
|
|
37
|
+
debts.select do |debt|
|
|
38
|
+
debt[1] == person
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def incoming_debts_amount(person)
|
|
43
|
+
incoming_debts(person).inject(0.0) do |sum, debt|
|
|
44
|
+
sum += debt[2]
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def balance_for(person)
|
|
49
|
+
person = people.find{|p| p == person}
|
|
50
|
+
raise "#{person.name} isn't in this distribution" unless person
|
|
51
|
+
initial_balance = average_expenses - person.total_expenses
|
|
52
|
+
initial_balance += incoming_debts_amount(person)
|
|
53
|
+
initial_balance -= outgoing_debts_amount(person)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def calculate
|
|
57
|
+
while(!even?)
|
|
58
|
+
from = most_positive_balance
|
|
59
|
+
to = most_negative_balance
|
|
60
|
+
|
|
61
|
+
if balance_for(from) > -balance_for(to)
|
|
62
|
+
add_debt(from, to, -balance_for(to))
|
|
63
|
+
else
|
|
64
|
+
add_debt(from, to, balance_for(from))
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def most_positive_balance
|
|
70
|
+
people.shuffle.select{|p| balance_for(p) > 0}.max{|p| balance_for(p)}
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def most_negative_balance
|
|
74
|
+
people.shuffle.select{|p| balance_for(p) < 0}.min{|p| balance_for(p)}
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def even?
|
|
78
|
+
people.all?{|p| balance_for(p) >= 0}
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require 'owemegod/expense'
|
|
2
|
+
|
|
3
|
+
module Owemegod
|
|
4
|
+
class ExpenseCollection
|
|
5
|
+
include Enumerable
|
|
6
|
+
|
|
7
|
+
def expenses
|
|
8
|
+
@expenses ||= []
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def add_expense(name, value)
|
|
12
|
+
expenses << Expense.new(name: name, value: value)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def value
|
|
16
|
+
inject(0){|sum, expense| sum + expense.value}
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def each(&block)
|
|
20
|
+
expenses.each do |expense|
|
|
21
|
+
block.call expense
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require 'owemegod/debt_distribution'
|
|
2
|
+
|
|
3
|
+
module Owemegod
|
|
4
|
+
class Group
|
|
5
|
+
|
|
6
|
+
attr_accessor :people
|
|
7
|
+
|
|
8
|
+
# Initializes an event with a certain array of people
|
|
9
|
+
def initialize(people = [])
|
|
10
|
+
@people ||= []
|
|
11
|
+
people.each do |person|
|
|
12
|
+
add_person person
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def add_person(person)
|
|
17
|
+
people << person
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def distribute
|
|
21
|
+
distribution = DebtDistribution.new(people)
|
|
22
|
+
distribution.calculate
|
|
23
|
+
distribution
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require 'ostruct'
|
|
2
|
+
require 'owemegod/expense_collection'
|
|
3
|
+
|
|
4
|
+
module Owemegod
|
|
5
|
+
class Person < OpenStruct
|
|
6
|
+
attr_accessor :expenses
|
|
7
|
+
|
|
8
|
+
def initialize(*args)
|
|
9
|
+
super
|
|
10
|
+
self.expenses = ExpenseCollection.new
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def expenses
|
|
14
|
+
@expenses
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def add_expense(name, amount)
|
|
18
|
+
expenses.add_expense(name, amount)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def total_expenses
|
|
22
|
+
expenses.value
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
data/owemegod.gemspec
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
|
3
|
+
require "owemegod/version"
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |s|
|
|
6
|
+
s.name = "owemegod"
|
|
7
|
+
s.version = Owemegod::VERSION
|
|
8
|
+
s.authors = ["Josep Jaume"]
|
|
9
|
+
s.email = ["josepjaume@gmail.com"]
|
|
10
|
+
s.homepage = ""
|
|
11
|
+
s.summary = %q{A gem for easily distribute debts among friends}
|
|
12
|
+
s.description = %q{A gem for easily distribute debts among friends}
|
|
13
|
+
|
|
14
|
+
s.rubyforge_project = "owemegod"
|
|
15
|
+
|
|
16
|
+
s.files = `git ls-files`.split("\n")
|
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
|
19
|
+
s.require_paths = ["lib"]
|
|
20
|
+
|
|
21
|
+
s.add_development_dependency "minitest"
|
|
22
|
+
s.add_development_dependency "spinach"
|
|
23
|
+
s.add_development_dependency "minitest-reporters"
|
|
24
|
+
s.add_development_dependency "ansi"
|
|
25
|
+
end
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
require_relative '../spec_helper'
|
|
2
|
+
require 'owemegod/debt_distribution'
|
|
3
|
+
require 'ostruct'
|
|
4
|
+
|
|
5
|
+
describe Owemegod::DebtDistribution do
|
|
6
|
+
subject{ Owemegod::DebtDistribution.new(people) }
|
|
7
|
+
|
|
8
|
+
let(:james) { OpenStruct.new(name: 'James', total_expenses: 15) }
|
|
9
|
+
let(:john) { OpenStruct.new(name: 'John' , total_expenses: 5) }
|
|
10
|
+
let(:alex) { OpenStruct.new(name: 'Alex' , total_expenses: 0) }
|
|
11
|
+
let(:sally) { OpenStruct.new(name: 'Sally', total_expenses: 10) }
|
|
12
|
+
let(:people){ [james, john, alex, sally] }
|
|
13
|
+
|
|
14
|
+
before do
|
|
15
|
+
subject.add_debt(alex, james, 5)
|
|
16
|
+
subject.add_debt(john, sally, 1)
|
|
17
|
+
subject.add_debt(john, james, 1)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
describe "#average_expenses" do
|
|
22
|
+
it "should return the average expenses" do
|
|
23
|
+
subject.average_expenses.must_equal 30.0 / 4
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe "debts" do
|
|
28
|
+
describe "#outgoing_debts" do
|
|
29
|
+
it "returns a list of all the debts for a person" do
|
|
30
|
+
subject.outgoing_debts(alex).length.must_equal 1
|
|
31
|
+
subject.outgoing_debts(james).length.must_equal 0
|
|
32
|
+
subject.outgoing_debts(john).length.must_equal 2
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
describe "#outgoing_debts_amount" do
|
|
37
|
+
it "returns the total amount of the debts of a person" do
|
|
38
|
+
subject.outgoing_debts_amount(alex).must_equal 5
|
|
39
|
+
subject.outgoing_debts_amount(john).must_equal 2
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
describe "#incoming_debts" do
|
|
44
|
+
it "returns a list of all the debts for a person" do
|
|
45
|
+
subject.incoming_debts(james).length.must_equal 2
|
|
46
|
+
subject.incoming_debts(john).length.must_equal 0
|
|
47
|
+
subject.incoming_debts(sally).length.must_equal 1
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
describe "#incoming_debts_amount" do
|
|
52
|
+
it "returns the total amount of debts other people have with a person" do
|
|
53
|
+
subject.incoming_debts_amount(james).must_equal 6
|
|
54
|
+
subject.incoming_debts_amount(sally).must_equal 1
|
|
55
|
+
subject.incoming_debts_amount(alex).must_equal 0
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
describe "#balance_for" do
|
|
61
|
+
describe "when there's no debt" do
|
|
62
|
+
before do
|
|
63
|
+
subject.debts = []
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it "returns the starting balance for that person" do
|
|
67
|
+
subject.balance_for(james).must_equal -7.5
|
|
68
|
+
subject.balance_for(john).must_equal 2.5
|
|
69
|
+
subject.balance_for(alex).must_equal 7.5
|
|
70
|
+
subject.balance_for(sally).must_equal -2.5
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
describe "when there are some debts" do
|
|
75
|
+
it "returns the actual balance for that person" do
|
|
76
|
+
subject.balance_for(james).must_equal -1.5
|
|
77
|
+
subject.balance_for(john).must_equal 0.5
|
|
78
|
+
subject.balance_for(alex).must_equal 2.5
|
|
79
|
+
subject.balance_for(sally).must_equal -1.5
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
describe "#calculate" do
|
|
85
|
+
before do
|
|
86
|
+
subject.debts = nil
|
|
87
|
+
end
|
|
88
|
+
it "sets the balance of everyone to 0" do
|
|
89
|
+
subject.calculate
|
|
90
|
+
subject.people.each do |person|
|
|
91
|
+
subject.balance_for(person).must_equal 0
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
require_relative '../spec_helper'
|
|
2
|
+
require 'owemegod/expense_collection'
|
|
3
|
+
|
|
4
|
+
require 'ostruct'
|
|
5
|
+
|
|
6
|
+
module Owemegod
|
|
7
|
+
describe Owemegod::ExpenseCollection do
|
|
8
|
+
subject { Owemegod::ExpenseCollection.new }
|
|
9
|
+
describe "#first" do
|
|
10
|
+
it "is nil when there's no expenses" do
|
|
11
|
+
subject.first.must_equal nil
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "returns the first expense when there's more expenses" do
|
|
15
|
+
subject.add_expense 'Foo', 2
|
|
16
|
+
subject.add_expense 'Bar', 3
|
|
17
|
+
subject.first.name.must_equal 'Foo'
|
|
18
|
+
subject.first.value.must_equal 2
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
describe "#total" do
|
|
23
|
+
it "returns 0 when there's no expense" do
|
|
24
|
+
subject.value.must_equal 0
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "returns the total amount of expenses" do
|
|
28
|
+
subject.add_expense "Foo", 5
|
|
29
|
+
subject.add_expense "Bar", 10
|
|
30
|
+
subject.value.must_equal 15
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
describe "#max" do
|
|
35
|
+
it "returns nil if there's no expense" do
|
|
36
|
+
subject.max.must_equal nil
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "returns the max expense" do
|
|
40
|
+
subject.add_expense "Foo", 5
|
|
41
|
+
subject.add_expense "Bar", 10
|
|
42
|
+
subject.max.value.must_equal 10
|
|
43
|
+
subject.max.name.must_equal "Bar"
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
describe "#to_a" do
|
|
48
|
+
it "returns a comprehensible array of expenses" do
|
|
49
|
+
subject.add_expense "Foo", 5
|
|
50
|
+
subject.add_expense "Bar", 10
|
|
51
|
+
subject.to_a[0].value.must_equal 5
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require_relative '../spec_helper'
|
|
2
|
+
require 'owemegod/group'
|
|
3
|
+
|
|
4
|
+
module Owemegod
|
|
5
|
+
describe Group do
|
|
6
|
+
describe "#initializer" do
|
|
7
|
+
it "initializes an array of people" do
|
|
8
|
+
person1 = Object.new
|
|
9
|
+
person2 = Object.new
|
|
10
|
+
event = Group.new [person1, person2]
|
|
11
|
+
event.people.must_include person1
|
|
12
|
+
event.people.must_include person2
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require_relative '../spec_helper'
|
|
2
|
+
require 'owemegod/person'
|
|
3
|
+
|
|
4
|
+
describe Owemegod::Person do
|
|
5
|
+
subject{ Owemegod::Person.new(name: 'Josep Jaume')}
|
|
6
|
+
describe "#name" do
|
|
7
|
+
it "has a name" do
|
|
8
|
+
subject.name.must_equal "Josep Jaume"
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
describe "#total_expenses" do
|
|
13
|
+
describe "when there's no expense" do
|
|
14
|
+
it "returns 0" do
|
|
15
|
+
subject.total_expenses.must_equal 0
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
begin
|
|
2
|
+
require 'simplecov'
|
|
3
|
+
SimpleCov.start do
|
|
4
|
+
add_filter "/spec/"
|
|
5
|
+
end
|
|
6
|
+
rescue nil
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
require 'minitest/spec'
|
|
10
|
+
require 'minitest/autorun'
|
|
11
|
+
|
|
12
|
+
require 'minitest/reporters'
|
|
13
|
+
MiniTest::Unit.runner = MiniTest::SuiteRunner.new
|
|
14
|
+
MiniTest::Unit.runner.reporters << MiniTest::Reporters::ProgressReporter.new
|
metadata
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: owemegod
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
prerelease:
|
|
6
|
+
platform: ruby
|
|
7
|
+
authors:
|
|
8
|
+
- Josep Jaume
|
|
9
|
+
autorequire:
|
|
10
|
+
bindir: bin
|
|
11
|
+
cert_chain: []
|
|
12
|
+
date: 2012-02-19 00:00:00.000000000 Z
|
|
13
|
+
dependencies:
|
|
14
|
+
- !ruby/object:Gem::Dependency
|
|
15
|
+
name: minitest
|
|
16
|
+
requirement: &70365355724080 !ruby/object:Gem::Requirement
|
|
17
|
+
none: false
|
|
18
|
+
requirements:
|
|
19
|
+
- - ! '>='
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: '0'
|
|
22
|
+
type: :development
|
|
23
|
+
prerelease: false
|
|
24
|
+
version_requirements: *70365355724080
|
|
25
|
+
- !ruby/object:Gem::Dependency
|
|
26
|
+
name: spinach
|
|
27
|
+
requirement: &70365355723440 !ruby/object:Gem::Requirement
|
|
28
|
+
none: false
|
|
29
|
+
requirements:
|
|
30
|
+
- - ! '>='
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0'
|
|
33
|
+
type: :development
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: *70365355723440
|
|
36
|
+
- !ruby/object:Gem::Dependency
|
|
37
|
+
name: minitest-reporters
|
|
38
|
+
requirement: &70365355723000 !ruby/object:Gem::Requirement
|
|
39
|
+
none: false
|
|
40
|
+
requirements:
|
|
41
|
+
- - ! '>='
|
|
42
|
+
- !ruby/object:Gem::Version
|
|
43
|
+
version: '0'
|
|
44
|
+
type: :development
|
|
45
|
+
prerelease: false
|
|
46
|
+
version_requirements: *70365355723000
|
|
47
|
+
- !ruby/object:Gem::Dependency
|
|
48
|
+
name: ansi
|
|
49
|
+
requirement: &70365355722500 !ruby/object:Gem::Requirement
|
|
50
|
+
none: false
|
|
51
|
+
requirements:
|
|
52
|
+
- - ! '>='
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0'
|
|
55
|
+
type: :development
|
|
56
|
+
prerelease: false
|
|
57
|
+
version_requirements: *70365355722500
|
|
58
|
+
description: A gem for easily distribute debts among friends
|
|
59
|
+
email:
|
|
60
|
+
- josepjaume@gmail.com
|
|
61
|
+
executables: []
|
|
62
|
+
extensions: []
|
|
63
|
+
extra_rdoc_files: []
|
|
64
|
+
files:
|
|
65
|
+
- .gitignore
|
|
66
|
+
- .rvmrc
|
|
67
|
+
- Gemfile
|
|
68
|
+
- Guardfile
|
|
69
|
+
- Rakefile
|
|
70
|
+
- Readme.md
|
|
71
|
+
- features/debt_distribution.feature
|
|
72
|
+
- features/steps/debt_distribution.rb
|
|
73
|
+
- features/support/env.rb
|
|
74
|
+
- lib/owemegod.rb
|
|
75
|
+
- lib/owemegod/debt.rb
|
|
76
|
+
- lib/owemegod/debt_distribution.rb
|
|
77
|
+
- lib/owemegod/expense.rb
|
|
78
|
+
- lib/owemegod/expense_collection.rb
|
|
79
|
+
- lib/owemegod/group.rb
|
|
80
|
+
- lib/owemegod/person.rb
|
|
81
|
+
- lib/owemegod/version.rb
|
|
82
|
+
- owemegod.gemspec
|
|
83
|
+
- spec/owemegod/debt_distribution_spec.rb
|
|
84
|
+
- spec/owemegod/expense_collection_spec.rb
|
|
85
|
+
- spec/owemegod/expense_spec.rb
|
|
86
|
+
- spec/owemegod/group_spec.rb
|
|
87
|
+
- spec/owemegod/person_spec.rb
|
|
88
|
+
- spec/spec_helper.rb
|
|
89
|
+
homepage: ''
|
|
90
|
+
licenses: []
|
|
91
|
+
post_install_message:
|
|
92
|
+
rdoc_options: []
|
|
93
|
+
require_paths:
|
|
94
|
+
- lib
|
|
95
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
96
|
+
none: false
|
|
97
|
+
requirements:
|
|
98
|
+
- - ! '>='
|
|
99
|
+
- !ruby/object:Gem::Version
|
|
100
|
+
version: '0'
|
|
101
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
102
|
+
none: false
|
|
103
|
+
requirements:
|
|
104
|
+
- - ! '>='
|
|
105
|
+
- !ruby/object:Gem::Version
|
|
106
|
+
version: '0'
|
|
107
|
+
requirements: []
|
|
108
|
+
rubyforge_project: owemegod
|
|
109
|
+
rubygems_version: 1.8.16
|
|
110
|
+
signing_key:
|
|
111
|
+
specification_version: 3
|
|
112
|
+
summary: A gem for easily distribute debts among friends
|
|
113
|
+
test_files:
|
|
114
|
+
- features/debt_distribution.feature
|
|
115
|
+
- features/steps/debt_distribution.rb
|
|
116
|
+
- features/support/env.rb
|
|
117
|
+
- spec/owemegod/debt_distribution_spec.rb
|
|
118
|
+
- spec/owemegod/expense_collection_spec.rb
|
|
119
|
+
- spec/owemegod/expense_spec.rb
|
|
120
|
+
- spec/owemegod/group_spec.rb
|
|
121
|
+
- spec/owemegod/person_spec.rb
|
|
122
|
+
- spec/spec_helper.rb
|