Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file.
28 changes: 28 additions & 0 deletions projects/001-lotto-game/python/bill_generator/bill.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
class Bill:
"""Represents a single Lotto ticket.

Attributes:
giocata (str): Type of bet (ambata, ambo, etc.).
ruota (str): Wheel on which the game is played.
numbers (List[int]): Numbers generated for the ticket.
"""

def __init__(self, giocata: str, ruota: str, numbers: list[int]):
"""Initializes a Lotto bet slip.

Args:
giocata (str): Type of bet.
ruota (str): Selected wheel.
numbers (List[int]): List of generated numbers.
"""
self.giocata = giocata
self.ruota = ruota
self.numbers = numbers

def __str__(self):
"""Returns a textual representation of the ticket.

Returns:
str: String containing the type of giocata, numbers, and ruota.
"""
return f"{self.giocata} {self.ruota} {self.numbers} "
83 changes: 83 additions & 0 deletions projects/001-lotto-game/python/bill_generator/bill_generator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import random
from typing import List


class BillGenerator:
"""Class to generate numbers, wheels, and play selections."""

@staticmethod
def get_numbers(n_numbers: int) -> list[int]:
"""Generates a list of unique random numbers between 1 and 90.

Args:
n_numbers (int): Number of numbers to generate.

Returns:
List[int]: List of generated numbers.
"""
numbers: list[int] = []
while len(numbers) < n_numbers:
n = random.randint(1, 90)
if n not in numbers:
numbers.append(n)
return numbers

@staticmethod
def get_ruota() -> str:
"""Displays available wheels and allows the user to select one.

Returns:
str: Wheel selected by the user.
"""
print("\nChoose a 'ruota' from the list below:\n")
ruote: List[str] = [
"Bari",
"Cagliari",
"Firenze",
"Genova",
"Milano",
"Napoli",
"Palermo",
"Roma",
"Torino",
"Venezia",
"Tutte",
]

while True:
for i, route in enumerate(ruote, start=1):
print(f"{i}. {route}")

if (choice := input("Select a route: ")).isdigit():
choice = int(choice)
if 1 <= choice <= len(ruote):
return ruote[choice - 1]

print("Invalid 'ruota', try again.\n")

@staticmethod
def giocata() -> tuple[str, int] | None:
"""Displays the available types of play and allows selection.

Returns:
Tuple[str, int]: Name of the play and minimum number of numbers required.
"""
print("\nChoose a 'giocata' from the list below:\n")
giocate_list: dict[str, int] = {
"ambata": 2,
"ambo": 2,
"terno": 3,
"quaterna": 4,
"cinquina": 5,
}
keys: List[str] = list(giocate_list.keys())

for i, play in enumerate(keys, start=1):
print(f"{i}. {play}")

while (choice := input("Select a 'giocata': ")) is not None:
if choice.isdigit() and 1 <= int(choice) <= len(keys):
selected = keys[int(choice) - 1]
return selected, giocate_list[selected]
print("Invalid choice, select a number from the list.\n")
return None
93 changes: 93 additions & 0 deletions projects/001-lotto-game/python/bill_generator/controller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import sys
from typing import List

from bill_generator.bill import Bill
from bill_generator.bill_generator import BillGenerator
from bill_generator.user_interface import UserInterface


class Controller:
"""Controller class to manage ticket generation and display."""

def __init__(self):
"""Initializes the controller and the ticket generator."""
self.bill_generator: BillGenerator = BillGenerator()
self.bills: dict[int, Bill] = {}

def how_many_bills(self) -> int:
"""Asks the user how many tickets to generate.

Returns:
int: Number of tickets to generate.
"""
while True:
try:
if (
num_bills := int(
input(
"How many bills would you like to generate? (1–5, 0 to exit): "
)
)
) == 0:
sys.exit("Thank you for using this program")

if 1 <= num_bills <= 5:
return num_bills

print("Invalid choice. Please select a number between 1 and 5.")

except ValueError:
print("Invalid input, insert only numbers.")

def how_many_numbers_for_bills(self, min_required: int) -> int:
"""Asks the user how many numbers to generate for a ticket.

Args:
min_required (int): Minimum number of numbers required for the selected play.

Returns:
int: Number of numbers chosen by the user.
"""
while True:
try:
if (
numbers := int(
input(
f"How many numbers would you like to generate? (min {min_required}): "
)
)
) >= min_required:
return numbers

print(f"You must insert at least {min_required} numbers.")

except ValueError:
print("Invalid input, numbers only.")

def create_bills(self) -> None:
"""Generates all tickets requested by the user."""
numbers_of_bills: int = self.how_many_bills()

for number in range(numbers_of_bills):
print(f"Generating bill number {number + 1}...")
giocata_name, min_numbers = self.bill_generator.giocata()

numbers_in_bills: int = self.how_many_numbers_for_bills(min_numbers)
ruota: str = self.bill_generator.get_ruota()
numbers: List[int] = self.bill_generator.get_numbers(numbers_in_bills)
bill: Bill = Bill(giocata_name, ruota, numbers)
self.bills[number] = bill

def print_bills(self):
"""Prints all generated tickets."""
if not self.bills:
print("No bills were generated.")
for number, bill in enumerate(self.bills.values(), start=1):
UserInterface.print_bill(number, bill.giocata, bill.ruota, bill.numbers)

def run(self):
"""Runs the full program flow."""
UserInterface.show_intro()
UserInterface.show_description()
self.create_bills()
self.print_bills()
62 changes: 62 additions & 0 deletions projects/001-lotto-game/python/bill_generator/user_interface.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
from typing import List


class UserInterface:
"""Handles displaying tickets on screen."""

def show_intro():
print("Welcome to Lotto Bill Generator")

def show_description():
print("With this software you can generate betting slips for the 'Lotto game'")
print(
"\nDISCLAIMER: There is no scientific proof of the correlation between the tickets generated and the probability of winning.\n"
)

@staticmethod
def print_bill(
bill_number: int, giocata: str, ruota: str, numbers: List[int]
) -> None:
"""Prints a ticket in a dynamic centered table.

Args:
bill_number (int): Number of the generated ticket.
giocata (str): Type of play.
ruota (str): Selected wheel.
numbers (List[int]): Generated numbers for the ticket.
"""
numbers_str: str = " ".join(str(n) for n in numbers)
headers: List[str] = ["Bill", "Giocata", "Ruota", "Generate Numbers"]
row: List[str] = [f"Bill {bill_number}", giocata, ruota, numbers_str]

col_widths: List[int] = [
max(len(headers[i]), len(str(row[i]))) + 2 for i in range(len(headers))
]

def make_line(left: str, fill: str, sep: str, right: str) -> str:
return left + sep.join(fill * w for w in col_widths) + right

def center_text(text: str, width: int) -> str:
return text.center(width)

def make_row(items: List[str]) -> str:
cells: List[str] = [
center_text(items[i], col_widths[i]) for i in range(len(items))
]
return "║" + "║".join(cells) + "║"

top: str = make_line("╔", "═", "╦", "╗")
sep: str = make_line("╠", "═", "╬", "╣")
bottom: str = make_line("╚", "═", "╩", "╝")

bill: str = f"""


{top}
{make_row(headers)}
{sep}
{make_row(row)}
{bottom}

"""
print(bill)
5 changes: 5 additions & 0 deletions projects/001-lotto-game/python/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from bill_generator.controller import Controller

if __name__ == "__main__":
controller = Controller()
controller.run()