moneybook 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem "shoulda", ">= 0"
10
+ gem "bundler", "~> 1.0.0"
11
+ gem "jeweler", "~> 1.5.2"
12
+ gem "rcov", ">= 0"
13
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,20 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ git (1.2.5)
5
+ jeweler (1.5.2)
6
+ bundler (~> 1.0.0)
7
+ git (>= 1.2.5)
8
+ rake
9
+ rake (0.8.7)
10
+ rcov (0.9.9)
11
+ shoulda (2.11.3)
12
+
13
+ PLATFORMS
14
+ ruby
15
+
16
+ DEPENDENCIES
17
+ bundler (~> 1.0.0)
18
+ jeweler (~> 1.5.2)
19
+ rcov
20
+ shoulda
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 luca cioria
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,19 @@
1
+ = moneybook
2
+
3
+ Simple program to keep track of money in a ground, for example during a trip
4
+
5
+ == Contributing to moneybook
6
+
7
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
8
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
9
+ * Fork the project
10
+ * Start a feature/bugfix branch
11
+ * Commit and push until you are happy with your contribution
12
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
13
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2011 luca cioria. See LICENSE.txt for
18
+ further details.
19
+
data/Rakefile ADDED
@@ -0,0 +1,55 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ Jeweler::Tasks.new do |gem|
14
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
+ gem.name = "moneybook"
16
+ gem.homepage = "http://github.com/vircheck/moneybook"
17
+ gem.license = "MIT"
18
+ gem.summary = "keep track of money in a group"
19
+ gem.description = "keep track of money in a group"
20
+ gem.email = "noreply@mail.com"
21
+ gem.authors = ["luca cioria"]
22
+ # Include your dependencies below. Runtime dependencies are required when using your gem,
23
+ # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
24
+ gem.add_runtime_dependency 'terminal-table'
25
+ gem.add_runtime_dependency 'commander'
26
+ gem.add_runtime_dependency 'andand'
27
+ # gem.add_development_dependency 'rspec', '> 1.2.3'
28
+ end
29
+ Jeweler::RubygemsDotOrgTasks.new
30
+
31
+ require 'rake/testtask'
32
+ Rake::TestTask.new(:test) do |test|
33
+ test.libs << 'lib' << 'test'
34
+ test.pattern = 'test/**/test_*.rb'
35
+ test.verbose = true
36
+ end
37
+
38
+ require 'rcov/rcovtask'
39
+ Rcov::RcovTask.new do |test|
40
+ test.libs << 'test'
41
+ test.pattern = 'test/**/test_*.rb'
42
+ test.verbose = true
43
+ end
44
+
45
+ task :default => :test
46
+
47
+ require 'rake/rdoctask'
48
+ Rake::RDocTask.new do |rdoc|
49
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
50
+
51
+ rdoc.rdoc_dir = 'rdoc'
52
+ rdoc.title = "moneybook #{version}"
53
+ rdoc.rdoc_files.include('README*')
54
+ rdoc.rdoc_files.include('lib/**/*.rb')
55
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/bin/moneybook ADDED
@@ -0,0 +1,169 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'terminal-table/import'
4
+ require 'commander/import'
5
+ require 'date'
6
+ require 'andand'
7
+ require 'abbrev'
8
+ require 'pp'
9
+
10
+ # :name is optional, otherwise uses the basename of this executable
11
+ program :name, 'MoneyBook'
12
+ program :version, '0.1'
13
+ program :description, 'A simple program to manage group expenses, for example a trip with friends...'
14
+
15
+ command :new do |c|
16
+ c.syntax = 'moneybook new'
17
+ c.description = 'create a skeleton moneybook file'
18
+ c.action do |args, options|
19
+ title = ask("Title: ")
20
+ people = ask('People (separated by spaces): ', lambda{|x|x.split(/\s+/)})
21
+ text = "### #{title} ###
22
+ # #{Date.today.to_s}
23
+ #######
24
+ # - everyone is included:
25
+ # pizza (45Luca)
26
+ # - only M and L are included because they sum up to the total
27
+ # cinema (30Lu) 12M 18L #names can be abbreviated
28
+ # - everyone is included because T doesn't reach the total
29
+ # cinema (30Mark) 7T
30
+ # - everyone but Mary is included
31
+ # dinner (50Fra 16Tom) +5Tom -2Jack -Mary #Tom spends 5 more than the others, Jack 2 less
32
+ # - synctactic sugar, instead of ...
33
+ # pay back (20L) T
34
+ # - ... you can write
35
+ # 20L -> T
36
+ #######
37
+
38
+ PEOPLE: #{people.join(' ')}"
39
+
40
+ filename = "moneybook_#{title.downcase.gsub(' ','_')}.txt"
41
+ if File.open(filename,'w'){|f|f.write text} then
42
+ puts "File #{filename} created!"
43
+ else
44
+ puts "Could not create file #{filename}.."
45
+ end
46
+ end
47
+ end
48
+
49
+ command :parse do |c|
50
+ c.syntax = 'moneybook parse [options] [file]'
51
+ c.description = 'calculate total debts for everyone'
52
+ intermediate = agree("Do you want to see the intermediate results? ")
53
+ c.action do |args, options|
54
+ people = []
55
+ people_abbreviations = []
56
+ sq = [] #big table to make the computations..
57
+ File.open(args.first,'r').read.each_line{|line|
58
+ if line =~ /^\s*\#/ || line =~ /\A\s*\Z/
59
+ # this is interpreted as a comment line
60
+ elsif (m = line.match(/\A\s*PEOPLE\s*\:?\s*((\s+\w+)+)\s*\Z/).andand[1].andand.split(/\s+/).andand.delete_if{|x|x==""}) != nil then
61
+ m.each{|z|people<<z.to_s.downcase}
62
+ people_abbreviations = people.abbrev
63
+ else
64
+ original_str = false
65
+ if temp=line.match(/\A\s*(.+)\s*\-+\>\s*(.+)\Z/) then
66
+ original_str = line.strip
67
+ line = "PAYBACK (#{temp[1].to_s}) #{temp[2].to_s}"
68
+ end
69
+ x = line.strip.match(/^\s*([\w\ ]+?)\s*\((.+)\)\s*(.+)?/).to_a.map{|z| z.to_s}
70
+ sq << {:name => x[1].to_s, :original_str => original_str || line.strip, :true_str => x[2].to_s, :virtual_str => x[3].to_s, :true => {}, :virtual => {}, :balance => {},
71
+ :true_total => 0, :virtual_total => 0}
72
+ c=sq.last
73
+ people.each{|person| c[:true][person]=0;c[:virtual][person]=0;c[:balance][person]=0}
74
+
75
+ # parsing of true_str
76
+ c[:true_str].split(/\s+/).each{|y|
77
+ temp = y.match(/([\d\.]+)([A-Za-z]+)/)
78
+ if (person=people_abbreviations[temp[2].to_s.downcase]) != nil
79
+ c[:true][person] += temp[1].to_f
80
+ c[:true_total] += temp[1].to_f
81
+ else
82
+ puts "error: ambiguos or inexistent name: #{temp[2].to_s}"
83
+ exit
84
+ end
85
+ }
86
+
87
+ # parsing of virtual_str
88
+ if c[:virtual_str] =~ /\A\s*\Z/ then
89
+ c[:virtual].each_key{|person|c[:virtual][person] = c[:true_total]/people.length}
90
+ else
91
+ avoid = []
92
+ people_to_complete = []
93
+ complete_automatically = true
94
+ c[:virtual_str].split(/\s+/).each{|y|
95
+ if (temp = y.match(/([\+\-\d\.]*)([A-Za-z]+)/)) then
96
+ if (person=people_abbreviations[temp[2].to_s.downcase]) != nil
97
+ if temp[1].to_s == "" then
98
+ complete_automatically = false
99
+ people_to_complete << person
100
+ avoid << person
101
+ elsif temp[1].to_s[0,1] == '+'
102
+ c[:virtual][person] += temp[1].to_s[1..-1].to_f
103
+ c[:virtual_total] -= temp[1].to_f
104
+ elsif temp[1].to_s[0,1] == '-'
105
+ if temp[1].to_s == '-' then
106
+ c[:virtual][person] = 0
107
+ avoid << person
108
+ else
109
+ c[:virtual][person] -= temp[1].to_s[1..-1].to_f
110
+ c[:virtual_total] += temp[1].to_f
111
+ end
112
+ else
113
+ c[:virtual][person] += temp[1].to_f
114
+ c[:virtual_total] += temp[1].to_f
115
+ avoid << person
116
+ end
117
+ else
118
+ puts "error: ambiguos or inexistent name: #{temp[2].to_s}"
119
+ exit
120
+ end
121
+ end
122
+ }
123
+ if c[:virtual_total] > c[:true_total]
124
+ puts "error: Virtual total doesn't match.."
125
+ exit
126
+ end
127
+ if complete_automatically then
128
+ others = c[:virtual].map{|i,v|i}-avoid
129
+ others.each { |p|
130
+ c[:virtual][p] += (c[:true_total] - c[:virtual_total])/others.length
131
+ }
132
+ else
133
+ people_to_complete.each { |p|
134
+ c[:virtual][p] += (c[:true_total] - c[:virtual_total])/people_to_complete.length
135
+ }
136
+ end
137
+ end
138
+ c[:balance].each_key{|person|
139
+ c[:balance][person] = c[:true][person] - c[:virtual][person]
140
+ }
141
+ ### PRINT INTERMEDIATE RESULTS ###
142
+ if intermediate then
143
+ puts "==== #{c[:original_str].to_s} ===="
144
+ puts "true total: #{c[:true_total].to_s}, virtual_total: #{c[:virtual_total].to_s}"
145
+ mytable = table do |t|
146
+ t.headings = people.sort
147
+ t << c[:true].sort.map{|z|z[1] == 0 ? "" : "%.1f" % z[1]}
148
+ t << c[:virtual].sort.map{|z|z[1] == 0 ? "" : "%.1f" % z[1]}
149
+ t.add_separator
150
+ t << c[:balance].sort.map{|z|z[1] == 0 ? "" : "%.1f" % z[1]}
151
+ end
152
+ puts mytable
153
+ end
154
+ ###
155
+ end
156
+ }
157
+ ### PRINT FINAL RESULTS ###
158
+ final = {}
159
+ people.each{|person| final[person]=0;}
160
+ sq.each {|c|
161
+ c[:balance].each_pair{|person, value|
162
+ final[person] += value
163
+ }
164
+ }
165
+ final.each_pair {|person, value|
166
+ puts "#{person} \t #{value > 0 ? 'receives' : 'gives '} #{"%.1f" % value}"
167
+ }
168
+ end
169
+ end
data/moneybook.gemspec ADDED
@@ -0,0 +1,73 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{moneybook}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["luca cioria"]
12
+ s.date = %q{2011-01-10}
13
+ s.default_executable = %q{moneybook}
14
+ s.description = %q{keep track of money in a group}
15
+ s.email = %q{noreply@mail.com}
16
+ s.executables = ["moneybook"]
17
+ s.extra_rdoc_files = [
18
+ "LICENSE.txt",
19
+ "README.rdoc"
20
+ ]
21
+ s.files = [
22
+ ".document",
23
+ "Gemfile",
24
+ "Gemfile.lock",
25
+ "LICENSE.txt",
26
+ "README.rdoc",
27
+ "Rakefile",
28
+ "bin/moneybook",
29
+ "moneybook.gemspec",
30
+ "test/helper.rb",
31
+ "test/test_moneybook.rb"
32
+ ]
33
+ s.homepage = %q{http://github.com/vircheck/moneybook}
34
+ s.licenses = ["MIT"]
35
+ s.require_paths = ["lib"]
36
+ s.rubygems_version = %q{1.4.2}
37
+ s.summary = %q{keep track of money in a group}
38
+ s.test_files = [
39
+ "test/helper.rb",
40
+ "test/test_moneybook.rb"
41
+ ]
42
+
43
+ if s.respond_to? :specification_version then
44
+ s.specification_version = 3
45
+
46
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
47
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
48
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
49
+ s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
50
+ s.add_development_dependency(%q<rcov>, [">= 0"])
51
+ s.add_runtime_dependency(%q<terminal-table/import>, [">= 0"])
52
+ s.add_runtime_dependency(%q<commander/import>, [">= 0"])
53
+ s.add_runtime_dependency(%q<andand>, [">= 0"])
54
+ else
55
+ s.add_dependency(%q<shoulda>, [">= 0"])
56
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
57
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
58
+ s.add_dependency(%q<rcov>, [">= 0"])
59
+ s.add_dependency(%q<terminal-table/import>, [">= 0"])
60
+ s.add_dependency(%q<commander/import>, [">= 0"])
61
+ s.add_dependency(%q<andand>, [">= 0"])
62
+ end
63
+ else
64
+ s.add_dependency(%q<shoulda>, [">= 0"])
65
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
66
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
67
+ s.add_dependency(%q<rcov>, [">= 0"])
68
+ s.add_dependency(%q<terminal-table/import>, [">= 0"])
69
+ s.add_dependency(%q<commander/import>, [">= 0"])
70
+ s.add_dependency(%q<andand>, [">= 0"])
71
+ end
72
+ end
73
+
data/test/helper.rb ADDED
@@ -0,0 +1,18 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'test/unit'
11
+ require 'shoulda'
12
+
13
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
15
+ require 'moneybook'
16
+
17
+ class Test::Unit::TestCase
18
+ end
@@ -0,0 +1,7 @@
1
+ require 'helper'
2
+
3
+ class TestMoneybook < Test::Unit::TestCase
4
+ should "probably rename this file and start testing for real" do
5
+ flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,180 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: moneybook
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - luca cioria
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-01-10 00:00:00 +01:00
19
+ default_executable: moneybook
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ prerelease: false
23
+ name: shoulda
24
+ type: :development
25
+ version_requirements: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ hash: 3
31
+ segments:
32
+ - 0
33
+ version: "0"
34
+ requirement: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ prerelease: false
37
+ name: bundler
38
+ type: :development
39
+ version_requirements: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ hash: 23
45
+ segments:
46
+ - 1
47
+ - 0
48
+ - 0
49
+ version: 1.0.0
50
+ requirement: *id002
51
+ - !ruby/object:Gem::Dependency
52
+ prerelease: false
53
+ name: jeweler
54
+ type: :development
55
+ version_requirements: &id003 !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ~>
59
+ - !ruby/object:Gem::Version
60
+ hash: 7
61
+ segments:
62
+ - 1
63
+ - 5
64
+ - 2
65
+ version: 1.5.2
66
+ requirement: *id003
67
+ - !ruby/object:Gem::Dependency
68
+ prerelease: false
69
+ name: rcov
70
+ type: :development
71
+ version_requirements: &id004 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ hash: 3
77
+ segments:
78
+ - 0
79
+ version: "0"
80
+ requirement: *id004
81
+ - !ruby/object:Gem::Dependency
82
+ prerelease: false
83
+ name: terminal-table
84
+ type: :runtime
85
+ version_requirements: &id005 !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ hash: 3
91
+ segments:
92
+ - 0
93
+ version: "0"
94
+ requirement: *id005
95
+ - !ruby/object:Gem::Dependency
96
+ prerelease: false
97
+ name: commander
98
+ type: :runtime
99
+ version_requirements: &id006 !ruby/object:Gem::Requirement
100
+ none: false
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ hash: 3
105
+ segments:
106
+ - 0
107
+ version: "0"
108
+ requirement: *id006
109
+ - !ruby/object:Gem::Dependency
110
+ prerelease: false
111
+ name: andand
112
+ type: :runtime
113
+ version_requirements: &id007 !ruby/object:Gem::Requirement
114
+ none: false
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ hash: 3
119
+ segments:
120
+ - 0
121
+ version: "0"
122
+ requirement: *id007
123
+ description: keep track of money in a group
124
+ email: noreply@mail.com
125
+ executables:
126
+ - moneybook
127
+ extensions: []
128
+
129
+ extra_rdoc_files:
130
+ - LICENSE.txt
131
+ - README.rdoc
132
+ files:
133
+ - .document
134
+ - Gemfile
135
+ - Gemfile.lock
136
+ - LICENSE.txt
137
+ - README.rdoc
138
+ - Rakefile
139
+ - VERSION
140
+ - bin/moneybook
141
+ - moneybook.gemspec
142
+ - test/helper.rb
143
+ - test/test_moneybook.rb
144
+ has_rdoc: true
145
+ homepage: http://github.com/vircheck/moneybook
146
+ licenses:
147
+ - MIT
148
+ post_install_message:
149
+ rdoc_options: []
150
+
151
+ require_paths:
152
+ - lib
153
+ required_ruby_version: !ruby/object:Gem::Requirement
154
+ none: false
155
+ requirements:
156
+ - - ">="
157
+ - !ruby/object:Gem::Version
158
+ hash: 3
159
+ segments:
160
+ - 0
161
+ version: "0"
162
+ required_rubygems_version: !ruby/object:Gem::Requirement
163
+ none: false
164
+ requirements:
165
+ - - ">="
166
+ - !ruby/object:Gem::Version
167
+ hash: 3
168
+ segments:
169
+ - 0
170
+ version: "0"
171
+ requirements: []
172
+
173
+ rubyforge_project:
174
+ rubygems_version: 1.4.2
175
+ signing_key:
176
+ specification_version: 3
177
+ summary: keep track of money in a group
178
+ test_files:
179
+ - test/helper.rb
180
+ - test/test_moneybook.rb