Skip to content

Commit

Permalink
Merge pull request #1 from jamietsao/ansi-escape-progress-bar
Browse files Browse the repository at this point in the history
Created race animation using ansi escape codes
  • Loading branch information
jamietsao authored Aug 21, 2021
2 parents 7b38cb1 + cbd6330 commit 729ed7f
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 49 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/bin
main
random-winner
21 changes: 21 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# credit: https://vic.demuzere.be/articles/golang-makefile-crosscompile/
PLATFORMS := darwin/386 darwin/amd64 linux/386 linux/amd64 windows/386 windows/amd64

checkenv:
ifndef TAG
$(error release TAG is required - e.g v0.1.0)
endif

temp = $(subst /, ,$@)
os = $(word 1, $(temp))
arch = $(word 2, $(temp))
name = random-winner
longname = $(name)-$(TAG)-$(os)-$(arch)

release: $(PLATFORMS)

$(PLATFORMS): checkenv
GOOS=$(os) GOARCH=$(arch) go build -o 'bin/$(longname)/$(name)' main.go
cd bin/$(longname) && zip $(longname).zip $(name)

.PHONY: checkenv release $(PLATFORMS) zip
26 changes: 24 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,29 @@
# random-winner
After receiving a $100 gift card to DoorDash for taking a sales call with one of our software vendors, I decided to give it to someone random on the team. I wrote a quick program to select the winner.
After receiving a $100 gift card to DoorDash for taking a sales call with a software vendor, I wanted to give it to someone random on the team. As a manager that rarely gets to write code these days, I decided to write a quick program to select the winner 🤓.

# Drumroll, please ... 🥁🥁🥁🥁
## UPDATE - 1/26/21
After reading this wonderful [post](https://www.lihaoyi.com/post/BuildyourownCommandLinewithANSIescapecodes.html) about [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code), this silly program I wrote a few months back was the perfect opportunity to dabble with them. So instead of immediately displaying the final results with an anti-climatic drumroll (see original version below), I used ANSI escape codes to simulate a dramatic race to the finish line.

Here was the original version from 8/4/20:

<img src="gifs/original.gif">

Here's the latest version using ANSI escape codes (and of course emojis):

<img src="gifs/latest.gif">

## Wanna use yourself?
1. Download script:
- If you have Go installed: `go get github.com/jamietsao/random-winner`
- Else download the binary directly: https://github.com/jamietsao/random-winner/releases
5. Run script:

`random-winner -names=Steph,Klay,Draymond,Iggy,Bogut`

***

## Original Version (run on 8/4/20)
### Drumroll, please ... 🥁🥁🥁🥁
This was the result:
```
➜ random go run main.go
Expand Down
Binary file added gifs/latest.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added gifs/original.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
123 changes: 76 additions & 47 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,71 +1,100 @@
package main

import (
"flag"
"fmt"
"math/rand"
"os"
"sort"
"strings"
"time"
)

// backend team
var team = map[int]string{
0: "Brandon",
1: "Bigo",
2: "Jeff",
3: "Benny",
4: "Andy",
5: "Eric",
6: "Leilani",
7: "Carmen",
const (
target = 1000
snail = "🐌"
)

func init() {
// seed rng
rand.Seed(time.Now().UnixNano())
}

func main() {
// seed it!
rand.Seed(time.Now().UnixNano())
var nameStr string

// parse flags
flag.StringVar(&nameStr, "names", "", "Comma separated list of names")
flag.Parse()

names := strings.Split(nameStr, ",")

if len(names) < 2 {
fmt.Println("Must supply at least two names via -names flag:")
flag.Usage()
os.Exit(0)
}

// pick winner
winner()
winner(names)
}

func winner() {
results := make(map[string]int)

// run 10 million times
for i := 0; i < 10000000; i++ {
i := rand.Intn(len(team))
results[team[i]]++
func winner(names []string) {
nameCount := len(names)
longest := 0
for _, names := range names {
if len(names) > longest {
longest = len(names)
}
}

// find winner
fmt.Printf("First to %d wins!\n", target)
fmt.Printf("%s", strings.Repeat("\n", nameCount))

// run until winner is determined
runs := 0
winner := ""
top := 0
fmt.Printf("\n")
for name, count := range results {
if count > top {
winner = name
top = count
results := make(map[string]int)
for {
runs++

// random choice
i := rand.Intn(nameCount)
results[names[i]]++

// move cursor back to top left
fmt.Printf("\u001b[%dD\u001b[%dA", 50, nameCount)

// print current progress
multiplier := target / 100
for _, name := range names {
// show progress as a portion of 50 marks
width := results[name] / (2 * multiplier)
fmt.Printf("[%*v _%s%s%s]\n", longest+1, name, strings.Repeat("_", width), snail, strings.Repeat(" ", 50-width))
}
fmt.Printf("%10v => %d\n", name, count)
}

// drumroll, please
fmt.Printf("\nThe winner is .......\n")

ticker := time.NewTicker(500 * time.Millisecond)
done := make(chan bool)
go func() {
for {
select {
case <-done:
return
case <-ticker.C:
fmt.Printf("🥁\n")
}
// stop once someone hits the target
if results[names[i]] == target {
winner = names[i]
break
}
}()
time.Sleep(3 * time.Second)
ticker.Stop()
done <- true

fmt.Printf("\n%s!!\n", strings.ToUpper(winner))
time.Sleep(1 * time.Millisecond)
}

// sort & display final results
sort.Slice(names, func(i, j int) bool {
// reverse sort to show highest to lowest
return results[names[i]] > results[names[j]]
})

fmt.Printf("\n FINAL RESULTS \n")
fmt.Printf("------------------\n")
for _, name := range names {
fmt.Printf("%*v %5d\n", longest+1, name, results[name])
}
fmt.Printf("\n%*v %5d\n", longest+1, "TOTAL", runs)

// drumroll, please
fmt.Printf("\nThe winner is ....... %s!\n", strings.ToUpper(winner))
}

0 comments on commit 729ed7f

Please sign in to comment.