diff --git a/give_away.py b/give_away.py index f568916..dac7b74 100644 --- a/give_away.py +++ b/give_away.py @@ -4,70 +4,111 @@ # Copyright: MIT #--------------------------------------------- - import csv import signal import sys -import os +import os import random from collections import namedtuple from random import shuffle +# Defining data type for namedtuple +Participant = namedtuple('participants', ['name', 'lastname']) +Reward = namedtuple('reward', ['item']) -# load csv files -def cvsReader(filename:str) -> list: +def cvsReader(filename:str) -> list: + """ + The function `cvsReader` reads a CSV file and returns its data as a list of named tuples. + """ with open('{}.csv'.format(filename),'r') as f: reader = csv.reader(f) data = namedtuple(filename,next(reader)) return [data(*row) for row in reader ] - -participants = cvsReader('participants') -reward = cvsReader('reward') - -winners = [] - -def winner(data:list) -> str: - try: - shuffle(data) - w = data.pop() - w = '{} {}'.format(w.name,w.lastname) - winners.append(w) - return w - except IndexError: - os.kill(os.getpid(), signal.SIGINT) - -def get_reward(data:list) -> str: - try: - shuffle(data) - w = random.choice(data) - w = '{}'.format(w.item) - remove_reward(w) - return w - except IndexError: - os.kill(os.getpid(), signal.SIGINT) +def winner(data:list[Participant]) -> str: + """ + This Python function randomly selects a participant from a list, adds their full name to a winners + list, and then deletes the participant from the list. + """ + if not data: + raise ValueError("The participant list is empty.") + + if not isinstance(data, list): + raise TypeError("The data must be of type list.") + + if not all(isinstance(participant, tuple) and hasattr(participant, 'name') and hasattr(participant, 'lastname') for participant in data): + raise AttributeError("All elements in the data must be of type Participant.") + + shuffle(data) + w = random.choice(data) + w = '{} {}'.format(w.name,w.lastname) + winners.append(w) + delete_participant_by_fullname(w) + return w + +def get_reward(data:list[Reward]) -> str: + """ + This function randomly selects and returns a reward item from a list, removing it from the list in + the process, and raises an IndexError exception if the list is empty. + """ + if not data: + raise ValueError("The reward list is empty.") + + if not isinstance(data, list): + raise TypeError("The data must be of type list.") + + if not all(isinstance(reward, tuple) and hasattr(reward, 'item') for reward in data): + raise AttributeError("All elements in the data must be of type Participant.") + + shuffle(data) + w = random.choice(data) + w = '{}'.format(w.item) + remove_reward(w) + return w def exit_app(signal,frame): - ''' - Exit the loop with Ctrl-C - ''' + """ + The function `exit_app` prints out a congratulatory message to the winners and exits the + application. + """ w = "\n".join(winners) print("\nFelicitaciones a las personas Ganadoras\n{}".format(w)) sys.exit(0) def remove_reward(r): + """ + The function `remove_reward` iterates through a list of reward objects and removes the object with a + specific item value. + """ for reward_object in reward: if(reward_object.item == r): reward.remove(reward_object) -signal.signal(signal.SIGINT, exit_app) +def delete_participant_by_fullname(fullname: str): + """ + This function deletes a participant from a list based on their full name. + """ + name, lastname = fullname.split(" ", 1) + + participants[:] = [p for p in participants if not (p.name.lower() == name.lower() and p.lastname.lower() == lastname.lower())] +def run_app(): + for x in range(0, len(reward)): + try: + input("El premio es para ....") + print(winner(participants) + " [ PREMIO: "+ get_reward(reward) +" ]") + except Exception as e: + print('ERROR-HANDLE', e) + os.kill(os.getpid(), signal.SIGINT) - -for x in range(0, len(reward)): - input("El premio es para ....") - print(winner(participants) + " [ PREMIO: "+ get_reward(reward) +" ]") +# Global variable +signal.signal(signal.SIGINT, exit_app) +participants: list[Participant] = cvsReader('participants') +reward: list[Reward] = cvsReader('reward') +winners: list[Participant] = [] -w = "\n".join(winners) -print("\nFelicitaciones a las personas Ganadoras\n{}".format(w)) +if __name__ == '__main__': + run_app() + w = "\n".join(winners) + print("\nFelicitaciones a las personas Ganadoras\n{}".format(w)) diff --git a/participants_test_data.csv b/participants_test_data.csv new file mode 100644 index 0000000..b31a685 --- /dev/null +++ b/participants_test_data.csv @@ -0,0 +1,25 @@ +name,lastname +Leonardo,Orozco +jose,vallejo +carlos, perez +name,lastname +cesar,herdenez +javier,daza +Leonardo,Orozco +Leonardo,Orozco +Leonardo,Orozco +javier,daza +javier,daza +javier,daza +cesar,herdenez +cesar,herdenez +cesar,herdenez +cesar,herdenez +cesar,herdenez +cesar,herdenez +cesar,herdenez +cesar,herdenez +cesar,herdenez +cesar,herdenez +cesar,herdenez +cesar,herdenez \ No newline at end of file diff --git a/reward.csv b/reward.csv index 08d1b2d..d54d024 100644 --- a/reward.csv +++ b/reward.csv @@ -1,4 +1,5 @@ item Mackbook Pro Cup of tea -Camiseta del evento \ No newline at end of file +Camiseta del evento +Balon de futbol \ No newline at end of file diff --git a/test_give_away.py b/test_give_away.py new file mode 100644 index 0000000..a090c8d --- /dev/null +++ b/test_give_away.py @@ -0,0 +1,52 @@ +from collections import namedtuple +import unittest +import give_away; + +class TestStringMethods(unittest.TestCase): + def test_winner_should_return_random_user(self): + w: str = give_away.winner(give_away.cvsReader('participants_test_data')) + assert isinstance(w, str) and w is not '' + + def test_winner_handle_empty_param(self): + with self.assertRaises(ValueError): + give_away.winner([]) + + def test_winner_should_handle_type_error(self): + with self.assertRaises(TypeError): + give_away.winner("not a list") + + with self.assertRaises(TypeError): + give_away.winner(1) + + with self.assertRaises(TypeError): + give_away.winner({'test': 1}) + + def test_winner_with_tuple_missing_attribute(self): + ParticipantWithoutName = namedtuple('ParticipantWithoutName', ['lastname']) + ParticipantWithoutLasName = namedtuple('ParticipantWithoutName', ['name']) + + participants = [ParticipantWithoutName('Orozco'), ParticipantWithoutName('Herdenez')] + with self.assertRaises(AttributeError): + give_away.winner(participants) + + participants = [ParticipantWithoutLasName('Pedro'), ParticipantWithoutName('Carlos')] + with self.assertRaises(AttributeError): + give_away.winner(participants) + + def test_winner_with_tuple_different_attribute(self): + ParticipantWithoutName = namedtuple('ParticipantWithoutName', ['lastName', 'firstName']) + + participants = [ParticipantWithoutName('Orozco', 'Pedro'), ParticipantWithoutName('Perez', 'Jose')] + + with self.assertRaises(AttributeError): + give_away.winner(participants) + + def test_winner_should_remove_winners_of_data(self): + give_away.participants = give_away.cvsReader('participants_test_data'); + initial_len = len(give_away.participants) + give_away.winner(give_away.cvsReader('participants_test_data')) + self.assertNotEqual(initial_len, len(give_away.participants)) + + +if __name__ == '__main__': + unittest.main() \ No newline at end of file