chore: Refactor Golang code

This commit is contained in:
Irvi Firqotul Aini 2020-07-17 10:08:23 +07:00
parent fbe24e35b5
commit bccccf5861
4 changed files with 232 additions and 97 deletions

20
go/Makefile Normal file
View File

@ -0,0 +1,20 @@
NAME := gilded-rose
# set default compiler
GO := go
.PHONY: prebuild
prebuild:
all: lint test
.PHONY: lint
lint: ## Verifies `golint` passes.
@echo "+ $@"
@golint ./... | grep -v '.pb.go:' | grep -v vendor | tee /dev/stderr
.PHONY: test
test: prebuild ## Runs the go tests.
@echo "+ $@"
@$(GO) test -v $(shell $(GO) list ./... | grep -v vendor)

View File

@ -1,58 +1,159 @@
package main package main
import "fmt"
type Item struct { type Item struct {
name string name string
sellIn, quality int sellIn, quality int
} }
func UpdateQuality(items []*Item) { var items = []Item{
for i := 0; i < len(items); i++ { Item{"+5 Dexterity Vest", 10, 20},
Item{"Aged Brie", 2, 0},
Item{"Elixir of the Mongoose", 5, 7},
Item{"Sulfuras, Hand of Ragnaros", 0, 80},
Item{"Backstage passes to a TAFKAL80ETC concert", 15, 20},
Item{"Conjured Mana Cake", 3, 6},
}
if items[i].name != "Aged Brie" && items[i].name != "Backstage passes to a TAFKAL80ETC concert" { type Updatable interface {
if items[i].quality > 0 { Update()
if items[i].name != "Sulfuras, Hand of Ragnaros" { }
items[i].quality = items[i].quality - 1
}
}
} else {
if items[i].quality < 50 {
items[i].quality = items[i].quality + 1
if items[i].name == "Backstage passes to a TAFKAL80ETC concert" {
if items[i].sellIn < 11 {
if items[i].quality < 50 {
items[i].quality = items[i].quality + 1
}
}
if items[i].sellIn < 6 {
if items[i].quality < 50 {
items[i].quality = items[i].quality + 1
}
}
}
}
}
if items[i].name != "Sulfuras, Hand of Ragnaros" { type UpdatableItem func(item *Item) Updatable
items[i].sellIn = items[i].sellIn - 1
}
if items[i].sellIn < 0 { type AgedBrieItem struct {
if items[i].name != "Aged Brie" { *Item
if items[i].name != "Backstage passes to a TAFKAL80ETC concert" { }
if items[i].quality > 0 {
if items[i].name != "Sulfuras, Hand of Ragnaros" { func (item *AgedBrieItem) Update() {
items[i].quality = items[i].quality - 1 item.updateSellIn(-1)
} if item.sellIn < 0 {
} item.updateQuality(+2)
} else { } else {
items[i].quality = items[i].quality - items[i].quality item.updateQuality(+1)
} }
} else { item.limitQualityToMax(50)
if items[i].quality < 50 { }
items[i].quality = items[i].quality + 1
} type SulfurasItem struct {
*Item
}
func (item *SulfurasItem) Update() {
}
type BackstagePassesItem struct {
*Item
}
func (item *BackstagePassesItem) Update() {
item.updateSellIn(-1)
sellIn := item.sellIn
switch {
case sellIn >= 10:
item.updateQuality(+1)
case sellIn < 10 && sellIn >= 5:
item.updateQuality(+2)
case sellIn < 15 && sellIn >= 0:
item.updateQuality(+3)
case sellIn < 0:
item.limitQualityToMax(0)
}
item.limitQualityToMax(50)
}
type RegularItem struct {
*Item
}
func (item *RegularItem) Update() {
item.updateSellIn(-1)
if item.sellIn < 0 {
item.updateQuality(-2)
} else {
item.updateQuality(-1)
}
item.limitQualityToMin(0)
}
type ConjuredItem struct {
*Item
}
func (item *ConjuredItem) Update() {
item.updateSellIn(-1)
if item.sellIn < 0 {
item.updateQuality(-4)
} else {
item.updateQuality(-2)
}
item.limitQualityToMin(0)
}
func UpdatableItemFactory(createClosure map[string]UpdatableItem, item *Item) Updatable {
create, exists := createClosure[item.name]
if exists {
return create(item)
}
return &RegularItem{
Item: item,
}
}
func (item *Item) updateSellIn(updatedBy int) {
item.sellIn += updatedBy
}
func (item *Item) updateQuality(updatedBy int) {
item.quality += updatedBy
}
func (item *Item) limitQualityToMax(max int) {
if item.quality > max {
item.quality = max
}
}
func (item *Item) limitQualityToMin(min int) {
if item.quality < min {
item.quality = min
}
}
func GildedRose(items []Item) {
creationMap := map[string]UpdatableItem{
"Aged Brie": func(item *Item) Updatable {
return &AgedBrieItem{
Item: item,
} }
} },
"Sulfuras, Hand of Ragnaros": func(item *Item) Updatable {
return &SulfurasItem{
Item: item,
}
},
"Backstage passes to a TAFKAL80ETC concert": func(item *Item) Updatable {
return &BackstagePassesItem{
Item: item,
}
},
"Conjured Mana Cake": func(item *Item) Updatable {
return &ConjuredItem{
Item: item,
}
},
} }
for i := 0; i < len(items); i++ {
updatableItem := UpdatableItemFactory(creationMap, &items[i])
updatableItem.Update()
}
} }
func main() {
fmt.Println("# Before updating")
// fmt.Println(items)
GildedRose(items)
}

View File

@ -1,15 +1,73 @@
package main package main
import "testing" import (
"fmt"
"io"
"os"
"testing"
)
func Test_Foo(t *testing.T) { var tests = []struct {
var items = []*Item{ startItem Item
&Item{"foo", 0, 0}, expectedItem Item
} days int
}{
{Item{"normal", 10, 20}, Item{"normal", 10, 20}, 0},
{Item{"normal", 10, 20}, Item{"normal", 0, 10}, 10},
{Item{"normal", 10, 20}, Item{"normal", -1, 8}, 11},
{Item{"normal", 10, 20}, Item{"normal", -20, 0}, 30},
{Item{"Aged Brie", 2, 0}, Item{"Aged Brie", 2, 0}, 0},
{Item{"Aged Brie", 2, 0}, Item{"Aged Brie", 0, 2}, 2},
{Item{"Aged Brie", 2, 0}, Item{"Aged Brie", -23, 48}, 25},
{Item{"Aged Brie", 2, 0}, Item{"Aged Brie", -24, 50}, 26},
{Item{"Aged Brie", 2, 0}, Item{"Aged Brie", -25, 50}, 27},
{Item{"Aged Brie", 2, 0}, Item{"Aged Brie", -28, 50}, 30},
{Item{"Sulfuras, Hand of Ragnaros", 0, 80}, Item{"Sulfuras, Hand of Ragnaros", 0, 80}, 0},
{Item{"Sulfuras, Hand of Ragnaros", 0, 80}, Item{"Sulfuras, Hand of Ragnaros", 0, 80}, 15},
{Item{"Sulfuras, Hand of Ragnaros", 0, 80}, Item{"Sulfuras, Hand of Ragnaros", 0, 80}, 30},
{Item{"Backstage passes to a TAFKAL80ETC concert", 15, 20}, Item{"Backstage passes to a TAFKAL80ETC concert", 15, 20}, 0},
{Item{"Backstage passes to a TAFKAL80ETC concert", 15, 20}, Item{"Backstage passes to a TAFKAL80ETC concert", 14, 21}, 1},
{Item{"Backstage passes to a TAFKAL80ETC concert", 15, 20}, Item{"Backstage passes to a TAFKAL80ETC concert", 13, 22}, 2},
{Item{"Backstage passes to a TAFKAL80ETC concert", 15, 20}, Item{"Backstage passes to a TAFKAL80ETC concert", 10, 25}, 5},
{Item{"Backstage passes to a TAFKAL80ETC concert", 15, 20}, Item{"Backstage passes to a TAFKAL80ETC concert", 9, 27}, 6},
{Item{"Backstage passes to a TAFKAL80ETC concert", 15, 20}, Item{"Backstage passes to a TAFKAL80ETC concert", 8, 29}, 7},
{Item{"Backstage passes to a TAFKAL80ETC concert", 15, 20}, Item{"Backstage passes to a TAFKAL80ETC concert", 5, 35}, 10},
{Item{"Backstage passes to a TAFKAL80ETC concert", 15, 20}, Item{"Backstage passes to a TAFKAL80ETC concert", 4, 38}, 11},
{Item{"Backstage passes to a TAFKAL80ETC concert", 15, 20}, Item{"Backstage passes to a TAFKAL80ETC concert", 3, 41}, 12},
{Item{"Backstage passes to a TAFKAL80ETC concert", 15, 20}, Item{"Backstage passes to a TAFKAL80ETC concert", 0, 50}, 15},
{Item{"Backstage passes to a TAFKAL80ETC concert", 15, 20}, Item{"Backstage passes to a TAFKAL80ETC concert", -1, 0}, 16},
{Item{"Backstage passes to a TAFKAL80ETC concert", 15, 20}, Item{"Backstage passes to a TAFKAL80ETC concert", -10, 0}, 25},
{Item{"Conjured Mana Cake", 3, 6}, Item{"Conjured Mana Cake", 3, 6}, 0},
{Item{"Conjured Mana Cake", 3, 6}, Item{"Conjured Mana Cake", 2, 4}, 1},
{Item{"Conjured Mana Cake", 3, 6}, Item{"Conjured Mana Cake", 1, 2}, 2},
{Item{"Conjured Mana Cake", 3, 6}, Item{"Conjured Mana Cake", 0, 0}, 3},
{Item{"Conjured Mana Cake", 3, 6}, Item{"Conjured Mana Cake", -1, 0}, 4},
{Item{"Conjured Mana Cake", 3, 6}, Item{"Conjured Mana Cake", -2, 0}, 5},
{Item{"Conjured Mana Cake", 3, 6}, Item{"Conjured Mana Cake", -7, 0}, 10},
}
UpdateQuality(items) func TestGildedRose(t *testing.T) {
oldStdout := os.Stdout
if items[0].name != "fixme" { r, w, _ := os.Pipe()
t.Errorf("Name: Expected %s but got %s ", "fixme", items[0].name) defer func() {
os.Stdout = oldStdout
w.Close()
if t.Failed() {
fmt.Println("=== Start Captured Stdout ===")
io.Copy(os.Stdout, r)
fmt.Println("=== End Captured Stdout ===")
}
}()
os.Stdout = w
for tn, test := range tests {
items = []Item{test.startItem}
for i := 0; i < test.days; i++ {
main()
}
if items[0] != test.expectedItem {
t.Logf("Test Number[%d]: Expected starting item %+v to equal %+v after %d days: Got %v", tn, test.startItem, test.expectedItem, test.days, items[0])
t.Fail()
}
} }
} }

View File

@ -1,44 +0,0 @@
package main
import (
"fmt"
"os"
"strconv"
)
func main() {
fmt.Println("OMGHAI!")
var items = []*Item{
&Item{"+5 Dexterity Vest", 10, 20},
&Item{"Aged Brie", 2, 0},
&Item{"Elixir of the Mongoose", 5, 7},
&Item{"Sulfuras, Hand of Ragnaros", 0, 80},
&Item{"Sulfuras, Hand of Ragnaros", -1, 80},
&Item{"Backstage passes to a TAFKAL80ETC concert", 15, 20},
&Item{"Backstage passes to a TAFKAL80ETC concert", 10, 49},
&Item{"Backstage passes to a TAFKAL80ETC concert", 5, 49},
&Item{"Conjured Mana Cake", 3, 6}, // <-- :O
}
days := 2
var err error
if len(os.Args) > 1 {
days, err = strconv.Atoi(os.Args[1])
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
days++
}
for day := 0; day < days; day++ {
fmt.Printf("-------- day %d --------\n", day)
fmt.Println("name, sellIn, quality")
for i := 0; i < len(items); i++ {
fmt.Println(items[i])
}
fmt.Println("")
UpdateQuality(items)
}
}