mirror of
https://github.com/AmanTahiliani/gophercises.git
synced 2026-08-07 19:56:17 -04:00
89 lines
2.0 KiB
Go
89 lines
2.0 KiB
Go
|
|
package main
|
||
|
|
|
||
|
|
import (
|
||
|
|
"bufio"
|
||
|
|
"encoding/csv"
|
||
|
|
"flag"
|
||
|
|
"fmt"
|
||
|
|
"log"
|
||
|
|
"os"
|
||
|
|
"strings"
|
||
|
|
"time"
|
||
|
|
)
|
||
|
|
|
||
|
|
var (
|
||
|
|
// set flags
|
||
|
|
csvPath = flag.String("csv", "problems.csv", "a csv file in the format of 'question,answer'")
|
||
|
|
limit = flag.Int("limit", 30, "the time limit for the quiz in seconds'")
|
||
|
|
)
|
||
|
|
|
||
|
|
func main() {
|
||
|
|
// parse the flags
|
||
|
|
flag.Parse()
|
||
|
|
|
||
|
|
// open the csv file
|
||
|
|
file, err := os.Open(*csvPath)
|
||
|
|
if err != nil {
|
||
|
|
log.Println(err)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
defer file.Close()
|
||
|
|
|
||
|
|
// open the csv file
|
||
|
|
csvReader := csv.NewReader(file)
|
||
|
|
// parse the csv file
|
||
|
|
csvData, err := csvReader.ReadAll()
|
||
|
|
if err != nil {
|
||
|
|
log.Println(err)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
// put question/answer pairs into a map where questions are keys and answers are values
|
||
|
|
qaPair := make(map[string]string, len(csvData))
|
||
|
|
for _, data := range csvData {
|
||
|
|
qaPair[data[0]] = data[1]
|
||
|
|
}
|
||
|
|
|
||
|
|
// create a ticker for the time limit and a channel to signal the user finished the quiz
|
||
|
|
ticker := time.NewTicker(time.Second * time.Duration(*limit))
|
||
|
|
done := make(chan bool)
|
||
|
|
|
||
|
|
// create a scanner for user input
|
||
|
|
scanner := bufio.NewScanner(os.Stdin)
|
||
|
|
|
||
|
|
var userAnswer string
|
||
|
|
qNum, numCorrect := 0, 0
|
||
|
|
go func() {
|
||
|
|
// iteration order for maps in go is randomized so the questions won't be in the same order every time
|
||
|
|
for question, answer := range qaPair {
|
||
|
|
qNum++
|
||
|
|
// ask a question
|
||
|
|
fmt.Printf("Problem #%d: %s = ", qNum, question)
|
||
|
|
// get an answer
|
||
|
|
scanner.Scan()
|
||
|
|
userAnswer = scanner.Text()
|
||
|
|
// trim leading and trailing whitespace
|
||
|
|
userAnswer = strings.TrimSpace(userAnswer)
|
||
|
|
userAnswer = strings.ToLower(userAnswer)
|
||
|
|
answer = strings.ToLower(answer)
|
||
|
|
// check the answer
|
||
|
|
if answer == userAnswer {
|
||
|
|
numCorrect++
|
||
|
|
}
|
||
|
|
}
|
||
|
|
done <- true
|
||
|
|
}()
|
||
|
|
|
||
|
|
// select chooses the first channel with an available value
|
||
|
|
// if done is available first, the user finished
|
||
|
|
// if ticker is available first, the time limit has been reached
|
||
|
|
select {
|
||
|
|
case <-done:
|
||
|
|
case <-ticker.C:
|
||
|
|
fmt.Println("time's up!")
|
||
|
|
}
|
||
|
|
|
||
|
|
// print the results
|
||
|
|
fmt.Printf("You scored %d out of %d.\n", numCorrect, len(qaPair))
|
||
|
|
}
|