Skip to content

Commit c18e401

Browse files
Tobi Fuhrimannjoncalhoun
authored andcommitted
Add mastertinner's solution (#46)
1 parent da36ae0 commit c18e401

File tree

1 file changed

+118
-0
lines changed

1 file changed

+118
-0
lines changed

students/mastertinner/main.go

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
package main
2+
3+
import (
4+
"bufio"
5+
"encoding/csv"
6+
"errors"
7+
"flag"
8+
"fmt"
9+
"io"
10+
"log"
11+
"math/rand"
12+
"os"
13+
"strings"
14+
"time"
15+
)
16+
17+
// problem is a problem to be solved by a user.
18+
type problem struct {
19+
challenge string
20+
correctAnswer string
21+
}
22+
23+
// scoreboard keeps track of a user's score.
24+
type scoreboard struct {
25+
total int64
26+
correct int64
27+
}
28+
29+
func main() {
30+
var (
31+
csvFileName = flag.String("csv", "problems.csv", "the location of the CSV file")
32+
timeLimit = flag.Int("time-limit", 30, "the time limit for the user to answer all problems")
33+
doShuffle = flag.Bool("shuffle", false, "whether to shuffle the order of problems or not")
34+
)
35+
flag.Parse()
36+
37+
problems, err := readProblemsFromCSVFile(*csvFileName)
38+
if err != nil {
39+
log.Fatal(fmt.Errorf("error reading problems from CSV file: %s", err))
40+
}
41+
if *doShuffle {
42+
rand.Seed(time.Now().Unix())
43+
rand.Shuffle(len(problems), func(i, j int) { problems[i], problems[j] = problems[j], problems[i] })
44+
}
45+
46+
doneCh := make(chan bool)
47+
scr := &scoreboard{
48+
total: int64(len(problems)),
49+
}
50+
51+
go func() {
52+
for i, p := range problems {
53+
fmt.Printf("What is %s?\n", p.challenge)
54+
inputReader := bufio.NewReader(os.Stdin)
55+
fmt.Print("Answer: ")
56+
answer, err := inputReader.ReadString('\n')
57+
if err != nil {
58+
log.Fatal(fmt.Errorf("error reading user input: %s", err))
59+
}
60+
if purifyString(answer) == purifyString(p.correctAnswer) {
61+
scr.correct++
62+
fmt.Println("You are correct!")
63+
} else {
64+
fmt.Printf("Unfortunately not... The correct answer is %s\n", p.correctAnswer)
65+
}
66+
fmt.Printf("Your current score is %v/%v\n\n", scr.correct, scr.total)
67+
if i == len(problems)-1 {
68+
doneCh <- true
69+
}
70+
}
71+
}()
72+
73+
go func() {
74+
timer := time.NewTimer(time.Duration(*timeLimit) * time.Second)
75+
<-timer.C
76+
fmt.Println("")
77+
fmt.Println("")
78+
fmt.Println("Your time is up...")
79+
doneCh <- true
80+
}()
81+
82+
<-doneCh
83+
fmt.Println("")
84+
fmt.Printf("Your final score is %v/%v\n\n", scr.correct, scr.total)
85+
}
86+
87+
// readProblemsFromCSVFile reads problems from a CSV file.
88+
func readProblemsFromCSVFile(fileName string) ([]problem, error) {
89+
csvFile, err := os.Open(fileName)
90+
if err != nil {
91+
return nil, fmt.Errorf("error opening file: %s", err)
92+
}
93+
reader := csv.NewReader(bufio.NewReader(csvFile))
94+
var problems []problem
95+
for {
96+
line, err := reader.Read()
97+
if err != nil {
98+
if err == io.EOF {
99+
break
100+
}
101+
return nil, fmt.Errorf("error reading CSV line: %s", err)
102+
}
103+
if len(line) != 2 {
104+
return nil, errors.New("invalid line in CSV")
105+
}
106+
p := problem{
107+
challenge: line[0],
108+
correctAnswer: line[1],
109+
}
110+
problems = append(problems, p)
111+
}
112+
return problems, nil
113+
}
114+
115+
// purifyString strips all unneeded variations from a string.
116+
func purifyString(str string) string {
117+
return strings.TrimSpace(strings.ToLower(str))
118+
}

0 commit comments

Comments
 (0)