mirror of
https://github.com/onyx-and-iris/lottery-cli.git
synced 2026-08-17 08:44:25 +00:00
initial commit
This commit is contained in:
30
.github/workflows/golang-ci.yml
vendored
Normal file
30
.github/workflows/golang-ci.yml
vendored
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: ['main']
|
||||||
|
paths:
|
||||||
|
- '**.go'
|
||||||
|
pull_request:
|
||||||
|
branches: ['main']
|
||||||
|
paths:
|
||||||
|
- '**.go'
|
||||||
|
jobs:
|
||||||
|
lint:
|
||||||
|
name: Lint
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.event_name == 'pull_request'
|
||||||
|
timeout-minutes: 3
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 1
|
||||||
|
- name: Setup Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: '1.24'
|
||||||
|
- name: golangci-lint
|
||||||
|
uses: golangci/golangci-lint-action@v9
|
||||||
|
with:
|
||||||
|
version: v2.6.0
|
||||||
|
args: --config .golangci.yml
|
||||||
28
.github/workflows/release.yml
vendored
Normal file
28
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
name: goreleaser
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
goreleaser:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
- name: Run GoReleaser
|
||||||
|
uses: goreleaser/goreleaser-action@v6
|
||||||
|
with:
|
||||||
|
distribution: goreleaser
|
||||||
|
version: '~> v2'
|
||||||
|
args: release --clean
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
30
.github/workflows/update-go-modules.yml
vendored
Normal file
30
.github/workflows/update-go-modules.yml
vendored
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
name: Auto-Update Go Modules
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 * * 1' # Runs every Monday at midnight
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
update-go-modules:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout Code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: stable
|
||||||
|
|
||||||
|
- name: Update Dependencies
|
||||||
|
run: |
|
||||||
|
go get -u ./...
|
||||||
|
go mod tidy
|
||||||
|
git config user.name "github-actions[bot]"
|
||||||
|
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||||
|
git add go.mod go.sum
|
||||||
|
git commit -m "chore: auto-update Go modules"
|
||||||
|
git push
|
||||||
37
.gitignore
vendored
Normal file
37
.gitignore
vendored
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
# Generated by ignr: github.com/onyx-and-iris/ignr
|
||||||
|
|
||||||
|
## Go ##
|
||||||
|
# If you prefer the allow list template instead of the deny list, see community template:
|
||||||
|
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
|
||||||
|
#
|
||||||
|
# Binaries for programs and plugins
|
||||||
|
*.exe
|
||||||
|
*.exe~
|
||||||
|
*.dll
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Test binary, built with `go test -c`
|
||||||
|
*.test
|
||||||
|
|
||||||
|
# Code coverage profiles and other test artifacts
|
||||||
|
*.out
|
||||||
|
coverage.*
|
||||||
|
*.coverprofile
|
||||||
|
profile.cov
|
||||||
|
|
||||||
|
# Dependency directories (remove the comment below to include it)
|
||||||
|
# vendor/
|
||||||
|
|
||||||
|
# Go workspace file
|
||||||
|
go.work
|
||||||
|
go.work.sum
|
||||||
|
|
||||||
|
# env file
|
||||||
|
.env
|
||||||
|
|
||||||
|
# Editor/IDE
|
||||||
|
# .idea/
|
||||||
|
# .vscode/
|
||||||
|
|
||||||
|
# End of ignr
|
||||||
142
.golangci.yml
Normal file
142
.golangci.yml
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
version: '2'
|
||||||
|
|
||||||
|
run:
|
||||||
|
timeout: 3m
|
||||||
|
tests: true
|
||||||
|
go: '1.24'
|
||||||
|
|
||||||
|
linters:
|
||||||
|
disable: []
|
||||||
|
enable:
|
||||||
|
# Default enabled linters
|
||||||
|
- errcheck # Check for unchecked errors
|
||||||
|
- govet # Go's built-in vetting tool
|
||||||
|
- ineffassign # Detect ineffectual assignments
|
||||||
|
- staticcheck # Advanced static analysis
|
||||||
|
- unused # Check for unused code
|
||||||
|
# Additional useful linters
|
||||||
|
- misspell # Detect common misspellings
|
||||||
|
- unparam # Check for unused function parameters
|
||||||
|
- gosec # Security checks
|
||||||
|
- asciicheck # Check for non-ASCII characters
|
||||||
|
- errname # Check error variable names
|
||||||
|
- godot # Check for missing periods in comments
|
||||||
|
- revive # Highly configurable linter for style and correctness
|
||||||
|
- gocritic # Detect code issues and suggest improvements
|
||||||
|
- gocyclo # Check for cyclomatic complexity
|
||||||
|
- dupl # Check for code duplication
|
||||||
|
- predeclared # Check for shadowing of predeclared identifiers
|
||||||
|
- copyloopvar # Check for loop variable capture in goroutines
|
||||||
|
- errorlint # Check for common mistakes in error handling
|
||||||
|
- goconst # Check for repeated strings that could be constants
|
||||||
|
- gosmopolitan # Check for non-portable code
|
||||||
|
|
||||||
|
settings:
|
||||||
|
misspell:
|
||||||
|
locale: UK
|
||||||
|
|
||||||
|
errcheck:
|
||||||
|
check-type-assertions: true
|
||||||
|
check-blank: true
|
||||||
|
exclude-functions:
|
||||||
|
- fmt.Fprintf
|
||||||
|
- fmt.Fprintln
|
||||||
|
- fmt.Printf
|
||||||
|
- fmt.Println
|
||||||
|
- fmt.Errorf
|
||||||
|
|
||||||
|
revive:
|
||||||
|
severity: warning
|
||||||
|
rules:
|
||||||
|
# Code quality and style
|
||||||
|
- name: exported
|
||||||
|
arguments:
|
||||||
|
- 'checkPrivateReceivers'
|
||||||
|
- 'sayRepetitiveInsteadOfStutters'
|
||||||
|
- name: var-naming
|
||||||
|
- name: package-comments
|
||||||
|
- name: range-val-in-closure
|
||||||
|
- name: time-naming
|
||||||
|
- name: context-as-argument
|
||||||
|
- name: context-keys-type
|
||||||
|
- name: dot-imports
|
||||||
|
- name: empty-block
|
||||||
|
- name: error-return
|
||||||
|
- name: error-strings
|
||||||
|
- name: error-naming
|
||||||
|
- name: if-return
|
||||||
|
- name: increment-decrement
|
||||||
|
- name: indent-error-flow
|
||||||
|
- name: receiver-naming
|
||||||
|
- name: redefines-builtin-id
|
||||||
|
- name: superfluous-else
|
||||||
|
- name: unexported-return
|
||||||
|
- name: unreachable-code
|
||||||
|
- name: unused-parameter
|
||||||
|
- name: var-declaration
|
||||||
|
- name: blank-imports
|
||||||
|
- name: range
|
||||||
|
|
||||||
|
# Disabled rules (can be enabled if needed)
|
||||||
|
# - name: line-length-limit
|
||||||
|
# arguments: [120]
|
||||||
|
# - name: function-length
|
||||||
|
# arguments: [50, 0]
|
||||||
|
# - name: cyclomatic
|
||||||
|
# arguments: [10]
|
||||||
|
|
||||||
|
gosec:
|
||||||
|
excludes:
|
||||||
|
- G104 # Duplicated errcheck checks
|
||||||
|
- G115 # integer overflow conversion int -> uint32
|
||||||
|
|
||||||
|
exclusions:
|
||||||
|
warn-unused: false
|
||||||
|
rules:
|
||||||
|
# Exclude some linters from running on tests files.
|
||||||
|
- path: _test\.go
|
||||||
|
linters:
|
||||||
|
- gocyclo
|
||||||
|
- errcheck
|
||||||
|
- dupl
|
||||||
|
- gosec
|
||||||
|
|
||||||
|
paths:
|
||||||
|
- vendor
|
||||||
|
|
||||||
|
# Formatters configuration
|
||||||
|
formatters:
|
||||||
|
# Enable specific formatters
|
||||||
|
enable:
|
||||||
|
- gofumpt # Stricter gofmt alternative
|
||||||
|
- goimports # Organizes imports
|
||||||
|
- gci # Controls import order/grouping
|
||||||
|
- golines # Enforces line length
|
||||||
|
|
||||||
|
# Formatter-specific settings
|
||||||
|
settings:
|
||||||
|
goimports:
|
||||||
|
local-prefixes: [github.com/onyx-and-iris/lottery-cli]
|
||||||
|
|
||||||
|
gci:
|
||||||
|
# Define import sections order
|
||||||
|
sections:
|
||||||
|
- standard # Standard library
|
||||||
|
- default # Everything else
|
||||||
|
- prefix(github.com/onyx-and-iris/lottery-cli) # Current module
|
||||||
|
|
||||||
|
gofumpt:
|
||||||
|
extra-rules: true # Enable additional formatting rules
|
||||||
|
|
||||||
|
exclusions:
|
||||||
|
warn-unused: true
|
||||||
|
|
||||||
|
paths:
|
||||||
|
- vendor
|
||||||
|
|
||||||
|
issues:
|
||||||
|
# Limit the number of same issues reported to avoid spam
|
||||||
|
max-same-issues: 50
|
||||||
|
|
||||||
|
# Limit the number of issues per linter to keep output manageable
|
||||||
|
max-issues-per-linter: 100
|
||||||
55
.goreleaser.yaml
Normal file
55
.goreleaser.yaml
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
# This is an example .goreleaser.yml file with some sensible defaults.
|
||||||
|
# Make sure to check the documentation at https://goreleaser.com
|
||||||
|
|
||||||
|
# The lines below are called `modelines`. See `:help modeline`
|
||||||
|
# Feel free to remove those if you don't want/need to use them.
|
||||||
|
# yaml-language-server: $schema=https://goreleaser.com/static/schema.json
|
||||||
|
# vim: set ts=2 sw=2 tw=0 fo=cnqoj
|
||||||
|
|
||||||
|
version: 2
|
||||||
|
|
||||||
|
before:
|
||||||
|
hooks:
|
||||||
|
# You may remove this if you don't use go modules.
|
||||||
|
- go mod tidy
|
||||||
|
# you may remove this if you don't need go generate
|
||||||
|
- go generate ./...
|
||||||
|
|
||||||
|
builds:
|
||||||
|
- main: ./cmd/lottery/
|
||||||
|
env:
|
||||||
|
- CGO_ENABLED=0
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
- windows
|
||||||
|
- darwin
|
||||||
|
|
||||||
|
archives:
|
||||||
|
- formats: ['tar.gz']
|
||||||
|
# this name template makes the OS and Arch compatible with the results of `uname`.
|
||||||
|
name_template: >-
|
||||||
|
{{ .ProjectName }}_
|
||||||
|
{{- title .Os }}_
|
||||||
|
{{- if eq .Arch "amd64" }}x86_64
|
||||||
|
{{- else if eq .Arch "386" }}i386
|
||||||
|
{{- else }}{{ .Arch }}{{ end }}
|
||||||
|
{{- if .Arm }}v{{ .Arm }}{{ end }}
|
||||||
|
# use zip for windows archives
|
||||||
|
format_overrides:
|
||||||
|
- goos: windows
|
||||||
|
formats: ['zip']
|
||||||
|
|
||||||
|
changelog:
|
||||||
|
sort: asc
|
||||||
|
filters:
|
||||||
|
exclude:
|
||||||
|
- '^docs:'
|
||||||
|
- '^test:'
|
||||||
|
- '^chore:'
|
||||||
|
|
||||||
|
release:
|
||||||
|
footer: >-
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Released by [GoReleaser](https://github.com/goreleaser/goreleaser).
|
||||||
5
.pre-commit-config.yaml
Normal file
5
.pre-commit-config.yaml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
repos:
|
||||||
|
- repo: https://github.com/tekwizely/pre-commit-golang
|
||||||
|
rev: v1.0.0-rc.4
|
||||||
|
hooks:
|
||||||
|
- id: go-mod-tidy
|
||||||
75
cmd/lottery/main.go
Normal file
75
cmd/lottery/main.go
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"runtime/debug"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"charm.land/huh/v2"
|
||||||
|
"github.com/charmbracelet/fang"
|
||||||
|
"github.com/onyx-and-iris/lottery-cli"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
var version string
|
||||||
|
|
||||||
|
func versionFromBuild() string {
|
||||||
|
if version != "" {
|
||||||
|
return version
|
||||||
|
}
|
||||||
|
|
||||||
|
info, ok := debug.ReadBuildInfo()
|
||||||
|
if !ok {
|
||||||
|
return "(unable to read version)"
|
||||||
|
}
|
||||||
|
return strings.Split(info.Main.Version, "-")[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
var cmd = &cobra.Command{
|
||||||
|
Use: "lottery",
|
||||||
|
Short: "A CLI for National Lottery games.",
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
var selected string
|
||||||
|
|
||||||
|
form := huh.NewForm(
|
||||||
|
huh.NewGroup(
|
||||||
|
huh.NewSelect[string]().
|
||||||
|
Title("Pick a lottery.").
|
||||||
|
Options(
|
||||||
|
huh.NewOption("Lotto", "lotto"),
|
||||||
|
huh.NewOption("EuroMillions", "euromillions"),
|
||||||
|
huh.NewOption("SetForLife", "setforlife"),
|
||||||
|
huh.NewOption("Thunderball", "thunderball"),
|
||||||
|
huh.NewOption("Powerball", "powerball"),
|
||||||
|
).
|
||||||
|
Value(&selected),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
err := form.Run()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
kind, err := lottery.ParseKind(selected)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
l, err := lottery.New(kind)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
l.Draw()
|
||||||
|
fmt.Println(renderDraw(l))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if err := fang.Execute(context.Background(), cmd, fang.WithVersion(versionFromBuild())); err != nil {
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
61
cmd/lottery/render.go
Normal file
61
cmd/lottery/render.go
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"charm.land/lipgloss/v2"
|
||||||
|
"github.com/onyx-and-iris/lottery-cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
func formatNumberList(numbers []int) string {
|
||||||
|
parts := make([]string, len(numbers))
|
||||||
|
for i, n := range numbers {
|
||||||
|
parts[i] = strconv.Itoa(n)
|
||||||
|
}
|
||||||
|
return strings.Join(parts, " ")
|
||||||
|
}
|
||||||
|
|
||||||
|
func renderDraw(l lottery.Lottery) string {
|
||||||
|
titleStyle := lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("12"))
|
||||||
|
labelStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("8"))
|
||||||
|
numbersStyle := lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("10"))
|
||||||
|
specialStyle := lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("11"))
|
||||||
|
|
||||||
|
var title string
|
||||||
|
var lines []string
|
||||||
|
|
||||||
|
switch game := l.(type) {
|
||||||
|
case *lottery.Lotto:
|
||||||
|
title = "Lotto"
|
||||||
|
lines = append(lines, labelStyle.Render("Numbers:")+" "+numbersStyle.Render(formatNumberList(game.Numbers[:])))
|
||||||
|
case *lottery.EuroMillions:
|
||||||
|
title = "EuroMillions"
|
||||||
|
lines = append(lines, labelStyle.Render("Main:")+" "+numbersStyle.Render(formatNumberList(game.Numbers[:])))
|
||||||
|
lines = append(lines, labelStyle.Render("Lucky Stars:")+" "+specialStyle.Render(formatNumberList(game.LuckyStars[:])))
|
||||||
|
case *lottery.SetForLife:
|
||||||
|
title = "Set For Life"
|
||||||
|
lines = append(lines, labelStyle.Render("Main:")+" "+numbersStyle.Render(formatNumberList(game.Numbers[:])))
|
||||||
|
lines = append(lines, labelStyle.Render("Life Ball:")+" "+specialStyle.Render(strconv.Itoa(game.LifeBall)))
|
||||||
|
case *lottery.Thunderball:
|
||||||
|
title = "Thunderball"
|
||||||
|
lines = append(lines, labelStyle.Render("Main:")+" "+numbersStyle.Render(formatNumberList(game.Numbers[:])))
|
||||||
|
lines = append(lines, labelStyle.Render("Thunderball:")+" "+specialStyle.Render(strconv.Itoa(game.Thunderball)))
|
||||||
|
case *lottery.Powerball:
|
||||||
|
title = "Powerball"
|
||||||
|
lines = append(lines, labelStyle.Render("Main:")+" "+numbersStyle.Render(formatNumberList(game.Numbers[:])))
|
||||||
|
lines = append(lines, labelStyle.Render("Powerball:")+" "+specialStyle.Render(strconv.Itoa(game.Powerball)))
|
||||||
|
default:
|
||||||
|
title = "Lottery"
|
||||||
|
lines = append(lines, "Unknown lottery type")
|
||||||
|
}
|
||||||
|
|
||||||
|
body := strings.Join(lines, "\n")
|
||||||
|
card := lipgloss.NewStyle().
|
||||||
|
BorderStyle(lipgloss.RoundedBorder()).
|
||||||
|
BorderForeground(lipgloss.Color("8")).
|
||||||
|
Padding(0, 1).
|
||||||
|
MarginTop(1)
|
||||||
|
|
||||||
|
return card.Render(titleStyle.Render(title+" draw") + "\n" + body)
|
||||||
|
}
|
||||||
44
go.mod
Normal file
44
go.mod
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
module github.com/onyx-and-iris/lottery-cli
|
||||||
|
|
||||||
|
go 1.26.1
|
||||||
|
|
||||||
|
require (
|
||||||
|
charm.land/huh/v2 v2.0.3
|
||||||
|
charm.land/lipgloss/v2 v2.0.5
|
||||||
|
github.com/charmbracelet/fang v1.0.0
|
||||||
|
github.com/spf13/cobra v1.10.2
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
charm.land/bubbles/v2 v2.0.0 // indirect
|
||||||
|
charm.land/bubbletea/v2 v2.0.2 // indirect
|
||||||
|
github.com/atotto/clipboard v0.1.4 // indirect
|
||||||
|
github.com/catppuccin/go v0.2.0 // indirect
|
||||||
|
github.com/charmbracelet/colorprofile v0.4.3 // indirect
|
||||||
|
github.com/charmbracelet/ultraviolet v0.0.0-20260205113103-524a6607adb8 // indirect
|
||||||
|
github.com/charmbracelet/x/ansi v0.11.7 // indirect
|
||||||
|
github.com/charmbracelet/x/exp/charmtone v0.0.0-20250603201427-c31516f43444 // indirect
|
||||||
|
github.com/charmbracelet/x/exp/ordered v0.1.0 // indirect
|
||||||
|
github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0 // indirect
|
||||||
|
github.com/charmbracelet/x/term v0.2.2 // indirect
|
||||||
|
github.com/charmbracelet/x/termios v0.1.1 // indirect
|
||||||
|
github.com/charmbracelet/x/windows v0.2.2 // indirect
|
||||||
|
github.com/clipperhouse/displaywidth v0.11.0 // indirect
|
||||||
|
github.com/clipperhouse/uax29/v2 v2.7.0 // indirect
|
||||||
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.4.0 // indirect
|
||||||
|
github.com/mattn/go-runewidth v0.0.23 // indirect
|
||||||
|
github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect
|
||||||
|
github.com/muesli/cancelreader v0.2.2 // indirect
|
||||||
|
github.com/muesli/mango v0.1.0 // indirect
|
||||||
|
github.com/muesli/mango-cobra v1.2.0 // indirect
|
||||||
|
github.com/muesli/mango-pflag v0.1.0 // indirect
|
||||||
|
github.com/muesli/roff v0.1.0 // indirect
|
||||||
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
|
github.com/spf13/pflag v1.0.9 // indirect
|
||||||
|
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||||
|
golang.org/x/sync v0.19.0 // indirect
|
||||||
|
golang.org/x/sys v0.46.0 // indirect
|
||||||
|
golang.org/x/text v0.24.0 // indirect
|
||||||
|
)
|
||||||
98
go.sum
Normal file
98
go.sum
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
charm.land/bubbles/v2 v2.0.0 h1:tE3eK/pHjmtrDiRdoC9uGNLgpopOd8fjhEe31B/ai5s=
|
||||||
|
charm.land/bubbles/v2 v2.0.0/go.mod h1:rCHoleP2XhU8um45NTuOWBPNVHxnkXKTiZqcclL/qOI=
|
||||||
|
charm.land/bubbletea/v2 v2.0.2 h1:4CRtRnuZOdFDTWSff9r8QFt/9+z6Emubz3aDMnf/dx0=
|
||||||
|
charm.land/bubbletea/v2 v2.0.2/go.mod h1:3LRff2U4WIYXy7MTxfbAQ+AdfM3D8Xuvz2wbsOD9OHQ=
|
||||||
|
charm.land/huh/v2 v2.0.3 h1:2cJsMqEPwSywGHvdlKsJyQKPtSJLVnFKyFbsYZTlLkU=
|
||||||
|
charm.land/huh/v2 v2.0.3/go.mod h1:93eEveeeqn47MwiC3tf+2atZ2l7Is88rAtmZNZ8x9Wc=
|
||||||
|
charm.land/lipgloss/v2 v2.0.5 h1:kbNxgeeUOYv5J0YdpxFjfvf3dFvqH8Aci4zB6xqFtrY=
|
||||||
|
charm.land/lipgloss/v2 v2.0.5/go.mod h1:9oqhxt4yxIMe6q5A4kHr44DremZk7J9UNh74GlWa5nc=
|
||||||
|
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
|
||||||
|
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
|
||||||
|
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
|
||||||
|
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
|
||||||
|
github.com/aymanbagabas/go-udiff v0.4.1 h1:OEIrQ8maEeDBXQDoGCbbTTXYJMYRCRO1fnodZ12Gv5o=
|
||||||
|
github.com/aymanbagabas/go-udiff v0.4.1/go.mod h1:0L9PGwj20lrtmEMeyw4WKJ/TMyDtvAoK9bf2u/mNo3w=
|
||||||
|
github.com/catppuccin/go v0.2.0 h1:ktBeIrIP42b/8FGiScP9sgrWOss3lw0Z5SktRoithGA=
|
||||||
|
github.com/catppuccin/go v0.2.0/go.mod h1:8IHJuMGaUUjQM82qBrGNBv7LFq6JI3NnQCF6MOlZjpc=
|
||||||
|
github.com/charmbracelet/colorprofile v0.4.3 h1:QPa1IWkYI+AOB+fE+mg/5/4HRMZcaXex9t5KX76i20Q=
|
||||||
|
github.com/charmbracelet/colorprofile v0.4.3/go.mod h1:/zT4BhpD5aGFpqQQqw7a+VtHCzu+zrQtt1zhMt9mR4Q=
|
||||||
|
github.com/charmbracelet/fang v1.0.0 h1:jESBY40agJOlLYnnv9jE0mLqDGTxEk0hkOnx7YGyRlQ=
|
||||||
|
github.com/charmbracelet/fang v1.0.0/go.mod h1:P5/DNb9DddQ0Z0dbc0P3ol4/ix5Po7Ofr2KMBfAqoCo=
|
||||||
|
github.com/charmbracelet/ultraviolet v0.0.0-20260205113103-524a6607adb8 h1:eyFRbAmexyt43hVfeyBofiGSEmJ7krjLOYt/9CF5NKA=
|
||||||
|
github.com/charmbracelet/ultraviolet v0.0.0-20260205113103-524a6607adb8/go.mod h1:SQpCTRNBtzJkwku5ye4S3HEuthAlGy2n9VXZnWkEW98=
|
||||||
|
github.com/charmbracelet/x/ansi v0.11.7 h1:kzv1kJvjg2S3r9KHo8hDdHFQLEqn4RBCb39dAYC84jI=
|
||||||
|
github.com/charmbracelet/x/ansi v0.11.7/go.mod h1:9qGpnAVYz+8ACONkZBUWPtL7lulP9No6p1epAihUZwQ=
|
||||||
|
github.com/charmbracelet/x/conpty v0.1.1 h1:s1bUxjoi7EpqiXysVtC+a8RrvPPNcNvAjfi4jxsAuEs=
|
||||||
|
github.com/charmbracelet/x/conpty v0.1.1/go.mod h1:OmtR77VODEFbiTzGE9G1XiRJAga6011PIm4u5fTNZpk=
|
||||||
|
github.com/charmbracelet/x/errors v0.0.0-20240508181413-e8d8b6e2de86 h1:JSt3B+U9iqk37QUU2Rvb6DSBYRLtWqFqfxf8l5hOZUA=
|
||||||
|
github.com/charmbracelet/x/errors v0.0.0-20240508181413-e8d8b6e2de86/go.mod h1:2P0UgXMEa6TsToMSuFqKFQR+fZTO9CNGUNokkPatT/0=
|
||||||
|
github.com/charmbracelet/x/exp/charmtone v0.0.0-20250603201427-c31516f43444 h1:IJDiTgVE56gkAGfq0lBEloWgkXMk4hl/bmuPoicI4R0=
|
||||||
|
github.com/charmbracelet/x/exp/charmtone v0.0.0-20250603201427-c31516f43444/go.mod h1:T9jr8CzFpjhFVHjNjKwbAD7KwBNyFnj2pntAO7F2zw0=
|
||||||
|
github.com/charmbracelet/x/exp/golden v0.0.0-20250806222409-83e3a29d542f h1:pk6gmGpCE7F3FcjaOEKYriCvpmIN4+6OS/RD0vm4uIA=
|
||||||
|
github.com/charmbracelet/x/exp/golden v0.0.0-20250806222409-83e3a29d542f/go.mod h1:IfZAMTHB6XkZSeXUqriemErjAWCCzT0LwjKFYCZyw0I=
|
||||||
|
github.com/charmbracelet/x/exp/ordered v0.1.0 h1:55/qLwjIh0gL0Vni+QAWk7T/qRVP6sBf+2agPBgnOFE=
|
||||||
|
github.com/charmbracelet/x/exp/ordered v0.1.0/go.mod h1:5UHwmG+is5THxMyCJHNPCn2/ecI07aKNrW+LcResjJ8=
|
||||||
|
github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0 h1:qko3AQ4gK1MTS/de7F5hPGx6/k1u0w4TeYmBFwzYVP4=
|
||||||
|
github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0/go.mod h1:pBhA0ybfXv6hDjQUZ7hk1lVxBiUbupdw5R31yPUViVQ=
|
||||||
|
github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk=
|
||||||
|
github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI=
|
||||||
|
github.com/charmbracelet/x/termios v0.1.1 h1:o3Q2bT8eqzGnGPOYheoYS8eEleT5ZVNYNy8JawjaNZY=
|
||||||
|
github.com/charmbracelet/x/termios v0.1.1/go.mod h1:rB7fnv1TgOPOyyKRJ9o+AsTU/vK5WHJ2ivHeut/Pcwo=
|
||||||
|
github.com/charmbracelet/x/windows v0.2.2 h1:IofanmuvaxnKHuV04sC0eBy/smG6kIKrWG2/jYn2GuM=
|
||||||
|
github.com/charmbracelet/x/windows v0.2.2/go.mod h1:/8XtdKZzedat74NQFn0NGlGL4soHB0YQZrETF96h75k=
|
||||||
|
github.com/charmbracelet/x/xpty v0.1.3 h1:eGSitii4suhzrISYH50ZfufV3v085BXQwIytcOdFSsw=
|
||||||
|
github.com/charmbracelet/x/xpty v0.1.3/go.mod h1:poPYpWuLDBFCKmKLDnhBp51ATa0ooD8FhypRwEFtH3Y=
|
||||||
|
github.com/clipperhouse/displaywidth v0.11.0 h1:lBc6kY44VFw+TDx4I8opi/EtL9m20WSEFgwIwO+UVM8=
|
||||||
|
github.com/clipperhouse/displaywidth v0.11.0/go.mod h1:bkrFNkf81G8HyVqmKGxsPufD3JhNl3dSqnGhOoSD/o0=
|
||||||
|
github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJv2v7Vk=
|
||||||
|
github.com/clipperhouse/uax29/v2 v2.7.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||||
|
github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s=
|
||||||
|
github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||||
|
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||||
|
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||||
|
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.4.0 h1:UtrWVfLdarDgc44HcS7pYloGHJUjHV/4FwW4TvVgFr4=
|
||||||
|
github.com/lucasb-eyer/go-colorful v1.4.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||||
|
github.com/mattn/go-runewidth v0.0.23 h1:7ykA0T0jkPpzSvMS5i9uoNn2Xy3R383f9HDx3RybWcw=
|
||||||
|
github.com/mattn/go-runewidth v0.0.23/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
|
||||||
|
github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=
|
||||||
|
github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE=
|
||||||
|
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
|
||||||
|
github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
|
||||||
|
github.com/muesli/mango v0.1.0 h1:DZQK45d2gGbql1arsYA4vfg4d7I9Hfx5rX/GCmzsAvI=
|
||||||
|
github.com/muesli/mango v0.1.0/go.mod h1:5XFpbC8jY5UUv89YQciiXNlbi+iJgt29VDC5xbzrLL4=
|
||||||
|
github.com/muesli/mango-cobra v1.2.0 h1:DQvjzAM0PMZr85Iv9LIMaYISpTOliMEg+uMFtNbYvWg=
|
||||||
|
github.com/muesli/mango-cobra v1.2.0/go.mod h1:vMJL54QytZAJhCT13LPVDfkvCUJ5/4jNUKF/8NC2UjA=
|
||||||
|
github.com/muesli/mango-pflag v0.1.0 h1:UADqbYgpUyRoBja3g6LUL+3LErjpsOwaC9ywvBWe7Sg=
|
||||||
|
github.com/muesli/mango-pflag v0.1.0/go.mod h1:YEQomTxaCUp8PrbhFh10UfbhbQrM/xJ4i2PB8VTLLW0=
|
||||||
|
github.com/muesli/roff v0.1.0 h1:YD0lalCotmYuF5HhZliKWlIx7IEhiXeSfq7hNjFqGF8=
|
||||||
|
github.com/muesli/roff v0.1.0/go.mod h1:pjAHQM9hdUUwm/krAfrLGgJkXJ+YuhtsfZ42kieB2Ig=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||||
|
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
|
github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
|
||||||
|
github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
|
||||||
|
github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY=
|
||||||
|
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
|
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||||
|
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
|
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
|
||||||
|
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
|
||||||
|
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||||
|
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
|
||||||
|
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
|
||||||
|
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||||
|
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||||
|
golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw=
|
||||||
|
golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||||
|
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
|
||||||
|
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
30
kinds.go
Normal file
30
kinds.go
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
package lottery
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type Kind string
|
||||||
|
|
||||||
|
const (
|
||||||
|
KindLotto Kind = "lotto"
|
||||||
|
KindEuroMillions Kind = "euromillions"
|
||||||
|
KindSetForLife Kind = "setforlife"
|
||||||
|
KindThunderball Kind = "thunderball"
|
||||||
|
KindPowerball Kind = "powerball"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ParseKind(kind string) (Kind, error) {
|
||||||
|
switch kind {
|
||||||
|
case "lotto":
|
||||||
|
return KindLotto, nil
|
||||||
|
case "euromillions":
|
||||||
|
return KindEuroMillions, nil
|
||||||
|
case "setforlife":
|
||||||
|
return KindSetForLife, nil
|
||||||
|
case "thunderball":
|
||||||
|
return KindThunderball, nil
|
||||||
|
case "powerball":
|
||||||
|
return KindPowerball, nil
|
||||||
|
default:
|
||||||
|
return "", fmt.Errorf("invalid lottery kind: %s", kind)
|
||||||
|
}
|
||||||
|
}
|
||||||
111
lottery.go
Normal file
111
lottery.go
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
package lottery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Lottery is an interface that defines the methods that all lottery games must implement.
|
||||||
|
type Lottery interface {
|
||||||
|
Draw()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lotto represents the Lotto lottery game.
|
||||||
|
// It draws 6 numbers from a pool of 1 to 59 without replacement.
|
||||||
|
// There is no bonus ball in this game.
|
||||||
|
type Lotto struct {
|
||||||
|
Numbers [6]int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Lotto) Draw() {
|
||||||
|
numbers := drawUnique(len(l.Numbers), 59)
|
||||||
|
for i := range l.Numbers {
|
||||||
|
l.Numbers[i] = numbers[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EuroMillions represents the EuroMillions lottery game.
|
||||||
|
// It draws 5 numbers from a pool of 1 to 50 without replacement.
|
||||||
|
// Additionally, it draws 2 Lucky Stars from a pool of 1 to 12 without replacement.
|
||||||
|
type EuroMillions struct {
|
||||||
|
Numbers [5]int
|
||||||
|
LuckyStars [2]int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *EuroMillions) Draw() {
|
||||||
|
numbers := drawUnique(len(e.Numbers), 50)
|
||||||
|
for i := range e.Numbers {
|
||||||
|
e.Numbers[i] = numbers[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
luckyStars := drawUnique(len(e.LuckyStars), 12)
|
||||||
|
for i := range e.LuckyStars {
|
||||||
|
e.LuckyStars[i] = luckyStars[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetForLife represents the Set For Life lottery game.
|
||||||
|
// It draws 5 numbers from a pool of 1 to 47 without replacement.
|
||||||
|
// Additionally, it draws 1 Life Ball from a pool of 1 to 10 without replacement.
|
||||||
|
type SetForLife struct {
|
||||||
|
Numbers [5]int
|
||||||
|
LifeBall int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SetForLife) Draw() {
|
||||||
|
numbers := drawUnique(len(s.Numbers), 47)
|
||||||
|
for i := range s.Numbers {
|
||||||
|
s.Numbers[i] = numbers[i]
|
||||||
|
}
|
||||||
|
s.LifeBall = rand.Intn(10) + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Thunderball represents the Thunderball lottery game.
|
||||||
|
// It draws 5 numbers from a pool of 1 to 39 without replacement.
|
||||||
|
// Additionally, it draws 1 Thunderball from a pool of 1 to 14 without replacement.
|
||||||
|
type Thunderball struct {
|
||||||
|
Numbers [5]int
|
||||||
|
Thunderball int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Thunderball) Draw() {
|
||||||
|
numbers := drawUnique(len(t.Numbers), 39)
|
||||||
|
for i := range t.Numbers {
|
||||||
|
t.Numbers[i] = numbers[i]
|
||||||
|
}
|
||||||
|
t.Thunderball = rand.Intn(14) + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Powerball represents the Powerball lottery game.
|
||||||
|
// It draws 5 numbers from a pool of 1 to 69 without replacement.
|
||||||
|
// Additionally, it draws 1 Powerball from a pool of 1 to 26 without replacement.
|
||||||
|
type Powerball struct {
|
||||||
|
Numbers [5]int
|
||||||
|
Powerball int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Powerball) Draw() {
|
||||||
|
numbers := drawUnique(len(p.Numbers), 69)
|
||||||
|
for i := range p.Numbers {
|
||||||
|
p.Numbers[i] = numbers[i]
|
||||||
|
}
|
||||||
|
p.Powerball = rand.Intn(26) + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new instance of the selected lottery game.
|
||||||
|
func New(selected Kind) (Lottery, error) {
|
||||||
|
switch selected {
|
||||||
|
case KindLotto:
|
||||||
|
return &Lotto{}, nil
|
||||||
|
case KindEuroMillions:
|
||||||
|
return &EuroMillions{}, nil
|
||||||
|
case KindSetForLife:
|
||||||
|
return &SetForLife{}, nil
|
||||||
|
case KindThunderball:
|
||||||
|
return &Thunderball{}, nil
|
||||||
|
case KindPowerball:
|
||||||
|
return &Powerball{}, nil
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unknown lottery type: %s", string(selected))
|
||||||
|
}
|
||||||
|
}
|
||||||
19
util.go
Normal file
19
util.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package lottery
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
"sort"
|
||||||
|
)
|
||||||
|
|
||||||
|
// drawUnique returns count unique numbers in the range [1, max].
|
||||||
|
// It uses the rand.Perm function to generate a random permutation of numbers and selects the first count numbers from it.
|
||||||
|
// The result is sorted before being returned.
|
||||||
|
func drawUnique(count, max int) []int {
|
||||||
|
perm := rand.Perm(max)
|
||||||
|
result := make([]int, count)
|
||||||
|
for i := range result {
|
||||||
|
result[i] = perm[i] + 1
|
||||||
|
}
|
||||||
|
sort.Ints(result)
|
||||||
|
return result
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user