Partage
  • Partager sur Facebook
  • Partager sur Twitter

Exercices POO

Venez progresser !

Anonyme
26 novembre 2009 à 7:03:18

Bonjour,
J'ai vu sur le forum PHP un certain nombre de sujets proposant des exercices de PHP, mais c'était très souvent (presque exclusivement) des fonctions d'algorithmique, ou d'autres assez inutiles.
Aujourd'hui, je vous propose que l'on fasse la même chose, mais avec des mini-modules codés en POO.
Ces mini-modules ne seraient pas forcément à utiliser pour votre site, mais le but est qu'ils vous fassent progresser.

Exercice 1 : un système de QCM


Description :



Vous aurez besoin de trois classes :
  • Qcm ;
  • Question ;
  • Reponse.

Je vous le rappelle, aucune de ces trois classes ne doit hériter d'une autre : on ne peut parler d'héritage exclusivement quand, avec une classe A et B, on peut dire que B est un A. Or ici une réponse n'est pas une question, une question n'est pas un Qcm.

Fonctionnalités requises


  • Ajouter une question
    • Pouvoir ajouter les réponses possibles à une question ;
    • Pouvoir définir la bonne réponse comme telle ;
  • Pouvoir définir les explications de la correction d'une question.
  • Pouvoir définir plusieurs appréciations en fonction de la note (sur vingt) obtenue ;

À la fin, il doit être possible de faire ceci pour générer un Qcm :

<?php
$qcm = new Qcm();

$question1 = new Question('Et paf, ça fait ...');
$question1->ajouterReponse(new Reponse('Des mielpops'));
$question1->ajouterReponse(new Reponse('Des chocapics', Reponse::BONNE_REPONSE));
$question1->ajouterReponse(new Reponse('Des actimels'));
$question1->setExplications('Et oui, la célèbre citation est « Et paf, ça fait des chocapics ! »');
$qcm->ajouterQuestion($question1);

$question2 = new Question('POO signifie');
$question2->ajouterReponse(new Reponse('Php Orienté Objet'));
$question2->ajouterReponse(new Reponse('ProgrammatiOn Orientée'));
$question2->ajouterReponse(new Reponse('Programmation Orientée Objet', Reponse::BONNE_REPONSE));
$question2->setExplications('Sans commentaires si vous avez eu faux :-°');
$qcm->ajouterQuestion($question2);

$qcm->setAppreciation(array('0-10' => 'Pas top du tout ...', 
					        '10-20' => 'Très bien ...'));
$qcm->generer();


Résolutions


Cet exercice n'a pas encore été résolu.

Indices



Une fois que le formulaire du QCM a été validé, je vous conseille de vous servir du md5() des questions pour récupérer l'objet qui correspond.
Exemple :
<?php
public function getQuestionFromMd5($md5) {
	foreach($this->questions as $q) {
		if(md5($q->getQuestion()) == $md5) {
			return $q;
		}
	}
	return FALSE;
}




Une fois que vous pensez avoir fini, postez vos codes en réponse. :)
La correction sera donnée dans deux semaines à compter d'aujourd'hui, le 26 novembre 2009.
Si vous voulez me proposer des exercices, envoyez moi un MP. ;)
Bonne chance à tous !
Que la force soit avec vous



  • Partager sur Facebook
  • Partager sur Twitter
Anonyme
26 novembre 2009 à 17:43:06

Bon, je viens de terminer ma classe!

Avantages :
  • Totalement fonctionnel
  • Possibilité d'avoir plusieurs QCM sur la même page sans risques de conflits
  • Pas besoin de s'occuper de savoir si le formulaire à été envoyé, la classe s'en occupe toute seul dans la méthode générer
  • Un code bien indenté


Inconvénients :
  • Pas de CSS et difficulté (voir impossibilité) d'en mettre une extérieur
  • Code non commenté
  • Presque aucune gestion des erreurs


Une dernier truc : les méthodes d'action renvoient toutes (sauf Qcm::Generer) l'instance en cours, ce qui permet de pouvoir le réutiliser directement, et donc de ne pas avoir à réécrire 150 le nom de l'instance ;)
Qcm::generer fait exception étant donné que compte mettre une option pour qu'il renvoie le code source du QCM et affin de pouvoir le manipuler ensuite.


<?php
class Qcm {
   private $questions;
   private $appreciation;
   
   public function __construct() {
      $this->questions = array();
      $this->appreciation = array();
   }
   
   public function ajouterQuestion($question) {
      $this->questions[] = $question;
      return $this;
   }
   
   public function setAppreciation($appreciation) {
      foreach($appreciation as $key=>$appr) {
         if(is_numeric($key))
            $this->appreciation[(int)$appr] = $appr;
         else {
            list($min, $max) = explode('-', $key);
            if($min>$max)
               list($min, $max) = array($max, $min);
            for($i=(int)$min;$i<=$max;$i++)
               $this->appreciation[$i] = $appr;
         }
      }
      return $this;
   }
   
   public function generer() {
      $id = md5(serialize($this));
      if(isset($_POST['qcm_id']) AND $_POST['qcm_id']==$id) {
         $nbrBonneReponses = 0;
         foreach($this->questions as $i=>$question) {
            echo 'Question '.$i.' : '.htmlspecialchars($question->getQuestion()).'<br /><br />';
            if($_POST['qcm_q'.$i]==$question->getNumBonneReponse()) {
               echo 'Bonne réponse!<br /><br />';
               $nbrBonneReponses++;
            }
            else
               echo 'Mauvaise réponse : '.htmlspecialchars($question->getReponse($_POST['qcm_q'.$i])->getText()).'<br />';
            echo 'La bonne réponse était : '.htmlspecialchars($question->getBonneReponse()->getText()).'<br /><br />';
            echo 'Explication : '.htmlspecialchars($question->getExplication());
            echo '<hr />';
         }
         $note = round($nbrBonneReponses/count($this->questions)*20);
         echo 'Note : '.$note.'/20<br />';
         if(isset($this->appreciation[$note]))
            echo 'Appréciation : '.htmlspecialchars($this->appreciation[$note]);
      }
      else {
         echo '<form method="post" />';
         echo '<input type="hidden" value="'.$id.'" name="qcm_id" />';
         foreach($this->questions as $i=>$question) {
            echo '<fieldset>Question '.$i.' : '.htmlspecialchars($question->getQuestion()).'<br />';
            foreach($question->getReponses() as $j=>$reponse) {
               echo '<input type="radio" name="qcm_q'.$i.'" value="'.$j.'" />';
               echo htmlspecialchars($reponse->getText()).'<br />';
            }
            echo '</fieldset><br />';
         }
         echo '<input type="submit" value="envoyer" /></form>';
      }
   }
}

<?php
class Question {
   private $question;
   private $reponses;
   private $explication;

   public function __construct($question) {
      $this->question = $question;
      $this->reponse = array();
   }

   public function ajouterReponse($reponse) {
      $this->reponses[] = $reponse;
      return $this;
   }

   public function setExplications($explication) {
      $this->explication = $explication;
      return $this;
   }

   public function getNumBonneReponse() {
      foreach($this->reponses as $i=>$reponse)
         if($reponse->getStatus())
            return $i;
   }

   public function getBonneReponse() {
      foreach($this->reponses as $reponse)
         if($reponse->getStatus())
            return $reponse;
   }

   public function getReponses() {
      return $this->reponses;
   }

   public function getReponse($num) {
      return $this->reponses[$num];
   }

   public function getQuestion() {
      return $this->question;
   }

   public function getExplication() {
      return $this->explication;
   }
}

<?php
class Reponse {
   private $reponse;
   private $status;
   const MAUVAIS_REPONSE = false;
   const BONNE_REPONSE = true;

   public function __construct($reponse, $status = self::MAUVAIS_REPONSE) {
      $this->reponse = $reponse;
      $this->status = $status;
   }

   public function getStatus() {
      return $this->status;
   }

   public function getText() {
      return $this->reponse;
   }
}

<?php
$qcm = new Qcm();

$question1 = new Question('Et paf, ça fait ...');
$question1->ajouterReponse(new Reponse('Des mielpops'))
    ->ajouterReponse(new Reponse('Des chocapics', Reponse::BONNE_REPONSE))
    ->ajouterReponse(new Reponse('Des actimels'))
    ->setExplications('Et oui, la célèbre citation est « Et paf, ça fait des chocapics ! »');

$question2 = new Question('POO signifie');
$question2->ajouterReponse(new Reponse('Php Orienté Objet'))
    ->ajouterReponse(new Reponse('ProgrammatiOn Orientée'))
    ->ajouterReponse(new Reponse('Programmation Orientée Objet', Reponse::BONNE_REPONSE))
    ->setExplications('Sans commentaires si vous avez eu faux :-°');

$qcm->ajouterQuestion($question1)
    ->ajouterQuestion($question2)
    ->setAppreciation(array(
       '0-10'=>'Pas top du tout ...',
       '10-20'=>'Très bien ...'))
    ->generer();


Comme vous pouvez le voir, le code n'est pas forcément orienté dans la performance, mais plus dans la clarté. Par exemple, je n'hésite pas à faire plusieurs echo à la suite pour éviter des lignes à rallonge.
  • Partager sur Facebook
  • Partager sur Twitter
Anonyme
26 novembre 2009 à 21:32:58

Berdes1 tes classes marchent, mais mets les codes dans la balise <secret></secret> , mais pense à mettre des labels à tes checkbox. ;)
  • Partager sur Facebook
  • Partager sur Twitter
Anonyme
26 novembre 2009 à 21:40:32

Le problème des <label> ces que quand il y a un choix, un choix sera définie par défaut et ça peut orienter l'utilisateur (oui, je sait, osef...)
  • Partager sur Facebook
  • Partager sur Twitter
Anonyme
2 décembre 2009 à 21:10:17

Elle est pour quand la correction?
  • Partager sur Facebook
  • Partager sur Twitter
Anonyme
4 décembre 2009 à 19:32:09

Je la donne dès que je suis sur mon ordinateur. ;)
  • Partager sur Facebook
  • Partager sur Twitter
4 décembre 2009 à 22:19:14

Citation : berdes1

Le problème des <label>, c'est que quand il y a un choix, il sera défini par défaut et ça peut orienter l'utilisateur


Je ne vois pas où est le problème... Le label ne fait que donner le focus au contrôle.
Après, ca peut être utile de faire une option dans le select qui aura une valeur "nulle" (0 si les clés sont des entiers ou '' si les clés sont des chaines), et dont le texte afficher serait "A préciser..." par exemple...
Ca permet de visualiser que la liste n'a pas encore été modifiée, de définir une valeur par défaut pour le traitement de $_POST, et si tu as un problème avec les lables, cette astuce peut la résoudre. ;)
  • Partager sur Facebook
  • Partager sur Twitter
16 octobre 2013 à 19:51:46

je pense qu'elle n'arrivera jamais la correction...
  • Partager sur Facebook
  • Partager sur Twitter
30 avril 2021 à 11:53:16

Oui

-
Edité par Jeyslee 30 avril 2021 à 11:53:35

  • Partager sur Facebook
  • Partager sur Twitter
Amilcar
30 avril 2021 à 12:56:01

Bonjour,

Déterrage

Citation des règles générales du forum :

Avant de poster un message, vérifiez la date du sujet dans lequel vous comptiez intervenir.

Si le dernier message sur le sujet date de plus de deux mois, mieux vaut ne pas répondre.
En effet, le déterrage d'un sujet nuit au bon fonctionnement du forum, et l'informatique pouvant grandement changer en quelques mois il n'est donc que rarement pertinent de déterrer un vieux sujet.

Au lieu de déterrer un sujet il est préférable :

  • soit de contacter directement le membre voulu par messagerie privée en cliquant sur son pseudonyme pour accéder à sa page profil, puis sur le lien "Ecrire un message"
  • soit de créer un nouveau sujet décrivant votre propre contexte
  • ne pas répondre à un déterrage et le signaler à la modération

Je ferme ce sujet. En cas de désaccord, me contacter par MP.

  • Partager sur Facebook
  • Partager sur Twitter
Seul on va plus vite, ensemble on va plus loin ... A maîtriser : Conception BDD, MySQL, PHP/MySQL