diff --git a/COMPTE_RENDU.md b/COMPTE_RENDU.md index 2f1ad9e..5f1e458 100644 --- a/COMPTE_RENDU.md +++ b/COMPTE_RENDU.md @@ -348,3 +348,19 @@ disparaissent. F8 passe de **M = 4 à M = 5** : l'amélioration temporelle n'implique pas une baisse de M. Les tests comparent les résultats à la récursion initiale pour les sommes de -2 à 40 et de 0 à 8 types de pièces, y compris la somme nulle et l'absence de pièces. + +### F9 — Séparer les règles des débits et des crédits + +`categorie` répartit les transactions entre débit, montant nul et crédit. +Les règles propres aux débits et aux crédits sont regroupées dans deux +fonctions auxiliaires, avec des retours directs. Le test du week-end +`jour % 7 >= 5` remplace les deux comparaisons reliées par `||`. + +Le temps reste **`O(1)`** et la complexité cyclomatique de F9 passe de +**14 à 3**, sous l'objectif de 10. Les auxiliaires `categorie_debit` +et `categorie_credit` ont respectivement **M = 5** et **M = 7** : les +décisions ne sont pas simplement déplacées vers une autre fonction +dépassant l'objectif. Les tests confrontent les 20 montants situés aux +seuils et à leurs voisins, y compris `LONG_MIN` et `LONG_MAX`, à la fonction +initiale, pour 20 clients et 210 jours (cycle commun des modulos 7 et 30), +soit **84 000 classifications**. diff --git a/banque.c b/banque.c index 7b71498..face485 100644 --- a/banque.c +++ b/banque.c @@ -259,37 +259,44 @@ long nb_facons_rendre(int somme, int nb_pieces) } /* F9 : catégorie d'une transaction (pour les statistiques) */ +static int categorie_debit(const Transaction *t) +{ + if (t->montant < -20000) { + if (t->jour % 7 >= 5) + return 1; + return 2; + } + if (t->montant < -5000) + return 3; + if (t->client % 10 == 0) + return 4; + return 5; +} + +static int categorie_credit(const Transaction *t) +{ + if (t->montant > 30000) { + if (t->client % 10 == 0 && t->jour % 7 < 5) + return 6; + return 7; + } + if (t->montant > 10000) + return 8; + if (t->montant > 1000) { + if (t->jour % 30 == 0) + return 9; + return 10; + } + return 11; +} + int categorie(const Transaction *t) { - if (t->montant < 0) { - if (t->montant < -20000) { - if (t->jour % 7 == 5 || t->jour % 7 == 6) - return 1; - else - return 2; - } else if (t->montant < -5000) { - return 3; - } else { - if (t->client % 10 == 0) - return 4; - return 5; - } - } else if (t->montant == 0) { + if (t->montant < 0) + return categorie_debit(t); + if (t->montant == 0) return 0; - } else { - if (t->montant > 30000) { - if (t->client % 10 == 0 && t->jour % 7 < 5) - return 6; - return 7; - } else if (t->montant > 10000) { - return 8; - } else if (t->montant > 1000) { - if (t->jour % 30 == 0) - return 9; - return 10; - } - return 11; - } + return categorie_credit(t); } /* F10 : ajoute une ligne à la fin du rapport */ diff --git a/tests/test_banque.c b/tests/test_banque.c index 110738e..e0d86d2 100644 --- a/tests/test_banque.c +++ b/tests/test_banque.c @@ -224,6 +224,55 @@ static void tester_monnaie(void) assert(nb_facons_rendre(s, k) == monnaie_reference(s, k)); } +static int categorie_reference(const Transaction *t) +{ + if (t->montant < 0) { + if (t->montant < -20000) { + if (t->jour % 7 == 5 || t->jour % 7 == 6) + return 1; + else + return 2; + } else if (t->montant < -5000) { + return 3; + } else { + if (t->client % 10 == 0) + return 4; + return 5; + } + } else if (t->montant == 0) { + return 0; + } else { + if (t->montant > 30000) { + if (t->client % 10 == 0 && t->jour % 7 < 5) + return 6; + return 7; + } else if (t->montant > 10000) { + return 8; + } else if (t->montant > 1000) { + if (t->jour % 30 == 0) + return 9; + return 10; + } + return 11; + } +} + +static void tester_categories(void) +{ + const long montants[] = { + LONG_MIN, -20001, -20000, -19999, -5001, -5000, -4999, -1, + 0, 1, 999, 1000, 1001, 9999, 10000, 10001, 29999, 30000, 30001, LONG_MAX + }; + for (size_t m = 0; m < sizeof(montants) / sizeof(*montants); m++) { + for (int c = 0; c < 20; c++) { + for (int j = 0; j < 210; j++) { + Transaction t = {0, c, j, montants[m]}; + assert(categorie(&t) == categorie_reference(&t)); + } + } + } +} + int main(void) { tester_tri(); @@ -234,6 +283,7 @@ int main(void) tester_recherches(); tester_paires(); tester_monnaie(); + tester_categories(); puts("Tests banque : OK"); return 0; }