diff --git a/main.go b/main.go index 0f89c83..fa65a1b 100644 --- a/main.go +++ b/main.go @@ -1,12 +1,8 @@ package main import ( - "bufio" - "bytes" - "fmt" "os" "strconv" - "strings" "time" ) @@ -66,118 +62,6 @@ func Main() error { return Terminal(db) } -func Terminal(db DB) error { - user := IDU(os.Getenv("USER")) - failed, err := Review(db, user) - if err != nil { - return err - } - for len(failed) > 0 { - for i := len(failed) - 1; i >= 0; i-- { - if _, passed, err := ReviewQ(db, user, failed[i]); err != nil { - return err - } else if passed == CMD_PASS { - return nil - } else if passed != CMD_FAIL { - failed = append(failed[:i], failed[i+1:]...) - } - } - } - return nil -} - -func Review(db DB, user IDU) ([]IDQ, error) { - failed := []IDQ{} - - for q, _ := range db.HistoryOf(user) { - if time.Until(db.Next(user, q)) > 0 { - continue - } - response, passed, err := ReviewQ(db, user, q) - if err != nil { - return nil, err - } - switch passed { - case CMD_QUIT: - return nil, nil - case CMD_FAIL: - failed = append(failed, q) - if err := db.PushAnswer(user, q, Renderable(response), false); err != nil { - return nil, err - } - case CMD_PASS: - if err := db.PushAnswer(user, q, Renderable(response), true); err != nil { - return nil, err - } - } - fmt.Println() - } - return failed, nil -} - -func ReviewQ(db DB, user IDU, q IDQ) (string, string, error) { - question := db.Question(q) - fmt.Printf("> Q: %s\n", question.Q.ToString(db.UserResolution(user))) - fmt.Printf("\n") - fmt.Printf("> %+v\n", question.Tags) - var response string - gotAClue := false - for i := range question.Clues { - if i == 0 { - fmt.Printf("> /clue for a clue\n") - } - response = readline() - if response != "/clue" { - break - } - gotAClue = true - fmt.Printf("> %s", question.Clues[i].ToString(db.UserResolution(user))) - if i+1 < len(question.Clues) { - fmt.Printf(" | /clue for another clue") - } - fmt.Printf("\n") - } - if len(question.Clues) == 0 || response == "/clue" { - response = readline() - } - if !gotAClue && len(question.Solution) > 0 && question.Solution[0].ToString(1) == response { - return response, CMD_PASS, nil - } - if len(question.Solution) > 0 { - fmt.Printf("> Solution:") - for i := range question.Solution { - fmt.Printf("\n\t%s", question.Solution[i].ToString(db.UserResolution(user))) - } - fmt.Println() - } - if id, _ := db.LastAnswer(user, q); id == "" { - } else if lastAnswer := db.Answer(id); lastAnswer.A != "" { - fmt.Printf("> Last time, you responded:\n\t%s\n", lastAnswer.A) - } - fmt.Printf("> Did you pass this time? [%s%s%s%s]\n", - strings.ToUpper(CMD_PASS), - strings.ToLower(CMD_FAIL), - strings.ToLower(CMD_SKIP), - strings.ToLower(CMD_QUIT), - ) - switch strings.ToLower(readline()) { - case CMD_SKIP: - return response, CMD_SKIP, nil - case CMD_FAIL: - return response, CMD_FAIL, nil - case CMD_QUIT: - return response, CMD_QUIT, nil - } - return response, CMD_PASS, nil -} - -func readline() string { - fmt.Printf("\t") - reader := bufio.NewReader(os.Stdin) - text, _ := reader.ReadString('\n') - return strings.TrimSpace(text) -} - func NewDB() (DB, error) { return newYamlDB(os.Getenv("DB")) } @@ -190,13 +74,3 @@ func (q Question) Tagged(tag IDT) bool { } return false } - -func (renderable Renderable) ToString(resolution int) string { - s := string(renderable) - if !strings.HasPrefix(s, "img:") { - return s - } - buff := bytes.NewBuffer(nil) - ViewAt(buff, s[4:], resolution) - return string(buff.Bytes()) -} diff --git a/terminal.go b/terminal.go new file mode 100644 index 0000000..baa2ce9 --- /dev/null +++ b/terminal.go @@ -0,0 +1,132 @@ +package main + +import ( + "bufio" + "bytes" + "fmt" + "os" + "strings" + "time" +) + +func Terminal(db DB) error { + user := IDU(os.Getenv("USER")) + failed, err := Review(db, user) + if err != nil { + return err + } + for len(failed) > 0 { + for i := len(failed) - 1; i >= 0; i-- { + if _, passed, err := ReviewQ(db, user, failed[i]); err != nil { + return err + } else if passed == CMD_PASS { + return nil + } else if passed != CMD_FAIL { + failed = append(failed[:i], failed[i+1:]...) + } + } + } + return nil +} + +func Review(db DB, user IDU) ([]IDQ, error) { + failed := []IDQ{} + + for q, _ := range db.HistoryOf(user) { + if time.Until(db.Next(user, q)) > 0 { + continue + } + response, passed, err := ReviewQ(db, user, q) + if err != nil { + return nil, err + } + switch passed { + case CMD_QUIT: + return nil, nil + case CMD_FAIL: + failed = append(failed, q) + if err := db.PushAnswer(user, q, Renderable(response), false); err != nil { + return nil, err + } + case CMD_PASS: + if err := db.PushAnswer(user, q, Renderable(response), true); err != nil { + return nil, err + } + } + fmt.Println() + } + return failed, nil +} + +func ReviewQ(db DB, user IDU, q IDQ) (string, string, error) { + question := db.Question(q) + fmt.Printf("> Q: %s\n", question.Q.ToString(db.UserResolution(user))) + fmt.Printf("\n") + fmt.Printf("> %+v\n", question.Tags) + var response string + gotAClue := false + for i := range question.Clues { + if i == 0 { + fmt.Printf("> /clue for a clue\n") + } + response = readline() + if response != "/clue" { + break + } + gotAClue = true + fmt.Printf("> %s", question.Clues[i].ToString(db.UserResolution(user))) + if i+1 < len(question.Clues) { + fmt.Printf(" | /clue for another clue") + } + fmt.Printf("\n") + } + if len(question.Clues) == 0 || response == "/clue" { + response = readline() + } + if !gotAClue && len(question.Solution) > 0 && question.Solution[0].ToString(1) == response { + return response, CMD_PASS, nil + } + if len(question.Solution) > 0 { + fmt.Printf("> Solution:") + for i := range question.Solution { + fmt.Printf("\n\t%s", question.Solution[i].ToString(db.UserResolution(user))) + } + fmt.Println() + } + if id, _ := db.LastAnswer(user, q); id == "" { + } else if lastAnswer := db.Answer(id); lastAnswer.A != "" { + fmt.Printf("> Last time, you responded:\n\t%s\n", lastAnswer.A) + } + fmt.Printf("> Did you pass this time? [%s%s%s%s]\n", + strings.ToUpper(CMD_PASS), + strings.ToLower(CMD_FAIL), + strings.ToLower(CMD_SKIP), + strings.ToLower(CMD_QUIT), + ) + switch strings.ToLower(readline()) { + case CMD_SKIP: + return response, CMD_SKIP, nil + case CMD_FAIL: + return response, CMD_FAIL, nil + case CMD_QUIT: + return response, CMD_QUIT, nil + } + return response, CMD_PASS, nil +} + +func readline() string { + fmt.Printf("\t") + reader := bufio.NewReader(os.Stdin) + text, _ := reader.ReadString('\n') + return strings.TrimSpace(text) +} + +func (renderable Renderable) ToString(resolution int) string { + s := string(renderable) + if !strings.HasPrefix(s, "img:") { + return s + } + buff := bytes.NewBuffer(nil) + ViewAt(buff, s[4:], resolution) + return string(buff.Bytes()) +}