Skip to content

Commit

Permalink
Add text file input
Browse files Browse the repository at this point in the history
  • Loading branch information
brunetton committed Jul 30, 2015
1 parent 57a3fb3 commit 8ecc683
Show file tree
Hide file tree
Showing 8 changed files with 131 additions and 21 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Changelog

## 1.2 - 30/07/2015
Add text file format

## 1.1 - 02/06/2015
Add possibility to visually separate datas in "sub-arrays" in OpenOffice document (look at sample2.ods)

Expand Down
33 changes: 26 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,36 @@ The table looks like this :

## Usage

### Create the LibreOffice document
Expenses are given in a file. This file can be :
* a simple text file in a defined format (.txt)
* an OpenOffice Spreadsheet document (.ods document)

In order to pass this array of datas to the program, we use an ODS (LIbreOffice calc, OpenOffice calc, ...) that containts :
* members list
* this array of expenses
### Create the input document

You can open and modify the existing `sample.ods` file.
Depending on file format you want to use, you can use LibreOffice calc, OpenOffice calc for spreadsheet documents, or a simple text editor for text format (more simple on a smartphone in hollydays).

### Edit config file
You can open and modify the existing `sample.txt` or `sample.ods` files.

You can edit config.yml to let the program to find "who paid ?", "How much ?", "For who ?" and "What for ?" coulumns.
#### Text file example

Here is the `sample.txt` file you can find in project:

Participants: Penny, Sheldon, Leonard, Rajesh

## Day 1
- Sheldon 132 2 packbags [Leonard, Penny]
- Leonard 32 bad restaurant
- Penny 23 watter bottle airport [Sheldon]
- Leonard 50 good restaurant
## Day 2
- Penny 33 tour effeil Visit [Leonard, Rajesh, Penny]
- Rajesh 3 toilets for Sheldon [Sheldon]
- Rajesh 6,5 bus tickets
- Leonard 43 restaurant

### Edit config file (for ODS format)

If you use ODS file, you can edit config.yml to let the program to find "who paid ?", "How much ?", "For who ?" and "What for ?" coulumns (if not using defaults values).

### Lunch program and get results

Expand Down
24 changes: 18 additions & 6 deletions comptes
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,18 @@ require "docopt"
require 'pp'

require_relative 'oo_reader'
require_relative 'txt_reader'
require_relative 'comptes'
require_relative 'depenses'

doc = <<DOCOPT
Usage: #{__FILE__} <fichier_comptes.ods> [-c <config_file>]
Usage: #{__FILE__} <input_file> [-c <config_file>]
Options:
-c --config Config file to use
Input file can be OpenOffice Spreadsheet file (.ods), or text file (.txt).
See examples for more about format.
DOCOPT

begin
Expand All @@ -24,10 +28,10 @@ rescue Docopt::Exit => e
end


# Test Ods file existence
ods_file = docopt['<fichier_comptes.ods>']
unless File.exists?(ods_file)
puts "#{ods_file} n'existe pas"
# Test file existence
input_file = docopt['<input_file>']
unless File.exists?(input_file)
puts "#{input_file} doesn't exists"
exit 1
end

Expand All @@ -36,7 +40,15 @@ config_file = docopt['--config'] ? docopt['<config_file>'] : 'config.yml'
conf = YAML.load_file(config_file)

# Solving
o = OoReader.new(ods_file, conf)
if input_file.end_with?('.ods')
o = OoReader.new(input_file, conf)
elsif input_file.end_with?('.txt')
o = TxtReader.new(input_file, conf)
else
puts "#{input_file}: unknown file extension. Must be '.txt' or '.ods'."
exit 2
end

Comptes.affichage_probleme(o)

resultat = Comptes.calcul_dettes(o, conf['transfers_priorities_order'])
Expand Down
6 changes: 4 additions & 2 deletions comptes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ def almost_zero?(precision)
class Comptes

def self.affichage_probleme(oo_reader)
puts "Dépenses :" + (oo_reader.nb_tableaux_parse > 1 ? " (#{oo_reader.nb_tableaux_parse} sous tableaux trouvés)" : '')
print "Dépenses :"
print " (#{oo_reader.nb_tableaux_parse} sous tableaux trouvés)" if oo_reader.nb_tableaux_parse and oo_reader.nb_tableaux_parse > 1
print "\n"
puts oo_reader.depenses
end

Expand Down Expand Up @@ -54,7 +56,7 @@ def self.calcul_dettes(depenses, payers_order=nil, precision=0.001)
# Checking param type
if depenses.class == Depenses
# nop
elsif depenses.class == OoReader
elsif depenses.class < FileReader
depenses = depenses.depenses
else
raise "type de donnée inconnue pour les dépenses : #{depenses.class}"
Expand Down
10 changes: 10 additions & 0 deletions file_reader.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# -*- encoding : utf-8 -*-

class FileReader

attr_accessor :filename
attr_accessor :participants
attr_accessor :nb_tableaux_parse
attr_accessor :depenses

end
8 changes: 2 additions & 6 deletions oo_reader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,11 @@
require 'matrix'

require_relative 'depenses'
require_relative 'file_reader'

class OoReader
class OoReader < FileReader

attr_accessor :filename
attr_accessor :contenu_xml
attr_accessor :participants
attr_accessor :nb_tableaux_parse # Nombre de sous tableaux trouvés

attr_accessor :depenses

# config : {
# 'texte_participants' => 'Participants :',
Expand Down
12 changes: 12 additions & 0 deletions sample.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Participants: Penny, Sheldon, Leonard, Rajesh

## Day 1
- Sheldon 132 2 packbags [Leonard, Penny]
- Leonard 32 bad restaurant
- Penny 23 watter bottle airport [Sheldon]
- Leonard 50 good restaurant
## Day 2
- Penny 33 tour effeil Visit [Leonard, Rajesh, Penny]
- Rajesh 3 toilets for Sheldon [Sheldon]
- Rajesh 6,5 bus tickets
- Leonard 43 restaurant
56 changes: 56 additions & 0 deletions txt_reader.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# -*- encoding : utf-8 -*-
require 'rubygems'
# require 'matrix'

require_relative 'depenses'
require_relative 'file_reader'

class TxtReader < FileReader

def initialize(filename, config)
@filename = filename
parse
end

protected

def parse
@participants = nil
f = File.open(filename, "r")

# Scan for participants
while true
line = f.gets
if line.nil?
# end of reached without finding participants ?
raise 'participants list not found in file'
break
end
if line.match(/^Participants:\s*([\w-]+(\s*,\s*[\w-]+)*)/)
@participants = $1.scan(/[\w-]+/)
break
end
end

# Scan for expenses
@depenses = Depenses.new(@participants)
while line = f.gets
next if line[0] == '#' or line.strip.empty? # Ignore commented lines
if line.match(/^\s*[-*]\s*([\w-]+)\s+(\d+([\.,]\d+)?)\s+([^\[\]]+)\s+(\[([\w-]+)(\s*,\s*[\w-]+)*\])?/)
# Match something like "- Chris 4.5 tickets for boat [Bruno, Chris]"
payer = $1
amount = to_f($2)
why = $4
concerned_persons = $5 ? $5.scan(/[\w-]+/) : :tous
@depenses.ajouter_depense(payer, amount, concerned_persons, why)
else
raise "Unparsed line: #{line}"
end
end
end

def to_f(str)
return str.tr(',','.').to_f
end

end

0 comments on commit 8ecc683

Please sign in to comment.