-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtimergame.go
More file actions
339 lines (301 loc) · 10.7 KB
/
timergame.go
File metadata and controls
339 lines (301 loc) · 10.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
package main
import "fmt"
import "time"
import "bufio"
import "os"
import "strings"
//Public variables
var onSlice []int64 //Pushed values from logTimeSpent function
var offSlice []int64 //Pushed values from logTimeSpent function
var totalTime int64 = 0 //Given value at end of game in beginGameContainer
//Timer Game in Golang
//Game flow is as follows: User is provided game directions and is prompted to
//start the game by pressing 's'. During the game, user toggles on/off mode of
//timer. the user can do this for as long as they like; when they have
//finished, the user types 'x'. The game is then gracefully shut down and the
//user is shown:
//1. total on and off time for the game
//2. total on and off time by session
//3. total game time
//4. evaluation of whether all time was accounted for
//Project Method:
//1. Used coding rules from Hongkiat, added addl specs for total func overview
//2. Built personal library after code completion as a measure of refactoring
//3. Created timergame_test.go file for function testing
//Project Notes: Opted to use int64 for time since converted to milliseconds
//Project Notes: Placement of endtime value in evaluateInput important
//Project Notes: scanForInput was returning spaces. Why? Added trim function to correct.
//Project Notes: Whenver data type is in question, use go "reflect" pkg
//Project Notes: Ideally, I would like to get rid of all public variables
//Additional Notes: Unused functions are found below the main function.
//retained for future projects
//Notes template to be used on Golang projects
//(@func, @var, etc.)
//@desc -
//@params - Line explaining each parameter
//@return - Line explaining each return
//@type -
//@pkg -
//@requiredFuncs if applicable
//@src if obtained in whole from another source
//@func - scanForInput
//@desc - Loop to retrieve user input, shave off end line and spaces
//@params - none
//@return 1. userInput String
//@type - none
//@pkg - "bufio", "os", "strings"
func scanForInput() string{
fmt.Println("Waiting for input...")
reader1 := bufio.NewReader(os.Stdin)
userInput, _ := reader1.ReadString('\n') //Remove the newline character?
return strings.TrimSpace(userInput)
}
//@func - recurCompareInput
//@desc - Container function to wait for user to make the correct selection
//Note: combined scan and switch functions to create this comprehensive func
//@params 1. comparator String
//@comparator is value user must match in order to move forward in program
//@params 2. successMsg String
//@successMsg is message displayed when user provides desired input.
//@return - none
//@type - none
//@pkg - "strings", "fmt", "bufio"
func recurCompareInput(comparator string, successMsg string){
fmt.Println("Waiting for input...")
reader1 := bufio.NewReader(os.Stdin)
userInput, _ := reader1.ReadString('\n')
theInput := strings.TrimSpace(userInput)
switch theInput{
case comparator: fmt.Println(successMsg)
default:
fmt.Println("That is not a valid input. Please type ",comparator," to continue.")
recurCompareInput(comparator, successMsg)
}
}
//@func - changeToggleState
//@desc - Change toggle from one state to another
//@params 1. toggle String
//@params 2. stateOne String
//@params 3. stateTwo String
//@return 1. toggle String
//@type - none
//@pkg - none
func changeToggleState(toggle string, stateOne string, stateTwo string) string{
if toggle == stateOne{
toggle = stateTwo
}else if toggle == stateTwo{
toggle = stateOne
}
return toggle
}
//@func - getCurrentTimeMillis
//@desc - Gets the current time since EPOCH in milliseconds AS INT64
//@params - none
//@return 1. currentTime int64
//@type - none
//@pkg - "time"
func getCurrentTimeMillis() int64{
now := time.Now()
nanos := now.UnixNano()
millis := nanos/ 1000000
currentTime := millis
return currentTime
}
//@func - sumOfArrayItems
//@desc - Sums all items inside of array
//@params 1. array []int64
//@return 1. sum int64
//@type - none
//@pkg - none
func sumOfArrayItems(array []int64)int64{
var sum int64 = 0
for i := 0; i < len(array); i += 1 {
sum = sum + array[i]
}
return sum
}
//@func - displayArrayAndIndexPlusOne
//@desc - Displays array as starting from 1 rather than zero. Adds 'round' name.
//@params 1. array []int64
//@return - none
//@type - none
//@pkg - "fmt"
func displayArrayAndIndexPlusOne(array []int64, indexName string){
for i := 0; i < len(array); i += 1 {
fmt.Println(indexName," ",i+1,": ",array[i])
}
}
//This section holds the game containers
//ALL ITEMS BELOW THIS LINE ARE WRITTEN IN A PROGRAM SPECIFIC FASHION
//@func - alertUserStateChg
//@desc - Tells the user that they are now i on or off mode
//@params 1. toggle String
//@return - none
//@type - none
//@pkg - "fmt"
func alertUserStateChg(toggle string){
fmt.Println("The Game is now in ", toggle, " mode.")
}
//@func - startGamePrompts
//@desc - Used to print to terminal rules of the game
//@params - none
//@return - none
//@type - none
//@pkg - "fmt"
func startGamePrompts(){
fmt.Println("This program will record all on/off time.")
fmt.Println("Rules of the game: 1. Start the game, 2. Toggle, 3. End the Game")
fmt.Println("Game commands may be found below:")
fmt.Println("Start Game = s")
fmt.Println("Toggle On/Off = t")
fmt.Println("End Game = x")
fmt.Println("Type 's' into the counsel and hit Enter to get started!")
}
//on user starting game, sets variables
//This container will calculate total time for the game.
func beginGameContainer(){
gameStartTime := getCurrentTimeMillis()
toggle := "off"
gameEndTime := recurGameContainer(toggle, gameStartTime) //Will not come back until user quits game
totalTime = gameEndTime - gameStartTime
}
//this is the container where all the action will take place during game.
//evaluateInput does most of the heavy lifting
//container recurs until user indicates end of game
func recurGameContainer(toggle string, initStartTime int64) int64{
theInput := scanForInput()
endTime := evaluateInput(theInput, initStartTime, toggle)
return endTime
}
//Note: This function feels really clunky
//Note: endTime here not acting as expected!
//@func - evaluateInput
//@desc - Evaluate user input during game for toggle or end game.
//@params 1. theInput String
//@theInput will be a single letter provided by user
//@return 1. endTime int64
//@endTime is ONLY returned when user exits game.
//@type - none
//@pkg - none
func evaluateInput(theInput string, startTime int64, toggle string) int64{
endTime := getCurrentTimeMillis()
switch theInput {
case "x":
endTime = getCurrentTimeMillis()
logTimeSpent(toggle, startTime, endTime) //drops to end of switch statement
case "t":
logTimeSpent(toggle, startTime, endTime)
toggle = changeToggleState(toggle, "on", "off")
alertUserStateChg(toggle)
recurGameContainer(toggle, endTime)
default:
fmt.Println("That is not a valid input.")
recurGameContainer(toggle, startTime) //returns start time as it was received
}
endTime = getCurrentTimeMillis()
return endTime
}
//@func - logTimeSpent
//@desc - Used to log time spent on and off. Store to public array.
//@params 1. toggle String
//@params 2. initStartTime int64
//@params 3. endTime int64
//@return - none - appends to public array
//@type - none
//@pkg - none
func logTimeSpent(toggle string, initStartTime int64, endTime int64){
roundTime := endTime - initStartTime
if toggle == "on"{
//append to the on array
onSlice = append(onSlice, roundTime)
fmt.Println(roundTime)
fmt.Println(onSlice)
}else if toggle == "off"{
//append to the off array
offSlice = append(offSlice, roundTime)
fmt.Println(roundTime)
fmt.Println(offSlice)
}
}
//Note: I was going to use math.Abs here, but that is only valid on floats!
//@func - compareTime
//@desc - Compare totalTime to (on + off) time for quality control
//@params - none
//@return - none
//@type - none
//@pkg - "fmt"
func compareTime(){
totalOnTime := sumOfArrayItems(onSlice)
totalOffTime := sumOfArrayItems(offSlice)
totalArrayTime := totalOnTime + totalOffTime
variance := totalTime - totalArrayTime
if variance < 5 && variance > (-5) {
fmt.Println("Success! Variance within threshhold. Variance is ", variance, " milliseconds.")
fmt.Println("Value of total game time: ", totalTime)
fmt.Println("Value of total On time: ", totalOnTime)
fmt.Println("Value of total Off time: ", totalOffTime)
fmt.Println("Value of On + Off time: ", totalArrayTime)
}else if totalTime != totalArrayTime{
fmt.Println("Failure, the variance is: ", variance)
fmt.Println("Value of total game time: ", totalTime)
fmt.Println("Value of total On time: ", totalOnTime)
fmt.Println("Value of total Off time: ", totalOffTime)
fmt.Println("Value of On + Off time: ", totalArrayTime)
}
}
func printTimeArrays(){
fmt.Println("\nOff Time: \n")
displayArrayAndIndexPlusOne(offSlice, "Round")
fmt.Println("\nOn Time: \n")
displayArrayAndIndexPlusOne(onSlice, "Round")
}
func main(){
startGamePrompts() //Prompts to user
recurCompareInput("s","Game starting in 'off' mode.") //recurrent function waits for user to start game
beginGameContainer() //function call recurrent game loop, gathers data
compareTime() //provides user stats at end of the game
printTimeArrays()
}
//THIS FUNCTION DISREGARDED, TREATING ON/OFF AS STRING NOW
//@func -changeTruthState
//@desc -Turns true to false and false to true
//@params 1.toggle Boolean
//@return 1. toggleReturn Boolean
//toggle will be returned as opposite Boolean from when it was received.
//@type - none
//@pkg -none
//func changeTruthState(toggle bool) bool{
// if toggle == true{
// toggle = false
// }else if toggle == false{
// toggle = true
// }
// return toggle
//}
//THIS FUNCTION DISREGARDED, CONVERTING TIME TO INTEGER FOR WORK
//@func - roundNumber
//@desc - Rounds numbers to desired decimal place and on desired breaking point.
//@params 1. val float64
//@val is the number you want to round
//@params 2. roundOn float64
//@roundOn is an expression of the breaking point for rounding. Normally .5
//@params 3. places integer
//@places is the number of decimal places you would like to round to
//@return 1. newVal float64
//@newVal is the rounded number
//@type - none
//@pkg - "math"
//@src - https://gist.github.com/DavidVaini/10308388
//func roundNumber(val float64, roundOn float64, places int ) float64 {
// var round float64
// pow := math.Pow(10, float64(places))
// digit := pow * val
// _, div := math.Modf(digit)
// if div >= roundOn {
// round = math.Ceil(digit)
// } else {
// round = math.Floor(digit)
// }
// newVal := round / pow
// return newVal
//}