From 4fdacb561d1840f41a6de2e099cf41b1166a3347 Mon Sep 17 00:00:00 2001 From: Dahmane Lynda <lynda.dahmane.etu@118p28.fil.univ-lille.fr> Date: Wed, 27 Mar 2024 10:26:17 +0100 Subject: [PATCH] Tp8 --- Tp8/bataille-carte.zip | Bin 0 -> 5560 bytes Tp8/bataille-carte/apl1test.py | 89 +++++++++++++++ Tp8/bataille-carte/apqueue.py | 104 +++++++++++++++++ Tp8/bataille-carte/apstack.py | 126 +++++++++++++++++++++ Tp8/bataille-carte/card.py | 197 +++++++++++++++++++++++++++++++++ Tp8/bataille-carte/war.py | 91 +++++++++++++++ 6 files changed, 607 insertions(+) create mode 100644 Tp8/bataille-carte.zip create mode 100644 Tp8/bataille-carte/apl1test.py create mode 100644 Tp8/bataille-carte/apqueue.py create mode 100644 Tp8/bataille-carte/apstack.py create mode 100755 Tp8/bataille-carte/card.py create mode 100644 Tp8/bataille-carte/war.py diff --git a/Tp8/bataille-carte.zip b/Tp8/bataille-carte.zip new file mode 100644 index 0000000000000000000000000000000000000000..c80b007b4f8b729e06787f0cc5effd95f1d7383a GIT binary patch literal 5560 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 V$_5H=Rt8pvX^adEJfH|-002;(<}UyM literal 0 HcmV?d00001 diff --git a/Tp8/bataille-carte/apl1test.py b/Tp8/bataille-carte/apl1test.py new file mode 100644 index 0000000..8533cca --- /dev/null +++ b/Tp8/bataille-carte/apl1test.py @@ -0,0 +1,89 @@ +import thonnycontrib +from thonnycontrib.backend.evaluator import Evaluator +import thonnycontrib.backend.l1test_backend +from thonny.plugins.cpython_backend.cp_back import MainCPythonBackend +import thonnycontrib.backend.doctest_parser +from thonnycontrib.backend.doctest_parser import ExampleWithExpected, ExampleWithoutExpected +import thonnycontrib.backend.ast_parser +from thonnycontrib.backend.ast_parser import L1DocTest +import thonnycontrib.backend.verdicts +from thonnycontrib.backend.verdicts.ExceptionVerdict import ExceptionVerdict + +import inspect +import tempfile +import os +import sys + +class MockBackend(MainCPythonBackend): + """ + Fake backend. + """ + def __init__(self): + ... + + def send_message(self, msg) -> None: + ... + +# register backend +thonnycontrib.backend.l1test_backend.BACKEND = MockBackend() + +def l1test_to_org(filename: str, source: str=""): + """ + Return an org abstract of the tests presents in `filename` file. + """ + abstract = {'total': 0, + 'success': 0, + 'failures': 0, + 'errors': 0, + 'empty': 0} + + if source == "": + with open(filename, 'rt') as fin: + source = fin.read() + evaluator = Evaluator(filename=filename, + source=source) + tests = evaluator.evaluate() + n = len(tests) + abstract['total'] = n + res = "" + for test in tests: + examples = test.get_examples() + res_examples = "" + nb_test, nb_test_ok = 0, 0 + empty = True + for example in examples: + verdict = test.get_verdict_from_example(example) + if isinstance(example, ExampleWithExpected): + nb_test += 1 + if verdict.isSuccess(): + nb_test_ok += 1 + abstract['success'] += 1 + else: + abstract['failures'] += 1 + empty = False + if isinstance(verdict, ExceptionVerdict): + abstract['errors'] += 1 + empty = False + res_examples += f"** {verdict}\n\n" + if not verdict.isSuccess(): + res_examples += f" {verdict.get_details()}\n\n" + if not empty: + res += f"* {test.get_name()} ~ {nb_test_ok}/{nb_test} réussis\n\n" + else: + abstract['empty'] += 1 + res += f"* {test.get_name()}\n\n Aucun test trouvé !\n\n" + res += res_examples + res = f"Tests exécutés : {abstract['total']}\nSuccès: {abstract['success']}, \ +Echecs: {abstract['failures']}, Erreurs: {abstract['errors']}, \ +Vide: {abstract['empty']}\n\n" + res + return res + + +def testmod(modulename: str): + """ + mimic the doctest.testmod function + for `modulename` module + """ + print(l1test_to_org(modulename)) + + diff --git a/Tp8/bataille-carte/apqueue.py b/Tp8/bataille-carte/apqueue.py new file mode 100644 index 0000000..cdc44f7 --- /dev/null +++ b/Tp8/bataille-carte/apqueue.py @@ -0,0 +1,104 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + +""" +:mod:`apqueue` module + +:author: `FIL - Faculté des Sciences et Technologies - + Univ. Lille <http://portail.fil.univ-lille1.fr>`_ + +:date: 2015, september +:last revision: 2024, March + +A module for queue data structure. + +:Provides: + +* class ApQueue + +and methods + +* `enqueue` +* `dequeue` +* `is_empty` +""" +from typing import TypeVar +T = TypeVar('T') + +class ApQueueEmptyError(Exception): + """ + Exception for empty stacks + """ + def __init__(self, msg): + self.message = msg + + +class ApQueue(): + """ + $$$ ap_queue = ApQueue() + $$$ ap_queue.is_empty() + True + $$$ ap_queue.enqueue(1) + $$$ ap_queue.is_empty() + False + $$$ ap_queue.enqueue(2) + $$$ str(ap_queue) + '→2|1→' + $$$ ap_queue.dequeue() + 1 + $$$ ap_queue.dequeue() + 2 + $$$ ap_queue.is_empty() + True + $$e ap_queue.dequeue() + ApQueueEmptyError + """ + ARROW = chr(0x2192) + + def __init__(self): + """ + build a new empty queue + precondition: none + """ + self.__content = [] + + def enqueue(self, elt: T): + """ + insert an element at the begining of the queue + precondition: none + """ + self.__content.insert(0, elt) + + def dequeue(self) -> T: + """ + return the element on top of self + Side effect: self contains an element less + precondition: self must be non empty + """ + if len(self.__content) > 0: + res = self.__content.pop() + else: + raise ApQueueEmptyError('empty queue, nothing to dequeue') + return res + + def is_empty(self) -> bool: + """ + return: + * ``True`` if s is empty + * ``False`` otherwise + precondition: none + """ + return self.__content == [] + + def __str__(self) -> str: + """ + return the string representation of this queue. + """ + return ApQueue.ARROW + \ + "|".join(str(el) for el in self.__content) + \ + ApQueue.ARROW + + +if __name__ == '__main__': + import apl1test + apl1test.testmod('apqueue.py') diff --git a/Tp8/bataille-carte/apstack.py b/Tp8/bataille-carte/apstack.py new file mode 100644 index 0000000..d9a5121 --- /dev/null +++ b/Tp8/bataille-carte/apstack.py @@ -0,0 +1,126 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + +""" +:mod:`stack` module + +:author: `FIL - Faculté des Sciences et Technologies - + Univ. Lille <http://portail.fil.univ-lille1.fr>`_ + +:date: 2015, september +:last revision: 2017, october + +A module for stack data structure. + +:Provides: + +* class ApStack + +and methods + +* `push` +* `pop` +* `top` +* `is_empty` + +:Examples: +""" +from typing import TypeVar +T = TypeVar('T') + +class ApStackEmptyError(Exception): + """ + Exception for empty stacks + """ + def __init__(self, msg): + self.message = msg + + +class ApStack(): + """ + $$$ stak = ApStack() + $$$ stak.is_empty() + True + $$$ stak.push(1) + $$$ stak.is_empty() + False + $$$ stak.push(2) + $$$ stak.top() + 2 + $$$ stak.pop() + 2 + $$$ stak.top() + 1 + $$$ stak.pop() + 1 + $$$ stak.is_empty() + True + $$e stak.pop() + ApStackEmptyError + """ + + def __init__(self): + """ + build a new empty stack + précondition : none + """ + self.__content = [] + + def push(self, el: T): + """ + add el on top of the stack. + précondition : none + """ + self.__content.append(el) + + def pop(self) -> T: + """ + return the element on top of self + + Side effect: self contains an element less + + précondition : self must be non empty + """ + if len(self.__content) == 0: + raise ApStackEmptyError('empty stack, nothing to pop') + return self.__content.pop() + + def top(self) -> T: + """ + return the element on top of self without removing it + + précondition : self must be non empty + """ + if len(self.__content) == 0: + raise ApStackEmptyError('empty stack, nothing to pop') + return self.__content[-1] + + def is_empty(self) -> bool: + """ + return: + * ``True`` if s is empty + * ``False`` otherwise + précondition : none + """ + return self.__content == [] + + def __str__(self) -> str: + """ + return a stack representation + """ + mlen = 1 + if not self.is_empty(): + mlen = max(len(str(el)) for el in self.__content) + res = [] + for el in self.__content: + pad = mlen - len(str(el)) + left = pad // 2 + right = pad - left + res.insert(0, "|" + " " * left + str(el) + " " * right + "|") + res.append("+" + "-" * mlen + "+") + return "\n".join(res) + + +if (__name__ == '__main__'): + import apl1test + apl1test.testmod('apstack.py') diff --git a/Tp8/bataille-carte/card.py b/Tp8/bataille-carte/card.py new file mode 100755 index 0000000..ce1e8e1 --- /dev/null +++ b/Tp8/bataille-carte/card.py @@ -0,0 +1,197 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + +""" +:mod:`card` module + +:author: `FIL - Faculté des Sciences et Technologies - + Univ. Lille <http://portail.fil.univ-lille1.fr>`_ + +:date: 2017, september. +:last revision: 2024, march + +""" +from __future__ import annotations +import random + + + +class Card(object): + """ + Cards are defined by a value and a color. + Possible values and colors are listed in ``Card.VALUES`` and ``Card.COLORS``. + + $$$ c1 = Card("Ace", "heart") + $$$ c1.color + 'heart' + $$$ c1.value + 'Ace' + $$$ c1 + Card("Ace", "heart") + $$$ c2 = Card("King", "spade") + $$$ c2.value in Card.VALUES + True + $$$ c2.color in Card.COLORS + True + $$$ c1 == c1 + True + $$$ c1 != c1 + False + $$$ c1 < c1 + False + $$$ c1 <= c1 + True + """ + + ## tuple of possible values and colors in ascending order + VALUES = ("Ace", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Knight", "Queen", "King") + COLORS = ("spade", "heart", "diamond", "club") + + def __init__(self, value: str, color: str): + """ + creates a card with value and color + + précondition : value in VALUES and color in COLORS + """ + self.value=value + self.color=color + + + def __hash__(self) -> int: + """ + Renvoie un haché de self. + """ + return hash((self.color,self.value)) + + def __repr__(self) -> str: + """ + return a string representation of the card + + $$$ repr(Card('Ace', 'heart')) + 'Card("Ace", "heart")' + """ + return f"Card('{self.value}','{self.color}')" + + def compare(self, card: Card) -> int: + """ + compares cards. + + Order on cards is defined by order on values + + return: + + * a positive number if self is greater than card + * a negative number if self is lower than card + * 0 if self is the same than card + + précondition: none + exemples: + + $$$ c1 = Card('Ace', 'heart') + $$$ c2 = Card('King', 'heart') + $$$ c3 = Card('Ace','spade') + $$$ c1bis = Card('Ace','heart') + $$$ c1.compare(c2) < 0 + True + $$$ c2.compare(c1) > 0 + True + $$$ c1.compare(c3) == 0 + True + """ + self_index=self.VALUES.index(self.value) + Card_index=self.VALUES.index(Card.value) + return self_index-card_index + + + @staticmethod + def deck(n_card: int) -> list[Card]: + """ + return a list of `n_card` randomly chosen cards + + precondition: n_card > 0 and n_card <= 4*13 + + Exemples: + + $$$ cartes = Card.deck( 10 ) + $$$ len(cartes) == 10 + True + $$$ all( isinstance(c, Card) for c in cartes) + True + $$$ len(set(cartes)) + len(cartes) + """ + deck=[] + for i in range(n_Card): + value=random.choice(Card.VALUES) + color=random.choice(Card.COLORS) + card=Card(value,color) + deck.append(card) + return deck + + def __eq__(self, card: Card) -> bool: + """ + return True if self equals card + False otherwise + """ + if self.value==card.value and self.color==card.color: + return True + else: + return False + + def __neq__(self, card: Card) -> bool: + """ + return True if self don't equal card + False otherwise + """ + if self.value!=card.value and self.color!=card.color: + return True + else: + return False + + + def __lt__(self, card: Card) -> bool: + """ + return True if self is strictly inferior to card + False otherwise + """ + if self.VALUES.index(self.value) < self.VALUES.index(card.value): + return True + else: + return False + + + def __le__(self, card: Card) -> bool: + """ + return True if self is inferior or equal to card + False otherwise + """ + if self.VALUES.index(self.value) <= self.VALUES.index(card.value): + return True + else: + return False + + def __gt__(self, card: Card) -> bool: + """ + return True if self is strictly superior to card + False otherwise + """ + if self.VALUES.index(self.value) > self.VALUES.index(card.value): + return True + else: + return False + + def __ge__(self, card: Card) -> bool: + """ + return True if self is superior or equal to card + False otherwise + """ + if self.VALUES.index(self.value) >= self.VALUES.index(card.value): + return True + else: + return False + + +if (__name__ == '__main__'): + import apl1test + apl1test.testmod('card.py') + diff --git a/Tp8/bataille-carte/war.py b/Tp8/bataille-carte/war.py new file mode 100644 index 0000000..e1acacc --- /dev/null +++ b/Tp8/bataille-carte/war.py @@ -0,0 +1,91 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + +""" +:mod:`war` game + +:author: `FIL - Faculté des Sciences et Technologies - + Univ. Lille <http://portail.fil.univ-lille1.fr>` + +:date: 2021, april. +:last revision: 2024, march. +""" + +from card import Card +from apqueue import * +from apstack import * + + +def distribute(n_card: int) -> tuple[ApQueue, ApQueue]: + """ + renvoie un couple (m1, m2) constitué de deux files, + contenant pour chacune `n_card` cartes + + precondition : n_card > 0 + exemples : + + $$$ m1, m2 = distribute( 4 ) + $$$ len(m1) == 4 + True + $$$ len(m2) == 4 + True + $$$ type(m1) == ApQueue + True + $$$ type(m2) == ApQueue + True + $$$ carte = m1.dequeue() + $$$ isinstance(carte, Card) + True + """ + ... + +def gather_stack(main: ApQueue, pile: ApStack) -> None: + """ + ajoute les carte de la pile dans la main + + exemples : + + $$$ cartes = Card.deck(4) + $$$ main = ApQueue() + $$$ pile = ApStack() + $$$ for c in cartes: + ... pile.push(c) + $$$ gather_stack( main, pile ) + $$$ len( main ) == 4 + True + $$$ all( main.dequeue() == cartes[ 3 - i ] for i in range(3)) + True + """ + ... + +def play_one_round(m1: ApQueue, m2: ApQueue, pile: ApStack) -> None: + """ + Simule une étape du jeu : + `j1`` et ``j2`` prennent la première carte de leur + main. On compare les deux cartes : + + * Si la carte de ``j1`` est supérieure à celle de ``j2``, alors + ``j1`` remporte toutes les cartes de la pile ; + * Si la carte de ``j1`` est inférieure à celle de ``j2``, alors + ``j2`` remporte toutes les cartes de la pile ; + * Si les cartes sont égales, alors elles sont *empilées* sur la + pile. + + precondition : m1 et m2 ne sont pas vides + """ + ... + +def play(n_card: int, n_round: int) -> None: + """ + simule une partie de bataille + + n_card: le nombre de cartes à distribuer à chaque joueur. + n_round: le nombre maximal de tours + """ + ... + + +if __name__ == "__main__": + import apl1test + apl1test.testmod("war.py") + -- GitLab