Skip to content

Commit

Permalink
DataScanner v2
Browse files Browse the repository at this point in the history
Version 2 of DataScanner.au3, storing the results in a CSV file instead of in a SQLite database. (Team Names will now be stored in a separate file instead of in a separate table in the database).
  • Loading branch information
mikejed authored Feb 19, 2024
1 parent 96204db commit 06e2c15
Showing 1 changed file with 59 additions and 177 deletions.
236 changes: 59 additions & 177 deletions 2. Collect/DataScanner.au3
Original file line number Diff line number Diff line change
@@ -1,28 +1,25 @@
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Icon=../favicon.ico
#AutoIt3Wrapper_Res_ProductName=CocoNuts Data Scanner
#AutoIt3Wrapper_Res_ProductVersion=1.1
#AutoIt3Wrapper_Res_LegalCopyright=2022 by Michael Garrison
#AutoIt3Wrapper_Res_ProductVersion=2.0
#AutoIt3Wrapper_Res_LegalCopyright=2024 by Michael Garrison
#AutoIt3Wrapper_Res_Language=1033
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

; Compiled using AutoIt v3.3.16.0

#include <includes\Json.au3>
#include <SQLite.au3>

#include <EditConstants.au3>
#include <GuiListView.au3>
#include <GUIConstants.au3>

FileInstall("includes\SQLite3.dll", @TempDir & "\SQLite3.dll")

Global $hDB, $aColList, $sColListPath = @ScriptDir & "\DataList.txt"
Global $aResult, $iRows, $iCols

; I need a list of the columns to include in the database. If the file doesn't exist, create it.
; I need a list of the columns to include in the headers. If the file doesn't exist, create it.
If Not FileExists($sColListPath) Then
If MsgBox(1, "Columns not found", "File DataList.txt not found - click OK to create a default file or cancel to exit" & @CRLF & @CRLF &"(Team Number, Team Name, Match, and Comment will always be included)") = 2 Then Exit
If MsgBox(1, "Columns not found", "File DataList.txt not found - click OK to create a default file or cancel to exit" & @CRLF & @CRLF &"(Team Number, Match, and Comment will always be included)") = 2 Then Exit
$hColList = FileOpen($sColListPath,2)
FileWriteLine($hColList,"PrefStart")
FileWriteLine($hColList,"CycleTime")
Expand All @@ -41,202 +38,109 @@ EndIf
; Read the list of columns from the file for the rest of this session
$aColList = FileReadToArray($sColListPath)

;Start the SQLite engine from the dll we installed in the temp dir
_SQLite_Startup(@TempDir & "\SQLite3.dll")
If @error Then
MsgBox($MB_SYSTEMMODAL, "SQLite Error", "SQLite3.dll Can't be Loaded!" & @CRLF & @CRLF & _
"Not FOUND in @ScriptDir, @WorkingDir," & @CRLF & @TAB & "@LocalAppDataDir\AutoIt v3\SQLite," & @CRLF & @TAB & "@SystemDir or @WindowsDir")
Exit
EndIf

#Region; Create the UI
Global $hGui = GUICreate("CocoNuts Scouting Data Entry", 320, 260)
Global $hFileMenu = GUICtrlCreateMenu("File")
Global $hNewMenu = GUICtrlCreateMenuItem("New", $hFileMenu)
Global $hOpenMenu = GUICtrlCreateMenuItem("Open", $hFileMenu)

Global $hMatchList = GUICtrlCreateListView("Team|Match|Comment", 0, 0, 320, 140)
GUICtrlSetState($hMatchList, $GUI_DISABLE)
Global $hDeleteMatchRow = GUICtrlCreateButton("(delete selected)", 0, 140, 100, 20)
GUICtrlSetState($hDeleteMatchRow, $GUI_DISABLE)

Global $hAddDataButton = GUICtrlCreateButton("Open or create a database" & @CRLF & "file to add data", 80, 170, 170, 40, $BS_MULTILINE)
GUICtrlSetState($hAddDataButton, $GUI_DISABLE)
Global $hNewDataInput = GUICtrlCreateEdit("", 0, 0, 320, 140, BitOR($ES_WANTRETURN, $ES_AUTOVSCROLL))
Global $hNewDataSubmit = GUICtrlCreateButton("Open or create a .csv" & @CRLF & "file to add data", 80, 170, 170, 40, $BS_MULTILINE)
GUICtrlSetState($hNewDataSubmit, $GUI_DISABLE)

Global $hStatusBar = GUICtrlCreateLabel(" No file open", 0, 220, 320, 20)
GUICtrlSetBkColor(-1, 0xFFFFFF)
#EndRegion

;Now show the main UI and run the loop until it's closed.
;Now show the UI and run the loop until it's closed.
GUISetState()
While 1
Global $msg = GUIGetMsg()
Switch $msg
Case -3 ; The main UI was closed
Case -3 ; The UI was closed
DoExit()

Case $hNewMenu ; File > New
Local $sNewDbPath = FileSaveDialog("New File", @WorkingDir, "Database Files (*.db)", 18)
Local $sNewDbPath = FileSaveDialog("New File", @WorkingDir, "CSV Files (*.csv)", 18)
If @error Then ContinueLoop ; cancel button clicked

; If another database is already open, close it.
If $hDB <> '' Then _SQLite_Close()
; If another file is already open, close it.
If $hDB <> '' Then FileClose($hDB)

; Attempt to open the file selected (which will create a new file assuming it doesn't already exist). Don't delete previous contents if it does already exist, just in case.
$hDB = _SQLite_Open($sNewDbPath)
; Attempt to open the file selected (which will create a new file assuming it doesn't already exist).
$hDB = FileOpen($sNewDbPath, 1)
If @error Then
MsgBox(16, "Error", "Error opening database. Exiting")
MsgBox(16, "Error", "Error opening data file. Exiting")
DoExit()
EndIf

; Now create the tables in the database. Teams should be rather static, but Matches only has 3 hardcoded columns I rely on existing- the rest will be added dynamically below.
_SQLite_Exec(-1, "CREATE TABLE [Teams] ([TeamNumber], [TeamName])")
_SQLite_Exec(-1, "CREATE TABLE [Matches] ([TeamNumber], [Match], [Comment])")

; Now that the tables exist, add all of the dynamic columns to [Matches].
UpdateMatchColumnList()
; Now create the header row (remember this is the equivalent of the [Matches] table in the old database approach).
Local $sColList = "TeamNumber,Match,"
For $_i = 0 To UBound($aColList)-1
$sColList &= $aColList[$_i] & ","
Next
$sColList &= "Comment"
FileWriteline($hDB, $sColList)

; Indicate the file path of the new database in the status bar. This also enables the controls now that a file is open.
; Indicate the file path of the new file in the status bar. This also enables the controls now that a file is open.
SetStatusBar($sNewDbPath)

; Show list of matches. Should be blank, but better safe than sorry.
UpdateMatchRowList()

Case $hOpenMenu ; File > Open
Local $sNewDbPath = FileOpenDialog("Open File", @WorkingDir, "Database Files (*.db)")
Local $sNewDbPath = FileOpenDialog("Open File", @WorkingDir, "CSV Files (*.csv)")
If @error Then ContinueLoop ; cancel button clicked

; If another database is already open, close it.
If $hDB <> '' Then _SQLite_Close()
; If another file is already open, close it.
If $hDB <> '' Then FileClose($hDB)

; Attempt to open the file selected.
$hDB = _SQLite_Open($sNewDbPath)
$hDB = FileOpen($sNewDbPath, 1)
If @error Then
MsgBox(16, "Error", "Error opening database.")
MsgBox(16, "Error", "Error opening data file.")
SetStatusBar("No file open")
_SQLite_Close()
$hDB = ''
ContinueLoop
EndIf

; Make sure that the [Matches] table exists - I don't create the table on opened databases.
_SQLite_GetTable2D(-1, "SELECT * FROM [Matches] LIMIT 1", $aResult, $iRows, $iCols)
If @error Or $iCols < 3 Then
MsgBox(16, "Error", "The selected database isn't compatible with this program")
SetStatusBar("No file open")
_SQLite_Close()
$hDB = ''
; Indicate the file path of the now-open file in the status bar.
SetStatusBar($sNewDbPath)

Case $hNewDataSubmit
If $hDB == '' Then
MsgBox(16, "Error", "You must open a data file before you can add data")
ContinueLoop
EndIf

; Make sure the [Teams] table exists - I don't create the table on opened databases.
_SQLite_GetTable2D(-1, "SELECT * FROM [Teams] LIMIT 1", $aResult, $iRows, $iCols)
If @error Or $iCols < 2 Then
MsgBox(16, "Error", "The selected database isn't compatible with this program")
SetStatusBar("No file open")
_SQLite_Close()
$hDB = ''
ContinueLoop
; Data entered - now digest the data and add it to the file. Extra data (not indicated by custom column file) is ignored.
$s_Input = Json_Decode(StringStripCR(GUICtrlRead($hNewDataInput)))

If UBound(Json_ObjGetKeys($s_Input)) - 4 <> UBound($aColList) Then
MsgBox(16, "Error", "The data doesn't seem to be formatted correctly. Maybe try scanning again?")
ExitLoop
EndIf

; Make sure all the custom columns exist in the [Matches] table. Extra columns don't hurt anything, if others already existed.
UpdateMatchColumnList()
Local $sTeamNumber = GetEscapedJson($s_Input, 'TeamNumber')
Local $sMatch = GetEscapedJson($s_Input, 'Match')
Local $sComment = GetEscapedJson($s_Input, 'Comment')

; Indicate the file path of the now-open database in the status bar.
SetStatusBar($sNewDbPath)
; Start building the query: first list all of the columns we'll insert data into.
Local $sQuery = $sTeamNumber & "," & $sMatch

; Show a list of all [Matches] table records.
UpdateMatchRowList()
; Continue building the query: now list all of the data to put into the columns.
For $i = 0 To UBound($aColList)-1
$sQuery &= ',' & GetEscapedJson($s_Input, $aColList[$i])
Next
$sQuery &= ',"' & StringReplace($sComment, '"', '""') & '"'

Case $hAddDataButton
If $hDB == '' Then
MsgBox(16, "Error", "You must open a database before you can add data")
ContinueLoop
EndIf
; Now run the query to store the data.
FileWriteLine($hDB, $sQuery)

; Create the dialogue UI.
Global $h_NewDataGui = GUICreate("Add Match Data", 320, 140)
Global $h_NewDataInput = GUICtrlCreateEdit("", 0, 0, 320, 100, BitOR($ES_WANTRETURN, $ES_AUTOVSCROLL))
Global $h_NewDataSubmit = GUICtrlCreateButton("Load Data", 50, 100, 220, 40)
GUISetState(@SW_SHOW, $h_NewDataGui)

While 1
$msg = GUIGetMsg()
Switch $msg
Case -3 ; Dialog closed
GUISetState(@SW_HIDE, $h_NewDataGui)
ExitLoop

Case $h_NewDataSubmit ; Data entered - now digest the data and enter it into the database. Extra data (not indicated by custom column file) is ignored.

$s_Input = Json_Decode(StringStripCR(GUICtrlRead($h_NewDataInput)))
GUIDelete($h_NewDataGui)

If UBound(Json_ObjGetKeys($s_Input)) - 4 <> UBound($aColList) Then
MsgBox(16, "Error", "The data doesn't seem to be formatted correctly. Maybe try scanning again?")
ExitLoop
EndIf

Local $sTeamNumber = GetEscapedJson($s_Input, 'TeamNumber')
Local $sTeamName = GetEscapedJson($s_Input, 'TeamName')
Local $sMatch = GetEscapedJson($s_Input, 'Match')
Local $sComment = GetEscapedJson($s_Input, 'Comment')

; Add or update team name in [Teams] table
_SQLite_GetTable2D(-1, "SELECT [TeamNumber], [TeamName] FROM [Teams] WHERE [TeamNumber] = " & $sTeamNumber, $aResult, $iRows, $iCols)
If $iRows > 0 Then
If $aResult[1][1] <> $sTeamName And $sTeamName <> "" Then
If MsgBox(36, "Change team name?", "Team " & $sTeamNumber & " is already recorded with a name of " & $aResult[1][1] & ". Do you want to update their name to " & $sTeamName & "?") == 6 Then
; Team name already recorded but they've chosen to update it.
_SQLite_Exec(-1, "UPDATE [Teams] SET [TeamName] = '" & $sTeamName & "' WHERE [TeamNumber] = " & $sTeamNumber)
EndIf
EndIf
Else
; Team name not already recorded. Add it.
_SQLite_Exec(-1, "INSERT INTO [Teams] ([TeamNumber], [TeamName]) VALUES (" & $sTeamNumber & ", '" & $sTeamName & "')")
EndIf

; See if the team number and match number match a record already in the database. If so, confirm they want to duplicate data.
_SQLite_GetTable2D(-1, "SELECT * FROM [Matches] WHERE [TeamNumber] = " & $sTeamNumber & " AND [Match] = " & $sMatch, $aResult, $iRows, $iCols)
If $iRows == 0 Or MsgBox(36, "Duplicate Record", "You already have a record for team " & $sTeamNumber & " on match " & $sMatch & ". Are you sure you want to add this data also?") == 6 Then

; Start building the query: first list all of the columns we'll insert data into.
Local $sQuery = "INSERT INTO [Matches] (" & "[TeamNumber], [Match], [Comment]"
For $i = 0 To UBound($aColList)-1
$sQuery &= ", [" & $aColList[$i] & "]"
Next

; Continue building the query: now list all of the data to put into the columns.
$sQuery &= ") VALUES (" & $sTeamNumber & ", " & $sMatch & ", '" & $sComment & "'"
For $i = 0 To UBound($aColList)-1
$sQuery &= ", '" & GetEscapedJson($s_Input, $aColList[$i]) & "'"
Next
$sQuery &= ")"

; Now run the query to store the data.
_SQLite_Exec(-1, $sQuery)
EndIf

UpdateMatchRowList()

ExitLoop

EndSwitch
WEnd

Case $hDeleteMatchRow
If MsgBox(36, "Are you sure?", "Are you sure you want to delete this record from the database?") == 7 Then ContinueLoop
Local $_values = StringSplit(GUICtrlRead(GUICtrlRead($hMatchList)), "|")
If $_values[0] == 4 Then
_SQLite_Exec(-1, "DELETE FROM [Matches] WHERE [TeamNumber] = " & $_values[1] & " AND [Match] = " & $_values[2] & " AND [Comment] LIKE '" & $_values[3] & "%'")
UpdateMatchRowList()
Else
MsgBox(16, "Error", "Oops- something went wrong trying to identify the row to delete")
EndIf
; Finally, clear out the input so it's ready for the next scan.
GUICtrlSetData($hNewDataInput, "")

EndSwitch
WEnd


; Function to update the status bar: first take the rightmost 50 characters, and then if there's a backslash strip everything to the left and prepend with '...'
Func SetStatusBar($_sText)
If StringLen($_sText) > 50 Then
Expand All @@ -246,41 +150,19 @@ Func SetStatusBar($_sText)
GUICtrlSetData($hStatusBar, $_sText)

; Since a file is now open, make sure the controls are enabled.
GUICtrlSetData($hAddDataButton, "Add new match data >")
GUICtrlSetState($hMatchList, $GUI_ENABLE)
GUICtrlSetState($hDeleteMatchRow, $GUI_ENABLE)
GUICtrlSetState($hAddDataButton, $GUI_ENABLE)
GUICtrlSetData($hNewDataSubmit, "Load Data")
GUICtrlSetState($hNewDataSubmit, $GUI_ENABLE)
EndFunc

; Function to loop through the custom columns and see if they already exist in [Matches] table. If not, add them.
Func UpdateMatchColumnList()
Local $_aResult, $_iRows, $_iCols
For $_i = 0 To UBound($aColList)-1
_SQLite_GetTable2D(-1, "SELECT [" & $aColList[$_i] & "] FROM [Matches] LIMIT 1", $_aResult, $_iRows, $_iCols)
If @error Or $_iCols < 1 Then
_SQLite_Exec(-1, "ALTER TABLE [Matches] ADD COLUMN [" & $aColList[$_i] & "]")
EndIf
Next
EndFunc

; Function to get the property of a specific key from the indicated JSON string.
Func GetEscapedJson($_string, $_key)
Return StringReplace(StringReplace(Json_ObjGet($_string, $_key), '\n', @CRLF), "'", "''")
EndFunc

; Function to update the [Matches] listing in the UI
Func UpdateMatchRowList()
Local $_aResult, $_iRows, $_iCols
_GUICtrlListView_DeleteAllItems($hMatchList)
_SQLite_GetTable2D(-1, "SELECT [TeamNumber],[Match],[Comment] FROM [Matches]", $_aResult, $_iRows, $_iCols)
For $_i = 1 To $_iRows
GUICtrlCreateListViewItem($_aResult[$_i][0] & "|" & $_aResult[$_i][1] & "|" & $_aResult[$_i][2], $hMatchList)
Next
EndFunc

; Call this function instead of Exit once the SQLite engine is running to make sure everything shuts down gracefully.
; Call this function instead of Exit to make sure everything shuts down gracefully.
Func DoExit()
If $hDB <> '' Then _SQLite_Close()
_SQLite_Shutdown()
If $hDB <> '' Then FileClose($hDB)
Exit
EndFunc

0 comments on commit 06e2c15

Please sign in to comment.