package main import ( "database/sql" "flag" "fmt" "math/rand" "os" "os/exec" "time" _ "modernc.org/sqlite" ) var ( verbose = flag.Bool("v", false, "debug output") file = flag.String("f", "cards", "cards file") ) func main() { if !*verbose { // Seed the RNG rand.Seed(time.Now().UnixNano()) } flag.Parse() db, err := sql.Open("sqlite", *file) if err != nil { panic(err) } // Get number of cards var N int _ = db.QueryRow("SELECT COUNT(*) FROM cards").Scan(&N) s := segmentTree{N, make([]int, 4*N)} // Build segment tree rows, err := db.Query("SELECT weight FROM cards") if err != nil { panic(err) } s.Build(rows, 0, N-1, 1) rows.Close() if *verbose { fmt.Println(s) } // https://stackoverflow.com/questions/14094190/function-similar-to-getchar // disable input buffering exec.Command("stty", "-F", "/dev/tty", "cbreak", "min", "1").Run() // do not display entered characters on the screen exec.Command("stty", "-F", "/dev/tty", "-echo").Run() // restore the echoing state when exiting defer exec.Command("stty", "-F", "/dev/tty", "echo").Run() for { // Choose a random card x := rand.Intn(s.seg[1]) w, i := s.Query(x, 0, N-1, 1) if *verbose { fmt.Println(s.seg[1]) fmt.Println(x) fmt.Println(w) fmt.Println(i) } // Get card contents from database var key, val string db.QueryRow("SELECT key, val FROM cards WHERE idx=?", i).Scan(&key, &val) fmt.Println("> " + key) // Wait for confirmation var b []byte = make([]byte, 1) os.Stdin.Read(b) fmt.Println(val) // Read user input os.Stdin.Read(b) if b[0] == byte('y') { w >>= 1 } else if b[0] == byte('n') { w <<= 3 } else { return } // Update segment tree and database s.Update(i, w, 0, N-1, 1) _, err = db.Exec("UPDATE cards SET weight=? WHERE idx=?", w, i) if err != nil { panic(err) } } }