Introduction
Le comptoir obtient des prix, mais sa méthode de comparaison ne renvoie toujours aucun gagnant. Vous lui ferez comparer les objets de règles, conserver tous les ex æquo au prix minimal et enregistrer un fichier complet de devis pour plusieurs colis.
Ce laboratoire démarre indépendamment, avec les deux règles du laboratoire guidé précédent déjà préparées. Il suppose acquises les notions d’interface, d’admissibilité et de tarification par paliers entiers. Vous ajouterez une nouvelle instance paramétrée d’une règle existante, sans inventer un autre algorithme de prix. Tous les tarifs sont synthétiques. La durée est une estimation de l’auteur.
Comparer à travers l’interface
Dans cette étape, vous implémenterez une méthode de comparaison compatible avec toute ShippingRule fournie, y compris une implémentation que le comparateur n’a jamais rencontrée.
Ouvrez l’onglet WebIDE, puis choisissez Terminal → New Terminal dans le menu pour ouvrir le terminal intégré. Exécutez les commandes suivantes dans ce terminal WebIDE. Elles utilisent le même shell ; cd change son répertoire de travail. Si vous rouvrez un terminal, répétez la commande cd. Le JDK et le code de base sont préparés ; aucun outil de construction n’est à installer.
cd /home/labex/project/parcels
./quote.sh quote 1500
Town et Steps affichent tous deux 600. Cet ex æquo normal montre pourquoi garder une seule règle moins chère supprimerait une option valide. Voici le contrat public et les entrées prises en charge :
Le contrat public comprend ShippingRule.id() et ShippingRule.quote(Parcel), ainsi que Quote.eligible() et Quote.cents(). RuleFactory.flat(String, int, long) et RuleFactory.stepped(String, int, int, long) créent les objets de règles ; QuoteEngine.bestRules(Parcel, List<ShippingRule>) renvoie les ID de toutes les règles gagnantes. Ces signatures permettent au même appelant d’utiliser différentes implémentations. Vous pouvez organiser les classes autrement, y compris modifier RuleFactory pour les construire. Conservez ces méthodes publiques et les formats de commande et de sortie fournis ; les noms des classes internes à la fabrique et votre choix d’éditeur ne sont pas évalués.
Les poids acceptés sont des entiers de 1 à 1,000,000 grammes. Les limites des règles et les tailles de palier sont également des entiers de 1 à 1,000,000 ; chaque prix fixe ou par palier est un entier de 0 à 1,000,000 centimes. Une offre admissible à zéro centime est valide. Elle se distingue de Quote.unavailable(), dont eligible() vaut false et dont le montant stocké ne doit pas participer à la comparaison. Un long conserve les montants calculés, afin qu’un grand produit valide ne déborde pas un int de 32 bits. Tous les tarifs, personnes et noms de colis sont synthétiques ; il ne s’agit pas de prix réels de transporteurs consultés en direct.
Le comparateur reçoit une List<ShippingRule>. Chaque élément peut avoir une autre implémentation ; une boucle for améliorée visite chaque objet. Appelez quote(parcel) au lieu de tester un nom de règle ou d’utiliser instanceof pour reproduire sa logique métier.
Commencez avec une liste de gagnants vide et Long.MAX_VALUE, le plus grand long, comme valeur sentinelle. Ignorez les devis non admissibles avec continue. Un prix strictement inférieur remplace le minimum précédent : clear() retire donc les anciens gagnants. Un prix égal ajoute son ID. Il s’agit de deux instructions if distinctes : le minimum qui vient d’être établi doit lui aussi être ajouté. Si rien n’est admissible, la liste reste vide.
La commande suivante remplace un fichier source Java. cat copie le texte entre les deux lignes JAVA vers le chemin placé après > ; les guillemets du marqueur initial empêchent les substitutions du shell dans le code Java. Collez tout le bloc, y compris le dernier JAVA seul sur sa ligne. Vous pouvez aussi modifier le même fichier dans WebIDE, l’enregistrer et revenir au terminal WebIDE. Si un collage incomplet laisse une invite de continuation, appuyez sur Ctrl+C puis recollez le bloc complet.
cat > src/QuoteEngine.java <<'JAVA'
import java.util.ArrayList;
import java.util.List;
public final class QuoteEngine {
public static List<String> bestRules(Parcel parcel, List<ShippingRule> rules) {
List<String> winners = new ArrayList<>();
long lowest = Long.MAX_VALUE;
for (ShippingRule rule : rules) {
Quote quote = rule.quote(parcel);
if (!quote.eligible()) continue;
if (quote.cents() < lowest) {
lowest = quote.cents();
winners.clear();
}
if (quote.cents() == lowest) winners.add(rule.id());
}
return winners;
}
}
JAVA
./quote.sh batch data/parcels.tsv data/rates.tsv
batch reçoit le chemin d’un TSV de colis et celui d’un TSV de tarifs. Les lignes de colis contiennent ID, nom affiché et grammes entiers. La sortie regroupe chaque colis avec tous ses devis et une ligne BEST. UNAVAILABLE signifie qu’une règle ne peut pas le transporter ; BEST NONE signifie qu’aucune ne le peut. Un lot valide sans offre admissible se termine avec succès, avec le code 0.
Pour P02, Town et Steps doivent figurer dans BEST ; P03 pèse un gramme de plus et seul Town gagne. P01 et P02 s’appellent tous deux Gift, mais leurs ID distincts séparent leurs devis. P04 n’a aucune règle admissible. Conservez chaque colis et chaque règle, même les résultats indisponibles.
Enregistrer une autre règle et conserver les devis complets
Dans cette étape, vous enregistrerez une nouvelle instance de prix fixe sans modifier le comparateur, puis sauvegarderez des résultats lisibles plus tard par le comptoir.
Continuez dans le terminal WebIDE, dans /home/labex/project/parcels. Le lecteur de tarifs utilise RuleFactory pour construire les implémentations demandées. Une autre ligne flat crée donc un autre objet aux paramètres indépendants. Ne modifiez pas les fichiers originaux de data/. cp crée une copie de travail ; printf écrit du texte, \t représente une tabulation et \n termine la ligne. >> ajoute au fichier au lieu de le remplacer.
cp data/rates.tsv work/rates.tsv
printf 'flat\tRelay\t6000\t600\n' >> work/rates.tsv
./quote.sh batch data/parcels.tsv work/rates.tsv
Relay est admissible jusqu’à 6,000 grammes inclus pour 600 centimes. P02 a maintenant trois gagnants ex æquo, alors que P04, à 6,500 grammes, n’a toujours aucune offre. Vous avez modifié la collection enregistrée, et le code de comparaison initial continue de fonctionner.
La sortie constitue le véritable livrable de devis. > enregistre la sortie standard dans un fichier et remplace un fichier existant du même nom. N’enregistrez qu’un lot valide, car le shell ouvre le fichier avant que Java ne valide les entrées :
./quote.sh batch data/parcels.tsv work/rates.tsv > work/quotes.tsv
cat work/quotes.tsv
Chaque ID doit avoir une ligne PARCEL, une ligne QUOTE par règle enregistrée et une ligne BEST contenant tous les ID admissibles de prix minimal séparés par des virgules, ou NONE. Les montants restent des centimes entiers. Les règles et gagnants peuvent suivre l’ordre d’enregistrement ; ce sont les membres et leurs relations qui comptent.
Un poids invalide diffère d’un colis valide sans offre. L’exemple invalide fourni contient BAD à zéro gramme. L’analyseur valide tout le lot avant d’afficher un devis ; un lot invalide sort avec le code 2, écrit une explication sur la sortie d’erreur standard et ne produit aucune ligne de devis. Exécutez cet échec prévu sans le rediriger sur votre bon fichier :
./quote.sh batch data/invalid-parcels.tsv work/rates.tsv
Attendez-vous à INVALID_WEIGHT BAD. Reprenez avec le fichier de colis valide :
./quote.sh batch data/parcels.tsv work/rates.tsv
Les données originales de colis et de tarifs ainsi que votre bon work/quotes.tsv restent intactes. Corrigez et enregistrez le fichier indiqué en cas d’erreur de compilation, ou répétez cd /home/labex/project/parcels en cas d’erreur de chemin, puis relancez. Le lanceur recompile les sources enregistrées à chaque exécution et utilise explicitement UTF-8, comme au laboratoire précédent.
Les vérifications compilent des copies inchangées dans des jeux temporaires, avec d’autres paramètres et implémentations d’interface valides. Elles ne complètent pas les résultats manquants sur place et ne réécrivent pas votre espace de travail. C’est une évaluation fonctionnelle dans un environnement de formation, pas une protection contre la falsification de fichiers par un administrateur.
Résumé
Vous avez comparé des objets d’interface sans branches propres aux transporteurs, conservé tous les minimums ex æquo et représenté explicitement l’absence valide d’offres. L’ajout d’une règle configurée réutilise le même flux. Votre fichier conserve l’identité et l’ensemble des choix de chaque colis.



