]>
Commit | Line | Data |
---|---|---|
5172ecf8 IB |
1 | #!/usr/bin/en perl |
2 | # The MIT License (MIT) | |
3 | # | |
4 | # Copyright (c) 2011-2015 Ismaël Bouya http://www.normalesup.org/~bouya/ | |
5 | # | |
6 | # Permission is hereby granted, free of charge, to any person obtaining a copy | |
7 | # of this software and associated documentation files (the "Software"), to deal | |
8 | # in the Software without restriction, including without limitation the rights | |
9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
10 | # copies of the Software, and to permit persons to whom the Software is | |
11 | # furnished to do so, subject to the following conditions: | |
12 | # | |
13 | # The above copyright notice and this permission notice shall be included in | |
14 | # all copies or substantial portions of the Software. | |
15 | # | |
16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
22 | # THE SOFTWARE. | |
23 | ||
24 | use Switch; | |
25 | use strict; | |
26 | ||
27 | my $file = "comptes.data"; | |
28 | ||
29 | my @actions=('Ajouter un participant'); | |
30 | my %participants = (); | |
31 | my @transactions = (); | |
32 | my @descriptions = (); | |
33 | my $evenement_def; | |
34 | my $remboursements = ""; | |
35 | ||
36 | if($#ARGV==0) { | |
37 | open FILE, $ARGV[0] || die "Impossible de lire le fichier"; | |
38 | $evenement_def = <FILE>; | |
39 | chomp($evenement_def); | |
40 | while(my $noms = <FILE>) { | |
41 | if($noms eq "\n") { last; } | |
42 | my ($numero,$nom) = split(/ /,$noms,2); | |
43 | chomp($nom); | |
44 | $participants{$nom} = $numero; | |
45 | } | |
46 | while(my $transaction = <FILE>) { | |
47 | if($transaction eq "\n") { last; } | |
48 | chomp($transaction); | |
49 | push(@transactions,$transaction); | |
50 | my $description = <FILE>; | |
51 | chomp($description); | |
52 | push(@descriptions,$description); | |
53 | } | |
54 | $file = $ARGV[0]; | |
55 | } | |
56 | ||
57 | GLOBALE: while(1) { | |
58 | if(keys(%participants)>0) { | |
59 | $actions[1]="Ajouter une dépense"; | |
60 | $actions[2]="Enregistrer"; | |
61 | } | |
62 | if(scalar(@transactions)>0) { | |
63 | $actions[3]="Voir les dépenses de quelqu'un"; | |
64 | $actions[2]="Enregistrer"; | |
65 | $actions[4]="Equilibrage"; | |
66 | $actions[5]="Voir une transaction"; | |
67 | } | |
68 | ||
69 | my $action; | |
70 | while(1) { | |
71 | my $i = 1; | |
72 | my $var; | |
73 | my @vart = ( @actions, 'Sortir' ); | |
74 | my $message = ''; | |
75 | foreach $var ( @vart ) { | |
76 | $message .= $i++.') '.$var."\n"; | |
77 | } | |
78 | print $message; | |
79 | $var = <STDIN>; | |
80 | chop($var); | |
81 | if(/\D/ || $var < 1 || $var > $i) { | |
82 | print "Mauvaise entrée\n"; | |
83 | next; | |
84 | } | |
85 | $action = $vart[$var-1]; | |
86 | last; | |
87 | } | |
88 | switch ($action) { | |
89 | case "Ajouter un participant" { | |
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 | } | |
446 | } |