Skip to content

Commit e43dd79

Browse files
committed
feat: add obinna quiz implementation
1 parent 82fe91a commit e43dd79

File tree

7 files changed

+439
-0
lines changed

7 files changed

+439
-0
lines changed

students/obinna/go.mod

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module gophersizeEx1
2+
3+
go 1.24.3
4+
5+
require github.com/google/go-cmp v0.7.0

students/obinna/main.go

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
package main
2+
3+
import (
4+
"bufio"
5+
"context"
6+
"encoding/csv"
7+
"flag"
8+
"fmt"
9+
"io"
10+
"log"
11+
"os"
12+
"path/filepath"
13+
"strings"
14+
"time"
15+
)
16+
17+
func main() {
18+
var file string // flag -f for file
19+
flag.StringVar(&file, "f", "problems.csv", "file location of quiz")
20+
21+
var timeLimit int
22+
flag.IntVar(&timeLimit, "t", 30, "time limit for the quiz")
23+
24+
//parse the flag
25+
flag.Parse()
26+
27+
// validate correct file is used
28+
if err := validatePath(file); err != nil {
29+
log.Fatal(err)
30+
}
31+
32+
problems := NewProblemSheet()
33+
err := problems.populateSheet(file)
34+
if err != nil {
35+
log.Fatal(err)
36+
}
37+
38+
problems.StartQuiz(time.Duration(timeLimit)*time.Second, os.Stdin, os.Stdout)
39+
problems.DisplayResults(os.Stdout)
40+
}
41+
42+
func validatePath(path string) error {
43+
// validate extension is correct
44+
if filepath.Ext(path) != ".csv" {
45+
return fmt.Errorf("malformed file path: %s contains no csv extension", path)
46+
}
47+
48+
//check that file exists
49+
_, err := os.Stat(path)
50+
if os.IsNotExist(err) {
51+
return fmt.Errorf("path does not exist: %w", err)
52+
} else if err != nil {
53+
return fmt.Errorf("error getting file info: %w", err)
54+
}
55+
56+
return nil
57+
}
58+
59+
type Problem struct {
60+
Question string
61+
Answer string
62+
}
63+
64+
type ProblemSheet struct {
65+
Questions []Problem
66+
CorrectlyAnswered int
67+
}
68+
69+
func (p *ProblemSheet) populateSheet(file string) error {
70+
//open file
71+
f, err := os.Open(file)
72+
if err != nil {
73+
return fmt.Errorf("failed to open file: %w", err)
74+
}
75+
defer f.Close()
76+
77+
reader := csv.NewReader(f)
78+
lines, err := reader.ReadAll()
79+
if err != nil {
80+
return fmt.Errorf("failed to read csv: %w", err)
81+
}
82+
83+
if len(lines) == 0 {
84+
return fmt.Errorf("empty csv file loaded")
85+
}
86+
87+
for _, line := range lines {
88+
89+
newProblem := Problem{
90+
Question: strings.TrimSpace(line[0]),
91+
Answer: strings.TrimSpace(line[1]),
92+
}
93+
94+
p.Questions = append(p.Questions, newProblem)
95+
}
96+
return nil
97+
}
98+
99+
func NewProblemSheet() *ProblemSheet {
100+
return &ProblemSheet{}
101+
}
102+
103+
func (p *ProblemSheet) StartQuiz(limit time.Duration, r io.Reader, w io.Writer) {
104+
105+
reader := bufio.NewReader(r)
106+
107+
fmt.Fprintln(w, "Press Enter to begin quiz")
108+
reader.ReadString('\n')
109+
110+
ctx, cancel := context.WithTimeout(context.Background(), limit)
111+
defer cancel()
112+
113+
for _, problem := range p.Questions {
114+
answerCh := make(chan string, 1)
115+
116+
go func(q string) {
117+
fmt.Fprintf(w, "\n\nQuestion: %s\n", q)
118+
fmt.Fprint(w, "answer: ")
119+
userAns, _ := reader.ReadString('\n')
120+
answerCh <- strings.TrimSpace(userAns)
121+
}(problem.Question)
122+
123+
select {
124+
case userAnswer := <-answerCh:
125+
if userAnswer == problem.Answer {
126+
p.CorrectlyAnswered++
127+
}
128+
case <-ctx.Done():
129+
fmt.Fprintln(w, "\nquiz not completed before timeout")
130+
return
131+
}
132+
}
133+
}
134+
135+
func (p *ProblemSheet) DisplayResults(w io.Writer) {
136+
fmt.Fprintln(w, "Quiz has ended")
137+
fmt.Fprintf(w, "You answered %d/%d questions\n", p.CorrectlyAnswered, len(p.Questions))
138+
}
139+
140+
//type workerFunc func() string
141+
//
142+
//func timeLimit(worker workerFunc, limit time.Duration) (string, error) {
143+
// out := make(chan string, 1)
144+
// ctx, cancel := context.WithTimeout(context.Background(), limit)
145+
// defer cancel()
146+
//
147+
// go func() {
148+
// fmt.Println("goroutine started")
149+
// out <- worker()
150+
// }()
151+
//
152+
// select {
153+
// case result := <-out:
154+
// return result, nil
155+
// case <-ctx.Done():
156+
// return "quiz not completed before timeout", errors.New("work timed out")
157+
// }
158+
//}
159+
160+
//func (p *problemSheet) StartQuiz() string {
161+
// for _, problem := range p.questions {
162+
// fmt.Printf("\n\nQuestion: %s\n", problem.question)
163+
// fmt.Print("answer: ")
164+
// var answer string
165+
// fmt.Scanln(&answer)
166+
//
167+
// if answer == problem.answer {
168+
// p.correctlyAnswered++
169+
// }
170+
// }
171+
//
172+
// return "Quiz completed before timeout"
173+
//}

0 commit comments

Comments
 (0)