31, 2=>28+date('L'), 3=>31, 4=>30, 5=>31, 6=>30, 7=>31, 8=>31, 9=>30, 10=>31, 11=>30, 12=>31); $fin_mois = mktime(23, 59, 59, $num_mois, $dernier_jour[$num_mois], $annee); $bornes = array($debut_mois, $fin_mois); return $bornes; } //Return what A must pay to B function dettes($A, $B, $debut_mois, $fin_mois) { global $bdd; //When A paid and B was here $reqA_B = $bdd->prepare('SELECT id, date, montant, copains, invites FROM depenses WHERE date>'.$debut_mois.' AND date<'.$fin_mois.' AND de=:param1 AND (copains LIKE "%,'.(int) $B.',%" OR copains LIKE "%,'.(int)$B.'" OR copains LIKE "'.(int) $B.',%" OR copains LIKE "'.(int) $B.'")'); $reqA_B->bindvalue(':param1',$A); $reqA_B->execute(); //When B paid and A was here $reqB_A = $bdd->prepare('SELECT id, date, montant, copains, invites FROM depenses WHERE date>'.$debut_mois.' AND date<'.$fin_mois.' AND de=:param1 AND (copains LIKE "%,'.(int) $A.',%" OR copains LIKE "%,'.(int)$A.'" OR copains LIKE "'.(int) $A.',%" OR copains LIKE "'.(int) $A.'")'); $reqB_A->bindvalue(':param1',$B); $reqB_A->execute(); //What A already paid to B $reqPaiementsA_B = $bdd -> prepare('SELECT paiements.montant AS montant FROM paiements LEFT JOIN depenses ON paiements.id_depense=depenses.id WHERE depenses.date >'.$debut_mois.' AND depenses.date<'.$fin_mois.' AND paiements.de=:de AND paiements.a=:a'); $reqPaiementsA_B->bindvalue(':de',$A); $reqPaiementsA_B->bindvalue(':a',$B); $reqPaiementsA_B->execute(); //Same thing for B to A $reqPaiementsB_A = $bdd -> prepare('SELECT paiements.montant AS montant FROM paiements LEFT JOIN depenses ON paiements.id_depense=depenses.id WHERE depenses.date >'.$debut_mois.' AND depenses.date<'.$fin_mois.' AND paiements.de=:de AND paiements.a=:a'); $reqPaiementsB_A->bindvalue(':de',$B); $reqPaiementsB_A->bindvalue(':a',$A); $reqPaiementsB_A->execute(); //$deltaAB : What A must pay to B $deltaAB = 0; while($donneesA_B = $reqA_B->fetch()) { //We get the price of the meal, divided by the number of people who ate //nb of comma + 1 $deltaAB -= $donneesA_B['montant']/(substr_count($donneesA_B['copains'], ',') + 1 + $donneesA_B['invites']); } while($donneesB_A = $reqB_A->fetch()) //idem { $deltaAB += $donneesB_A['montant']/(substr_count($donneesB_A['copains'], ',') + 1 + $donneesB_A['invites']); } while($donneesPaiementsA_B = $reqPaiementsA_B->fetch()) //what has been already paid { $deltaAB -= $donneesPaiementsA_B['montant']; } while($donneesPaiementsB_A = $reqPaiementsB_A->fetch()) //idem { $deltaAB += $donneesPaiementsB_A['montant']; } return $deltaAB; } // Reduces the matrix in n steps function simplify ($copains){ // We work directly with $debts global $debts; global $matrix; $max = maximum($debts); // On cherche le plus proche en valeur absolue du maximum $near = nearest($debts, $max); // On en déduit l'écart entre leurs valeurs absolues $delta = $max["val"] + $near["val"]; // Case : //A : max 100 //B :near -90 // delta 10 // m[A][B] -90 // m[B][A] 90 if ($delta > 0){ $matrix[$max["id"]][$near["id"]] = -$debts[$near["id"]]; $matrix[$near["id"]][$max["id"]] = $debts[$near["id"]]; $debts[$max["id"]] = $delta; $debts[$near["id"]] = 0; } else { $matrix[$max["id"]][$near["id"]] = $debts[$max["id"]]; $matrix[$near["id"]][$max["id"]] = -$debts[$max["id"]]; $debts[$max["id"]] = 0; $debts[$near["id"]] = $delta; } return $matrix; } // Return the nearest value function nearest($debts, $max) { // Initialize with the maximum distance $d_min = max($debts) - min($debts); // Initialize the default id to one key in the array $debts_keys = array_keys($debts); $id_min = $debts_keys[1]; foreach($debts as $id => $val) { // Computes the absolute distance $d = abs($max["val"] + $val); // If it's a new minimum AND the value isn't positive if ($d <= $d_min && $val < 0) { $id_min = $id; $d_min = $d; } } return array("id"=>$id_min, "val"=>$debts[$id_min]); } function maximum($tableau) { $max["id"] = 0; $max["val"] = 0; foreach($tableau as $id=>$val) { if($val >= $max["val"]) { $max["val"] = $val; $max["id"] = $id; } } return $max; } // Function to insert a regulation between A and B for the simplification // system only. function inserer_paiement_rbmt($donnees_depense, $de_paiement, $a_paiement, $rbmt) { if ($de_paiement == $a_paiement) return 1; global $bdd; // We get all the payments between a and de (we just filter thanks to the // id which is linked to the a field) $paiement_existe_req = $bdd->prepare('SELECT montant, COUNT(*) AS nbre_paiement FROM paiements WHERE id_depense=:id_depense AND de=:de'); $paiement_existe_req->bindValue(':id_depense', $donnees_depense['id']); $paiement_existe_req->bindValue(':de', $de_paiement); $paiement_existe_req->execute(); $deja_paye = 0; while ($donnees = $paiement_existe_req->fetch()) { $deja_paye += $donnees['montant']; } $montant = $donnees_depense['montant']/(substr_count($donnees_depense['copains'], ',') + 1 + $donnees_depense['invites']) - $deja_paye; $req = $bdd->prepare('INSERT INTO paiements(id, de, a, id_depense, date, montant, rbmt) VALUES("", :de, :a, :id_depense, :date, :montant, :rbmt)'); $req->bindValue(':de', $de_paiement); $req->bindValue(':a', $a_paiement); $req->bindValue(':id_depense', $donnees_depense['id']); $req->bindValue(':date', time()); $req->bindValue(':rbmt', $rbmt); $req->bindValue(':montant', $montant); $req->execute(); return 1; } if(!(isset($_GET['confirm']) && isset($_POST['matrix']) && isset($_POST['copains']) && isset($_POST['date']))) { ?>
";
// Output the matrix
foreach($copains as $keyA=>$copainA)
{
foreach($copains as $keyB=>$copainB)
{
if (isset($matrix[$keyA][$keyB]) && $matrix[$keyA][$keyB] > 0)
echo '' . $copains[$keyA] . ' doit '. round($matrix[$keyA][$keyB], 2) . ' à ' . $copains[$keyB] .'
';
}
}
// Show a forme to confirm
?>
Doit\À | '; //Construct the header of the table and display it for the previous months foreach($copains as $key => $copain) { if($_SESSION['nom'] == $copain) $copain = ''.$copain.''; $table .= ''.$copain.' | '; } $table .= '|
---|---|---|
'.$copainA.' | '; foreach($copains as $keyB=>$copainB) { if($matrix[$keyA][$keyB] <= 0) $table .= '- | '; else $table .= ''.$matrix[$keyA][$keyB].' | '; } $table .= '
'; echo 'Retour à l\'accueil'; echo '
'; echo ''; ?>