11 Commits

Author SHA1 Message Date
a986348168 add python version classifiers
patch bump
2026-02-21 22:57:25 +00:00
bccf1b1ad2 upd pdm badge 2026-02-21 22:16:14 +00:00
3ecfb84a87 remove comment 2026-02-21 22:12:55 +00:00
039487cfc5 sort the numbers before printing them
upd screenshot to reflect sorted results

patch bump
2026-02-21 22:08:45 +00:00
84fcbd326a add annotations 2026-02-21 22:03:52 +00:00
47ced52722 check for empty selection and return early if blank.
this fixes a crash should a draw be attempted without a selection.
2026-02-21 21:56:05 +00:00
9405b4a588 fix the build
minor bump
2026-02-21 21:41:34 +00:00
ea8eae6ec3 patch bump 2026-02-21 21:22:38 +00:00
d3e9363424 remove unused rules 2026-02-21 21:22:07 +00:00
ca2862f3aa replace screenshot 2026-02-21 21:16:30 +00:00
e2e30944b7 typo 2026-02-21 21:10:46 +00:00
6 changed files with 37 additions and 161 deletions

View File

@@ -1,6 +1,6 @@
# Lottery TUI
[![pdm-managed](https://img.shields.io/badge/pdm-managed-blueviolet)](https://pdm.fming.dev)
[![pdm-managed](https://img.shields.io/endpoint?url=https%3A%2F%2Fcdn.jsdelivr.net%2Fgh%2Fpdm-project%2F.github%2Fbadge.json)](https://pdm-project.org)
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
[![PyPI - Version](https://img.shields.io/pypi/v/lottery-tui.svg)](https://pypi.org/project/lottery-tui)
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/lottery-tui.svg)](https://pypi.org/project/lottery-tui)
@@ -25,7 +25,7 @@ uv tool install lottery-tui
*with pipx*
```console
pipx install lotter-tui
pipx install lottery-tui
```
The TUI should now be discoverable as lottery-tui.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 23 KiB

View File

@@ -1,15 +1,32 @@
[project]
name = "lottery-tui"
version = "0.1.0"
version = "0.2.3"
description = "A terminal user interface for lottery games."
authors = [{ name = "onyx-and-iris", email = "code@onyxandiris.online" }]
dependencies = ["textual>=8.0.0"]
requires-python = ">=3.10"
readme = "README.md"
license = { text = "MIT" }
classifiers = [
"Development Status :: 4 - Beta",
"Programming Language :: Python",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
]
[project.scripts]
lottery-tui = "lottery_tui.tui:main"
[build-system]
requires = ["pdm-backend"]
build-backend = "pdm.backend"
[tool.pdm]
distribution = true
[tool.pdm.build]
package-dir = "src"
includes = ["src/**/*", "README.md", "LICENSE"]

View File

@@ -12,7 +12,7 @@ class Result(NamedTuple):
def __str__(self) -> str:
"""Return a string representation of the lottery result."""
out = f'Numbers: {", ".join(str(n) for n in self.numbers)}'
out = f'Numbers: {", ".join(str(n) for n in sorted(self.numbers))}'
if self.bonus:
match self.kind:
case 'EuroMillions':
@@ -23,7 +23,7 @@ class Result(NamedTuple):
bonus_name = 'Thunderball'
case _:
bonus_name = 'Bonus Numbers'
out += f'\n{bonus_name}: {", ".join(str(n) for n in self.bonus)}'
out += f'\n{bonus_name}: {", ".join(str(n) for n in sorted(self.bonus))}'
return out
@@ -40,7 +40,7 @@ class Lottery(ABC):
"""An abstract base class for different types of lotteries."""
@abstractmethod
def draw(self):
def draw(self) -> Result:
"""Perform a lottery draw."""
@@ -54,7 +54,7 @@ class UKlotto(Lottery):
POSSIBLE_NUMBERS = range(1, 60)
def draw(self):
def draw(self) -> Result:
"""Perform a UK Lotto draw."""
result = random.sample(UKlotto.POSSIBLE_NUMBERS, 6)
return Result(kind='UK Lotto', numbers=result, bonus=None)
@@ -71,7 +71,7 @@ class EuroMillions(Lottery):
POSSIBLE_NUMBERS = range(1, 51)
POSSIBLE_BONUS_NUMBERS = range(1, 13)
def draw(self):
def draw(self) -> Result:
"""Perform a EuroMillions draw."""
numbers = random.sample(EuroMillions.POSSIBLE_NUMBERS, 5)
bonus = random.sample(EuroMillions.POSSIBLE_BONUS_NUMBERS, 2)
@@ -88,7 +88,7 @@ class SetForLife(Lottery):
POSSIBLE_NUMBERS = range(1, 40)
def draw(self):
def draw(self) -> Result:
"""Perform a Set For Life draw."""
numbers = random.sample(SetForLife.POSSIBLE_NUMBERS, 5)
life_ball = [random.randint(1, 10)]
@@ -103,9 +103,9 @@ class Thunderball(Lottery):
and 1 "Thunderball" number from a separate pool of 1 to 14, also without replacement.
"""
POSSIBLE_NUMBERS = range(1, 40) # Thunderball numbers range from 1 to 39
POSSIBLE_NUMBERS = range(1, 40)
def draw(self):
def draw(self) -> Result:
"""Perform a Thunderball draw."""
numbers = random.sample(Thunderball.POSSIBLE_NUMBERS, 5)
thunderball = [random.randint(1, 14)]

View File

@@ -37,11 +37,17 @@ class LotteryTUI(App):
def on_button_pressed(self, event):
"""Handle button press events."""
if event.button.id == 'draw-button':
if self.query_one('#lottery-select').is_blank():
self.query_one('#result-label').update(
'Please select a lottery before drawing.'
)
return
selected_lottery = self.query_one('#lottery-select').value
try:
lottery_obj = request_lottery_obj(selected_lottery)
result = lottery_obj.draw()
self.query_one('#result-label').update(f'Result: {result}')
except ValueError as e:
self.query_one('#result-label').update(str(e))

View File

@@ -61,9 +61,7 @@ LotteryTUI {
text-style: bold italic;
}
/* Additional styling for potential future widgets */
/* Button styling for lottery buttons */
/* Button styling */
Button {
background: #ffd700;
border: round #e6c200;
@@ -86,22 +84,6 @@ Button:focus {
color: #1a1a2e;
}
/* Input styling for lottery number inputs */
Input {
background: #2d3748;
border: round #4a5568;
color: #ffd700;
height: 3;
margin: 1;
padding: 0 1;
}
Input:focus {
background: #374151;
border: round #ffd700;
color: #ffed4a;
}
/* Label styling */
Label {
color: #e2e8f0;
@@ -132,7 +114,7 @@ Label {
color: #1a1a2e;
}
/* Results Label Styling - Enhanced Appearance */
/* Results Label Styling */
#result-label {
background: #1a365d;
border: thick #ffd700;
@@ -144,133 +126,4 @@ Label {
text-style: bold;
content-align: left middle;
width: 100%;
}
/* Container for lottery number display */
.lottery-numbers {
align: center middle;
background: #2d3748;
border: round #ffd700;
height: auto;
margin: 2;
padding: 2;
}
/* Individual lottery number balls */
.lottery-ball {
background: #ffd700;
border: round #e6c200;
color: #1a1a2e;
height: 3;
margin: 0 1;
text-align: center;
text-style: bold;
width: 6;
}
.lottery-ball:hover {
background: #ffed4a;
color: #16213e;
}
/* Results display */
.results {
background: #1a202c;
border: round #4a5568;
color: #e2e8f0;
height: auto;
margin: 2;
padding: 2;
}
.winning-number {
color: #48bb78;
text-style: bold;
}
.losing-number {
color: #f56565;
text-style: italic;
}
/* Status bar */
.status-bar {
background: #2d3748;
color: #a0aec0;
dock: bottom;
height: 1;
padding: 0 1;
}
/* Header */
.header {
background: #ffd700;
color: #1a1a2e;
dock: top;
height: 3;
text-align: center;
text-style: bold;
}
/* Footer */
.footer {
background: #1a1a2e;
color: #a0aec0;
dock: bottom;
height: 1;
text-align: center;
text-style: italic;
}
/* Sidebar styling */
.sidebar {
background: #2d3748;
border-right: solid #4a5568;
dock: left;
width: 20;
}
/* Content area */
.content {
background: $surface;
margin: 1;
padding: 1;
}
/* Error messages */
.error {
background: #fed7d7;
border: round #f56565;
color: #c53030;
margin: 1;
padding: 1;
text-style: bold;
}
/* Success messages */
.success {
background: #c6f6d5;
border: round #48bb78;
color: #22543d;
margin: 1;
padding: 1;
text-style: bold;
}
/* Loading spinner */
.loading {
color: #ffd700;
text-align: center;
text-style: bold;
}
/* Prize display */
.prize {
background: #ffd700;
border: round #e6c200;
color: #1a1a2e;
margin: 1;
padding: 2;
text-align: center;
text-style: bold;
}