Files
gophercises/1. Quiz Game Sol2/students/sewelol/main.go

160 lines
3.3 KiB
Go

package main
import (
"bufio"
"flag"
"fmt"
"io/ioutil"
"log"
"math/rand"
"os"
"strconv"
"strings"
"time"
)
// Problem structure
type Problem struct {
q string
a int
}
// PROBLEMBUFCOUNT sets number of problems in buffer
const PROBLEMBUFCOUNT = 100
// DEFAULTTIMELIMIT sets the default time limit for the quiz
const DEFAULTTIMELIMIT = 30 //seconds
// Problem counter
var count int
// Score counter
var score int
var faults int
// readProblems takes reads problems from file, line by line
// problems are written to problems channel
func readProblems(problems chan Problem, filename string, shuffle bool) {
// problems buffer
buf := make([]Problem, PROBLEMBUFCOUNT)
// Open problems file
fd, err := os.Open(filename)
if err != nil {
log.Fatal(err)
}
defer fd.Close()
// Scan file
scanner := bufio.NewScanner(fd)
for scanner.Scan() {
// Read comma separated line
line := strings.Split(scanner.Text(), ",")
// first value is the question string
q := line[0]
// Convert string answer to integer
ans, err := strconv.Atoi(line[1])
if err != nil {
log.Fatal(err)
}
// store problem in buffer
buf[count] = Problem{q, ans}
count++
}
// shuffle problems
if shuffle {
rand.Seed(time.Now().Unix())
for i := range buf[:count] {
j := rand.Intn(i + 1)
buf[i], buf[j] = buf[j], buf[i]
}
}
// send problems over channel
for _, p := range buf[:count] {
problems <- p
}
}
// solveProblem consumes problems from chan
// will check timer before giving points
func solveProblem(problems chan Problem) {
// IO reader
scanner := bufio.NewScanner(os.Stdin)
// start consuming problems from channel
for p := range problems {
// Print problem question
fmt.Printf("%s = ", p.q)
// Scan IO
scanner.Scan()
input := strings.Trim(scanner.Text(), " ") // remove whitespace
// convert string answer to integer
givenAns, err := strconv.Atoi(input)
if err != nil {
fmt.Printf("'%s' is not a valid answer\n", input)
continue
}
// Check answer and give points
if givenAns == p.a {
score++
fmt.Println("Correct!")
} else {
faults++
fmt.Println("Wrong!")
}
}
return
}
// startTimer blocks for n seconds
func startTimer(seconds int) {
time.Sleep(time.Duration(seconds) * time.Second)
}
func main() {
// Parse Command line flags
filenamePtr := flag.String("f", "problems.csv", "name of problem csv file")
secondsPtr := flag.Int("t", DEFAULTTIMELIMIT, "number of seconds to solve problems")
shufflePtr := flag.Bool("s", false, "shuffle questions")
debugPtr := flag.Bool("debug", false, "show debug information")
flag.Parse()
// Show debug/logging information
if !*debugPtr {
log.SetOutput(ioutil.Discard)
}
log.Println("debug:", *debugPtr)
log.Println("filename:", *filenamePtr)
log.Println("shuffle:", *shufflePtr)
log.Println("timer:", *secondsPtr)
// Problems channel (buffered)
problems := make(chan Problem, PROBLEMBUFCOUNT)
// read problems goroutine
go readProblems(problems, *filenamePtr, *shufflePtr)
// Prompt to start the game
fmt.Printf("Press any key to start the quiz!")
bufio.NewScanner(os.Stdin).Scan()
// solve problems goroutine
go solveProblem(problems)
// start timer barrier
startTimer(*secondsPtr)
// Show final tally
fmt.Printf("\nNumber of questions: %d\n", count)
fmt.Printf("Correct answers: %d\n", score)
fmt.Printf("Incorrect answers: %d\n", faults)
}