#!/usr/bin/en perl # The MIT License (MIT) # # Copyright (c) 2011-2015 Ismaël Bouya http://www.normalesup.org/~bouya/ # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. use Switch; use strict; my $file = "comptes.data"; my @actions=('Ajouter un participant'); my %participants = (); my @transactions = (); my @descriptions = (); my $evenement_def; my $remboursements = ""; if($#ARGV==0) { open FILE, $ARGV[0] || die "Impossible de lire le fichier"; $evenement_def = ; chomp($evenement_def); while(my $noms = ) { if($noms eq "\n") { last; } my ($numero,$nom) = split(/ /,$noms,2); chomp($nom); $participants{$nom} = $numero; } while(my $transaction = ) { if($transaction eq "\n") { last; } chomp($transaction); push(@transactions,$transaction); my $description = ; chomp($description); push(@descriptions,$description); } $file = $ARGV[0]; } GLOBALE: while(1) { if(keys(%participants)>0) { $actions[1]="Ajouter une dépense"; $actions[2]="Enregistrer"; } if(scalar(@transactions)>0) { $actions[3]="Voir les dépenses de quelqu'un"; $actions[2]="Enregistrer"; $actions[4]="Equilibrage"; $actions[5]="Voir une transaction"; } my $action; while(1) { my $i = 1; my $var; my @vart = ( @actions, 'Sortir' ); my $message = ''; foreach $var ( @vart ) { $message .= $i++.') '.$var."\n"; } print $message; $var = ; chop($var); if(/\D/ || $var < 1 || $var > $i) { print "Mauvaise entrée\n"; next; } $action = $vart[$var-1]; last; } switch ($action) { case "Ajouter un participant" { print "Nom du participant\n"; my $participant = ; chomp($participant); $participants{$participant} = keys(%participants)+1; } case "Ajouter une dépense" { print "Qui a payé ?\n"; my $paye; while(1) { my $i = 1; my $var; my @vart = ( keys(%participants), "Annuler" ); foreach $var ( @vart ) { print $i++.') '.$var."\n"; } $var = ; chop($var); if(/\D/ || $var < 1 || $var > $i) { print "Mauvaise entrée\n"; next; } $paye = $vart[$var-1]; last; } if($paye eq "Annuler") { next GLOBALE; } print "Quoi ?\n"; my $description = ; chomp($description); print "Combien ?\n"; my $prix = ; chomp($prix); print "Pour qui ?\n"; my $repartition = ""; my $total_parts = 0; DESTS: while(1) { my $dest; while(1) { my $i = 1; my $var; my @vart = ( keys(%participants), "Ajouter à tous", "Fini" ); foreach $var ( @vart ) { print $i++.') '.$var."\n"; } $var = ; chop($var); if(/\D/ || $var < 1 || $var > $i) { print "Mauvaise entrée\n"; next; } $dest = $vart[$var-1]; last; } switch($dest) { case "Fini" { if($repartition eq "") { print "Annulé\n"; } elsif($total_parts == 0) { print "Le nombre total de parts est nul, il faut en ajouter !\n"; next DESTS; } else { push(@transactions, $participants{$paye}.' '.$prix.$repartition); push(@descriptions, $description); } last DESTS; } case "Ajouter à tous" { print "Nombre de parts ?\n"; my $parts = ; chomp($parts); if(!($parts == 0)) { foreach my $participant (keys(%participants)) { $repartition .= ' '.$participants{$participant}.':'.scalar($parts); $total_parts += scalar($parts); } } } else { print "Nombre de parts ?\n"; my $parts = ; chomp($parts); if(!($parts == 0)) { $repartition .= ' '.$participants{$dest}.':'.scalar($parts); $total_parts += scalar($parts); } } } } } case "Voir les dépenses de quelqu'un" { my $personne; while(1) { my $i = 1; my $var; my @vart = ( keys(%participants), "Annuler" ); foreach $var ( @vart ) { print $i++.') '.$var."\n"; } $var = ; chop($var); if(/\D/ || $var < 1 || $var > $i) { print "Mauvaise entrée\n"; next; } $personne = $vart[$var-1]; last; } if($personne eq "Annuler") { next GLOBALE; } my $depenses = 0; my $frais = 0; foreach my $transaction (@transactions) { my @table_trans = split(/ /,$transaction); my $payeur = shift(@table_trans); my $prix = shift(@table_trans); if($payeur == $participants{$personne}) { $depenses += $prix; } my $parts = 0; my $frac = 0; my $repartition; foreach $repartition (@table_trans) { my ($pers,$part) = split(/:/,$repartition); if($pers == $participants{$personne}) { $frac += $part; } $parts += $part; } $frais += $prix*$frac/$parts; } print $personne." a payé ".$depenses." EUR\n"; print "et a pour ".sprintf("%.2f",$frais)." EUR de frais au total.\n"; print "Il a donc un solde de ".sprintf("%.2f",$depenses-$frais)." EUR\n"; my $pause = ; } case "Voir une transaction" { my $transaction; while(1) { my $i = 1; my $var; my @vart = ( @descriptions, "Annuler" ); foreach $var ( @vart ) { print $i++.') '.$var."\n"; } $var = ; chop($var); if(/\D/ || $var < 1 || $var > $i) { print "Mauvaise entrée\n"; next; } $transaction = $var-1; last; } my @table_trans = split(/ /,$transactions[$transaction]); my $payeur = shift(@table_trans); my $prix = shift(@table_trans); my $Tparts = 0; my $repartition; my %parts; foreach my $pers (keys(%participants)) { if($payeur == $participants{$pers}) { print $descriptions[$transaction]." (payé par ".$pers."), ".$prix." EUR\n"; last } } foreach $repartition (@table_trans) { my ($pers,$part) = split(/:/,$repartition); $Tparts += $part; $parts{$pers} += $part; } foreach my $pers (keys(%participants)) { if(!exists $parts{$participants{$pers}}) { next; } print $pers.", ".$parts{$participants{$pers}}." part(s), soit ". $prix*$parts{$participants{$pers}}/$Tparts." EUR\n"; } my $pause = ; } case "Enregistrer" { print "Nom de l'événement ?"; if(!($evenement_def eq "")) { print " [".$evenement_def."]"; } print "\n"; my $evenement = ; chomp($evenement); if($evenement eq "") { $evenement = $evenement_def; } open FILE, ">".$file; print FILE $evenement."\n"; my $key; foreach $key (keys(%participants)) { print FILE $participants{$key}." ".$key."\n"; } print FILE "\n"; for(my $i=0;$i; print "Y-a-t-il des remboursements plus aisés ?\n"; my $ouinon; while(1) { my $i = 1; my $var; my @vart = ( "Oui", "Non" ); foreach $var ( @vart ) { print $i++.') '.$var."\n"; } $var = ; chop($var); if(/\D/ || $var < 1 || $var > $i) { print "Mauvaise entrée\n"; next; } $ouinon = $vart[$var-1]; last; } AISE: while($ouinon eq "Oui") { print "Qui ?\n"; my $personne; while(1) { my $i = 1; my $var; my @vart = ( keys(%participants), "Fini" ); foreach $var ( @vart ) { print $i++.') '.$var."\n"; } $var = ; chop($var); if(/\D/ || $var < 1 || $var > $i) { print "Mauvaise entrée\n"; next; } $personne = $vart[$var-1]; last; } if($personne eq "Fini") { last AISE; } print "Avec qui ?\n"; my $personneb; while(1) { my $i = 1; my $var; my @vart = ( keys(%participants), "Annuler" ); foreach $var ( @vart ) { print $i++.') '.$var."\n"; } $var = ; chop($var); if(/\D/ || $var < 1 || $var > $i) { print "Mauvaise entrée\n"; next; } $personneb = $vart[$var-1]; last; } if($personneb eq "Annuler") { next AISE; } if($Tsolde{$personne}*$Tsolde{$personneb}<0) { my $pers_inf = ($Tsolde{$personne}<0)?$personne:$personneb; my $pers_sup = ($Tsolde{$personne}>0)?$personne:$personneb; my $inf = (abs($Tsolde{$personne})0)?$personne:$personneb; my $val = abs($Tsolde{$personne}); $remboursements .= $pers_inf." doit ".$val." EUR à ".$pers_sup."\n"; $Tsolde{$pers_inf} += $val; $Tsolde{$pers_sup} -= $val; next COUPLE; } } REMB: while(1) { # On supprime les 0, et on fait deux hashs my %Tneg = (); my %Tpos = (); foreach my $personne (keys(%Tsolde)) { if($Tsolde{$personne} == 0) { delete $Tsolde{$personne}; } elsif($Tsolde{$personne} < 0) { $Tneg{$personne} = $Tsolde{$personne}; } elsif($Tsolde{$personne} > 0) { $Tpos{$personne} = $Tsolde{$personne}; } } if(keys(%Tneg) == 0) { last REMB; } foreach my $neg (sort { $Tneg{$a} cmp $Tneg{$b} } keys %Tneg) { my $max = 0; my $positif = 0; foreach my $pos (sort { $Tpos{$a} cmp $Tpos{$b} } keys %Tpos) { if($Tpos{$pos} + $Tneg{$neg}>0) { $positif = $pos; last; } $max = $pos; } if(!($max eq 0)) { $remboursements .= $neg." doit ".$Tsolde{$max}." EUR à ".$max."\n"; $Tsolde{$neg} += $Tsolde{$max}; delete $Tsolde{$max}; } else { $remboursements .= $neg." doit ".-$Tsolde{$neg}." EUR à ".$positif."\n"; $Tsolde{$positif} += $Tsolde{$neg}; delete $Tsolde{$neg}; } next REMB; } } print $remboursements; my $pause = ; } case "Sortir" { last GLOBALE; } } }