-
Notifications
You must be signed in to change notification settings - Fork 728
Add hellosputnik's solution #9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| package main | ||
|
|
||
| import ( | ||
| "bufio" | ||
| "flag" | ||
| "fmt" | ||
| "os" | ||
| "strings" | ||
| "time" | ||
| ) | ||
|
|
||
| type Problem struct { | ||
| question string | ||
| answer string | ||
| } | ||
|
|
||
| type Quiz struct { | ||
| problems []Problem | ||
| score int | ||
| } | ||
|
|
||
| type Settings struct { | ||
| filename *string | ||
| timeLimit *int | ||
| } | ||
|
|
||
| func main() { | ||
| quiz := Quiz{} | ||
| settings := Settings{} | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might be a personal preference, but when creating the zero value of a type I prefer to do: var settings SettingsThere was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. bonus points for |
||
|
|
||
| settings.filename = flag.String("csv", "problems.csv", "a csv file in the format of 'question,answer'") | ||
| settings.timeLimit = flag.Int("limit", 30, "the time limit for the quiz in seconds") | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you wanted you could use type Settings struct {
filename string
timeLimit int
}
func main() {
var settings Settings
flag.StringVar(&settings.filename, "csv", "problems.csv", "a csv file in the format of 'question,answer'")
flag.IntVar(&settings.timeLimit, "limit", 30, "the time limit for the quiz in seconds")
flag.Parse()
fmt.Println(settings)
}The primary upside is not needing to mess with string and integer pointers from here onwards for those values. |
||
|
|
||
| // Get the flags (if any). | ||
| flag.Parse() | ||
|
|
||
| // Create a file handle for the file. | ||
| file, err := os.Open(*settings.filename) | ||
|
|
||
| // If there was an error opening the file, exit. | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Probably a personal preference, but for code like |
||
| defer file.Close() | ||
|
|
||
| // Create a buffered reader to read the file input. | ||
| fin := bufio.NewScanner(file) | ||
|
|
||
| // Read the problems from the comma-separated values file. | ||
| for fin.Scan() { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can avoid this using the package "encoding/csv" in the standard library
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 @hellosputnik Generally speaking when dealing with a CSV trying to do it on your own is dangerous. Eg what happens if someone gives you the input: From the looks of your code, this would probably end up causing issues. I'm guessing you didn't know about the |
||
| line := strings.Split(fin.Text(), ",") | ||
| problem := Problem{question: line[0], answer: line[1]} | ||
|
|
||
| quiz.problems = append(quiz.problems, problem) | ||
| } | ||
|
|
||
| // Create a timer to enforce a time limit. | ||
| timer := time.NewTimer(time.Second * time.Duration(*settings.timeLimit)) | ||
| defer timer.Stop() | ||
|
|
||
| go func() { | ||
| <-timer.C | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will run as soon as the time limit is up, but it won't terminate your program. I cover a few ways to do this in the videos that go w/ this exercise, but one way to quickly add it to your code would be to add something like below to the end of this goroutine closure: os.Exit(0)
|
||
| fmt.Printf("\nYou scored %d out of %d.", quiz.score, len(quiz.problems)) | ||
| }() | ||
|
|
||
| // Quiz the user. | ||
| for i, problem := range quiz.problems { | ||
| fmt.Printf("Problem #%d: %s = ", (i + 1), problem.question) | ||
|
|
||
| var input string | ||
| fmt.Scan(&input) | ||
|
|
||
| if input == problem.answer { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you want some more practice using Go you could look at ways to trim both the user in put and the problem answers of any extra whitespace, or even try to convert everything to upper or lowercase to avoid any case sensitivity issues. |
||
| quiz.score++ | ||
| } | ||
| } | ||
|
|
||
| // Print the user's results. | ||
| fmt.Printf("You scored %d out of %d.", quiz.score, len(quiz.problems)) | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right now it doesn't matter, but when putting things like
problemsandscorein the same struct try to think about how they might be used.Eg if we planned on giving the same quiz to 10 students then perhaps it makes more sense to have two types - one that is the "quiz" and stores the problems, another that is the answer sheet and maybe has responses plus a total score. You can kinda think of it like when your teacher hands you a quiz and says, "Don't write on the quiz, write on this separate answer sheet".
That said, if you expect your quizes to be unique for each student (eg maybe you mix up the problem order for each student) then maybe in those cases it makes more sense to store it like you have.
Again, this doesn't matter given the scope of this exercise, but just something I wanted to point out so you think about it in the future as you design your struct types 😄