Conception et Implémentation d'un Programme d'Évaluation Automatisée
Dans ce travail, nous avons développé un système de gestion des tests pour évaluer les réponses des étudiants. Le programme supporte différents types de questions : questions à choix multiples, questions à remplir, et questions standard avec réponses textuelles. La conception repose sur une architecture orientée objet pour gérer les entités telles que les questions, les étudiants, les copies d'examen et les corrections.
Structure des Classes
La classe de base Question encapsule les attributs essentiels : identifiant, contenu et réponse. Des sous-classes spécialisées gèrent les spécificités des types de questions, comme les choix multiples où la réponse peut contenir plusieurs options séparées par des espaces.
class ElementDeBase {
int identifiant;
String enonce;
String reponseCorrecte;
boolean supprime;
ElementDeBase(int id, String enonce, String reponse) {
this.identifiant = id;
this.enonce = enonce;
this.reponseCorrecte = reponse;
this.supprime = false;
}
}
class QuestionChoixMultiple extends ElementDeBase {
QuestionChoixMultiple(int id, String enonce, String reponse) {
super(id, enonce, reponse);
}
String evaluerReponse(String saisieUtilisateur) {
// Logique de comparaison pour les réponses multiples
if (saisieUtilisateur.trim().isEmpty()) return "faux";
Set<String> attendu = new HashSet<>(Arrays.asList(reponseCorrecte.split(" ")));
Set<String> fourni = new HashSet<>(Arrays.asList(saisieUtilisateur.split(" ")));
if (fourni.containsAll(attendu) && fourni.size() == attendu.size()) return "vrai";
if (Collections.disjoint(fourni, attendu) || fourni.isEmpty()) return "faux";
return "partiellement correct";
}
}
La classe Examen agrège les questions avec leurs coefficients de notation et gère les alertes si le total des points n'est pas 100.
Traitement des Données d'Entrée
Le programme analyse les entrées au format texte structuré, utilisant des expressions régulières pour extraire les informations sur les questions, les examens et les réponses. Les données peuvent arriver dans n'importe quel ordre, nécessitant une gestion flexible de la validation et de l'association des entités.
Pattern motifQuestion = Pattern.compile("#N:(\\d+) #Q:(.+?) #A:(.+)");
Pattern motifExamen = Pattern.compile("#T:(\\d+) ((?:\\d+-\\d+\\s*)+)");
Pattern motifReponse = Pattern.compile("#S:(\\d+) (\\d+) (#A:(\\d+-.+?)\\s*)*");
Les erreurs de format sont détectées et signalées avec des messages clairs, comme les références manquantes ou les numéros d'examen invalides.
Simulation de Circuits Électriques Domotiques
Un autre volet du travail a consisté à modéliser un système de circuit électrique pour la domotique, incluant des interrupteurs, des variateurs et des appareils contrôlés comme les lampes et les ventilateurs. La conception doit supporter des topologies série et parallèle.
Modélisation des Composants
Chaque composant est représenté par une classe qui hérite d'une classe abstraite ComposantCircuit. Les propriétés incluent l'identifiant, les broches d'entrée/sortie et des méthodes pour calculer les tensions et courants.
abstract class ComposantCircuit {
String idComposant;
abstract double obtenirTensionSortie(double tensionEntree);
}
class Interrupteur extends ComposantCircuit {
boolean etat;
Interrupteur(String id) {
this.idComposant = id;
this.etat = false;
}
void basculer() {
etat = !etat;
}
double obtenirTensionSortie(double tensionEntree) {
return etat ? tensionEntree : 0.0;
}
}
class VariateurContinu extends ComposantCircuit {
double position;
VariateurContinu(String id) {
this.idComposant = id;
this.position = 0.0;
}
void reglerPosition(double pos) {
this.position = Math.max(0.0, Math.min(1.0, pos));
}
double obtenirTensionSortie(double tensionEntree) {
return tensionEntree * position;
}
}
Pour les appareils comme les lampes incandescentes, la luminosité est calculée proportionnellement à la tension appliquée, avec des seuils spécifiques. Les ventilateurs ont des plages de fonctionnement définies par des intervalles de tension.
Gestion des Circuits Complexes
La structure des circuits est définie via des informations de connexion sérialisées. Le programme interprète les lignes de câblage, identifie les nœuds et construit un graphe pour calculer les tensions à travers le réseau. Les circuits parallèles sont gérés en traitant chaque branche indépendamment avant de combiner les résultats.
Les opérations de contrôle, comme l'activation des interrupteurs ou le réglage des variateurs, sont appliquées séquentiellement, avec recalcul des états après chaque modification. La sortie affiche l'état final de chaque composant dans un ordre prédéfini par type et numéro.
Défis et Solutions Techniques
Parmi les difficultés rencontrées, la gestion des entrées désordonnées et la validation des références croisées entre entités ont nécessité une attention particulière. Par exemple, lorsqu'un examen référence une question supprimée, le système doit afficher un message d'erreur spécifique au lieu de la question normale.
La conception des classes a été affinée pour assurer la cohérence entre les différentes parties du système. L'utilisation de collections ordonnées comme TreeMap a permis de maintenir un tri automatique des composants pour la sortie. Les expressions régulières, bien que puissantes, ont été simplifiées pour éviter une complexité excessive et faciliter la maintenance.
En conclusion, ces travaux pratiques ont mis en évidence l'importance d'une conception modulaire et d'une gestion rigoureuse des données d'entrée pour développer des systèmes robustes et extensibles.