-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from jamietsao/ansi-escape-progress-bar
Created race animation using ansi escape codes
- Loading branch information
Showing
6 changed files
with
124 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
/bin | ||
main | ||
random-winner |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)) | ||
} |