// Package tournament shows football competition results.
package tournament
import (
"encoding/csv"
"fmt"
"io"
"sort"
"strings"
)
// teamData stores the team's name, wins, draws and losses.
type teamData struct {
name string
w int
d int
l int
}
type table []teamData
// Tally writes results table created from input to w.
func Tally(input io.Reader, w io.Writer) error {
r := csv.NewReader(input)
r.Comma = ';'
r.Comment = '#'
records, err := r.ReadAll()
if err != nil {
return err
}
results := table{}
for _, row := range records {
if len(row) != 3 {
return fmt.Errorf("row length should be 3, got: %d %q", len(row), row)
}
if results.getID(row[0]) == -1 {
results = append(results, teamData{row[0], 0, 0, 0})
}
if results.getID(row[1]) == -1 {
results = append(results, teamData{row[1], 0, 0, 0})
}
switch row[2] {
case "win":
results[results.getID(row[0])].w++
results[results.getID(row[1])].l++
case "loss":
results[results.getID(row[1])].w++
results[results.getID(row[0])].l++
case "draw":
results[results.getID(row[1])].d++
results[results.getID(row[0])].d++
default:
return fmt.Errorf("unexpected result: %q", row[2])
}
}
sort.Slice(results, func(i, j int) bool {
if 3*results[i].w+results[i].d > 3*results[j].w+results[j].d {
return true
} else if 3*results[i].w+results[i].d == 3*results[j].w+results[j].d {
if strings.Compare(results[i].name, results[j].name) == -1 {
return true
}
}
return false
})
buf := strings.Builder{}
if _, err := buf.WriteString(
fmt.Sprintf("%-30s %s\n", "Team", "| MP | W | D | L | P")); err != nil {
return err
}
for _, t := range results {
if _, err := buf.WriteString(
fmt.Sprintf("%-30s | %2d | %2d | %2d | %2d | %2d\n",
t.name, t.w+t.d+t.l, t.w, t.d, t.l, 3*t.w+t.d)); err != nil {
return err
}
}
if _, err = w.Write([]byte(buf.String())); err != nil {
return err
}
return nil
}
func (t table) getID(name string) int {
for i, item := range t {
if item.name == name {
return i
}
}
return -1
}