Skip to content

Commit

Permalink
Add mastertinner's solution (gophercises#46)
Browse files Browse the repository at this point in the history
  • Loading branch information
Tobi Fuhrimann authored and joncalhoun committed Jul 22, 2019
1 parent da36ae0 commit c18e401
Showing 1 changed file with 118 additions and 0 deletions.
118 changes: 118 additions & 0 deletions students/mastertinner/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package main

import (
"bufio"
"encoding/csv"
"errors"
"flag"
"fmt"
"io"
"log"
"math/rand"
"os"
"strings"
"time"
)

// problem is a problem to be solved by a user.
type problem struct {
challenge string
correctAnswer string
}

// scoreboard keeps track of a user's score.
type scoreboard struct {
total int64
correct int64
}

func main() {
var (
csvFileName = flag.String("csv", "problems.csv", "the location of the CSV file")
timeLimit = flag.Int("time-limit", 30, "the time limit for the user to answer all problems")
doShuffle = flag.Bool("shuffle", false, "whether to shuffle the order of problems or not")
)
flag.Parse()

problems, err := readProblemsFromCSVFile(*csvFileName)
if err != nil {
log.Fatal(fmt.Errorf("error reading problems from CSV file: %s", err))
}
if *doShuffle {
rand.Seed(time.Now().Unix())
rand.Shuffle(len(problems), func(i, j int) { problems[i], problems[j] = problems[j], problems[i] })
}

doneCh := make(chan bool)
scr := &scoreboard{
total: int64(len(problems)),
}

go func() {
for i, p := range problems {
fmt.Printf("What is %s?\n", p.challenge)
inputReader := bufio.NewReader(os.Stdin)
fmt.Print("Answer: ")
answer, err := inputReader.ReadString('\n')
if err != nil {
log.Fatal(fmt.Errorf("error reading user input: %s", err))
}
if purifyString(answer) == purifyString(p.correctAnswer) {
scr.correct++
fmt.Println("You are correct!")
} else {
fmt.Printf("Unfortunately not... The correct answer is %s\n", p.correctAnswer)
}
fmt.Printf("Your current score is %v/%v\n\n", scr.correct, scr.total)
if i == len(problems)-1 {
doneCh <- true
}
}
}()

go func() {
timer := time.NewTimer(time.Duration(*timeLimit) * time.Second)
<-timer.C
fmt.Println("")
fmt.Println("")
fmt.Println("Your time is up...")
doneCh <- true
}()

<-doneCh
fmt.Println("")
fmt.Printf("Your final score is %v/%v\n\n", scr.correct, scr.total)
}

// readProblemsFromCSVFile reads problems from a CSV file.
func readProblemsFromCSVFile(fileName string) ([]problem, error) {
csvFile, err := os.Open(fileName)
if err != nil {
return nil, fmt.Errorf("error opening file: %s", err)
}
reader := csv.NewReader(bufio.NewReader(csvFile))
var problems []problem
for {
line, err := reader.Read()
if err != nil {
if err == io.EOF {
break
}
return nil, fmt.Errorf("error reading CSV line: %s", err)
}
if len(line) != 2 {
return nil, errors.New("invalid line in CSV")
}
p := problem{
challenge: line[0],
correctAnswer: line[1],
}
problems = append(problems, p)
}
return problems, nil
}

// purifyString strips all unneeded variations from a string.
func purifyString(str string) string {
return strings.TrimSpace(strings.ToLower(str))
}

0 comments on commit c18e401

Please sign in to comment.