Compare commits

...

4 Commits

Author SHA1 Message Date
481925d210 rename Limits record to Sample 2026-02-26 00:56:23 +00:00
72e7728e8f rename UKLotto to Lotto to match the national-lottery website
update the launch size of the app window to match the new layout.
2026-02-26 00:03:07 +00:00
46a10812b0 upd image 2026-02-25 23:03:43 +00:00
ccebf3530f improve the look of the GUI 2026-02-25 23:01:05 +00:00
8 changed files with 149 additions and 36 deletions

View File

@ -14,11 +14,15 @@
var window = base.CreateWindow(activationState); var window = base.CreateWindow(activationState);
const int newWidth = 600; const int newWidth = 600;
const int newHeight = 300; const int newHeight = 750;
window.Width = newWidth; window.Width = newWidth;
window.Height = newHeight; window.Height = newHeight;
// Optional: Set minimum size to prevent window from being too small
window.MinimumWidth = 400;
window.MinimumHeight = 600;
return window; return window;
} }
} }

View File

@ -5,10 +5,9 @@
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Lottery" xmlns:local="clr-namespace:Lottery"
Shell.FlyoutBehavior="Disabled" Shell.FlyoutBehavior="Disabled"
Title="Lottery Number Generator"> Title="">
<ShellContent <ShellContent
Title="Lottery Number Generator"
ContentTemplate="{DataTemplate local:MainPage}" ContentTemplate="{DataTemplate local:MainPage}"
Route="MainPage" /> Route="MainPage" />

View File

@ -3,16 +3,16 @@
internal class Generator internal class Generator
{ {
/// <summary> /// <summary>
/// Simple algorithm for generating a list of unique numbers of Limits.Count size /// Simple algorithm for generating a list of unique numbers of sample.Count size.
/// </summary> /// </summary>
/// <param name="limits">Defines the amount of numbers to generate, the min and max values</param> /// <param name="sample">Defines the sample size as well as the upper and lower bounds.</param>
/// <returns>Numbers are returned as a sorted set.</returns> /// <returns>Numbers are returned as a sorted set.</returns>
public static SortedSet<int> Generate(Limits limits) public static SortedSet<int> Generate(Sample sample)
{ {
List<int> candidates = Enumerable.Range(limits.Lower, limits.Upper).ToList(); List<int> candidates = [.. Enumerable.Range(sample.Lower, sample.Upper)];
SortedSet<int> numbers = []; SortedSet<int> numbers = [];
for (int i = 0; i < limits.Count; i++) for (int i = 0; i < sample.Count; i++)
{ {
int RandomIndex = Random.Shared.Next(candidates.Count); int RandomIndex = Random.Shared.Next(candidates.Count);
numbers.Add(candidates[RandomIndex]); numbers.Add(candidates[RandomIndex]);

View File

@ -5,7 +5,7 @@
/// </summary> /// </summary>
enum KindOfLottery : int enum KindOfLottery : int
{ {
Uk, Lotto,
Euro, Euro,
SetForLife, SetForLife,
Thunderball, Thunderball,

View File

@ -1,41 +1,41 @@
namespace Lottery namespace Lottery
{ {
internal record Limits(int Count, int Lower, int Upper); internal record Sample(int Lower, int Upper, int Count);
/// <summary> /// <summary>
/// Abstract base class for lotteries. /// Abstract base class for lotteries.
/// Limits property must be overridden. /// Sample property must be overridden.
/// </summary> /// </summary>
internal abstract class Lottery internal abstract class Lottery
{ {
protected virtual Limits Limits => throw new NotImplementedException(); protected virtual Sample Sample => throw new NotImplementedException();
public virtual string Play() => $"Numbers: {string.Join(", ", Generator.Generate(Limits))}"; public virtual string Play() => $"Numbers: {string.Join(", ", Generator.Generate(Sample))}";
} }
/// <summary> /// <summary>
/// Concrete UKLotto Lottery class. /// Concrete Lotto Lottery class.
/// Generates six balls from 1 to 59. /// Generates six balls from 1 to 59.
/// </summary> /// </summary>
internal class UKLottoLottery : Lottery internal class LottoLottery : Lottery
{ {
protected override Limits Limits { get; } = new(Count: 6, Lower: 1, Upper: 59); protected override Sample Sample { get; } = new(Lower: 1, Upper: 59, Count: 6);
} }
/// <summary> /// <summary>
/// Abstract base class for Lotteries with Special values. /// Abstract base class for Lotteries with Special values.
/// It subclasses Lottery. /// It subclasses Lottery.
/// SpecialLimits and SpecialIdentifier properties must be overridden. /// SpecialSample and SpecialIdentifier properties must be overridden.
/// </summary> /// </summary>
internal abstract class LotteryWithSpecial : Lottery internal abstract class LotteryWithSpecial : Lottery
{ {
protected virtual Limits SpecialLimits => throw new NotImplementedException(); protected virtual Sample SpecialSample => throw new NotImplementedException();
protected virtual string SpecialIdentifier => throw new NotImplementedException(); protected virtual string SpecialIdentifier => throw new NotImplementedException();
public override string Play() public override string Play()
{ {
return string.Join("\t", [ return string.Join("\n", [
$"Numbers: {string.Join(", ", Generator.Generate(Limits))}", $"Numbers: {string.Join(", ", Generator.Generate(Sample))}",
$"{SpecialIdentifier}: {string.Join(", ", Generator.Generate(SpecialLimits))}", $"{SpecialIdentifier}: {string.Join(", ", Generator.Generate(SpecialSample))}",
]); ]);
} }
} }
@ -46,8 +46,8 @@
/// </summary> /// </summary>
internal class EuroMillionsLottery : LotteryWithSpecial internal class EuroMillionsLottery : LotteryWithSpecial
{ {
protected override Limits Limits { get; } = new(Count: 5, Lower: 1, Upper: 50); protected override Sample Sample { get; } = new(Lower: 1, Upper: 50, Count: 5);
protected override Limits SpecialLimits { get; } = new(Count: 2, Lower: 1, Upper: 12); protected override Sample SpecialSample { get; } = new(Lower: 1, Upper: 12, Count: 2);
protected override string SpecialIdentifier => "Lucky Stars"; protected override string SpecialIdentifier => "Lucky Stars";
} }
@ -57,8 +57,8 @@
/// </summary> /// </summary>
internal class SetForLifeLottery : LotteryWithSpecial internal class SetForLifeLottery : LotteryWithSpecial
{ {
protected override Limits Limits { get; } = new(Count: 5, Lower: 1, Upper: 47); protected override Sample Sample { get; } = new(Lower: 1, Upper: 47, Count: 5);
protected override Limits SpecialLimits { get; } = new(Count: 1, Lower: 1, Upper: 10); protected override Sample SpecialSample { get; } = new(Lower: 1, Upper: 10, Count: 1);
protected override string SpecialIdentifier => "Life Ball"; protected override string SpecialIdentifier => "Life Ball";
} }
@ -68,8 +68,8 @@
/// </summary> /// </summary>
internal class ThunderballLottery : LotteryWithSpecial internal class ThunderballLottery : LotteryWithSpecial
{ {
protected override Limits Limits { get; } = new(Count: 5, Lower: 1, Upper: 39); protected override Sample Sample { get; } = new(Lower: 1, Upper: 39, Count: 5);
protected override Limits SpecialLimits { get; } = new(Count: 1, Lower: 1, Upper: 14); protected override Sample SpecialSample { get; } = new(Lower: 1, Upper: 14, Count: 1);
protected override string SpecialIdentifier => "Thunderball"; protected override string SpecialIdentifier => "Thunderball";
} }
} }

View File

@ -1,17 +1,127 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Lottery.MainPage"> x:Class="Lottery.MainPage"
BackgroundColor="{AppThemeBinding Light=#F5F5F5, Dark=#1E1E1E}">
<ScrollView> <ScrollView>
<VerticalStackLayout <VerticalStackLayout
Padding="30,0" Padding="20"
Spacing="25"> Spacing="30"
<Picker x:Name="LotteryPicker" Title="Pick your lottery" SelectedIndexChanged="LotteryPicker_SelectedIndexChanged" /> VerticalOptions="Center"
MaximumWidthRequest="500">
<Label x:Name="NumbersLabel" Text="Click Play to Begin" HorizontalOptions="Center" FontSize="Medium" /> <!-- Header -->
<Label
Text="🎰 Lottery Generator"
FontSize="32"
FontAttributes="Bold"
HorizontalOptions="Center"
TextColor="{AppThemeBinding Light=#2C3E50, Dark=#ECF0F1}"
Margin="0,20,0,10"/>
<!-- Card Container -->
<Border
BackgroundColor="{AppThemeBinding Light=White, Dark=#2D2D30}"
StrokeThickness="0"
Padding="25"
Margin="10,0"
Shadow="{Shadow Brush={AppThemeBinding Light=#40000000, Dark=#60000000}, Offset='0,4', Radius=8, Opacity=0.3}">
<Border.StrokeShape>
<RoundRectangle CornerRadius="16"/>
</Border.StrokeShape>
<VerticalStackLayout Spacing="20">
<!-- Lottery Picker Section -->
<Label
Text="Select Lottery"
FontSize="14"
FontAttributes="Bold"
TextColor="{AppThemeBinding Light=#7F8C8D, Dark=#95A5A6}"
Margin="0,0,0,-10"/>
<Border
BackgroundColor="{AppThemeBinding Light=#F8F9FA, Dark=#3E3E42}"
StrokeThickness="1"
Stroke="{AppThemeBinding Light=#E0E0E0, Dark=#4A4A4F}"
Padding="12,8">
<Border.StrokeShape>
<RoundRectangle CornerRadius="8"/>
</Border.StrokeShape>
<Picker
x:Name="LotteryPicker"
Title="Pick your lottery"
SelectedIndexChanged="LotteryPicker_SelectedIndexChanged"
TextColor="{AppThemeBinding Light=#2C3E50, Dark=#ECF0F1}"
TitleColor="{AppThemeBinding Light=#95A5A6, Dark=#7F8C8D}"
FontSize="16"
BackgroundColor="Transparent"/>
</Border>
<!-- Results Section -->
<BoxView
HeightRequest="1"
Color="{AppThemeBinding Light=#E0E0E0, Dark=#4A4A4F}"
Margin="0,10"/>
<Label
Text="Your Numbers"
FontSize="14"
FontAttributes="Bold"
TextColor="{AppThemeBinding Light=#7F8C8D, Dark=#95A5A6}"
Margin="0,0,0,-10"/>
<Border
BackgroundColor="{AppThemeBinding Light=#E8F5E9, Dark=#1B3A1E}"
StrokeThickness="0"
Padding="20"
MinimumHeightRequest="80">
<Border.StrokeShape>
<RoundRectangle CornerRadius="12"/>
</Border.StrokeShape>
<Label
x:Name="NumbersLabel"
Text="Click Play to Begin"
HorizontalOptions="Center"
VerticalOptions="Center"
FontSize="18"
FontAttributes="Bold"
TextColor="{AppThemeBinding Light=#27AE60, Dark=#52C77A}"
HorizontalTextAlignment="Center"/>
</Border>
<!-- Play Button -->
<Button
x:Name="PlayButton"
Text="🎲 Play"
Clicked="PlayButton_Clicked"
BackgroundColor="{AppThemeBinding Light=#3498DB, Dark=#2980B9}"
TextColor="White"
FontSize="18"
FontAttributes="Bold"
HeightRequest="56"
CornerRadius="12"
Margin="0,10,0,0"
Shadow="{Shadow Brush=#40000000, Offset='0,2', Radius=6, Opacity=0.25}">
<Button.Triggers>
<Trigger TargetType="Button" Property="IsPressed" Value="True">
<Setter Property="Scale" Value="0.96"/>
</Trigger>
</Button.Triggers>
</Button>
</VerticalStackLayout>
</Border>
<!-- Footer -->
<Label
Text="Good luck! 🍀"
FontSize="12"
HorizontalOptions="Center"
TextColor="{AppThemeBinding Light=#95A5A6, Dark=#7F8C8D}"
Margin="0,10,0,20"/>
<Button x:Name="PlayButton" Text="Play" Clicked="PlayButton_Clicked"/>
</VerticalStackLayout> </VerticalStackLayout>
</ScrollView> </ScrollView>

View File

@ -3,19 +3,19 @@
public partial class MainPage : ContentPage public partial class MainPage : ContentPage
{ {
readonly List<Lottery> Lotteries = [ readonly List<Lottery> Lotteries = [
new UKLottoLottery(), new LottoLottery(),
new EuroMillionsLottery(), new EuroMillionsLottery(),
new SetForLifeLottery(), new SetForLifeLottery(),
new ThunderballLottery() new ThunderballLottery()
]; ];
const KindOfLottery DefaultLottery = KindOfLottery.Uk; const KindOfLottery DefaultLottery = KindOfLottery.Lotto;
Lottery Lottery; Lottery Lottery;
public MainPage() public MainPage()
{ {
InitializeComponent(); InitializeComponent();
List<string> lottos = ["UK Lotto", "EuroMillions", "Set For Life", "Thunderball"]; List<string> lottos = ["Lotto", "EuroMillions", "Set For Life", "Thunderball"];
LotteryPicker.ItemsSource = lottos; LotteryPicker.ItemsSource = lottos;
LotteryPicker.SelectedIndex = (int)DefaultLottery; LotteryPicker.SelectedIndex = (int)DefaultLottery;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 33 KiB