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

121 lines
2.7 KiB
Go

package main
import (
"encoding/csv"
"flag"
"fmt"
"io"
"log"
"os"
"time"
quiz "github.com/gophercises/quiz/students/hackeryarn/myquiz"
"github.com/gophercises/quiz/students/hackeryarn/problem"
)
const (
// FileFlag is used to set a file for the questions
FileFlag = "file"
// FileFlagValue is the value used when no FileFlag is provided
FileFlagValue = "problems.csv"
// FileFlagUsage is the help string for the FileFlag
FileFlagUsage = "Questions file"
// TimerFlag is used for setting a timer for the quiz
TimerFlag = "timer"
// TimerFlagValue is the value used when no TimerFlag is provided
TimerFlagValue = 30
// TimerFlagUsage is the help string for the TimerFlag
TimerFlagUsage = "Amount of seconds the quiz will allow"
)
// Flagger configures the flags used
type Flagger interface {
StringVar(p *string, name, value, usage string)
IntVar(p *int, name string, value int, usage string)
}
type quizFlagger struct{}
func (q *quizFlagger) StringVar(p *string, name, value, usage string) {
flag.StringVar(p, name, value, usage)
}
func (q *quizFlagger) IntVar(p *int, name string, value int, usage string) {
flag.IntVar(p, name, value, usage)
}
// Timer is used to start a timer
type Timer interface {
NewTimer(d time.Duration) *time.Timer
}
type quizTimer struct{}
func (q quizTimer) NewTimer(d time.Duration) *time.Timer {
return time.NewTimer(d)
}
// ReadCSV parses the CSV file into a Problem struct
func ReadCSV(reader io.Reader) quiz.Quiz {
csvReader := csv.NewReader(reader)
problems := []problem.Problem{}
for {
record, err := csvReader.Read()
if err == io.EOF {
break
} else if err != nil {
log.Fatalln("Error reading CSV:", err)
}
problems = append(problems, problem.New(record))
}
return quiz.New(problems)
}
// TimerSeconds is the amount of time allowed for the quiz
var TimerSeconds int
var file string
// ConfigFlags sets all the flags used by the application
func ConfigFlags(f Flagger) {
f.StringVar(&file, FileFlag, FileFlagValue, FileFlagUsage)
f.IntVar(&TimerSeconds, TimerFlag, TimerFlagValue, TimerFlagUsage)
}
// StartTimer begins a timer once the user provides input
func StartTimer(w io.Writer, r io.Reader, timer Timer) *time.Timer {
fmt.Fprint(w, "Ready to start?")
fmt.Fscanln(r)
return timer.NewTimer(time.Second * time.Duration(TimerSeconds))
}
func init() {
flagger := &quizFlagger{}
ConfigFlags(flagger)
flag.Parse()
}
func main() {
file, err := os.Open(file)
if err != nil {
log.Fatalln("Could not open file", err)
}
quiz := ReadCSV(file)
timer := StartTimer(os.Stdout, os.Stdin, quizTimer{})
go func() {
<-timer.C
fmt.Println("")
quiz.PrintResults(os.Stdout)
os.Exit(0)
}()
quiz.Run(os.Stdout, os.Stdin)
}