helper

package
v0.14.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 25, 2026 License: Apache-2.0 Imports: 17 Imported by: 0

Documentation

Overview

Package-level note: excel.go implements the page-layout algorithm that writes pool match and elimination match data into an Excel workbook.

Layout model:

  • "Pool Matches" sheet: courts are placed side-by-side (8 columns each). Pools are rendered top-to-bottom within each court column. A soft page-break is inserted whenever the next pool block would overflow PoolMatchesRowsPerPage rows. Vertical page breaks separate courts so the sheet prints as distinct pages.

  • "Elimination Matches" section: elimination rounds are laid out top-to-bottom with all courts side-by-side. A new page break is inserted when the next match block would overflow EliminationRowsPerPage.

  • Tree sheets ("Tree 1", "Tree 2", …): one sheet per bracket segment. Leaf values reference pool-match winner cells via CONCATENATE formulas so the bracket updates automatically when scores are entered.

Row-count thresholds and layout constants are defined in constants.go.

Index

Constants

View Source
const (
	// PoolMatchesRowsPerPage is the soft row budget before inserting a page
	// break on the Pool Matches sheet.
	PoolMatchesRowsPerPage = 45

	// PoolSpaceLines is the number of blank rows added after the pool header
	// before the first match block.
	PoolSpaceLines = 3

	// PoolDrawRowsPerPage is the soft row budget before inserting a page
	// break on the Pool Draw sheet.
	PoolDrawRowsPerPage = 42
)

Pool match sheet layout constants.

View Source
const (
	// EliminationRowsPerPage is the soft row budget before inserting a page
	// break in the elimination-match section.
	EliminationRowsPerPage = 44

	// EliminationSpaceLines is the number of blank rows printed between
	// elimination match rounds.
	EliminationSpaceLines = 5

	// EliminationMatchHeight is the row-height of a single individual
	// elimination match block.
	EliminationMatchHeight = 8

	// EliminationTeamMatchHeightBase is added to the team-match count to get
	// the row-height of a team elimination match block.
	EliminationTeamMatchHeightBase = 11
)

Elimination match layout constants.

View Source
const (
	DefaultPort     = 8080
	DefaultWinners  = 2
	DefaultPoolSize = 3
	DefaultCourts   = 2
)

Default flag values used by CLI commands and the web handler.

View Source
const MaxCourts = 26

MaxCourts is the upper bound for the number of Shiaijo (courts). It comes from the single-letter A–Z labelling used on Shiaijo headers throughout the workbook; values above this are rejected up front by ValidateCourts so we never silently truncate a user-requested layout.

View Source
const MaxPlayersPerTree = 16

MaxPlayersPerTree is the maximum leaf count on a single tree sheet. 16 players form a balanced bracket that fits on one A4 landscape page.

View Source
const TreeTitleRows = 3

TreeTitleRows is the number of rows reserved at the top of every tree sheet for the user to add a title. Content starts below this offset.

Variables

View Source
var WebFs embed.FS

Functions

func AddPlayerDataToSheet added in v0.3.0

func AddPlayerDataToSheet(f *excelize.File, players []Player, sanitize bool, titlePrefix string)

func AddPoolDataToSheet added in v0.3.0

func AddPoolDataToSheet(f *excelize.File, pools []Pool, sanitize bool, titlePrefix string)

func AddPoolsToSheet

func AddPoolsToSheet(f *excelize.File, pools []Pool) error

func AddPoolsToTree

func AddPoolsToTree(f *excelize.File, sheetName string, pools []Pool)

func ApplySeeds added in v0.11.0

func ApplySeeds(players []Player, assignments []domain.SeedAssignment) error

ApplySeeds assigns seeds to the helper players, handling swaps if needed Returns an error if an assigned name could not be matched

func AssignPoolsToCourts added in v0.14.0

func AssignPoolsToCourts(numPools, numCourts int) ([]int, error)

AssignPoolsToCourts distributes numPools pools across numCourts courts using contiguous blocks that match the tree sheet grouping. The first court gets ceil(numPools/numCourts) pools, subsequent courts get the remainder. Returns an error when numCourts exceeds numPools.

func CalculateDepth

func CalculateDepth(node *Node) int

func CheckDuplicateEntries added in v0.14.0

func CheckDuplicateEntries(input []string) []string

CheckDuplicateEntries scans the raw entry list (one CSV row per element) for duplicates and returns a list of entries that appear more than once. Empty strings are ignored. The returned slice preserves first-seen order of the offending entries; an empty result means the list is unique.

func ConvertPlayersToWinners added in v0.3.0

func ConvertPlayersToWinners(players []Player, sanitized bool) map[string]MatchWinner

func CreateNamesToPrint

func CreateNamesToPrint(f *excelize.File, players []Player, sanitized bool)

func CreateNamesWithPoolToPrint added in v0.3.0

func CreateNamesWithPoolToPrint(f *excelize.File, pools []Pool, sanitized bool)

func CreatePoolMatches

func CreatePoolMatches(pools []Pool)

func CreatePoolRoundRobinMatches

func CreatePoolRoundRobinMatches(pools []Pool)

func CreateTagsSheet added in v0.11.0

func CreateTagsSheet(f *excelize.File, pools []Pool) error

func CreateTreeBracket

func CreateTreeBracket(f *excelize.File, sheet string, col int, startRow int, size int) string

func FillEstimations added in v0.6.0

func FillEstimations(f *excelize.File, numPools int64, totalPoolMatches int64, teamSize int64, numEliminationMatches int64, numCourts int)

func FillInMatches

func FillInMatches(f *excelize.File, eliminationMatchRounds [][]*Node)

func GenerateFinals

func GenerateFinals(pools []Pool, poolWinners int) []string

GenerateFinals interleaves pool finalists so that when CreateBalancedTree distributes them into bracket slots, the first-place finisher of one pool is paired against the second-place finisher of another pool.

The algorithm cycles through all pools, advancing a round counter every time a full set of pools has been placed. The position rank for each slot is computed as (i + round) % poolWinners, which shifts the rank picked for successive pools so that adjacent bracket slots always contain different finishing positions.

Example with 4 pools and 2 winners per pool:

result = [Pool_A-1st, Pool_B-2nd, Pool_C-1st, Pool_D-2nd,
          Pool_A-2nd, Pool_B-1st, Pool_C-2nd, Pool_D-1st]

func GetBorderStyleBottomLeft

func GetBorderStyleBottomLeft(f *excelize.File) int

func GetBorderStyleLeft

func GetBorderStyleLeft(f *excelize.File) int

func MatchHeader

func MatchHeader(f *excelize.File, sheetName string, startColName string, poolRow int, middleColName string, endColName string, mirror bool)

func NextPow2 added in v0.14.0

func NextPow2(n int) int

NextPow2 returns the smallest power of 2 that is >= n. Returns 1 for n <= 1.

func ParseSeedsFile added in v0.11.0

func ParseSeedsFile(filePath string) ([]domain.SeedAssignment, error)

ParseSeedsFile reads a CSV file mapping names to seed positions

func PrintLeafNodes

func PrintLeafNodes(node *Node, f *excelize.File, sheetName string, startCol int, startRow int, depth int, pools bool, matchWinners map[string]MatchWinner)

func PrintPoolMatches

func PrintPoolMatches(f *excelize.File, pools []Pool, teamMatches int, numWinners int, numCourts int, mirror bool) map[string]MatchWinner

func PrintTeamEliminationMatches added in v0.2.0

func PrintTeamEliminationMatches(f *excelize.File, poolMatchWinners map[string]MatchWinner, eliminationMatchRounds [][]*Node, numTeamMatches int, numCourts int, mirror bool)

func ReadEntriesFromFile added in v0.9.0

func ReadEntriesFromFile(filePath string) ([]string, error)

func RemoveDuplicates

func RemoveDuplicates(input []string) []string

RemoveDuplicates removes duplicate strings from the input slice and returns a new slice without duplicates.

The function takes a parameter named input, which is a slice of strings. It represents the input slice from which duplicates and empty strings will be removed.

func RoundToPowerOf2 added in v0.4.0

func RoundToPowerOf2(x, y float64) (int, error)

func SetSheetLayoutLandscapeA3 added in v0.11.0

func SetSheetLayoutLandscapeA3(f *excelize.File, sheetName string)

func SetSheetLayoutPortraitA4 added in v0.11.0

func SetSheetLayoutPortraitA4(f *excelize.File, sheetName string)

func SetSheetLayoutPortraitA4Centered added in v0.14.0

func SetSheetLayoutPortraitA4Centered(f *excelize.File, sheetName string)

SetSheetLayoutPortraitA4Centered configures portrait A4 with print-centering. Unlike SetSheetLayoutPortraitA4 it does not enable FitToPage, so smaller content keeps its natural size and the horizontal/vertical centering print option actually has room to take effect.

func SetSheetLayoutPortraitA4DownThenOver added in v0.14.0

func SetSheetLayoutPortraitA4DownThenOver(f *excelize.File, sheetName string, numCourts int)

func SetTreeSheetTitle added in v0.14.0

func SetTreeSheetTitle(f *excelize.File, sheetName string, title string)

SetTreeSheetTitle writes a title formula into the first row of a tree sheet, spanning a wide range of columns to cover the bracket layout. The formula prepends the value of data!$B$1 (the user-supplied title prefix) to the given title string, so editing that single cell updates all tree sheets.

func ValidateCourts added in v0.14.0

func ValidateCourts(n int) error

ValidateCourts returns an error when n is outside the supported court range. Courts are labelled A–Z, so MaxCourts (26) is the hard upper bound. n < 1 is also rejected so the caller does not have to guess what "0 courts" should mean.

Types

type Match

type Match struct {
	SideA *Player
	SideB *Player
}

type MatchWinner

type MatchWinner struct {
	// contains filtered or unexported fields
}

type Node

type Node struct {
	LeafNode bool

	// sheet for Cell Values
	SheetName string

	// Pool Number or Cell value
	LeafVal string
	Val     int64
	Left    *Node
	Right   *Node
	// contains filtered or unexported fields
}

func CreateBalancedTree

func CreateBalancedTree(leafValues []string) *Node

func OrderStringsAlphabetically

func OrderStringsAlphabetically(strings []*Node) []*Node

func SubdivideTree added in v0.4.0

func SubdivideTree(node *Node, numSubtrees int) []*Node

function that subdivides a tree into a specified number of subtrees

func TraverseRounds

func TraverseRounds(node *Node, depth int, maxDepth int) []*Node

type Player

type Player struct {
	Name        string
	DisplayName string
	Dojo        string
	Metadata    []string

	PoolPosition int64
	Seed         int
	// contains filtered or unexported fields
}

func CreatePlayers

func CreatePlayers(entries []string, withZekkenName bool) ([]Player, error)

func PoolSeeding added in v0.14.0

func PoolSeeding(players []Player, numPools int, numCourts int) []Player

PoolSeeding reorders players for pool distribution so that top seeds land in pools that are appropriately spread across the given number of courts.

It assigns seeds to courts in a round-robin fashion and uses a per-court priority to ensure correct bracket placement (e.g., top and bottom of the court's bracket) after the pools are deinterleaved by ReorderPoolsForCourts.

func StandardSeeding added in v0.11.0

func StandardSeeding(players []Player) []Player

StandardSeeding reorders players into bracket positions such that seeded participants (Seed > 0) are spaced according to tournament standards (e.g., #1 and #2 on opposite halves). Unseeded players fill the remaining slots.

type Pool

type Pool struct {
	PoolName string
	Players  []Player
	Matches  []Match
	// contains filtered or unexported fields
}

func CreatePools

func CreatePools(players []Player, poolSize int, isMax bool) ([]Pool, error)

func ReorderPoolsForCourts added in v0.14.0

func ReorderPoolsForCourts(pools []Pool, numCourts int) []Pool

ReorderPoolsForCourts deinterleaves pools so that when divided into contiguous court blocks, each block has balanced pool sizes and seeds are spread across courts. Original pool i goes to court block (i % numCourts). Pool names are re-assigned alphabetically after reordering.

type RowStack added in v0.2.0

type RowStack struct {
	// contains filtered or unexported fields
}

func (*RowStack) Peek added in v0.2.1

func (s *RowStack) Peek() (int, error)

func (*RowStack) Pop added in v0.2.0

func (s *RowStack) Pop() (int, error)

func (*RowStack) Push added in v0.2.0

func (s *RowStack) Push(value int)

func (*RowStack) PushHighest added in v0.2.1

func (s *RowStack) PushHighest(first int, second int)

type Stack

type Stack []*Node

func (*Stack) IsEmpty

func (s *Stack) IsEmpty() bool

func (*Stack) Pop

func (s *Stack) Pop() *Node

func (*Stack) Push

func (s *Stack) Push(node *Node)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL