/** * Code to grade Kyle's Go projects. * note: IO redirecting solutions modified from mattes's answer on https://stackoverflow.com/questions/10473800/in-go-how-do-i-capture-stdout-of-a-function-into-a-string */ package main import ( "fmt" "time" "math" "math/rand" "runtime" ) func simulation(numLines int, numCustomers int) (int, int, int, float64) { fmt.Println("Started simulation...") //numLines := 10 lineCapacity := 200 //numCustomers := 1000 minNumItems := 10 maxNumItems := 90 minItemSize := 2 maxItemSize := 800 minTimeBetweenCustomers := 1 maxTimeBetweenCustomers := 85000000 storeExit := make(chan Customer) lines := NewCheckoutLines(numLines, lineCapacity, storeExit) coordinator := NewCheckoutCoordinator(lines) fmt.Println("Created Coordinator...") fmt.Println("Turning on the checkout lines!") lines.Start() i:=0 fmt.Println("Creating initial customers...") //first create a customer for each line for ; i < numCustomers && i < numLines; i++ { numItems := rand.Intn(maxNumItems - minNumItems) + minNumItems items := make([]int, numItems, numItems) for j:= 0; j < numItems; j++ { items[j] = rand.Intn(maxItemSize - minItemSize) + minItemSize } customer := NewCustomer(i, items) coordinator.AddCustomer(customer) //fmt.Println("Added customer ", i, "...") //Don't sleep here because we want to put one person in each line /* sleepTime := rand.Intn(maxTimeBetweenCustomers - minTimeBetweenCustomers) + minTimeBetweenCustomers time.Sleep(sleepTime)*/ } fmt.Println("Started thread to create customers...") //thread creating all the customers go func() { for ; i < numCustomers; i++ { numItems := rand.Intn(maxNumItems - minNumItems) + minNumItems items := make([]int, numItems, numItems) for j:= 0; j < numItems; j++ { items[j] = rand.Intn(maxItemSize - minItemSize) + minItemSize } customer := NewCustomer(i, items) coordinator.AddCustomer(customer) sleepTime := (rand.Intn(maxTimeBetweenCustomers - minTimeBetweenCustomers) + minTimeBetweenCustomers) / numLines time.Sleep(time.Duration(sleepTime)) } fmt.Println("All customers sent to the checkout coordinator!") }() fmt.Println("All customer lines launched.") oneWhenAllDone := make(chan int, 100) //fmt.Println("Made the channel.") if numLines <= 20 { oneWhenAllDone <- 0 //not done yet //fmt.Println("Put 0 on the channel.") //stats printing loop go func() { fmt.Println("Stats Reporting Thread, checking in! Here we go!") for ; 1 != <- oneWhenAllDone; { //fmt.Println("Time for a short nap.") time.Sleep(2000000000) //I think this is waiting two seconds localStats := lines.GetStats() fmt.Println("~~~~~") for j:= 0; j < numLines; j++ { fmt.Println(fmt.Sprint("Line ", j, ": ", localStats[j], " (", len(lines.lines[j]), " waiting) ", lines.idleMs[j], "ms idle")) } fmt.Println("~~~~~") oneWhenAllDone <- 0 //put something in the channel in case we're not done yet } fmt.Println("Done printing the stats.") } () fmt.Println("Launched the stats-reporting thread!") } else { oneWhenAllDone <- 0 //not done yet //fmt.Println("Put 0 on the channel.") //stats printing loop go func() { fmt.Println("Stats Reporting Thread, checking in! Here we go!") for ; 1 != <- oneWhenAllDone; { //fmt.Println("Time for a short nap.") time.Sleep(5000000000) //I think this is waiting five seconds fmt.Println("Just marking time... there are ", runtime.NumGoroutine(), " active Goroutines.") oneWhenAllDone <- 0 //put something in the channel in case we're not done yet } //fmt.Println("Done printing the stats.") } () } fivePercent := numCustomers/20 //loop for collecting the customers at the end. for i := 0; i < numCustomers; i++ { <- storeExit //a customer exits the store if (i+1)/fivePercent > (i)/fivePercent { fmt.Println("customers served so far:", (i+1)) } } oneWhenAllDone <- 1 fmt.Println("All customers have left the store!") stats := lines.GetStats() max := 1 min := float64(stats[0]) for i := 1; i < len(stats); i++ { stat := stats[i] max = int(math.Max(float64(stat), float64(max))) min = math.Min(float64(stat), min) } fmt.Println("stats:", stats) fmt.Println("min: ", min, " \nmax: ", max); ratio := (int(min) * 100) / max fmt.Println("Ratio: ", ratio); return ratio, lines.LongestIdle(), lines.AverageIdle(), lines.PercentageIdleAverageOfMax() } func main() { //ratio, maxIdle, avgIdle := simulation(10, 100) ratio, maxIdle, avgIdle, percentAvgIdle := simulation(10, 1000) score := getScoreFrom(ratio, percentAvgIdle, 50) //fmt.Println("score: ", score) fmt.Println("Finished First Simulation. Starting second...") ratio, maxIdle, avgIdle, percentAvgIdle = simulation(500, 50000) fmt.Println(avgIdle, ", ", maxIdle) score += getScoreFrom(ratio, percentAvgIdle, 50) fmt.Println("total score: ", score) } //func getScoreFrom(ratio int, maxIdle int, avgIdle int, maxPoints int) int { func getScoreFrom(ratio int, percentageAvgIdle float64, maxPoints int) int { ratio = int(math.Max(float64(ratio), 0.0)) ratioScore := (maxPoints/2 * ratio) / 100 fmt.Println("ratio: ", ratio, " ---> ", ratioScore, "/", maxPoints/2) /* maxIdle = int(math.Max(float64(maxIdle), 0.0)) avgIdle = int(math.Max(float64(avgIdle), 0.0)) if (maxIdle == 0) { maxIdle = 1 avgIdle = 1 } */ idleScore := int(percentageAvgIdle) * maxPoints/200 fmt.Println("100 * avgIdle / maxIdle: ", int(percentageAvgIdle), " ---> ", idleScore, "/", maxPoints/2) return ratioScore + idleScore }