From 284f89dfb133da80c73805c9b3dc4e861f8da4a4 Mon Sep 17 00:00:00 2001 From: Abdul <47447989+abdul-manaan@users.noreply.github.com> Date: Tue, 9 Jul 2019 11:10:21 +0500 Subject: [PATCH] Solution with unit tests --- students/abdul/problem.csv | 13 ++++ students/abdul/quiz.go | 131 ++++++++++++++++++++++++++++++++++++ students/abdul/quiz_test.go | 59 ++++++++++++++++ 3 files changed, 203 insertions(+) create mode 100644 students/abdul/problem.csv create mode 100644 students/abdul/quiz.go create mode 100644 students/abdul/quiz_test.go diff --git a/students/abdul/problem.csv b/students/abdul/problem.csv new file mode 100644 index 0000000..ab5e298 --- /dev/null +++ b/students/abdul/problem.csv @@ -0,0 +1,13 @@ +5+5,10 +7+3,10 +1+1,2 +8+3,11 +1+2,3 +8+6,14 +3+1,4 +1+4,5 +5+1,6 +2+3,5 +3+3,6 +2+4,6 +5+2,7 \ No newline at end of file diff --git a/students/abdul/quiz.go b/students/abdul/quiz.go new file mode 100644 index 0000000..5f1e1ab --- /dev/null +++ b/students/abdul/quiz.go @@ -0,0 +1,131 @@ +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 + } + } +} diff --git a/students/abdul/quiz_test.go b/students/abdul/quiz_test.go new file mode 100644 index 0000000..de02f6d --- /dev/null +++ b/students/abdul/quiz_test.go @@ -0,0 +1,59 @@ +package quiz + +import ( + "strings" + "testing" + "time" + + "gotest.tools/assert" +) + +func testEachQuestion(t *testing.T) { + timer := time.NewTimer(time.Duration(2) * time.Second).C + done := make(chan string) + var quest Question + quest.question = "1+1" + quest.answer = "2" + var ans int + var err error + allDone := make(chan bool) + go func() { + ans, err = eachQuestion(quest.question, quest.answer, timer, done) + allDone <- true + }() + done <- "2" + + <-allDone + if err != nil { + t.Error(err) + } + assert.Equal(t, ans, 1) +} + +func testReadCSV(t *testing.T) { + str := "1+1,2\n2+1,3\n9+9,18\n" + quest, err := readCSV(strings.NewReader(str)) + if err != nil { + t.Error(err) + } + var que [3]Question + que[0].answer = "2" + que[1].answer = "3" + que[2].answer = "18" + que[0].question = "1+1" + que[1].question = "2+1" + que[2].question = "9+9" + + assert.Equal(t, que[0], quest[0]) + assert.Equal(t, que[1], quest[1]) + assert.Equal(t, que[2], quest[2]) + +} + +func TestEachQuestion(t *testing.T) { + t.Run("test eachQuestion", testEachQuestion) +} + +func TestReadCSV(t *testing.T) { + t.Run("test ReadCSV", testReadCSV) +}