shuffling
parent
da6097c5e2
commit
273b412e30
126
main.go
126
main.go
|
|
@ -1,12 +1,8 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -66,118 +62,6 @@ func Main() error {
|
||||||
return Terminal(db)
|
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) {
|
func NewDB() (DB, error) {
|
||||||
return newYamlDB(os.Getenv("DB"))
|
return newYamlDB(os.Getenv("DB"))
|
||||||
}
|
}
|
||||||
|
|
@ -190,13 +74,3 @@ func (q Question) Tagged(tag IDT) bool {
|
||||||
}
|
}
|
||||||
return false
|
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())
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -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())
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue