forked from gophercises/quiz
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added solution using timer.AfterFunc and a duration flag. (gophercise…
- Loading branch information
1 parent
b09f555
commit d06f1d1
Showing
2 changed files
with
125 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
package main | ||
|
||
import ( | ||
"encoding/csv" | ||
"flag" | ||
"fmt" | ||
"log" | ||
"os" | ||
"time" | ||
) | ||
|
||
var ( | ||
filename string | ||
timelimit time.Duration | ||
) | ||
|
||
func init() { | ||
flag.StringVar(&filename, "in", "problems.csv", "filename where problems are read from") | ||
flag.DurationVar(&timelimit, "time", 30*time.Second, "time to allot for quiz") | ||
} | ||
|
||
|
||
// problem represents a prompt and the correct response | ||
type problem struct { | ||
prompt string | ||
response string | ||
} | ||
|
||
// printResults prints a prompt to the user explaining the results achieved. | ||
func printResults(nWrong, nTotal int) { | ||
nRight := nTotal - nWrong | ||
fmt.Printf("You answered %d out of %d questions correctly.\n", nRight, nTotal) | ||
} | ||
|
||
// readFile reads from the file, sending back a slice of problems. | ||
func readFile() []problem { | ||
file, err := os.Open(filename) | ||
if err != nil { | ||
log.Fatal("Error opening file: %s", err.Error()) | ||
} | ||
|
||
r := csv.NewReader(file) | ||
records, err := r.ReadAll() | ||
|
||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
// Construct a slice of problems for later consumption | ||
result := make([]problem, len(records)) | ||
var i int | ||
for idx, rec := range records { | ||
if len(rec) < 2 { | ||
fmt.Println("Ignoring faulty or missing record from line %d", idx) | ||
continue | ||
} | ||
result[i] = problem{rec[0], rec[1]} | ||
i++ | ||
} | ||
|
||
return result | ||
} | ||
|
||
func main() { | ||
flag.Parse() | ||
|
||
problems := readFile() | ||
|
||
var nWrong, nDone int | ||
// timeout is used to signal that the timer has elapsed | ||
timeout := make(chan bool, 2) | ||
timer := time.AfterFunc(timelimit, func() { | ||
timeout <- true // signal that a timeout occurred | ||
}) | ||
|
||
startTime := time.Now() | ||
// Ask each question and get a response | ||
for _, prob := range problems { | ||
fmt.Printf("%s\n > ", prob.prompt) | ||
|
||
// A separate goroutine must be used to accept input from each question. At first I tried to just read from | ||
// Stdin on the main thread. That was a mistake. If you want to be able to interrupt the prompt when the time | ||
// expires, you need to have your main thread waiting on a response from either the timer or the answer thread. | ||
// | ||
// Lesson is to treat user input as an asynchronous message! | ||
answerCh := make(chan string) | ||
go func() { | ||
var answer string | ||
fmt.Scanf("%s\n", &answer) | ||
answerCh <- answer | ||
}() | ||
|
||
select { | ||
case <-timeout: | ||
fmt.Println("\nTimes up!") | ||
nWrong += len(problems) - nDone // All remaining problems are marked wrong | ||
printResults(nWrong, len(problems)) | ||
os.Exit(0) | ||
case response := <-answerCh: | ||
nDone++ | ||
if prob.response != response { | ||
nWrong++ | ||
} | ||
} | ||
} | ||
|
||
if timer.Stop() { | ||
fmt.Printf("You completed the quiz with %s remaining\n", (timelimit - time.Since(startTime)).String()) | ||
|
||
printResults(nWrong, len(problems)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |