diff options
author | Ismaël Bouya <ismael.bouya@normalesup.org> | 2015-08-31 19:39:25 +0200 |
---|---|---|
committer | Ismaël Bouya <ismael.bouya@normalesup.org> | 2015-08-31 19:39:25 +0200 |
commit | c2590696efd0b91972c238ab892555f739751bc9 (patch) | |
tree | 6d5deb55dee05b863bffd05f29a952154d450ea9 | |
parent | df1c9d58185639bc3c413175b8fadd2545ae1e4b (diff) | |
download | Public-c2590696efd0b91972c238ab892555f739751bc9.tar.gz Public-c2590696efd0b91972c238ab892555f739751bc9.tar.zst Public-c2590696efd0b91972c238ab892555f739751bc9.zip |
Amélioration script comptes
-rwxr-xr-x | comptes | 895 |
1 files changed, 492 insertions, 403 deletions
@@ -1,4 +1,4 @@ | |||
1 | #!/usr/bin/en perl | 1 | #!/usr/bin/env perl |
2 | # The MIT License (MIT) | 2 | # The MIT License (MIT) |
3 | # | 3 | # |
4 | # Copyright (c) 2011-2015 Ismaël Bouya http://www.normalesup.org/~bouya/ | 4 | # Copyright (c) 2011-2015 Ismaël Bouya http://www.normalesup.org/~bouya/ |
@@ -31,416 +31,505 @@ my %participants = (); | |||
31 | my @transactions = (); | 31 | my @transactions = (); |
32 | my @descriptions = (); | 32 | my @descriptions = (); |
33 | my $evenement_def; | 33 | my $evenement_def; |
34 | my $remboursements = ""; | 34 | my @remboursements = (); |
35 | 35 | my %initiales = (); | |
36 | if($#ARGV==0) { | 36 | |
37 | open FILE, $ARGV[0] || die "Impossible de lire le fichier"; | 37 | if($#ARGV == 0) { |
38 | $evenement_def = <FILE>; | 38 | open FILE, $ARGV[0] || die "Impossible de lire le fichier"; |
39 | chomp($evenement_def); | 39 | $evenement_def = <FILE>; |
40 | while(my $noms = <FILE>) { | 40 | chomp($evenement_def); |
41 | if($noms eq "\n") { last; } | 41 | while(my $noms = <FILE>) { |
42 | my ($numero,$nom) = split(/ /,$noms,2); | 42 | if($noms eq "\n") { last; } |
43 | chomp($nom); | 43 | my ($numero,$nom) = split(/ /,$noms,2); |
44 | $participants{$nom} = $numero; | 44 | chomp($nom); |
45 | $participants{$nom} = $numero; | ||
46 | } | ||
47 | while(my $transaction = <FILE>) { | ||
48 | if($transaction eq "\n") { last; } | ||
49 | chomp($transaction); | ||
50 | push(@transactions,$transaction); | ||
51 | my $description = <FILE>; | ||
52 | chomp($description); | ||
53 | push(@descriptions,$description); | ||
54 | } | ||
55 | while(my $remboursement = <FILE>) { | ||
56 | if($remboursement eq "\n") { last; } | ||
57 | chomp($remboursement); | ||
58 | my @remb = split(/ /, $remboursement); | ||
59 | push(@remboursements,\@remb); | ||
60 | } | ||
61 | $file = $ARGV[0]; | ||
62 | } | ||
63 | |||
64 | sub choose_action { | ||
65 | my @actions = ('Ajouter un participant'); | ||
66 | my $action; | ||
67 | |||
68 | if (keys(%participants) > 0) { | ||
69 | $actions[1] = "Ajouter une dépense"; | ||
70 | $actions[2] = "Enregistrer"; | ||
71 | } | ||
72 | if(scalar(@transactions) > 0) { | ||
73 | $actions[2] = "Enregistrer"; | ||
74 | $actions[3] = "Voir les frais de quelqu'un (dépenses - dettes)"; | ||
75 | $actions[4] = "Voir les frais de tout le monde"; | ||
76 | $actions[5] = "Equilibrage"; | ||
77 | $actions[6] = "Voir une transaction"; | ||
78 | } | ||
79 | if(scalar(@remboursements) > 0) { | ||
80 | $actions[7] = "Afficher les remboursements"; | ||
81 | } | ||
82 | |||
83 | while(1) { | ||
84 | my $i = 1; | ||
85 | my $var; | ||
86 | my @vart = ( @actions, 'Sortir' ); | ||
87 | my $message = ''; | ||
88 | foreach $var ( @vart ) { | ||
89 | $message .= $i++.') '.$var."\n"; | ||
90 | } | ||
91 | print $message; | ||
92 | $var = <STDIN>; | ||
93 | chop($var); | ||
94 | if(/\D/ || $var < 1 || $var > $i) { | ||
95 | print "Mauvaise entrée\n"; | ||
96 | next; | ||
97 | } | ||
98 | $action = $vart[$var-1]; | ||
99 | last; | ||
100 | } | ||
101 | |||
102 | return $action; | ||
103 | } | ||
104 | |||
105 | sub pp { | ||
106 | my ($price, $noteur) = @_; | ||
107 | |||
108 | if (!$noteur) { | ||
109 | return sprintf("%.2f", $price)." EUR"; | ||
110 | } else { | ||
111 | return sprintf("%.2f", $price); | ||
112 | } | ||
113 | } | ||
114 | |||
115 | sub compute_initiales { | ||
116 | %initiales = (); | ||
117 | } | ||
118 | |||
119 | sub add_participant { | ||
120 | print "Nom du participant ?\n"; | ||
121 | my $participant = <STDIN>; | ||
122 | chomp($participant); | ||
123 | $participant =~ s/\s/_/g; | ||
124 | $participants{$participant} = keys(%participants)+1; | ||
125 | compute_initiales(); | ||
126 | } | ||
127 | |||
128 | sub select_menu { | ||
129 | my (@vart) = @_; | ||
130 | while(1) { | ||
131 | my $i = 1; | ||
132 | my $var; | ||
133 | foreach $var ( @vart ) { | ||
134 | print $i++.') '.$var."\n"; | ||
135 | } | ||
136 | $var = <STDIN>; | ||
137 | chop($var); | ||
138 | if(/\D/ || $var < 1 || $var > scalar @vart) { | ||
139 | print "Mauvaise entrée\n"; | ||
140 | next; | ||
45 | } | 141 | } |
46 | while(my $transaction = <FILE>) { | 142 | return $vart[$var-1]; |
47 | if($transaction eq "\n") { last; } | 143 | } |
48 | chomp($transaction); | 144 | } |
49 | push(@transactions,$transaction); | 145 | |
50 | my $description = <FILE>; | 146 | sub select_participant { |
51 | chomp($description); | 147 | my ($annuler, @supplementaires) = @_; |
52 | push(@descriptions,$description); | 148 | while(1) { |
149 | my $i = 1; | ||
150 | my $var; | ||
151 | my @vart = ( keys(%participants), @supplementaires, ($annuler) ); | ||
152 | foreach $var ( @vart ) { | ||
153 | print $i++.') '.$var."\n"; | ||
53 | } | 154 | } |
54 | $file = $ARGV[0]; | 155 | $var = <STDIN>; |
156 | chop($var); | ||
157 | if(/\D/ || $var < 1 || $var > scalar @vart) { | ||
158 | print "Mauvaise entrée\n"; | ||
159 | next; | ||
160 | } | ||
161 | if ($var != scalar @vart) { | ||
162 | return $vart[$var-1]; | ||
163 | } else { | ||
164 | return; | ||
165 | } | ||
166 | } | ||
167 | } | ||
168 | |||
169 | sub select_transaction { | ||
170 | my $transaction; | ||
171 | while(1) { | ||
172 | my $i = 1; | ||
173 | my $var; | ||
174 | my @vart = ( @descriptions, "Annuler" ); | ||
175 | foreach $var ( @vart ) { | ||
176 | print $i++.') '.$var."\n"; | ||
177 | } | ||
178 | $var = <STDIN>; | ||
179 | chop($var); | ||
180 | if(/\D/ || $var < 1 || $var > $i) { | ||
181 | print "Mauvaise entrée\n"; | ||
182 | next; | ||
183 | } | ||
184 | $transaction = $var-1; | ||
185 | last; | ||
186 | } | ||
187 | |||
188 | my ($payeur, $prix, $total_parts, $split, $parts) = &parse_transaction($transactions[$transaction]); | ||
189 | return ($descriptions[$transaction], $payeur, $prix, $total_parts, $split, $parts); | ||
190 | } | ||
191 | |||
192 | sub add_transaction { | ||
193 | print "Qui a payé ?\n"; | ||
194 | my $paye = select_participant("Annuler"); | ||
195 | if(!$paye) { | ||
196 | print "Annulé"; | ||
197 | return; | ||
198 | } | ||
199 | print "Quoi ?\n"; | ||
200 | my $description = <STDIN>; | ||
201 | chomp($description); | ||
202 | print "Combien ?\n"; | ||
203 | my $prix = <STDIN>; | ||
204 | chomp($prix); | ||
205 | print "Pour qui ?\n"; | ||
206 | my $repartition = ""; | ||
207 | my $total_parts = 0; | ||
208 | DESTS: while(1) { | ||
209 | my $dest = select_participant("Fini", "Ajouter à tous"); | ||
210 | switch($dest) { | ||
211 | case undef { | ||
212 | if($repartition eq "") { | ||
213 | print "Annulé\n"; | ||
214 | return; | ||
215 | } | ||
216 | elsif($total_parts == 0) { | ||
217 | print "Le nombre total de parts est nul, il faut en ajouter !\n"; | ||
218 | next DESTS; | ||
219 | } | ||
220 | else { | ||
221 | push(@transactions, $participants{$paye}.' '.$prix.$repartition); | ||
222 | push(@descriptions, $description); | ||
223 | return; | ||
224 | } | ||
225 | } | ||
226 | case "Ajouter à tous" { | ||
227 | print "Nombre de parts ?\n"; | ||
228 | my $parts = <STDIN>; | ||
229 | chomp($parts); | ||
230 | if(!($parts == 0)) { | ||
231 | foreach my $participant (keys(%participants)) { | ||
232 | $repartition .= ' '.$participants{$participant}.':'.scalar($parts); | ||
233 | $total_parts += scalar($parts); | ||
234 | } | ||
235 | } | ||
236 | } | ||
237 | else { | ||
238 | print "Nombre de parts ?\n"; | ||
239 | my $parts = <STDIN>; | ||
240 | chomp($parts); | ||
241 | if(!($parts == 0)) { | ||
242 | $repartition .= ' '.$participants{$dest}.':'.scalar($parts); | ||
243 | $total_parts += scalar($parts); | ||
244 | } | ||
245 | } | ||
246 | } | ||
247 | } | ||
248 | } | ||
249 | |||
250 | sub find_participant { | ||
251 | my ($participant_number) = @_; | ||
252 | |||
253 | foreach my $name (keys(%participants)) { | ||
254 | if ($participant_number == $participants{$name}) { | ||
255 | return $name; | ||
256 | } | ||
257 | } | ||
258 | } | ||
259 | |||
260 | sub parse_transaction { | ||
261 | my ($transaction) = @_; | ||
262 | my @table_trans = split(/ /,$transaction); | ||
263 | |||
264 | my $payeur = shift(@table_trans); | ||
265 | $payeur = find_participant($payeur); | ||
266 | my $prix = shift(@table_trans); | ||
267 | my %parts; | ||
268 | my %split; | ||
269 | my $total_parts = 0; | ||
270 | foreach my $repartition (@table_trans) { | ||
271 | my ($participant, $part) = split(/:/, $repartition); | ||
272 | $participant = find_participant($participant); | ||
273 | $parts{$participant} ||= 0; | ||
274 | $parts{$participant} += $part; | ||
275 | $total_parts += $part; | ||
276 | } | ||
277 | if (!$parts{$payeur}) { | ||
278 | $parts{$payeur} = 0; | ||
279 | } | ||
280 | foreach my $participant (keys(%parts)) { | ||
281 | $split{$participant} = - ($parts{$participant} * $prix) / $total_parts; | ||
282 | if ($participant eq $payeur) { | ||
283 | $split{$participant} += $prix; | ||
284 | } | ||
285 | } | ||
286 | |||
287 | return ($payeur, $prix, $total_parts, \%split, \%parts); | ||
288 | } | ||
289 | |||
290 | sub max_length { | ||
291 | my (@strings) = @_; | ||
292 | my @string_lengths = sort { length($a) <=> length($b) } @strings; | ||
293 | return length($string_lengths[-1]); | ||
294 | } | ||
295 | |||
296 | sub list_transactions_for_participants { | ||
297 | my (@participants) = @_; | ||
298 | my $one_participant = 0; | ||
299 | if (scalar @participants == 0) { | ||
300 | @participants = keys(%participants); | ||
301 | } | ||
302 | if (scalar @participants == 1) { | ||
303 | $one_participant = 1; | ||
304 | } | ||
305 | |||
306 | my %depenses; | ||
307 | my %solde; | ||
308 | |||
309 | my @zipped = map {($transactions[$_], $descriptions[$_])} (0 .. $#descriptions); | ||
310 | while (scalar(@zipped) > 0) { | ||
311 | my $transaction = shift @zipped; | ||
312 | my $description = shift @zipped; | ||
313 | my ($payeur, $prix, $total_parts, $parsed_transaction, $parts) = &parse_transaction($transaction); | ||
314 | $depenses{$payeur} ||= 0; | ||
315 | $depenses{$payeur} += $prix; | ||
316 | |||
317 | my @intersection = grep( $parsed_transaction->{$_}, @participants); | ||
318 | if (scalar @intersection) { | ||
319 | my $phantom = " " x length($description.":"); | ||
320 | my $max_participant_length = max_length(@intersection); | ||
321 | |||
322 | print $description.":"; | ||
323 | foreach my $participant (@intersection) { | ||
324 | $solde{$participant} ||= 0; | ||
325 | $solde{$participant} += $parsed_transaction->{$participant}; | ||
326 | |||
327 | if ($one_participant) { | ||
328 | print " ".pp($parsed_transaction->{$participant}); | ||
329 | if ($payeur eq $participant) { | ||
330 | print " (a payé, ".pp($prix).")"; | ||
331 | } | ||
332 | print "\n"; | ||
333 | } else { | ||
334 | my $participant_padding = " " x ($max_participant_length - length($participant)); | ||
335 | print " ".$participant.$participant_padding." ".pp($parsed_transaction->{$participant}); | ||
336 | if ($payeur eq $participant) { | ||
337 | print " (a payé, ".pp($prix).")"; | ||
338 | } | ||
339 | print "\n".$phantom; | ||
340 | } | ||
341 | } | ||
342 | if (!$one_participant) { | ||
343 | print "\n"; | ||
344 | } | ||
345 | } | ||
346 | } | ||
347 | |||
348 | foreach my $personne (@participants) { | ||
349 | my $d = $depenses{$personne} || 0; | ||
350 | my $s = $solde{$personne} || 0; | ||
351 | if ($d) { | ||
352 | print $personne." a payé ".pp($d); | ||
353 | } else { | ||
354 | print $personne." n'a rien payé"; | ||
355 | } | ||
356 | if ($s) { | ||
357 | print " et a pour ".pp($d - $s)." de frais au total.\n"; | ||
358 | } else { | ||
359 | print " et n'a pas eu de frais.\n"; | ||
360 | } | ||
361 | print $personne." a donc un solde de ".pp($s)."\n"; | ||
362 | } | ||
363 | } | ||
364 | |||
365 | sub compute_equity { | ||
366 | my %depenses; | ||
367 | my %frais; | ||
368 | my %soldes; | ||
369 | foreach my $transaction (@transactions) { | ||
370 | my ($payeur, $prix, $total_parts, $split, $parts) = &parse_transaction($transaction); | ||
371 | $depenses{$payeur} += $prix; | ||
372 | |||
373 | foreach my $personne (keys(%{$split})) { | ||
374 | $soldes{$personne} += $split->{$personne}; | ||
375 | } | ||
376 | } | ||
377 | foreach my $personne (keys(%soldes)) { | ||
378 | $frais{$personne} = $depenses{$personne} - $soldes{$personne}; | ||
379 | } | ||
380 | |||
381 | return (\%depenses, \%frais, \%soldes); | ||
382 | } | ||
383 | |||
384 | sub delete_zeros { | ||
385 | my ($soldes, @participants) = @_; | ||
386 | |||
387 | foreach my $participant (@participants) { | ||
388 | delete $soldes->{$participant} if pp($soldes->{$participant}, 1) == 0; | ||
389 | } | ||
390 | } | ||
391 | |||
392 | sub compute_reimbursment { | ||
393 | my ($a, $b, $soldes) = @_; | ||
394 | my $s_a = $soldes->{$a}; | ||
395 | my $s_b = $soldes->{$b}; | ||
396 | |||
397 | return if (pp($s_a, 1) * pp($s_b, 1) >= 0); | ||
398 | my $debtor = pp($s_a, 1) < 0 ? $a : $b; | ||
399 | my $creditor = pp($s_a, 1) > 0 ? $a : $b; | ||
400 | my $exchange = (abs($s_a) < abs($s_b)) ? abs($s_a) : abs($s_b); | ||
401 | |||
402 | my @remboursement = ($debtor, $creditor, $exchange); | ||
403 | push @remboursements, \@remboursement; | ||
404 | $soldes->{$creditor} -= $exchange; | ||
405 | $soldes->{$debtor} += $exchange; | ||
406 | delete_zeros($soldes, $a, $b); | ||
407 | } | ||
408 | |||
409 | sub select_exchange_couple { | ||
410 | my ($soldes) = @_; | ||
411 | my $bd; # biggest debtor | ||
412 | my $sc; # smallest creditor | ||
413 | |||
414 | foreach my $p (keys(%{$soldes})) { | ||
415 | $bd = $p if $soldes->{$p} < 0 && (!$bd || $soldes->{$p} < $soldes->{$bd}); | ||
416 | $sc = $p if $soldes->{$p} > 0 && (!$sc || $soldes->{$p} < $soldes->{$sc}); | ||
417 | } | ||
418 | |||
419 | return ($bd, $sc); | ||
420 | } | ||
421 | |||
422 | sub print_remboursements { | ||
423 | foreach my $remboursement (@remboursements) { | ||
424 | my ($debtor, $creditor, $exchange) = (@{$remboursement}); | ||
425 | print $debtor." doit ".pp($exchange)." à ".$creditor."\n"; | ||
426 | } | ||
427 | my $pause = <STDIN>; | ||
55 | } | 428 | } |
56 | 429 | ||
57 | GLOBALE: while(1) { | 430 | GLOBALE: while(1) { |
58 | if(keys(%participants)>0) { | 431 | my $action = choose_action(); |
59 | $actions[1]="Ajouter une dépense"; | 432 | switch ($action) { |
60 | $actions[2]="Enregistrer"; | 433 | case "Ajouter un participant" { |
434 | add_participant(); | ||
435 | } | ||
436 | case "Ajouter une dépense" { | ||
437 | add_transaction(); | ||
438 | } | ||
439 | case "Voir les frais de quelqu'un (dépenses - dettes)" { | ||
440 | my $personne = select_participant("Annuler"); | ||
441 | if(!$personne) { | ||
442 | next GLOBALE; | ||
443 | } | ||
444 | list_transactions_for_participants(($personne)); | ||
445 | my $pause = <STDIN>; | ||
446 | } | ||
447 | case "Voir les frais de tout le monde" { | ||
448 | list_transactions_for_participants(keys(%participants)); | ||
449 | my $pause = <STDIN>; | ||
61 | } | 450 | } |
62 | if(scalar(@transactions)>0) { | 451 | case "Voir une transaction" { |
63 | $actions[3]="Voir les dépenses de quelqu'un"; | 452 | my ($description, $payeur, $prix, $total_parts, $split, $parts) = select_transaction(); |
64 | $actions[2]="Enregistrer"; | 453 | print $description." (payé par ".$payeur."), ".pp($prix)."\n"; |
65 | $actions[4]="Equilibrage"; | 454 | foreach my $pers (keys(%{$split})) { |
66 | $actions[5]="Voir une transaction"; | 455 | print $pers.", ".$parts->{$pers}." part(s), soit ". pp($split->{$pers}); |
456 | if ($pers eq $payeur) { | ||
457 | print " (".pp($prix)." - ".pp($prix - $split->{$pers}).")"; | ||
458 | } | ||
459 | print "\n"; | ||
460 | } | ||
67 | } | 461 | } |
462 | case "Enregistrer" { | ||
463 | print "Nom de l'événement ?"; | ||
464 | if(!($evenement_def eq "")) { | ||
465 | print " [".$evenement_def."]"; | ||
466 | } | ||
467 | print "\n"; | ||
468 | my $evenement = <STDIN>; | ||
469 | chomp($evenement); | ||
470 | if($evenement eq "") { | ||
471 | $evenement = $evenement_def; | ||
472 | } | ||
473 | open FILE, ">".$file; | ||
474 | print FILE $evenement."\n"; | ||
475 | my $key; | ||
476 | foreach $key (keys(%participants)) { | ||
477 | print FILE $participants{$key}." ".$key."\n"; | ||
478 | } | ||
479 | print FILE "\n"; | ||
480 | for(my $i=0;$i<scalar(@transactions);$i++) { | ||
481 | print FILE $transactions[$i]."\n"; | ||
482 | print FILE $descriptions[$i]."\n"; | ||
483 | } | ||
484 | print FILE "\n"; | ||
485 | foreach my $remboursement (@remboursements) { | ||
486 | print FILE join(" ", @{$remboursement})."\n"; | ||
487 | } | ||
488 | close FILE; | ||
489 | } | ||
490 | case "Equilibrage" { | ||
491 | my ($depenses, $frais, $soldes) = compute_equity(); | ||
492 | @remboursements = (); | ||
493 | |||
494 | foreach my $personne (keys(%participants)) { | ||
495 | print $personne." a un solde de ".pp($soldes->{$personne})." (+" . pp($depenses->{$personne}). " / -". pp($frais->{$personne}) . ")\n"; | ||
496 | } | ||
497 | my $pause = <STDIN>; | ||
498 | print "Y-a-t-il des remboursements plus aisés ?\n"; | ||
499 | my $ouinon = select_menu("Oui", "Non"); | ||
68 | 500 | ||
69 | my $action; | 501 | AISE: while($ouinon eq "Oui") { |
70 | while(1) { | 502 | print "Qui ?\n"; |
71 | my $i = 1; | 503 | my $personnea = select_participant("Fini"); |
72 | my $var; | 504 | if(!$personnea) { last AISE; } |
73 | my @vart = ( @actions, 'Sortir' ); | 505 | print "Avec qui ?\n"; |
74 | my $message = ''; | 506 | my $personneb = select_participant("Annuler"); |
75 | foreach $var ( @vart ) { | 507 | if(!$personneb) { next AISE; } |
76 | $message .= $i++.') '.$var."\n"; | 508 | compute_reimbursment($personnea, $personneb, $soldes); |
77 | } | 509 | } |
78 | print $message; | 510 | # Une boucle pour détecter si on a des couples qui s'annulent mutuellement |
79 | $var = <STDIN>; | 511 | delete_zeros($soldes, keys(%{$soldes})); |
80 | chop($var); | 512 | COUPLE: foreach my $personnea (keys(%participants)) { |
81 | if(/\D/ || $var < 1 || $var > $i) { | 513 | next if(pp($soldes->{$personnea}, 1) == 0); |
82 | print "Mauvaise entrée\n"; | 514 | foreach my $personneb (keys(%participants)) { |
83 | next; | 515 | next if (pp($soldes->{$personneb} + $soldes->{$personnea}, 1) != 0); |
84 | } | 516 | compute_reimbursment($personnea, $personneb, $soldes); |
85 | $action = $vart[$var-1]; | 517 | next COUPLE; |
86 | last; | 518 | } |
519 | } | ||
520 | REMB: while(1) { | ||
521 | last REMB if(keys(%{$soldes}) == 0); | ||
522 | |||
523 | my ($biggest_debtor, $smallest_creditor) = select_exchange_couple($soldes); | ||
524 | compute_reimbursment($biggest_debtor, $smallest_creditor, $soldes); | ||
525 | } | ||
526 | print_remboursements(); | ||
527 | } | ||
528 | case "Afficher les remboursements" { | ||
529 | print_remboursements(); | ||
87 | } | 530 | } |
88 | switch ($action) { | 531 | case "Sortir" { |
89 | case "Ajouter un participant" { | 532 | last GLOBALE; |
90 | print "Nom du participant\n"; | ||
91 | my $participant = <STDIN>; | ||
92 | chomp($participant); | ||
93 | $participants{$participant} = keys(%participants)+1; | ||
94 | } | ||
95 | case "Ajouter une dépense" { | ||
96 | print "Qui a payé ?\n"; | ||
97 | my $paye; | ||
98 | while(1) { | ||
99 | my $i = 1; | ||
100 | my $var; | ||
101 | my @vart = ( keys(%participants), "Annuler" ); | ||
102 | foreach $var ( @vart ) { | ||
103 | print $i++.') '.$var."\n"; | ||
104 | } | ||
105 | $var = <STDIN>; | ||
106 | chop($var); | ||
107 | if(/\D/ || $var < 1 || $var > $i) { | ||
108 | print "Mauvaise entrée\n"; | ||
109 | next; | ||
110 | } | ||
111 | $paye = $vart[$var-1]; | ||
112 | last; | ||
113 | } | ||
114 | if($paye eq "Annuler") { | ||
115 | next GLOBALE; | ||
116 | } | ||
117 | print "Quoi ?\n"; | ||
118 | my $description = <STDIN>; | ||
119 | chomp($description); | ||
120 | print "Combien ?\n"; | ||
121 | my $prix = <STDIN>; | ||
122 | chomp($prix); | ||
123 | print "Pour qui ?\n"; | ||
124 | my $repartition = ""; | ||
125 | my $total_parts = 0; | ||
126 | DESTS: while(1) { | ||
127 | my $dest; | ||
128 | while(1) { | ||
129 | my $i = 1; | ||
130 | my $var; | ||
131 | my @vart = ( keys(%participants), "Ajouter à tous", "Fini" ); | ||
132 | foreach $var ( @vart ) { | ||
133 | print $i++.') '.$var."\n"; | ||
134 | } | ||
135 | $var = <STDIN>; | ||
136 | chop($var); | ||
137 | if(/\D/ || $var < 1 || $var > $i) { | ||
138 | print "Mauvaise entrée\n"; | ||
139 | next; | ||
140 | } | ||
141 | $dest = $vart[$var-1]; | ||
142 | last; | ||
143 | } | ||
144 | switch($dest) { | ||
145 | case "Fini" { | ||
146 | if($repartition eq "") { print "Annulé\n"; } | ||
147 | elsif($total_parts == 0) { | ||
148 | print "Le nombre total de parts est nul, il faut en ajouter !\n"; | ||
149 | next DESTS; | ||
150 | } | ||
151 | else { | ||
152 | push(@transactions, $participants{$paye}.' '.$prix.$repartition); | ||
153 | push(@descriptions, $description); | ||
154 | } | ||
155 | last DESTS; | ||
156 | } | ||
157 | case "Ajouter à tous" { | ||
158 | print "Nombre de parts ?\n"; | ||
159 | my $parts = <STDIN>; | ||
160 | chomp($parts); | ||
161 | if(!($parts == 0)) { | ||
162 | foreach my $participant (keys(%participants)) { | ||
163 | $repartition .= ' '.$participants{$participant}.':'.scalar($parts); | ||
164 | $total_parts += scalar($parts); | ||
165 | } | ||
166 | } | ||
167 | } | ||
168 | else { | ||
169 | print "Nombre de parts ?\n"; | ||
170 | my $parts = <STDIN>; | ||
171 | chomp($parts); | ||
172 | if(!($parts == 0)) { | ||
173 | $repartition .= ' '.$participants{$dest}.':'.scalar($parts); | ||
174 | $total_parts += scalar($parts); | ||
175 | } | ||
176 | } | ||
177 | } | ||
178 | } | ||
179 | } | ||
180 | case "Voir les dépenses de quelqu'un" { | ||
181 | my $personne; | ||
182 | while(1) { | ||
183 | my $i = 1; | ||
184 | my $var; | ||
185 | my @vart = ( keys(%participants), "Annuler" ); | ||
186 | foreach $var ( @vart ) { | ||
187 | print $i++.') '.$var."\n"; | ||
188 | } | ||
189 | $var = <STDIN>; | ||
190 | chop($var); | ||
191 | if(/\D/ || $var < 1 || $var > $i) { | ||
192 | print "Mauvaise entrée\n"; | ||
193 | next; | ||
194 | } | ||
195 | $personne = $vart[$var-1]; | ||
196 | last; | ||
197 | } | ||
198 | if($personne eq "Annuler") { | ||
199 | next GLOBALE; | ||
200 | } | ||
201 | my $depenses = 0; | ||
202 | my $frais = 0; | ||
203 | foreach my $transaction (@transactions) { | ||
204 | my @table_trans = split(/ /,$transaction); | ||
205 | my $payeur = shift(@table_trans); | ||
206 | my $prix = shift(@table_trans); | ||
207 | if($payeur == $participants{$personne}) { | ||
208 | $depenses += $prix; | ||
209 | } | ||
210 | my $parts = 0; | ||
211 | my $frac = 0; | ||
212 | my $repartition; | ||
213 | foreach $repartition (@table_trans) { | ||
214 | my ($pers,$part) = split(/:/,$repartition); | ||
215 | if($pers == $participants{$personne}) { | ||
216 | $frac += $part; | ||
217 | } | ||
218 | $parts += $part; | ||
219 | } | ||
220 | $frais += $prix*$frac/$parts; | ||
221 | } | ||
222 | print $personne." a payé ".$depenses." EUR\n"; | ||
223 | print "et a pour ".sprintf("%.2f",$frais)." EUR de frais au total.\n"; | ||
224 | print "Il a donc un solde de ".sprintf("%.2f",$depenses-$frais)." EUR\n"; | ||
225 | my $pause = <STDIN>; | ||
226 | } | ||
227 | case "Voir une transaction" { | ||
228 | my $transaction; | ||
229 | while(1) { | ||
230 | my $i = 1; | ||
231 | my $var; | ||
232 | my @vart = ( @descriptions, "Annuler" ); | ||
233 | foreach $var ( @vart ) { | ||
234 | print $i++.') '.$var."\n"; | ||
235 | } | ||
236 | $var = <STDIN>; | ||
237 | chop($var); | ||
238 | if(/\D/ || $var < 1 || $var > $i) { | ||
239 | print "Mauvaise entrée\n"; | ||
240 | next; | ||
241 | } | ||
242 | $transaction = $var-1; | ||
243 | last; | ||
244 | } | ||
245 | my @table_trans = split(/ /,$transactions[$transaction]); | ||
246 | my $payeur = shift(@table_trans); | ||
247 | my $prix = shift(@table_trans); | ||
248 | my $Tparts = 0; | ||
249 | my $repartition; | ||
250 | my %parts; | ||
251 | foreach my $pers (keys(%participants)) { | ||
252 | if($payeur == $participants{$pers}) { | ||
253 | print $descriptions[$transaction]." (payé par ".$pers."), ".$prix." EUR\n"; | ||
254 | last | ||
255 | } | ||
256 | } | ||
257 | foreach $repartition (@table_trans) { | ||
258 | my ($pers,$part) = split(/:/,$repartition); | ||
259 | $Tparts += $part; | ||
260 | $parts{$pers} += $part; | ||
261 | } | ||
262 | foreach my $pers (keys(%participants)) { | ||
263 | if(!exists $parts{$participants{$pers}}) { | ||
264 | next; | ||
265 | } | ||
266 | print $pers.", ".$parts{$participants{$pers}}." part(s), soit ". $prix*$parts{$participants{$pers}}/$Tparts." EUR\n"; | ||
267 | } | ||
268 | my $pause = <STDIN>; | ||
269 | } | ||
270 | case "Enregistrer" { | ||
271 | print "Nom de l'événement ?"; | ||
272 | if(!($evenement_def eq "")) { | ||
273 | print " [".$evenement_def."]"; | ||
274 | } | ||
275 | print "\n"; | ||
276 | my $evenement = <STDIN>; | ||
277 | chomp($evenement); | ||
278 | if($evenement eq "") { | ||
279 | $evenement = $evenement_def; | ||
280 | } | ||
281 | open FILE, ">".$file; | ||
282 | print FILE $evenement."\n"; | ||
283 | my $key; | ||
284 | foreach $key (keys(%participants)) { | ||
285 | print FILE $participants{$key}." ".$key."\n"; | ||
286 | } | ||
287 | print FILE "\n"; | ||
288 | for(my $i=0;$i<scalar(@transactions);$i++) { | ||
289 | print FILE $transactions[$i]."\n"; | ||
290 | print FILE $descriptions[$i]."\n"; | ||
291 | } | ||
292 | print FILE "\n"; | ||
293 | print FILE $remboursements; | ||
294 | close FILE; | ||
295 | } | ||
296 | case "Equilibrage" { | ||
297 | my %Tdepenses = (); | ||
298 | my %Tfrais = (); | ||
299 | my %Tsolde = (); | ||
300 | $remboursements = ""; | ||
301 | foreach my $Ttransaction (@transactions) { | ||
302 | my @Ttable_trans = split(/ /,$Ttransaction); | ||
303 | my $Tpayeur = shift(@Ttable_trans); | ||
304 | my $Tprix = shift(@Ttable_trans); | ||
305 | $Tdepenses{$Tpayeur} = $Tdepenses{$Tpayeur} + $Tprix; | ||
306 | my $Tparts = 0; | ||
307 | my $Tfrac = 0; | ||
308 | my $Trepartition; | ||
309 | foreach $Trepartition (@Ttable_trans) { | ||
310 | my ($Tpers,$Tpart) = split(/:/,$Trepartition); | ||
311 | $Tparts += $Tpart; | ||
312 | } | ||
313 | foreach $Trepartition (@Ttable_trans) { | ||
314 | my ($Tpers,$Tpart) = split(/:/,$Trepartition); | ||
315 | $Tfrais{$Tpers} = $Tfrais{$Tpers} + $Tprix*$Tpart/$Tparts; | ||
316 | } | ||
317 | } | ||
318 | foreach my $Tpersonne (keys(%participants)) { | ||
319 | my $numero = $participants{$Tpersonne}; | ||
320 | $Tsolde{$Tpersonne} = sprintf("%.2f",$Tdepenses{$numero}-$Tfrais{$numero}); | ||
321 | print $Tpersonne." a un solde de ".$Tsolde{$Tpersonne}." EUR\n"; | ||
322 | } | ||
323 | my $pause = <STDIN>; | ||
324 | print "Y-a-t-il des remboursements plus aisés ?\n"; | ||
325 | my $ouinon; | ||
326 | while(1) { | ||
327 | my $i = 1; | ||
328 | my $var; | ||
329 | my @vart = ( "Oui", "Non" ); | ||
330 | foreach $var ( @vart ) { | ||
331 | print $i++.') '.$var."\n"; | ||
332 | } | ||
333 | $var = <STDIN>; | ||
334 | chop($var); | ||
335 | if(/\D/ || $var < 1 || $var > $i) { | ||
336 | print "Mauvaise entrée\n"; | ||
337 | next; | ||
338 | } | ||
339 | $ouinon = $vart[$var-1]; | ||
340 | last; | ||
341 | } | ||
342 | AISE: while($ouinon eq "Oui") { | ||
343 | print "Qui ?\n"; | ||
344 | my $personne; | ||
345 | while(1) { | ||
346 | my $i = 1; | ||
347 | my $var; | ||
348 | my @vart = ( keys(%participants), "Fini" ); | ||
349 | foreach $var ( @vart ) { | ||
350 | print $i++.') '.$var."\n"; | ||
351 | } | ||
352 | $var = <STDIN>; | ||
353 | chop($var); | ||
354 | if(/\D/ || $var < 1 || $var > $i) { | ||
355 | print "Mauvaise entrée\n"; | ||
356 | next; | ||
357 | } | ||
358 | $personne = $vart[$var-1]; | ||
359 | last; | ||
360 | } | ||
361 | if($personne eq "Fini") { last AISE; } | ||
362 | print "Avec qui ?\n"; | ||
363 | my $personneb; | ||
364 | while(1) { | ||
365 | my $i = 1; | ||
366 | my $var; | ||
367 | my @vart = ( keys(%participants), "Annuler" ); | ||
368 | foreach $var ( @vart ) { | ||
369 | print $i++.') '.$var."\n"; | ||
370 | } | ||
371 | $var = <STDIN>; | ||
372 | chop($var); | ||
373 | if(/\D/ || $var < 1 || $var > $i) { | ||
374 | print "Mauvaise entrée\n"; | ||
375 | next; | ||
376 | } | ||
377 | $personneb = $vart[$var-1]; | ||
378 | last; | ||
379 | } | ||
380 | if($personneb eq "Annuler") { next AISE; } | ||
381 | if($Tsolde{$personne}*$Tsolde{$personneb}<0) { | ||
382 | my $pers_inf = ($Tsolde{$personne}<0)?$personne:$personneb; | ||
383 | my $pers_sup = ($Tsolde{$personne}>0)?$personne:$personneb; | ||
384 | my $inf = (abs($Tsolde{$personne})<abs($Tsolde{$personneb}))?abs($Tsolde{$personne}):abs($Tsolde{$personneb}); | ||
385 | $remboursements .= $pers_inf." doit ".$inf." EUR à ".$pers_sup."\n"; | ||
386 | $Tsolde{$pers_inf} += $inf; | ||
387 | $Tsolde{$pers_sup} -= $inf; | ||
388 | } | ||
389 | } | ||
390 | # Une boucle pour détecter si on a des couples qui s'annulent mutuellement | ||
391 | COUPLE: foreach my $personne (keys(%participants)) { | ||
392 | if($Tsolde{$personne} == 0) { next; } | ||
393 | foreach my $personneb (keys(%participants)) { | ||
394 | if($Tsolde{$personneb} + $Tsolde{$personne} != 0) { next; } | ||
395 | my $pers_inf = ($Tsolde{$personne}<0)?$personne:$personneb; | ||
396 | my $pers_sup = ($Tsolde{$personne}>0)?$personne:$personneb; | ||
397 | my $val = abs($Tsolde{$personne}); | ||
398 | $remboursements .= $pers_inf." doit ".$val." EUR à ".$pers_sup."\n"; | ||
399 | $Tsolde{$pers_inf} += $val; | ||
400 | $Tsolde{$pers_sup} -= $val; | ||
401 | next COUPLE; | ||
402 | } | ||
403 | } | ||
404 | REMB: while(1) { | ||
405 | # On supprime les 0, et on fait deux hashs | ||
406 | my %Tneg = (); | ||
407 | my %Tpos = (); | ||
408 | foreach my $personne (keys(%Tsolde)) { | ||
409 | if($Tsolde{$personne} == 0) { delete $Tsolde{$personne}; } | ||
410 | elsif($Tsolde{$personne} < 0) { $Tneg{$personne} = $Tsolde{$personne}; } | ||
411 | elsif($Tsolde{$personne} > 0) { $Tpos{$personne} = $Tsolde{$personne}; } | ||
412 | } | ||
413 | if(keys(%Tneg) == 0) { | ||
414 | last REMB; | ||
415 | } | ||
416 | foreach my $neg (sort { $Tneg{$a} cmp $Tneg{$b} } keys %Tneg) { | ||
417 | my $max = 0; | ||
418 | my $positif = 0; | ||
419 | foreach my $pos (sort { $Tpos{$a} cmp $Tpos{$b} } keys %Tpos) { | ||
420 | if($Tpos{$pos} + $Tneg{$neg}>0) { | ||
421 | $positif = $pos; | ||
422 | last; | ||
423 | } | ||
424 | $max = $pos; | ||
425 | } | ||
426 | if(!($max eq 0)) { | ||
427 | $remboursements .= $neg." doit ".$Tsolde{$max}." EUR à ".$max."\n"; | ||
428 | $Tsolde{$neg} += $Tsolde{$max}; | ||
429 | delete $Tsolde{$max}; | ||
430 | } | ||
431 | else { | ||
432 | $remboursements .= $neg." doit ".-$Tsolde{$neg}." EUR à ".$positif."\n"; | ||
433 | $Tsolde{$positif} += $Tsolde{$neg}; | ||
434 | delete $Tsolde{$neg}; | ||
435 | } | ||
436 | next REMB; | ||
437 | } | ||
438 | } | ||
439 | print $remboursements; | ||
440 | my $pause = <STDIN>; | ||
441 | } | ||
442 | case "Sortir" { | ||
443 | last GLOBALE; | ||
444 | } | ||
445 | } | 533 | } |
534 | } | ||
446 | } | 535 | } |