Last active
November 30, 2020 17:17
-
-
Save Dainerx/0c142a110161fe229a5107f746a62c3f to your computer and use it in GitHub Desktop.
Simulating a chapatti store
This file contains hidden or 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
package main | |
import ( | |
"fmt" | |
"log" | |
"math/rand" | |
"time" | |
) | |
type ChappatiStore struct { | |
Verbose bool // True for logs from go routines | |
ChappatiToMake int // number of chappati to make | |
Bakers int // number of cooks doing baking | |
BakeMeanTime time.Duration // mean time to prepare dough for one chappati | |
BakeStdDev time.Duration // standard deviation of preparing dough for one chappati | |
BakeBufferSize int // buffer slots between baking and making | |
Makers int // number of chappati makers | |
MakeMeanTime time.Duration // mean time to make one chappati | |
MakeStdDev time.Duration // standard deviation for making one chappati with baked dough | |
MakeBufferSize int // buffer slots between making and packaging | |
PackageMeanTime time.Duration // mean time to package one sandwitch | |
PackageStdDev time.Duration // standard deviation for packaging one made chappati | |
} | |
type chappati int | |
// bake a chappati and send it to the baked channel. | |
func (ch *ChappatiStore) baker(baked chan<- chappati, toBake <-chan chappati) { | |
for c := range toBake { | |
if ch.Verbose { | |
log.Println("baking", c) | |
} | |
work(ch.BakeMeanTime, ch.BakeStdDev) | |
baked <- c | |
} | |
} | |
// retrive from the baked channel a dough and make a chappati with it. | |
func (ch *ChappatiStore) maker(made chan<- chappati, baked <-chan chappati) { | |
for c := range baked { | |
if ch.Verbose { | |
log.Println("making", c) | |
} | |
work(ch.MakeMeanTime, ch.MakeStdDev) | |
made <- c | |
} | |
} | |
// package a prepared a made chappati. | |
func (ch *ChappatiStore) packager(made <-chan chappati) { | |
for i := 0; i < ch.ChappatiToMake; i++ { | |
c := <-made | |
if ch.Verbose { | |
log.Println("packaging", c) | |
} | |
work(ch.PackageMeanTime, ch.PackageStdDev) | |
if ch.Verbose { | |
log.Println("sold", c) | |
} | |
} | |
} | |
// work blocks the calling goroutine for a period of time | |
// that is normally distributed around mean with a standard deviation of stddev. | |
func work(mean, stddev time.Duration) time.Duration { | |
delay := mean + time.Duration(rand.NormFloat64()*float64(stddev)) | |
time.Sleep(delay) | |
return delay | |
} | |
func (ch *ChappatiStore) Configuration() string { | |
var config string | |
config += fmt.Sprintf("Baking{Bakers:%d,BakeStdDev:%v,BakeMeanTime:%v,BakeBufferSize:%d}\n", | |
ch.Bakers, ch.BakeStdDev, ch.BakeMeanTime, ch.BakeBufferSize) | |
config += fmt.Sprintf("Making{Makers:%d,MakeStdDev:%v,MakeMeanTime:%v,MakeBufferSize:%d}\n", | |
ch.Makers, ch.MakeStdDev, ch.MakeMeanTime, ch.MakeBufferSize) | |
config += fmt.Sprintf("Packaging{PackageMeanTime:%v,PackageStdDev:%v}\n", | |
ch.PackageMeanTime, ch.PackageStdDev) | |
return config | |
} | |
// Run | |
func (ch *ChappatiStore) Run() time.Duration { | |
toBake := make(chan chappati, ch.ChappatiToMake) | |
baked := make(chan chappati, ch.BakeBufferSize) | |
made := make(chan chappati, ch.MakeBufferSize) | |
for i := 0; i < ch.ChappatiToMake; i++ { | |
toBake <- chappati(i) | |
} | |
start := time.Now() | |
// for every baker launch the bake method on different routine | |
for i := 0; i < ch.Bakers; i++ { | |
go ch.baker(baked, toBake) | |
} | |
for i := 0; i < ch.Makers; i++ { | |
go ch.maker(made, baked) | |
} | |
ch.packager(made) | |
return time.Since(start) | |
} | |
func main() { | |
ch := ChappatiStore{ | |
Verbose: true, // display goroutines progress | |
ChappatiToMake: 50, | |
Bakers: 10, | |
BakeStdDev: 10 * time.Millisecond, | |
BakeMeanTime: 500 * time.Millisecond, | |
BakeBufferSize: 1, | |
Makers: 5, | |
MakeStdDev: 10 * time.Millisecond, | |
MakeMeanTime: 50 * time.Millisecond, | |
MakeBufferSize: 1, | |
PackageMeanTime: 100 * time.Millisecond, | |
} | |
fmt.Printf("We closed, took %v to prepare %d chappatis.\n", ch.Run(), ch.ChappatiToMake) | |
fmt.Print(ch.Configuration()) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment