TP 3

Dice

Tout comme pour le TP_2, créez les deux fichiers dont le code est donné ci après et vérifiez que tous les tests passent en exécutant le fichier test_dice.py avec la bibliothèque py.test.

A faire :
  • la méthode de classe number_faces n’est pas testée. Créez un tet pour cette méthode (par exemple, créez un dé à 20 faces avec la méthode et testez que son nombre de faces est correct)
  • modifiez la méthode test_roll pour que le dé créé soit à une face et simplifiez le test.

dice.py

import random


class Dice:

    @classmethod
    def number_faces(cls, number_faces):
        dice = cls()
        dice.NUMBER_FACES = number_faces

        return dice

    def __init__(self, value=1):
        self.NUMBER_FACES = 6
        self._value = value

    def get_value(self):
        return self._value

    def set_value(self, new_value):
        self._value = new_value

    def roll(self):
        self.set_value(random.randint(1, max(self.NUMBER_FACES, 1)))

test_dice.py

from dice import Dice


def test_dice_creation_no_argument():
    un_de = Dice()
    assert un_de.get_value() == 1


def test_dice_creation_initial_creation():
    un_de = Dice(value=3)
    assert un_de.get_value() == 3


def test_dice_change_position():
    un_de = Dice()
    un_de.set_value(6)

    assert un_de.get_value() == 6


def test_roll():
    un_de = Dice()

    un_de.roll()

    assert 1 <= un_de.get_value() <= un_de.NUMBER_FACES

UI

Le code suivant crée un Dé. Il est lancé et le résultat affiché lorsque l’on clique sur le bouton roll.

Note

Si ce code ne fonctionne pas reportez vous au TP2 où vous avez déjà réglé ce problème.

from appJar import gui
from dice import Dice


dice = Dice()
DICE_LABEL = "dice value"


def on_click(button):
    dice.roll()

    app.setLabel(DICE_LABEL, dice.get_value())

app = gui()
app.setGeometry(400, 200)

app.addLabel(DICE_LABEL, dice.get_value(), 0, 0)
app.addButton("roll", on_click, 0, 1)


app.go()

Ajoutez une ligne de texte contenant l’heure et la valeur du nouveau dé à chaque fois que l’on clique.

Pour cela, vous pourrez utiliser :

Undo

DiceMemento

Créez la classe DiceMemento dans le fichier dice_memento.py et ses tests dans le fichiers test_dice_memento.py.

La classe DiceMemento doit avoir :
  • un Dice comme paramètre du constructeur.
  • une méthode restore() qui remet au dé sauvé la valeur qu’il avait à la création du memento.

Vous pouvez par exemple transformer le code ci-après en test(s) :

dice = Dice()
dice.set_value(2)

memento = DiceMemento(dice)
dice.set_value(6)

memento.restore()
print(dice.get_value())  # doit valoir 2

undo list

Nous allons (enfin, plutôt : vous allez) créer une classe Undo (dans le fichier undo.py) qui va nous permettre de sauver des dés (et leurs valeurs) et de les restaurer à la demande. Cette classe doit pouvoir :
  • sauver un dé avec la méthode : save(dice) (un DiceMemento sera créé dans la méthode save puis sauvegardé)
  • restaurer la dernière valeur sauvée avec la méthode restore()
  • connaitre le nombre d’item sauvegardé avec la commande len (il faut donc implémenter une méthode __len__)

Bien sur vous créerez un fichier de test test_undo.py qui testera les 3 fonctionnalités ci-dessus.

UI : Undo

Ajoutez à l’UI un bouton undo.

A chaque fois que l’on clique sur le bouton roll, la position du dé doit être sauvée. Cette position doit être restaurée lorsque l’on clique sur le bouton undo. De plus, on doit ajouter un message à la listbox qui prévient que la valeur du dé à été undoué.