Files
gophercises/1. Quiz Game Sol2/students/abdul/quiz.go

132 lines
2.5 KiB
Go

package quiz
import (
"bufio"
"encoding/csv"
"flag"
"fmt"
"io"
"log"
"os"
"strings"
"time"
)
//Number of Questions to ask
const totalQuestions = 5
//Question struct that stores question with answer
type Question struct {
question string
answer string
}
func main() {
filename, timeLimit := readArguments()
f, err := openFile(filename)
if err != nil {
return
}
questions, err := readCSV(f)
if err != nil {
// err := fmt.Errorf("Error in Reading Questions")
fmt.Println(err.Error())
return
}
if questions == nil {
return
}
score, err := askQuestion(questions, timeLimit)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("Your Score %d/%d\n", score, totalQuestions)
}
func readArguments() (string, int) {
filename := flag.String("filename", "problem.csv", "CSV File that conatins quiz questions")
timeLimit := flag.Int("limit", 30, "Time Limit for each question")
flag.Parse()
return *filename, *timeLimit
}
func readCSV(f io.Reader) ([]Question, error) {
// defer f.Close() // this needs to be after the err check
allQuestions, err := csv.NewReader(f).ReadAll()
if err != nil {
return nil, err
}
numOfQues := len(allQuestions)
if numOfQues == 0 {
return nil, fmt.Errorf("No Question in file")
}
var data []Question
for _, line := range allQuestions {
ques := Question{}
ques.question = line[0]
ques.answer = line[1]
data = append(data, ques)
}
return data, nil
}
func openFile(filename string) (io.Reader, error) {
return os.Open(filename)
}
func getInput(input chan string) {
for {
in := bufio.NewReader(os.Stdin)
result, err := in.ReadString('\n')
if err != nil {
log.Fatal(err)
}
input <- result
}
}
func askQuestion(questions []Question, timeLimit int) (int, error) {
totalScore := 0
timer := time.NewTimer(time.Duration(timeLimit) * time.Second)
done := make(chan string)
go getInput(done)
for i := range [totalQuestions]int{} {
ans, err := eachQuestion(questions[i].question, questions[i].answer, timer.C, done)
if err != nil && ans == -1 {
return totalScore, nil
}
totalScore += ans
}
return totalScore, nil
}
func eachQuestion(Quest string, answer string, timer <-chan time.Time, done <-chan string) (int, error) {
fmt.Printf("%s: ", Quest)
for {
select {
case <-timer:
return -1, fmt.Errorf("Time out")
case ans := <-done:
score := 0
if strings.Compare(strings.Trim(strings.ToLower(ans), "\n"), answer) == 0 {
score = 1
} else {
return 0, fmt.Errorf("Wrong Answer")
}
return score, nil
}
}
}