main.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. /*
  2. * kulma - Kul med matematik.
  3. * Copyright (C) 2024 Marcus Pedersén marcus@marcux.org
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. package main
  19. import (
  20. "os"
  21. "fmt"
  22. "errors"
  23. "strings"
  24. "strconv"
  25. "math/rand"
  26. "time"
  27. au "github.com/logrusorgru/aurora/v4"
  28. )
  29. // Struct represent
  30. // a multiplication
  31. // table
  32. type Mul struct {
  33. table int
  34. current int
  35. result map[int]bool
  36. }
  37. // Returns random number
  38. // from multiplication
  39. // table between 1-10
  40. // that has not been
  41. // used yet.
  42. func (m Mul) GetNumber() (int, int) {
  43. for {
  44. timeNow := time.Now().UnixNano()
  45. r := rand.New(rand.NewSource(timeNow))
  46. rInt := r.Intn(10) + 1
  47. if len(m.result) >= 10 {
  48. return 11, 11
  49. }
  50. if _, ok := m.result[rInt]; ! ok {
  51. return rInt, m.table
  52. }
  53. }
  54. }
  55. // Returns the next
  56. // random number in
  57. // a pritty print format
  58. // string: "a x b ="
  59. // Bool specifying if
  60. // there is a next or
  61. // all numbers in series
  62. // has been used.
  63. func (m *Mul) next() (string, bool) {
  64. a, b := m.GetNumber()
  65. m.current = a
  66. p := fmt.Sprintf("%d x %d = ", a, b)
  67. if len(m.result) >= 10 {
  68. return p, false
  69. } else {
  70. return p, true
  71. }
  72. }
  73. // Updates internal
  74. // referense and returns
  75. // bool if correct or not
  76. func (m *Mul) correct(a int) bool {
  77. res := false
  78. if (m.current * m.table) == a {
  79. m.result[m.current] = true
  80. res = true
  81. } else {
  82. m.result[m.current] = false
  83. }
  84. m.current = 0
  85. return res
  86. }
  87. // Returns a prity print
  88. // of total score if all
  89. // results otherwise
  90. // empty string.
  91. func (m Mul) summary() string {
  92. if len(m.result) == 10 {
  93. noCorr := 0
  94. for _, r := range m.result {
  95. if r {
  96. noCorr += 1
  97. }
  98. }
  99. resStr := fmt.Sprintf("Du hade %d rätt av 10!!\nBra jobbat!!", noCorr)
  100. return resStr
  101. }
  102. return ""
  103. }
  104. // Create a new table
  105. // Argument must be between
  106. // one and ten (1-10)
  107. func NewMul(tableNo int) (Mul, error) {
  108. if tableNo >= 1 && tableNo <= 10 {
  109. return Mul{
  110. table: tableNo,
  111. result: make(map[int]bool),
  112. },
  113. nil
  114. } else {
  115. return Mul{
  116. table: 0,
  117. result: make(map[int]bool),
  118. },
  119. errors.New("Table needs to be between one and ten (1-10)")
  120. }
  121. }
  122. // Print the initial
  123. // text when the program
  124. // is started.
  125. func headerText() {
  126. fmt.Printf("%s\n",
  127. au.Bold(au.Yellow("*************************")))
  128. fmt.Printf("%s %s %s\n",
  129. au.Bold(au.Yellow("*")),
  130. au.Bold(au.Green("Välkommen till kulma!")),
  131. au.Bold(au.Yellow("*")))
  132. fmt.Printf("%s\n",
  133. au.Bold(au.Yellow("*************************")))
  134. fmt.Println("")
  135. }
  136. // Get users name
  137. func getName() string {
  138. var name string
  139. fmt.Println("Vad heter du?")
  140. for {
  141. if _, err := fmt.Scanln(&name); err != nil {
  142. fmt.Println("Namnet kan inte vara tomt, försök igen.")
  143. } else {
  144. name = strings.TrimSpace(name)
  145. break
  146. }
  147. }
  148. return name
  149. }
  150. // Prints header
  151. // for multiplication
  152. func mulText() {
  153. fmt.Println("Dags att köra...")
  154. fmt.Printf("%s\n",
  155. au.Yellow("*******************"))
  156. fmt.Printf("%s %s %s\n",
  157. au.Yellow("*"),
  158. au.Green("Multiplikation!"),
  159. au.Yellow("*"))
  160. fmt.Printf("%s\n",
  161. au.Yellow("*******************"))
  162. fmt.Println("")
  163. }
  164. // Ask user for multiplication
  165. // table, returns Mul
  166. func getMulTable() Mul {
  167. var table string
  168. fmt.Printf("\nVälj multiplikationstabell (1-10):\n")
  169. for {
  170. if _, err := fmt.Scanln(&table); err != nil {
  171. fmt.Println("Tabellen måste vara ett tal mellan 1 och 10.")
  172. fmt.Println("Försök igen.")
  173. continue
  174. } else {
  175. if i, err := strconv.Atoi(table); err != nil {
  176. fmt.Println("Tabellen måste vara ett tal mellan 1 och 10.")
  177. fmt.Println("Försök igen.")
  178. continue
  179. } else {
  180. if i >= 1 && i <= 10 {
  181. m, _ := NewMul(i)
  182. return m
  183. } else {
  184. fmt.Println("Tabellen måste vara ett tal mellan 1 och 10.")
  185. fmt.Println("Försök igen.")
  186. continue
  187. }
  188. }
  189. }
  190. }
  191. }
  192. func main() {
  193. headerText()
  194. name := getName()
  195. fmt.Printf("\nHej, %s!\n\n", name)
  196. mulText()
  197. mul := getMulTable()
  198. timeStart := time.Now()
  199. var strAnswer string
  200. var corrAnswer bool
  201. for p, n := mul.next(); n == true; p, n = mul.next() {
  202. fmt.Print(p)
  203. if _, err := fmt.Scanln(&strAnswer); err != nil {
  204. corrAnswer = mul.correct(-1)
  205. } else {
  206. if a, err := strconv.Atoi(strAnswer); err == nil {
  207. corrAnswer = mul.correct(a)
  208. } else {
  209. corrAnswer = mul.correct(-1)
  210. }
  211. }
  212. if corrAnswer {
  213. fmt.Printf("%s\n\n",
  214. au.Green("Rätt svar!"))
  215. } else {
  216. fmt.Printf("%s\n\n",
  217. au.Red("Fel svar!"))
  218. }
  219. }
  220. timeUsed := time.Now().Sub(timeStart)
  221. timeText := fmt.Sprintf("Du gjorde tio uppgifter i\nmultiplikationstabell %d\npå tiden: %s", mul.table, timeUsed)
  222. fmt.Println(au.Bold(au.Green(timeText)))
  223. fmt.Println(au.Bold(au.Green(mul.summary())))
  224. }