Add Endless and NoColor options
This commit is contained in:
parent
bc8bd1d0c7
commit
bbceeee889
124
main.go
124
main.go
|
@ -5,62 +5,83 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
"tipitypy/colorizer"
|
"tipitypy/colorizer"
|
||||||
|
"tipitypy/db"
|
||||||
"tipitypy/reader"
|
"tipitypy/reader"
|
||||||
|
|
||||||
"golang.org/x/term"
|
"golang.org/x/term"
|
||||||
)
|
)
|
||||||
|
|
||||||
func finish(start time.Time) {
|
func finish(start time.Time, stat *db.Stat, finished bool) {
|
||||||
past := time.Now().Sub(start)
|
past := time.Since(start)
|
||||||
|
stat.Skipped = globalStat.Skipped
|
||||||
|
stat.Correct = globalStat.Correct
|
||||||
|
stat.False = globalStat.False
|
||||||
|
stat.Words = globalStat.Words
|
||||||
|
stat.Finished = finished
|
||||||
|
stat.CPM = float64(globalStat.Correct) / past.Minutes()
|
||||||
|
stat.WPM = float64(globalStat.Words+1) / past.Minutes()
|
||||||
|
stat.TimeTaken = past.Milliseconds()
|
||||||
fmt.Printf("\r\n%s", colorizer.Colors.Reset())
|
fmt.Printf("\r\n%s", colorizer.Colors.Reset())
|
||||||
fmt.Printf("Correct: %d ; False: %d ; Skipped: %d\r\n", globalStat.Correct, globalStat.False, globalStat.Skipped)
|
|
||||||
fmt.Println(past)
|
fmt.Println(past)
|
||||||
fmt.Print("\r\n")
|
|
||||||
fmt.Printf("CPM: %.2f ;; WPM: %.2f\r\n",
|
|
||||||
float64(globalStat.Correct)/past.Minutes(),
|
|
||||||
float64(globalStat.Words+1)/past.Minutes())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func ChooseToPrintColorized(r rune) string {
|
||||||
logFile, err := os.OpenFile("ttt.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
|
if Color {
|
||||||
if err != nil {
|
return colorizer.Accept(r)
|
||||||
panic(err)
|
|
||||||
}
|
}
|
||||||
defer logFile.Close()
|
return string(r)
|
||||||
log.SetOutput(logFile)
|
}
|
||||||
|
|
||||||
|
type ExitState int
|
||||||
|
|
||||||
|
const (
|
||||||
|
ExitStateUnspecified = 1 + iota
|
||||||
|
ExitStateBreak
|
||||||
|
ExitStateQuit
|
||||||
|
ExitStateSuccess
|
||||||
|
)
|
||||||
|
|
||||||
|
func SingleCycle() (*db.Stat, int, error) {
|
||||||
source, err := reader.GetSourceLine()
|
source, err := reader.GetSourceLine()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return nil, ExitStateUnspecified, fmt.Errorf("reader.GetSourceLine: %w", err)
|
||||||
}
|
}
|
||||||
log.Print("Start of tipitypy")
|
log.Print("Start of tipitypy")
|
||||||
|
if Color {
|
||||||
colorizer.PrintColorized(source)
|
colorizer.PrintColorized(source)
|
||||||
fmt.Printf("\n")
|
} else {
|
||||||
//
|
fmt.Println(source)
|
||||||
// Put the terminal in raw mode to read characters as they are typed
|
|
||||||
oldState, err := term.MakeRaw(int(os.Stdin.Fd()))
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
}
|
||||||
defer term.Restore(int(os.Stdin.Fd()), oldState) // Restore terminal state at the end
|
fmt.Printf("\r\n")
|
||||||
//
|
//
|
||||||
p := []rune(source)
|
p := []rune(source)
|
||||||
i := 0
|
i := 0
|
||||||
//
|
//
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
defer finish(startTime)
|
finished := true
|
||||||
|
stat := &db.Stat{}
|
||||||
|
defer finish(startTime, stat, finished)
|
||||||
reader := bufio.NewReader(os.Stdin)
|
reader := bufio.NewReader(os.Stdin)
|
||||||
for {
|
for {
|
||||||
r, _, err := reader.ReadRune()
|
r, _, err := reader.ReadRune()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return stat, ExitStateUnspecified, fmt.Errorf("reader.ReadRune: %w", err)
|
||||||
}
|
}
|
||||||
log.Printf("Read %c ; %d as rune", r, r)
|
log.Printf("Read %c ; %d as rune", r, r)
|
||||||
|
|
||||||
|
// CTRL + Q
|
||||||
|
if r == 17 {
|
||||||
|
finished = false
|
||||||
|
return stat, ExitStateQuit, nil
|
||||||
|
}
|
||||||
// CTRL + C
|
// CTRL + C
|
||||||
if r == 3 {
|
if r == 3 {
|
||||||
break
|
finished = false
|
||||||
|
return stat, ExitStateBreak, nil
|
||||||
}
|
}
|
||||||
// CTRL + D
|
// CTRL + D
|
||||||
if r == 4 {
|
if r == 4 {
|
||||||
|
@ -69,7 +90,7 @@ func main() {
|
||||||
// CTRL + S
|
// CTRL + S
|
||||||
if r == 19 {
|
if r == 19 {
|
||||||
globalStat.Skipped++
|
globalStat.Skipped++
|
||||||
fmt.Printf("%s", colorizer.Accept(p[i]))
|
fmt.Printf("%s", ChooseToPrintColorized(p[i]))
|
||||||
i++
|
i++
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -79,7 +100,7 @@ func main() {
|
||||||
globalStat.Words++
|
globalStat.Words++
|
||||||
}
|
}
|
||||||
globalStat.Correct++
|
globalStat.Correct++
|
||||||
fmt.Printf("%s", colorizer.Accept(r))
|
fmt.Printf("%s", ChooseToPrintColorized(r))
|
||||||
i++
|
i++
|
||||||
if i == len(p) {
|
if i == len(p) {
|
||||||
break
|
break
|
||||||
|
@ -88,4 +109,55 @@ func main() {
|
||||||
globalStat.False++
|
globalStat.False++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
globalStat.Words++
|
||||||
|
return stat, ExitStateSuccess, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
logFile, err := os.OpenFile("ttt.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer logFile.Close()
|
||||||
|
log.SetOutput(logFile)
|
||||||
|
ParseOptions()
|
||||||
|
|
||||||
|
sigChan := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
|
||||||
|
|
||||||
|
// Put the terminal in raw mode to read characters as they are typed
|
||||||
|
oldState, err := term.MakeRaw(int(os.Stdin.Fd()))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("term.MakeRaw: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
defer term.Restore(int(os.Stdin.Fd()), oldState) // Restore terminal state at the end
|
||||||
|
// This way we can still defer term.Restore function
|
||||||
|
c := make(chan bool, 1)
|
||||||
|
c <- true
|
||||||
|
if IsEndless {
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
c <- true
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
} else {
|
||||||
|
close(c)
|
||||||
|
}
|
||||||
|
//
|
||||||
|
outer:
|
||||||
|
for range c {
|
||||||
|
stat, state, err := SingleCycle()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("ERROR: %v", err)
|
||||||
|
}
|
||||||
|
switch state {
|
||||||
|
case ExitStateQuit:
|
||||||
|
break outer
|
||||||
|
case ExitStateSuccess:
|
||||||
|
if err := db.Connect().Create(stat).Error; err != nil {
|
||||||
|
log.Printf("ERROR: dbc.Create: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
24
options.go
Normal file
24
options.go
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "os"
|
||||||
|
|
||||||
|
var (
|
||||||
|
IsEndless = false
|
||||||
|
Color = true
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
EndlessOpt = "-e"
|
||||||
|
NoColorOpt = "-nc"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ParseOptions() {
|
||||||
|
for _, arg := range os.Args {
|
||||||
|
switch arg {
|
||||||
|
case EndlessOpt:
|
||||||
|
IsEndless = true
|
||||||
|
case NoColorOpt:
|
||||||
|
Color = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user