mirror of
https://github.com/onyx-and-iris/lottery-tui.git
synced 2026-04-19 18:13:29 +00:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 039487cfc5 | |||
| 84fcbd326a | |||
| 47ced52722 | |||
| 9405b4a588 | |||
| ea8eae6ec3 | |||
| d3e9363424 | |||
| ca2862f3aa | |||
| e2e30944b7 |
@@ -25,7 +25,7 @@ uv tool install lottery-tui
|
|||||||
*with pipx*
|
*with pipx*
|
||||||
|
|
||||||
```console
|
```console
|
||||||
pipx install lotter-tui
|
pipx install lottery-tui
|
||||||
```
|
```
|
||||||
|
|
||||||
The TUI should now be discoverable as lottery-tui.
|
The TUI should now be discoverable as lottery-tui.
|
||||||
|
|||||||
BIN
img/tui.png
BIN
img/tui.png
Binary file not shown.
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 23 KiB |
@@ -1,6 +1,6 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "lottery-tui"
|
name = "lottery-tui"
|
||||||
version = "0.1.0"
|
version = "0.2.2"
|
||||||
description = "A terminal user interface for lottery games."
|
description = "A terminal user interface for lottery games."
|
||||||
authors = [{ name = "onyx-and-iris", email = "code@onyxandiris.online" }]
|
authors = [{ name = "onyx-and-iris", email = "code@onyxandiris.online" }]
|
||||||
dependencies = ["textual>=8.0.0"]
|
dependencies = ["textual>=8.0.0"]
|
||||||
@@ -11,5 +11,13 @@ license = { text = "MIT" }
|
|||||||
[project.scripts]
|
[project.scripts]
|
||||||
lottery-tui = "lottery_tui.tui:main"
|
lottery-tui = "lottery_tui.tui:main"
|
||||||
|
|
||||||
|
[build-system]
|
||||||
|
requires = ["pdm-backend"]
|
||||||
|
build-backend = "pdm.backend"
|
||||||
|
|
||||||
[tool.pdm]
|
[tool.pdm]
|
||||||
distribution = true
|
distribution = true
|
||||||
|
|
||||||
|
[tool.pdm.build]
|
||||||
|
package-dir = "src"
|
||||||
|
includes = ["src/**/*", "README.md", "LICENSE"]
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ class Result(NamedTuple):
|
|||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
"""Return a string representation of the lottery result."""
|
"""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:
|
if self.bonus:
|
||||||
match self.kind:
|
match self.kind:
|
||||||
case 'EuroMillions':
|
case 'EuroMillions':
|
||||||
@@ -23,7 +23,7 @@ class Result(NamedTuple):
|
|||||||
bonus_name = 'Thunderball'
|
bonus_name = 'Thunderball'
|
||||||
case _:
|
case _:
|
||||||
bonus_name = 'Bonus Numbers'
|
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
|
return out
|
||||||
|
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ class Lottery(ABC):
|
|||||||
"""An abstract base class for different types of lotteries."""
|
"""An abstract base class for different types of lotteries."""
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def draw(self):
|
def draw(self) -> Result:
|
||||||
"""Perform a lottery draw."""
|
"""Perform a lottery draw."""
|
||||||
|
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ class UKlotto(Lottery):
|
|||||||
|
|
||||||
POSSIBLE_NUMBERS = range(1, 60)
|
POSSIBLE_NUMBERS = range(1, 60)
|
||||||
|
|
||||||
def draw(self):
|
def draw(self) -> Result:
|
||||||
"""Perform a UK Lotto draw."""
|
"""Perform a UK Lotto draw."""
|
||||||
result = random.sample(UKlotto.POSSIBLE_NUMBERS, 6)
|
result = random.sample(UKlotto.POSSIBLE_NUMBERS, 6)
|
||||||
return Result(kind='UK Lotto', numbers=result, bonus=None)
|
return Result(kind='UK Lotto', numbers=result, bonus=None)
|
||||||
@@ -71,7 +71,7 @@ class EuroMillions(Lottery):
|
|||||||
POSSIBLE_NUMBERS = range(1, 51)
|
POSSIBLE_NUMBERS = range(1, 51)
|
||||||
POSSIBLE_BONUS_NUMBERS = range(1, 13)
|
POSSIBLE_BONUS_NUMBERS = range(1, 13)
|
||||||
|
|
||||||
def draw(self):
|
def draw(self) -> Result:
|
||||||
"""Perform a EuroMillions draw."""
|
"""Perform a EuroMillions draw."""
|
||||||
numbers = random.sample(EuroMillions.POSSIBLE_NUMBERS, 5)
|
numbers = random.sample(EuroMillions.POSSIBLE_NUMBERS, 5)
|
||||||
bonus = random.sample(EuroMillions.POSSIBLE_BONUS_NUMBERS, 2)
|
bonus = random.sample(EuroMillions.POSSIBLE_BONUS_NUMBERS, 2)
|
||||||
@@ -88,7 +88,7 @@ class SetForLife(Lottery):
|
|||||||
|
|
||||||
POSSIBLE_NUMBERS = range(1, 40)
|
POSSIBLE_NUMBERS = range(1, 40)
|
||||||
|
|
||||||
def draw(self):
|
def draw(self) -> Result:
|
||||||
"""Perform a Set For Life draw."""
|
"""Perform a Set For Life draw."""
|
||||||
numbers = random.sample(SetForLife.POSSIBLE_NUMBERS, 5)
|
numbers = random.sample(SetForLife.POSSIBLE_NUMBERS, 5)
|
||||||
life_ball = [random.randint(1, 10)]
|
life_ball = [random.randint(1, 10)]
|
||||||
@@ -105,7 +105,7 @@ class Thunderball(Lottery):
|
|||||||
|
|
||||||
POSSIBLE_NUMBERS = range(1, 40) # Thunderball numbers range from 1 to 39
|
POSSIBLE_NUMBERS = range(1, 40) # Thunderball numbers range from 1 to 39
|
||||||
|
|
||||||
def draw(self):
|
def draw(self) -> Result:
|
||||||
"""Perform a Thunderball draw."""
|
"""Perform a Thunderball draw."""
|
||||||
numbers = random.sample(Thunderball.POSSIBLE_NUMBERS, 5)
|
numbers = random.sample(Thunderball.POSSIBLE_NUMBERS, 5)
|
||||||
thunderball = [random.randint(1, 14)]
|
thunderball = [random.randint(1, 14)]
|
||||||
|
|||||||
@@ -37,11 +37,17 @@ class LotteryTUI(App):
|
|||||||
def on_button_pressed(self, event):
|
def on_button_pressed(self, event):
|
||||||
"""Handle button press events."""
|
"""Handle button press events."""
|
||||||
if event.button.id == 'draw-button':
|
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
|
selected_lottery = self.query_one('#lottery-select').value
|
||||||
|
|
||||||
try:
|
try:
|
||||||
lottery_obj = request_lottery_obj(selected_lottery)
|
lottery_obj = request_lottery_obj(selected_lottery)
|
||||||
result = lottery_obj.draw()
|
result = lottery_obj.draw()
|
||||||
self.query_one('#result-label').update(f'Result: {result}')
|
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
self.query_one('#result-label').update(str(e))
|
self.query_one('#result-label').update(str(e))
|
||||||
|
|
||||||
|
|||||||
@@ -61,9 +61,7 @@ LotteryTUI {
|
|||||||
text-style: bold italic;
|
text-style: bold italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Additional styling for potential future widgets */
|
/* Button styling */
|
||||||
|
|
||||||
/* Button styling for lottery buttons */
|
|
||||||
Button {
|
Button {
|
||||||
background: #ffd700;
|
background: #ffd700;
|
||||||
border: round #e6c200;
|
border: round #e6c200;
|
||||||
@@ -86,22 +84,6 @@ Button:focus {
|
|||||||
color: #1a1a2e;
|
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 styling */
|
||||||
Label {
|
Label {
|
||||||
color: #e2e8f0;
|
color: #e2e8f0;
|
||||||
@@ -132,7 +114,7 @@ Label {
|
|||||||
color: #1a1a2e;
|
color: #1a1a2e;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Results Label Styling - Enhanced Appearance */
|
/* Results Label Styling */
|
||||||
#result-label {
|
#result-label {
|
||||||
background: #1a365d;
|
background: #1a365d;
|
||||||
border: thick #ffd700;
|
border: thick #ffd700;
|
||||||
@@ -145,132 +127,3 @@ Label {
|
|||||||
content-align: left middle;
|
content-align: left middle;
|
||||||
width: 100%;
|
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;
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user