diff --git a/README.md b/README.md index ae5cb60..ffbfa34 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,15 @@ kicker-cli event open 351e00bf-025c-4243-b381-2f5a135c3070 kicker-cli event delete 351e00bf-025c-4243-b381-2f5a135c3070 ``` +Event analysis: +```shell +# analyze with "double_player_rank" operator for "byp" event order by ELO +kicker-cli events analyze -m double_player_rank -t byp -o ELO + +# analyze with "single_player_rank" operator for "single" event order by win rate +kicker-cli events analyze -m single_player_rank -t single --sort-by elo +```` + Player management: ```shell # list players diff --git a/cmd/kicker-cli/cmd/import.go b/cmd/kicker-cli/cmd/import.go index c7ebb51..50c6b33 100644 --- a/cmd/kicker-cli/cmd/import.go +++ b/cmd/kicker-cli/cmd/import.go @@ -37,6 +37,10 @@ var importCmd = &cobra.Command{ return } + var players []string + for _, p := range instance.Conf.Players { + players = append(players, p.Name) + } eventsAdded := 0 for _, importPath := range args { if strings.HasPrefix(importPath, "~") { @@ -58,17 +62,39 @@ var importCmd = &cobra.Command{ } } if !found { - var needCreate bool if !importEventCreateUnknownPlayers { - needCreate, _ = pterm.DefaultInteractiveConfirm. - WithDefaultText(fmt.Sprintf("Create a new player with name `%s`", p.Name)). - WithDefaultValue(true). - Show() - } else { - needCreate = true - } - if needCreate { - instance.AddPlayer(*entity.NewPlayer(p.Name)) + text := fmt.Sprint("Unknown player: ", p.Name) + selectedOption, _ := pterm. + DefaultInteractiveSelect. + WithOptions([]string{ + "Create a new player", + "Attach to an existed player", + "Cancel", + }). + Show(text) + + if selectedOption == "Create a new player" { + instance.AddPlayer(*entity.NewPlayer(p.Name)) + pterm.Printfln("Creating player %s", p.Name) + } else if selectedOption == "Attach to an existed player" { + selectedPlayer, _ := pterm. + DefaultInteractiveSelect. + WithOptions(players). + Show("Choose a player") + sp := instance.FindPlayer(selectedPlayer) + if sp == nil { + errorMessageAndExit("Find player failed:", selectedPlayer) + } + sp.AddAlias(p.Name) + res := instance.SetPlayer(sp) + if res == nil { + errorMessageAndExit("Attach player failed", selectedPlayer) + } else { + pterm.Printfln("Attaching alias %s to player %s", p.Name, sp.Name) + } + } else { + errorMessageAndExit("Cancelled") + } } } } diff --git a/internal/app/conf.go b/internal/app/conf.go index d90671e..b69bd13 100644 --- a/internal/app/conf.go +++ b/internal/app/conf.go @@ -16,9 +16,16 @@ const DefaultName = ".kicker.yaml" type Conf struct { ManifestVersion string `yaml:"manifest_version"` + // Settings + // NoColors bool `yaml:"no_colors"` + + // Organization Organization entity.Organization `yaml:"organization"` - Events []entity.Event `yaml:"events"` + // Events + Events []entity.Event `yaml:"events"` + + // Players Players []entity.Player `yaml:"players"` } @@ -94,6 +101,29 @@ func (app App) GetPlayer(id string) *entity.Player { return nil } +// SetPlayer sets player data with the given id. +func (app App) SetPlayer(player *entity.Player) *entity.Player { + for idx, p := range app.Conf.Players { + if player.ID == p.ID { + app.Conf.Players[idx] = *player + return &p + } + } + + return nil +} + +// FindPlayer returns player with the given name +func (app App) FindPlayer(name string) *entity.Player { + for _, p := range app.Conf.Players { + if name == p.Name { + return &p + } + } + + return nil +} + // DeletePlayer delete a player func (app *App) DeletePlayer(id string) error { s := -1 diff --git a/internal/converter/converter.go b/internal/converter/converter.go index 015f224..1389e5f 100644 --- a/internal/converter/converter.go +++ b/internal/converter/converter.go @@ -174,7 +174,7 @@ func (c *Converter) playerRank( // remove third from fourth level fourthPos := lastPos - 1 for i, p := range c.record.Ranks[fourthPos] { - if p.ID == third[0].ID { + if len(third) > 0 && p.ID == third[0].ID { ranks := c.record.Ranks[fourthPos] ranks = append(ranks[:i], ranks[i+1:]...) c.record.Ranks[fourthPos] = ranks