diff --git a/students/dennisvis/main.go b/students/dennisvis/main.go new file mode 100644 index 0000000..7d947c6 --- /dev/null +++ b/students/dennisvis/main.go @@ -0,0 +1,155 @@ +package main + +import ( + "bufio" + "encoding/csv" + "flag" + "fmt" + "io" + "log" + "math/rand" + "os" + "strings" + "time" +) + +type problem struct { + question string + answer string +} + +var ( + problemsFile = flag.String("problems", "problems.csv", "A CSV file containing problems and their solutions") + quizTime = flag.Int("time", 30, "The time in seconds this quiz will run") + shuffle = flag.Bool("shuffle", false, "Wheteher or not to shuffle the problems") + osR = bufio.NewReader(os.Stdin) +) + +func readProblems(csvFile *os.File) []problem { + csvR := csv.NewReader(csvFile) + + problems := make([]problem, 0) + for { + record, err := csvR.Read() + if err == io.EOF { + break + } + if err != nil { + log.Fatal(err) + } + if record[0] != "" && record[1] != "" { + problems = append(problems, problem{record[0], strings.ToLower(record[1]}) + } + } + + return problems +} + +func shuffleProblems(problems []problem) { + r := rand.New(rand.NewSource(time.Now().Unix())) + for i1 := 0; i1 < len(problems); i1++ { + i2 := r.Intn(len(problems)) + + problem1 := problems[i1] + problem2 := problems[i2] + + problems[i1] = problem2 + problems[i2] = problem1 + } +} + +func askQuestion(q string, tries int8) string { + fmt.Printf("\n%s: ", q) + input, err := osR.ReadString('\n') + if err != nil { + if tries < 5 { + log.Println("Your answer could not be processed, please try again") + return askQuestion(q, tries+1) + } + log.Fatal("Something is wrong with this program, going to exit...") + } + return strings.ToLower(strings.TrimSpace(strings.TrimRight(input, "\n"))) +} + +func askQuestions(problems []problem, timer, correctAnswersChan, done chan interface{}) { + index := 0 + for { + select { + case <-timer: + fmt.Println("\nTime's up!") + return + + default: + if index >= len(problems) { + close(done) + return + } + + problem := problems[index] + answer := askQuestion(problem.question, 0) + if answer == problem.answer { + correctAnswersChan <- true + fmt.Println("Correct!") + } else { + fmt.Println("False...") + } + index = index + 1 + } + } +} + +func main() { + flag.Parse() + + if !strings.HasSuffix(*problemsFile, "csv") { + log.Fatalf("Provided problems file '%s' is not a CSV file", *problemsFile) + } + + csvFile, err := os.Open(*problemsFile) + if err != nil { + log.Fatalf("Could not open '%s'", *problemsFile) + } + + problems := readProblems(csvFile) + totalProblems := len(problems) + if *shuffle { + shuffleProblems(problems) + } + + timer := make(chan interface{}) + correctAnswersChan := make(chan interface{}) + done := make(chan interface{}) + + fmt.Println("Press ENTER to start the quiz...") + osR.ReadString('\n') + + correctAnswers := 0 + go func() { + for { + select { + case _ = <-correctAnswersChan: + correctAnswers = correctAnswers + 1 + case <-done: + return + } + } + }() + + go askQuestions(problems, timer, correctAnswersChan, done) + + time.Sleep(time.Duration(*quizTime) * time.Second) + close(timer) + close(done) + + if totalProblems == correctAnswers { + fmt.Println("\nCongratulations! You answered all questions correctly!") + } else { + fmt.Printf( + "\nYou answered %d questions correctly but failed to do so for %d questions, try again", + correctAnswers, + totalProblems-correctAnswers, + ) + } + + os.Exit(0) +} diff --git a/students/dennisvis/problems.csv b/students/dennisvis/problems.csv new file mode 100644 index 0000000..11506cb --- /dev/null +++ b/students/dennisvis/problems.csv @@ -0,0 +1,12 @@ +5+5,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