diff --git a/.gitignore b/.gitignore index d9c7f8a33ae807b7d0aacd54af2c9152680bb2b6..c05959c07590c12ab22d5188ee294faa5d2c5ef2 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,5 @@ newrelic_agent.log +.vscode/configurationCache.log +.vscode/dryrun.log +.vscode/settings.json +.vscode/targets.log diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000000000000000000000000000000000000..9adaa975f9b7ecb4e1d9a5cf6bf5960a2f9a5147 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,16 @@ +image: golang:alpine + +before_script: + - export GOPATH="$CI_PROJECT_DIR/.cache" + +stages: + - prepare + - test_day1 + - test_day2 + - test_day3 + - test_day4 + +include: + # local: ci/*.yml + - local: ci/.01-prepare_app.yml + - local: ci/.02-test_app.yml diff --git a/README.md b/README.md index 6742ed112531071692cfe4997e5b492c9db3acb2..db982836c83949426470b3b4c00643f83433d8a4 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ # or - go run ./day3/car.go ./day3/main.go -c 10 -d 150 + go run ./day3/main.go -c 10 -d 150 ``` - Test @@ -55,7 +55,7 @@ # or - go run ./day4/race.go ./day4/car.go ./day4/main.go -c 15 -d 150 -w 5 + go run ./day4/main.go -c 15 -d 150 -w 5 ``` - Test diff --git a/ci/.01-prepare_app.yml b/ci/.01-prepare_app.yml new file mode 100644 index 0000000000000000000000000000000000000000..26933928675fcd017e8b6808011619a55d0ccd26 --- /dev/null +++ b/ci/.01-prepare_app.yml @@ -0,0 +1,12 @@ +prepare_app: + stage: prepare + cache: + paths: + - .cache + script: + - apk add build-base make bash git + - mkdir -p .cache + only: + - merge_requests + - dev + - master diff --git a/ci/.02-test_app.yml b/ci/.02-test_app.yml new file mode 100644 index 0000000000000000000000000000000000000000..81ac2b7fcfb07a2f84d4cd772e9c40f2b4d874c6 --- /dev/null +++ b/ci/.02-test_app.yml @@ -0,0 +1,43 @@ +test_day1: + stage: test_day1 + script: + - apk add build-base make bash git + - go mod tidy + - make day1.test + only: + - merge_requests + - dev + - master + +test_day2: + stage: test_day2 + script: + - apk add build-base make bash git + - go mod tidy + - make day2.test + only: + - merge_requests + - dev + - master + +test_day3: + stage: test_day3 + script: + - apk add build-base make bash git + - go mod tidy + - make day3.test + only: + - merge_requests + - dev + - master + +test_day4: + stage: test_day4 + script: + - apk add build-base make bash git + - go mod tidy + - make day4.test + only: + - merge_requests + - dev + - master diff --git a/day1/vars.go b/day1/lib/vars.go similarity index 93% rename from day1/vars.go rename to day1/lib/vars.go index 22b2bcc1fefbbd1597451173c8b155d88b0f147c..e78bfffb72d1771870e7e8dbd5f175bc92917ab7 100644 --- a/day1/vars.go +++ b/day1/lib/vars.go @@ -1,4 +1,4 @@ -package main +package lib import "github.com/eaciit/toolkit" diff --git a/day1/vars_test.go b/day1/lib/vars_test.go similarity index 95% rename from day1/vars_test.go rename to day1/lib/vars_test.go index 4bee125038fc04deb126b6d7637318f4b76524d9..ce57f074940771d82ca64771e3ac5212ab9a822c 100644 --- a/day1/vars_test.go +++ b/day1/lib/vars_test.go @@ -1,11 +1,11 @@ -package main_test +package lib_test import ( "testing" // "github.com/stretchr/testify/assert" - . "go-sinau/day1" + . "go-sinau/day1/lib" "github.com/stretchr/testify/assert" ) diff --git a/day1/main.go b/day1/main.go index f3bdffcccd35507210a22531b7d00b703de7d906..1cece2966df36ac235005d6c160c348aaa262be4 100644 --- a/day1/main.go +++ b/day1/main.go @@ -1,6 +1,9 @@ package main -import "fmt" +import ( + "fmt" + . "go-sinau/day1/lib" +) var ( f32 float32 diff --git a/day2/word.go b/day2/lib/word.go similarity index 99% rename from day2/word.go rename to day2/lib/word.go index 819c93304801a889eca2ec3a4d68911d46dd93c9..432573c53e2ae1c8d229d0fa7b140b7e9ada6749 100644 --- a/day2/word.go +++ b/day2/lib/word.go @@ -1,4 +1,4 @@ -package main +package lib import ( "math" diff --git a/day2/word_test.go b/day2/lib/word_test.go similarity index 98% rename from day2/word_test.go rename to day2/lib/word_test.go index 1ac800ce4ff064e3420f929e08aab92aa5be5ed2..45ab2e54b6709eec27454015e03b1ecd236a2291 100644 --- a/day2/word_test.go +++ b/day2/lib/word_test.go @@ -1,7 +1,7 @@ -package main_test +package lib_test import ( - . "go-sinau/day2" + . "go-sinau/day2/lib" "testing" "github.com/stretchr/testify/assert" diff --git a/day2/main.go b/day2/main.go index edabc4cfd79aa2bb11db3d07f526af818ac4a07d..ade08d615e218144d499836ccf4906a975788ab4 100644 --- a/day2/main.go +++ b/day2/main.go @@ -1,6 +1,9 @@ package main -import "fmt" +import ( + "fmt" + . "go-sinau/day2/lib" +) func main() { txt := []string{"Hello", "World"} diff --git a/day3/car.go b/day3/lib/car.go similarity index 99% rename from day3/car.go rename to day3/lib/car.go index 29420d09c4449b70dd339b456794875a07562457..4a330397c5bc83085839dbfa70e15f47ff57ed41 100644 --- a/day3/car.go +++ b/day3/lib/car.go @@ -1,4 +1,4 @@ -package main +package lib import ( "fmt" diff --git a/day3/car_test.go b/day3/lib/car_test.go similarity index 98% rename from day3/car_test.go rename to day3/lib/car_test.go index c44d59b8ab26de38823d38acfa13507c71590c10..1cd53faf49944606215bdf74702b37a048051375 100644 --- a/day3/car_test.go +++ b/day3/lib/car_test.go @@ -1,7 +1,7 @@ -package main_test +package lib_test import ( - . "go-sinau/day3" + . "go-sinau/day3/lib" "testing" "github.com/logrusorgru/aurora" diff --git a/day3/main.go b/day3/main.go index 9d23c567069e36803312b80775cd166079d5da02..1d3c58b71717ab9b4316bb4e7d3f8ec9ba1558e6 100644 --- a/day3/main.go +++ b/day3/main.go @@ -3,6 +3,7 @@ package main import ( "flag" "fmt" + . "go-sinau/day3/lib" "time" "github.com/logrusorgru/aurora" diff --git a/day4/car.go b/day4/car.go deleted file mode 100644 index b28eeb77e69c33ba99f3b9091b12f62950db9ed4..0000000000000000000000000000000000000000 --- a/day4/car.go +++ /dev/null @@ -1,116 +0,0 @@ -package main - -import ( - "context" - "fmt" - "strings" - "sync" - "time" - - "github.com/eaciit/toolkit" - "github.com/logrusorgru/aurora" -) - -type Car struct { - ID string - Y int - Lapse int - Name string - - Color func(interface{}) aurora.Value -} - -func Print(c *Car, distance int, isCar bool) { - car := "|=" + c.ID + "->" - carTxt := strings.Repeat(" ", c.Lapse) + car - - if len(carTxt) < distance { - if isCar { - carTxt = "|" + strings.Repeat(" ", distance-len(carTxt)) + carTxt - } else { - carTxt = "|" + strings.Repeat(" ", distance) + "|" - } - } - - fmt.Printf("\033[%d;%dH", c.Y, 1) - fmt.Println(c.Color(carTxt)) -} - -func Race(ctx context.Context, wg *sync.WaitGroup, mtx *sync.Mutex, c *Car, distance int, cwon int, raceDetails *RaceDetails, cancel context.CancelFunc) { - defer wg.Done() - - for i := 0; i <= distance; i++ { - // stop the race - if len(raceDetails.Winners) >= cwon { - cancel() - break - } - - randInt := toolkit.RandInt(300) - times := time.Duration(randInt) * time.Millisecond - time.Sleep(times) - Print(c, i, true) - - // prevent race condition - mtx.Lock() - - details := raceDetails.Details - - if val, ok := details[c.ID]; ok { - val.Times = append(val.Times, randInt) - } else { - details[c.ID] = &RaceDetail{ - ID: c.ID, - Times: []int{randInt}, - } - } - - if i == distance { - raceDetails.Winners = append(raceDetails.Winners, c.ID) - details[c.ID].SetOrder(len(raceDetails.Winners)) - } - - mtx.Unlock() - } -} - -func PrepareCar(n int, cars *([]*Car)) { - *cars = make([]*Car, n) - - for i := 0; i < n; i++ { - car := new(Car) - car.ID = fmt.Sprintf("CAR-%d", i+1) - car.Lapse = 0 - car.Y = i + 1 - car.Name = toolkit.RandomString(4) - - switch i % 8 { - case 0: - car.Color = aurora.Red - - case 1: - car.Color = aurora.Yellow - - case 2: - car.Color = aurora.Green - - case 3: - car.Color = aurora.Cyan - - case 4: - car.Color = aurora.White - - case 5: - car.Color = aurora.Blue - - case 6: - car.Color = aurora.Magenta - - case 7: - car.Color = aurora.Red - - } - - (*cars)[i] = car - } -} diff --git a/day4/car_test.go b/day4/car_test.go deleted file mode 100644 index ffc36bfccbf52436b97976470dc63e0e0371e121..0000000000000000000000000000000000000000 --- a/day4/car_test.go +++ /dev/null @@ -1,130 +0,0 @@ -package main_test - -import ( - . "go-sinau/day4" - "testing" - - "github.com/logrusorgru/aurora" - "github.com/stretchr/testify/assert" -) - -func TestPrint(t *testing.T) { - type Payload struct { - Car Car - Distance int - IsCar bool - } - - tt := []struct { - Name string - Payload Payload - Expected interface{} - }{ - { - Name: "Will print winner car", - Payload: Payload{ - Car: Car{ - ID: "CAR-1", - Y: 1, - Lapse: 1, - Name: "John Doe", - Color: aurora.Red, - }, - Distance: 100, - IsCar: true, - }, - }, - { - Name: "Will print the pipe", - Payload: Payload{ - Car: Car{ - ID: "CAR-1", - Y: 1, - Lapse: 1, - Name: "John Doe", - Color: aurora.Red, - }, - Distance: 100, - IsCar: false, - }, - }, - } - - for _, test := range tt { - t.Run(test.Name, func(t *testing.T) { - payload := test.Payload - Print(&payload.Car, payload.Distance, payload.IsCar) - }) - } -} - -// func TestRace(t *testing.T) { -// type Payload struct { -// Car Car -// Distance int -// ChanWon chan string -// } - -// tt := []struct { -// Name string -// Payload Payload -// Expected interface{} -// }{ -// { -// Name: "Winner will save to channel", -// Payload: Payload{ -// Car: Car{ -// ID: "CAR-1", -// Y: 1, -// Lapse: 1, -// Name: "John Doe", -// Color: aurora.Red, -// }, -// Distance: 10, -// ChanWon: make(chan string), -// }, -// }, -// } - -// for _, test := range tt { -// t.Run(test.Name, func(t *testing.T) { -// payload := test.Payload -// go Race(&payload.Car, payload.Distance, payload.ChanWon) -// winner := <-payload.ChanWon -// assert.NotEmpty(t, winner) -// assert.Equal(t, winner, payload.Car.ID) -// }) -// } -// } - -func TestPrepareCar(t *testing.T) { - type Cars []*Car - type Payload struct { - Count int - Cars Cars - } - - tt := []struct { - Name string - Payload Payload - Expected int - }{ - { - Name: "Make 10 cars", - Payload: Payload{ - Count: 10, - Cars: Cars{}, - }, - Expected: 10, - }, - } - - for _, test := range tt { - t.Run(test.Name, func(t *testing.T) { - payload := &test.Payload - PrepareCar(payload.Count, (*[]*Car)(&payload.Cars)) - assert.NotEmpty(t, payload.Cars) - assert.Equal(t, len(payload.Cars), test.Expected) - }) - } -} diff --git a/day4/lib/car.go b/day4/lib/car.go new file mode 100644 index 0000000000000000000000000000000000000000..1ba57db1f792b690ad5a85462c9104305f30276f --- /dev/null +++ b/day4/lib/car.go @@ -0,0 +1,76 @@ +package lib + +import ( + "fmt" + "time" + + "github.com/eaciit/toolkit" + "github.com/logrusorgru/aurora" +) + +type Car struct { + ID string + Y int + Lapse int + Name string + + Color func(interface{}) aurora.Value + + trip int + times []time.Duration + totalTimes time.Duration +} + +func (c *Car) Trip() int { + return c.trip +} + +func (c *Car) Times() []time.Duration { + return c.times +} + +func (c *Car) TotalTimes() time.Duration { + return c.totalTimes +} + +func (c *Car) Speed() float64 { + return float64(c.trip) / c.totalTimes.Seconds() +} + +func PrepareCar(n int, cars *([]*Car)) { + *cars = make([]*Car, n) + + for i := 0; i < n; i++ { + car := new(Car) + car.ID = fmt.Sprintf("CAR-%03d", i+1) + car.Lapse = 0 + car.Y = i + 1 + car.Name = toolkit.RandomString(4) + + switch i % 7 { + case 0: + car.Color = aurora.Red + + case 1: + car.Color = aurora.Yellow + + case 2: + car.Color = aurora.Green + + case 3: + car.Color = aurora.Cyan + + case 4: + car.Color = aurora.White + + case 5: + car.Color = aurora.Blue + + case 6: + car.Color = aurora.Magenta + + } + + (*cars)[i] = car + } +} diff --git a/day4/lib/car_test.go b/day4/lib/car_test.go new file mode 100644 index 0000000000000000000000000000000000000000..67f4a00f041ce6a43d17b01b7deeab5dce2fdc00 --- /dev/null +++ b/day4/lib/car_test.go @@ -0,0 +1,40 @@ +package lib_test + +import ( + . "go-sinau/day4/lib" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestPrepareCar(t *testing.T) { + type Cars []*Car + type Payload struct { + Count int + Cars Cars + } + + tt := []struct { + Name string + Payload Payload + Expected int + }{ + { + Name: "Make 10 cars", + Payload: Payload{ + Count: 10, + Cars: Cars{}, + }, + Expected: 10, + }, + } + + for _, test := range tt { + t.Run(test.Name, func(t *testing.T) { + payload := &test.Payload + PrepareCar(payload.Count, (*[]*Car)(&payload.Cars)) + assert.NotEmpty(t, payload.Cars) + assert.Equal(t, len(payload.Cars), test.Expected) + }) + } +} diff --git a/day4/lib/race.go b/day4/lib/race.go new file mode 100644 index 0000000000000000000000000000000000000000..05d9cee87e7829ab7d5f9ce83e96497fd69f5f15 --- /dev/null +++ b/day4/lib/race.go @@ -0,0 +1,167 @@ +package lib + +import ( + "context" + "fmt" + "strings" + "sync" + "time" + + "github.com/eaciit/toolkit" +) + +type RaceOption struct { + mtx *sync.Mutex + ctx context.Context + cancel context.CancelFunc + wg *sync.WaitGroup + startTime time.Time + winners chan string + distance int + winnersMax int + forceStop bool + winnersFinished []*Car + duration int +} + +func NewRaceOption(wg *sync.WaitGroup) *RaceOption { + r := new(RaceOption) + r.mtx = new(sync.Mutex) + r.ctx, r.cancel = context.WithCancel(context.Background()) + r.wg = wg + r.startTime = time.Now() + r.winners = make(chan string) + + return r +} + +func (r *RaceOption) Context() context.Context { + return r.ctx +} + +func (r *RaceOption) Cancel() context.CancelFunc { + return r.cancel +} + +func (r *RaceOption) StartTime() time.Time { + return r.startTime +} + +func (r *RaceOption) SetDistance(distance int) { + r.distance = distance +} + +func (r *RaceOption) Distance() int { + return r.distance +} + +func (r *RaceOption) AddWinner(winner string) { + r.winners <- winner +} + +func (r *RaceOption) Winners() chan string { + return r.winners +} + +func (r *RaceOption) Wg() *sync.WaitGroup { + return r.wg +} + +func (r *RaceOption) SetWinnersMax(max int) { + r.winnersMax = max +} + +func (r *RaceOption) WinnersMax() int { + return r.winnersMax +} + +func (r *RaceOption) SetForceStop(force bool) { + r.forceStop = force +} + +func (r *RaceOption) ForceStop() bool { + return r.forceStop +} + +func (r *RaceOption) SetDuration(duration int) { + r.duration = duration +} + +func (r *RaceOption) Duration() int { + return r.duration +} + +func (r *RaceOption) WinnersFinished() []*Car { + return r.winnersFinished +} + +func (r *RaceOption) IsOver() bool { + return len(r.winnersFinished) >= r.winnersMax +} + +func Print(c *Car, distance int, isCar bool) { + car := "|=" + c.ID + "->" + carTxt := strings.Repeat(" ", c.Lapse) + car + + if len(carTxt) < distance { + if isCar { + carTxt = "|" + strings.Repeat(" ", distance-len(carTxt)) + carTxt + } else { + carTxt = "|" + strings.Repeat(" ", distance) + "|" + } + } + + fmt.Printf("\033[%d;%dH", c.Y, 1) + fmt.Println(c.Color(carTxt)) +} + +func Race(raceOption *RaceOption, c *Car) { + defer func() { + raceOption.wg.Done() + }() + + distance := raceOption.Distance() + + for i := 0; i <= distance; i++ { + select { + case <-raceOption.ctx.Done(): + return + default: + } + + randInt := toolkit.RandInt(raceOption.duration) + times := time.Duration(randInt) * time.Millisecond + time.Sleep(times) + + raceOption.mtx.Lock() + if !raceOption.IsOver() { + Print(c, i, true) + c.trip = i + } + raceOption.mtx.Unlock() + + duration := time.Since(raceOption.startTime) + durationPerLap := time.Since(raceOption.startTime) + + if len(c.times) > 0 { + lastLap := c.times[i-1] + durationPerLap = time.Since(raceOption.startTime.Add(lastLap)) + } + + c.times = append(c.times, durationPerLap) + c.totalTimes = duration + + if i == distance { + if raceOption.IsOver() { + // stop the race + raceOption.cancel() + } else { + raceOption.mtx.Lock() + raceOption.winnersFinished = append(raceOption.winnersFinished, c) + raceOption.mtx.Unlock() + } + + return + } + } +} diff --git a/day4/lib/race_test.go b/day4/lib/race_test.go new file mode 100644 index 0000000000000000000000000000000000000000..4a411f39d8dce5f03f636a1b225c383074343edc --- /dev/null +++ b/day4/lib/race_test.go @@ -0,0 +1,105 @@ +package lib_test + +import ( + . "go-sinau/day4/lib" + "sync" + "testing" + + "github.com/logrusorgru/aurora" + "github.com/stretchr/testify/assert" +) + +func TestPrint(t *testing.T) { + type Payload struct { + Car Car + Distance int + IsCar bool + } + + tt := []struct { + Name string + Payload Payload + Expected interface{} + }{ + { + Name: "Will print winner car", + Payload: Payload{ + Car: Car{ + ID: "CAR-1", + Y: 1, + Lapse: 1, + Name: "John Doe", + Color: aurora.Red, + }, + Distance: 100, + IsCar: true, + }, + }, + { + Name: "Will print the pipe", + Payload: Payload{ + Car: Car{ + ID: "CAR-1", + Y: 1, + Lapse: 1, + Name: "John Doe", + Color: aurora.Red, + }, + Distance: 100, + IsCar: false, + }, + }, + } + + for _, test := range tt { + t.Run(test.Name, func(t *testing.T) { + payload := test.Payload + Print(&payload.Car, payload.Distance, payload.IsCar) + }) + } +} + +func TestRace(t *testing.T) { + type Payload struct { + Car Car + Distance int + ChanWon chan string + } + + tt := []struct { + Name string + Payload Payload + Expected interface{} + }{ + { + Name: "Winner will saved", + Payload: Payload{ + Car: Car{ + ID: "CAR-1", + Y: 1, + Lapse: 1, + Name: "John Doe", + Color: aurora.Red, + }, + Distance: 10, + ChanWon: make(chan string), + }, + }, + } + + wg := new(sync.WaitGroup) + raceOpt := NewRaceOption(wg) + raceOpt.SetDistance(10) + raceOpt.SetWinnersMax(1) + raceOpt.SetDuration(10) + + for _, test := range tt { + raceOpt.Wg().Add(1) + t.Run(test.Name, func(t *testing.T) { + payload := test.Payload + Race(raceOpt, &payload.Car) + assert.GreaterOrEqual(t, len(raceOpt.WinnersFinished()), 1) + assert.Equal(t, raceOpt.WinnersFinished()[0].ID, payload.Car.ID) + }) + } +} diff --git a/day4/main.go b/day4/main.go index 3f99d6588f63a1b0518634f5f61e4a0e8e78ca34..886fbc4af55fe6715eb8637112dd05905d501e0a 100644 --- a/day4/main.go +++ b/day4/main.go @@ -1,21 +1,27 @@ package main import ( - "context" "flag" "fmt" + "sort" + "strings" "sync" "time" + . "go-sinau/day4/lib" + "github.com/dustin/go-humanize" "github.com/logrusorgru/aurora" ) var ( - carCount = flag.Int("c", 5, "-c=n | n is car count") - distance = flag.Int("d", 100, "-d=n | n is track distance") - winners = flag.Int("w", 3, "-w=n | n is winners taken") + carCount = flag.Int("c", 20, "-c=n | n is car count") + distance = flag.Int("d", 150, "-d=n | n is track distance") + winners = flag.Int("w", 5, "-w=n | n is winners taken") + duration = flag.Int("s", 50, "-s=n | n is random duration") cars []*Car + + winner string ) func main() { @@ -33,35 +39,84 @@ func main() { time.Sleep(3 * time.Second) fmt.Print("\033[2J") - ctx, cancel := context.WithCancel(context.Background()) - raceDetails := new(RaceDetails) - raceDetails.Details = map[string]*RaceDetail{} - wg := new(sync.WaitGroup) wg.Add(len(cars)) - - mtx := new(sync.Mutex) + raceOpt := NewRaceOption(wg) + raceOpt.SetDistance(*distance) + raceOpt.SetWinnersMax(*winners) + raceOpt.SetDuration(*duration) for _, c := range cars { - Print(c, *distance, false) - go Race(ctx, wg, mtx, c, *distance, *winners, raceDetails, cancel) + Print(c, raceOpt.Distance(), false) + go Race(raceOpt, c) + } + + printSeparator := func(sides ...string) { + _sides := "-" + if len(sides) > 0 { + _sides = sides[0] + } + + fmt.Printf("\t%s%s%s\n", _sides, strings.Repeat("-", 71), _sides) + } + + additionalSpace := len(cars) + 2 + + printTitle := func(title string) { + fmt.Printf("===== %s =====\n", title) } - wg.Wait() + printSpace := func(additional int) { + fmt.Printf("\033[%d;%dH", additionalSpace+additional, 1) + } + + getWinners := func() { + for i, v := range raceOpt.WinnersFinished() { + + if i == 0 { + printSpace(0) + printTitle(fmt.Sprintf("WINNERS %v", len(raceOpt.WinnersFinished()))) + } - fmt.Printf("\033[%d;%dH", len(cars)+2, 1) + printSpace(i + 1) + fmt.Println("\t", v.Color(humanize.Ordinal(i+1)), v.Color(v.ID)) - fmt.Println("Winners:") - for i := 0; i < *winners; i++ { - fmt.Printf("\t%v) %v\n", humanize.Ordinal(i+1), raceDetails.Winners[i]) + if i >= raceOpt.WinnersMax()-1 { + raceOpt.Cancel() + break + } + } } - fmt.Printf("\n\nDetails\n") - fmt.Println("\t| Car \t\t| Speed \t\t| Time \t\t|") - for i, v := range raceDetails.DetailsOrdered() { - fmt.Printf("\t| %v) %v \t| %vms/1dst \t\t| %v \t|\n", humanize.Ordinal(i+1), v.ID, v.Speed(), v.TotalTime().Format("04:05.000")) - if i+1 == *winners { - fmt.Println("\t---------------------------------------------------------") + raceOpt.Wg().Wait() + + getWinners() + + additionalSpace += (raceOpt.WinnersMax() + 1) + + sort.Slice(cars, func(i, j int) bool { + carI, carJ := cars[i], cars[j] + + if carI.Trip() == carJ.Trip() { + return carI.TotalTimes().Seconds() < carJ.TotalTimes().Seconds() + } + + return carI.Trip() > carJ.Trip() + }) + printSpace(1) + printTitle("DETAILS") + printSeparator() + fmt.Println("\t| Car \t\t\t| Trip \t\t| Time \t\t| Speed \t|") + printSeparator("+") + for i, c := range cars { + if i < 9 { + fmt.Printf("\t| %v) %v \t\t| %v du \t| %5f s \t| %5f du/s |\n", c.Color(humanize.Ordinal(i+1)), c.Color(c.ID), c.Color(c.Trip()), c.Color(c.TotalTimes().Seconds()), c.Color(c.Speed())) + } else { + fmt.Printf("\t| %v) %v \t| %v du \t| %5f s \t| %5f du/s |\n", c.Color(humanize.Ordinal(i+1)), c.Color(c.ID), c.Color(c.Trip()), c.Color(c.TotalTimes().Seconds()), c.Color(c.Speed())) + } + if i == raceOpt.WinnersMax()-1 { + printSeparator("+") } } + printSeparator() } diff --git a/day4/race.go b/day4/race.go deleted file mode 100644 index f3b59db8027b5aa4ff6383c5076c13f2cd2d9d13..0000000000000000000000000000000000000000 --- a/day4/race.go +++ /dev/null @@ -1,80 +0,0 @@ -package main - -import ( - "time" - - "github.com/novalagung/gubrak/v2" -) - -type RaceDetail struct { - ID string - order int - Times []int -} - -type RaceDetails struct { - Winners []string - Details map[string]*RaceDetail -} - -func (r *RaceDetails) DetailsOrdered() []*RaceDetail { - res := []*RaceDetail{} - - detailList := []*RaceDetail{} - - for _, v := range r.Details { - detailList = append(detailList, v) - } - - filterWinner := gubrak.From(detailList). - Filter(func(each *RaceDetail) bool { - return each.Order() > 0 - }).OrderBy(func(each *RaceDetail) int { - return each.Order() - }). - Result() - - if filterWinner != nil { - res = append(res, filterWinner.([]*RaceDetail)...) - } - - filterLooser := gubrak.From(detailList). - Filter(func(each *RaceDetail) bool { - return each.Order() < 1 - }).OrderBy(func(each *RaceDetail) int { - return each.Speed() - }). - Result() - - if filterLooser != nil { - res = append(res, filterLooser.([]*RaceDetail)...) - } - - return res -} - -func (r *RaceDetail) TotalTimeMs() int { - sum := 0 - - for _, v := range r.Times { - sum += v - } - - return sum -} - -func (r *RaceDetail) TotalTime() time.Time { - return time.Unix(0, int64(r.TotalTimeMs())*int64(time.Millisecond)) -} - -func (r *RaceDetail) Speed() int { - return r.TotalTimeMs() / len(r.Times) -} - -func (r *RaceDetail) Order() int { - return r.order -} - -func (r *RaceDetail) SetOrder(order int) { - r.order = order -} diff --git a/go.mod b/go.mod index 13562179c46e46f7c4a2478c8d3a862745f037b6..d7aadeb83b6822336ea4797e8d2922c172145011 100644 --- a/go.mod +++ b/go.mod @@ -5,12 +5,8 @@ go 1.17 require github.com/stretchr/testify v1.7.1 require ( - github.com/davecgh/go-spew v1.1.0 // indirect - github.com/dustin/go-humanize v1.0.0 // indirect - github.com/eaciit/toolkit v0.0.0-20210610161449-593d5fadf78e // indirect - github.com/logrusorgru/aurora v2.0.3+incompatible // indirect - github.com/novalagung/gubrak/v2 v2.0.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa // indirect - gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect + github.com/dustin/go-humanize v1.0.0 + github.com/eaciit/toolkit v0.0.0-20210610161449-593d5fadf78e + github.com/logrusorgru/aurora v2.0.3+incompatible + github.com/novalagung/gubrak/v2 v2.0.1 ) diff --git a/go.sum b/go.sum index 0fe50678e03f9dc995d39de6cb1b0463a07c3100..beb03d152f141d46d2871f5ac65301454f18f4d6 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,4 @@ +github.com/DefinitelyMod/gocsv v0.0.0-20181205141819-acfa5f112b45 h1:+OD9vawobD89HK04zwMokunBCSEeAb08VWAHPUMg+UE= github.com/DefinitelyMod/gocsv v0.0.0-20181205141819-acfa5f112b45/go.mod h1:+nlrAh0au59iC1KN5RA1h1NdiOQYlNOBrbtE1Plqht4= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -20,6 +21,7 @@ golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa h1:F+8P+gmewFQYRk6JoLQLwjBCT golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= diff --git a/makefile b/makefile index ac7394697ff008af2fb73509baedb88d626d96f6..5b82bce8c372690637a372efd47151872883ebe2 100644 --- a/makefile +++ b/makefile @@ -1,23 +1,23 @@ day1.run: - go run ./day1/vars.go ./day1/main.go + go run ./day1/main.go day1.test: go test ./day1/... -v -cover day2.run: - go run ./day2/word.go ./day2/main.go + go run ./day2/main.go day2.test: go test ./day2/... -v -cover day3.run: - go run ./day3/car.go ./day3/main.go + go run ./day3/main.go day3.test: go test ./day3/... -v -cover day4.run: - go run ./day4/race.go ./day4/car.go ./day4/main.go + go run ./day4/main.go day4.test: go test ./day4/... -v -cover