Option Explicit

' These declarations have to be copied in the beginning of a Visual Basic Application file
' to access the MemBrain DLL functions from out Visual Basic.

' Get the version information string of the DLL.
' Specify maximum length of string to be copied (excluding the terminating '\0'.
' A terminating '\0' will be attached in every case.
Private Declare Function MB_GetVersionInfo Lib "MEMBRAINDLL.dll" _
Alias "__MB_GetVersionInfo@8" (ByVal infoStr As String, ByVal maxLen As Long) As Long

' Add a new neural net to the DLL's internal array of neural nets.
Private Declare Sub MB_AddNet Lib "MEMBRAINDLL.dll" _
Alias "__MB_AddNet@0" ()

' Get number of currently available neural nets in the DLL's array
Private Declare Function MB_GetNetCount Lib "MEMBRAINDLL.dll" _
Alias "__MB_GetNetCount@0" () As Long

' Get index of the currently selected net
Private Declare Function MB_GetSelectedNet Lib "MEMBRAINDLL.dll" _
Alias "__MB_GetSelectedNet@0" () As Long

' Delete the neural net at index <idx>.
Private Declare Function MB_DeleteNet Lib "MEMBRAINDLL.dll" _
Alias "__MB_DeleteNet@4" (ByVal idx As Long) As Long

' Select one of the available nets as the currently active one.
Private Declare Function MB_SelectNet Lib "MEMBRAINDLL.dll" _
Alias "__MB_SelectNet@4" (ByVal idx As Long) As Long

' Load the currently active neural net from the given *.mbn file (including path)
Private Declare Function MB_LoadNet Lib "MEMBRAINDLL.dll" _
Alias "__MB_LoadNet@4" (ByVal fileName As String) As Long

' Save a MemBrain neural net to the given *.mbn file (including path)
Private Declare Function MB_SaveNetAs Lib "MEMBRAINDLL.dll" _
Alias "__MB_SaveNetAs@4" (ByVal fileName As String) As Long

' Save an already loaded MemBrain neural net (overwrite original file)
Private Declare Function MB_SaveNet Lib "MEMBRAINDLL.dll" _
Alias "__MB_SaveNet@0" () As Long

' Reset the net. All activations and link spikes are set to 0.
Private Declare Sub MB_ResetNet Lib "MEMBRAINDLL.dll" _
Alias "__MB_ResetNet@0" ()

' Get number of input neurons in the net
Private Declare Function MB_GetInputCount Lib "MEMBRAINDLL.dll" _
Alias "__MB_GetInputCount@0" () As Long

' Get number of output neurons in the net
Private Declare Function MB_GetOutputCount Lib "MEMBRAINDLL.dll" _
Alias "__MB_GetOutputCount@0" () As Long

' Get name of input neuron at index <idx>. Specify maximum length
' of string to be copied (excluding the terminating '\0'.
' A terminating '\0' will be attached in every case.
Private Declare Function MB_GetInputName Lib "MEMBRAINDLL.dll" _
Alias "__MB_GetInputName@12" (ByVal idx As Long, ByVal name As String, ByVal maxLen As Long) As Long

' Get name of output neuron at index <idx>. Specify maximum length
' of string to be copied (excluding the terminating '\0'.
' A terminating '\0' will be attached in every case.
Private Declare Function MB_GetOutputName Lib "MEMBRAINDLL.dll" _
Alias "__MB_GetOutputName@12" (ByVal idx As Long, ByVal name As String, ByVal maxLen As Long) As Long

' Apply an activation value to the input neuron at index <idx>.
Private Declare Function MB_ApplyInputAct Lib "MEMBRAINDLL.dll" _
Alias "__MB_ApplyInputAct@12" (ByVal idx As Long, ByVal act As Double) As Long

' Get the activation value of the input neuron at index <idx>.
Private Declare Function MB_GetInputAct Lib "MEMBRAINDLL.dll" _
Alias "__MB_GetInputAct@8" (ByVal idx As Long, ByRef act As Double) As Long

' Perform one think step of the net
Private Declare Sub MB_ThinkStep Lib "MEMBRAINDLL.dll" _
Alias "__MB_ThinkStep@0" ()

' Get the activation value of the ouTput neuron at index <idx>.
Private Declare Function MB_GetOutputAct Lib "MEMBRAINDLL.dll" _
Alias "__MB_GetOutputAct@8" (ByVal idx As Long, ByRef act As Double) As Long

' Get the output value of the output neuron at index <idx>.
Private Declare Function MB_GetOutputOut Lib "MEMBRAINDLL.dll" _
Alias "__MB_GetOutputOut@8" (ByVal idx As Long, ByRef outVal As Double) As Long

' Get index of the last output winner neuron of the net.
Private Declare Function MB_GetOutputWinnerNeuron Lib "MEMBRAINDLL.dll" _
Alias "__MB_GetOutputWinnerNeuron@0" () As Long

' Get the activation range of the input neuron at index <idx>.
Private Declare Function MB_GetInputActRange Lib "MEMBRAINDLL.dll" _
Alias "__MB_GetInputActRange@12" (ByVal idx As Long, ByRef actMin As Double, ByRef actMax As Double) As Long

' Get the activation range of the output neuron at index <idx>.
Private Declare Function MB_GetOutputActRange Lib "MEMBRAINDLL.dll" _
Alias "__MB_GetOutputActRange@12" (ByVal idx As Long, ByRef actMin As Double, ByRef actMax As Double) As Long







' --------------------- For lesson handling and teaching --------------------
' Load a lesson to be the currently active
Private Declare Function MB_LoadLesson Lib "MEMBRAINDLL.dll" _
Alias "__MB_LoadLesson@4" (ByVal fileName As String) As Long

' Import the currently active lesson from csv
Private Declare Function MB_ImportLesson Lib "MEMBRAINDLL.dll" _
Alias "__MB_ImportLesson@4" (ByVal fileName As String) As Long

' Import the currently active lesson from raw csv
Private Declare Function MB_ImportLessonRaw Lib "MEMBRAINDLL.dll" _
Alias "__MB_ImportLessonRaw@4" (ByVal fileName As String) As Long

' Import the currently active lesson inputs from raw csv
Private Declare Function MB_ImportLessonInputsRaw Lib "MEMBRAINDLL.dll" _
Alias "__MB_ImportLessonInputsRaw@4" (ByVal fileName As String) As Long

' Import the currently active lesson outputs from raw csv
Private Declare Function MB_ImportLessonOutputsRaw Lib "MEMBRAINDLL.dll" _
Alias "__MB_ImportLessonOutputsRaw@4" (ByVal fileName As String) As Long

' Save the currently active lesson to its current file name
Private Declare Function MB_SaveLesson Lib "MEMBRAINDLL.dll" _
Alias "__MB_SaveLesson@0" () As Long

' Save the currently active lesson to the given file name
Private Declare Function MB_SaveLessonAs Lib "MEMBRAINDLL.dll" _
Alias "__MB_SaveLessonAs@4" (ByVal fileName As String) As Long

' Export the currently active lesson to csv
Private Declare Function MB_ExportLesson Lib "MEMBRAINDLL.dll" _
Alias "__MB_EportLesson@8" (ByVal fileName As String, ByVal maxCols As Long) As Long

' Export the currently active lesson to raw csv
Private Declare Function MB_ExportLessonRaw Lib "MEMBRAINDLL.dll" _
Alias "__MB_EportLessonRaw@8" (ByVal fileName As String, ByVal maxCols As Long) As Long

' Export the inputs of the currently active lesson to raw csv
Private Declare Function MB_ExportLessonInputsRaw Lib "MEMBRAINDLL.dll" _
Alias "__MB_EportLessonInputsRaw@8" (ByVal fileName As String, ByVal maxCols As Long) As Long

' Export the outputs of the currently active lesson to raw csv
Private Declare Function MB_ExportLessonOutputsRaw Lib "MEMBRAINDLL.dll" _
Alias "__MB_EportLessonOutputsRaw@8" (ByVal fileName As String, ByVal maxCols As Long) As Long

' Set the number of inputs of the currently administered lesson
Private Declare Function MB_SetLessonInputCount Lib "MEMBRAINDLL.dll" _
Alias "__MB_SetLessonInputCount@4" (ByVal count As Long) As Long

' Get the number of inputs of the currently administered lesson
Private Declare Function MB_GetLessonInputCount Lib "MEMBRAINDLL.dll" _
Alias "__MB_GetLessonInputCount@0" () As Long

' Set the number of outputs of the currently administered lesson
Private Declare Function MB_SetLessonOutputCount Lib "MEMBRAINDLL.dll" _
Alias "__MB_SetLessonOutputCount@4" (ByVal count As Long) As Long

' Get the number of outputs of the currently administered lesson
Private Declare Function MB_GetLessonOutputCount Lib "MEMBRAINDLL.dll" _
Alias "__MB_GetLessonOutputCount@0" () As Long

' Set the input name at index <idx> of the currently active lesson
Private Declare Function MB_SetLessonInputName Lib "MEMBRAINDLL.dll" _
Alias "__MB_SetLessonInputName@8" (ByVal idx As Long, ByVal name As String) As Long

' Get the input name at index <idx> of the currently active lesson
Private Declare Function MB_GetLessonInputName Lib "MEMBRAINDLL.dll" _
Alias "__MB_GetLessonInputName@12" (ByVal idx As Long, ByVal name As String, ByVal maxLen As Long) As Long

' Set the output name at index <idx> of the currently active lesson
Private Declare Function MB_SetLessonOutputName Lib "MEMBRAINDLL.dll" _
Alias "__MB_SetLessonOutputName@8" (ByVal idx As Long, ByVal name As String) As Long

' Get the output name at index <idx> of the currently active lesson
Private Declare Function MB_GetLessonOutputName Lib "MEMBRAINDLL.dll" _
Alias "__MB_GetLessonOutputName@12" (ByVal idx As Long, ByVal name As String, ByVal maxLen As Long) As Long

' Set the input value at index <idx> of the current pattern
Private Declare Function MB_SetPatternInput Lib "MEMBRAINDLL.dll" _
Alias "__MB_SetPatternInput@12" (ByVal idx As Long, ByVal value As Double) As Long

' Get the input value at index <idx> of the current pattern
Private Declare Function MB_GetPatternInput Lib "MEMBRAINDLL.dll" _
Alias "__MB_GetPatternInput@8" (ByVal idx As Long, ByRef value As Double) As Long

' Set the output value at index <idx> of the current pattern
Private Declare Function MB_SetPatternOutput Lib "MEMBRAINDLL.dll" _
Alias "__MB_SetPatternOutput@12" (ByVal idx As Long, ByVal value As Double) As Long

' Get the output value at index <idx> of the current pattern
Private Declare Function MB_GetPatternOutput Lib "MEMBRAINDLL.dll" _
Alias "__MB_GetPatternOutput@8" (ByVal idx As Long, ByRef value As Double) As Long

' Select the currently active pattern of the currently active lesson
Private Declare Function MB_SelectPattern Lib "MEMBRAINDLL.dll" _
Alias "__MB_SelectPattern@4" (ByVal idx As Long) As Long

' Get the currently selected pattern index of the currently active lesson
Private Declare Function MB_GetSelectedPattern Lib "MEMBRAINDLL.dll" _
Alias "__MB_GetSelectedPattern@0" () As Long

' Delete the currently active pattern of the currently active lesson
Private Declare Function MB_DeletePattern Lib "MEMBRAINDLL.dll" _
Alias "__MB_DeletePattern@0" () As Long

' Add a pattern to the end of the active lesson
Private Declare Sub MB_AddPattern Lib "MEMBRAINDLL.dll" _
Alias "__MB_AddPattern@0" ()

' Get the number of patterns in the active lesson
Private Declare Function MB_GetLessonSize Lib "MEMBRAINDLL.dll" _
Alias "__MB_GetLessonSize@0" () As Long

' Enable/Disable the output data section of the active lesson
Private Declare Function MB_EnableLessonOutData Lib "MEMBRAINDLL.dll" _
Alias "__MB_EnableLessonOutData@4" (ByVal outDataEnabled As Long) As Long

' Transfer I/O names names and count from the currently active net to
' the currently active lesson
Private Declare Function MB_NamesFromNet Lib "MEMBRAINDLL.dll" _
Alias "__MB_NamesFromNet@0" () As Long

' Transfer I/O names names from the currently active lesson to
' the currently active net
Private Declare Function MB_NamesToNet Lib "MEMBRAINDLL.dll" _
Alias "__MB_NamesToNet@0" () As Long

' Set the number of currently administered lessons
Private Declare Function MB_SetLessonCount Lib "MEMBRAINDLL.dll" _
Alias "__MB_SetLessonCount@4" (ByVal count As Long) As Long

' Get the number of currently administered lessons
Private Declare Function MB_GetLessonCount Lib "MEMBRAINDLL.dll" _
Alias "__MB_GetLessonCount@0" () As Long

' Select the active lesson
Private Declare Function MB_SelectLesson Lib "MEMBRAINDLL.dll" _
Alias "__MB_SelectLesson@4" (ByVal idx As Long) As Long

' Get the index of the currently active lesson
Private Declare Function MB_GetSelectedLesson Lib "MEMBRAINDLL.dll" _
Alias "__MB_GetSelectedLesson@0" () As Long

' Apply the currently active pattern to the inputs of the currently active net
Private Declare Function MB_ApplyPattern Lib "MEMBRAINDLL.dll" _
Alias "__MB_ApplyPattern@0" () As Long

' Select the current recording type: 0 = Activation, 1 = Output
Private Declare Function MB_SetRecordingType Lib "MEMBRAINDLL.dll" _
Alias "__MB_SetRecordingType@4" (ByVal recordingType As Long) As Long

' Start recording data to a lesson: Specify lesson index to record to and step count
Private Declare Function MB_StartRecording Lib "MEMBRAINDLL.dll" _
Alias "__MB_SelectLesson@8" (ByVal idx As Long, ByVal stepCount As Long) As Long

' Stop recording data to lesson
Private Declare Sub MB_StopRecording Lib "MEMBRAINDLL.dll" _
Alias "__MB_StopRecording@0" ()

' Think on all patters of the currently active lesson
Private Declare Function MB_ThinkLesson Lib "MEMBRAINDLL.dll" _
Alias "__MB_ThinkLesson@0" () As Long

' Load a teacher file
Private Declare Function MB_LoadTeacherFile Lib "MEMBRAINDLL.dll" _
Alias "__MB_LoadTeacherFile@4" (ByVal fileName As String) As Long

' Select the active teacher by name
Private Declare Function MB_SelectTeacher Lib "MEMBRAINDLL.dll" _
Alias "__MB_SelectTeacher@4" (ByVal teacherName As String) As Long

' Perform one teach step (lesson run). Return result according to Teacher.h (TR_....)
Private Declare Function MB_TeachStep Lib "MEMBRAINDLL.dll" _
Alias "__MB_TeachStep@0" () As Long

' Conclude the current teach run. Should be called after every teach process completion.
Private Declare Sub MB_StopTeaching Lib "MEMBRAINDLL.dll" _
Alias "__MB_AddPattern@0" ()

' Get the number of available teachers
Private Declare Function MB_GetTeacherCount Lib "MEMBRAINDLL.dll" _
Alias "__MB_GetTeacherCount@0" () As Long

' Get the name of the teacher at index <idx> Specify maximum length
' of string to be copied (excluding the terminating '\0'.
' A terminating '\0' will be attached in every case.
Private Declare Function MB_GetTeacherName Lib "MEMBRAINDLL.dll" _
Alias "__MB_GetLessonInputName@12" (ByVal idx As Long, ByVal name As String, ByVal maxLen As Long) As Long

' Randomize the currently active net
Private Declare Sub MB_RandomizeNet Lib "MEMBRAINDLL.dll" _
Alias "__MB_RandomizeNet@0" ()

' Get the last known error of the currently active net
Private Declare Function MB_GetLastNetError Lib "MEMBRAINDLL.dll" _
Alias "__MB_GetLastNetError@0" () As Double


' static variables
Dim sInCount As Long
Dim sOutCount As Long
Dim sFileName As String
Dim sStepCount As Long
Dim sColumn
Dim sResultSheetCount As Long
Dim sResultSheetIdx As Long
Dim sResultSheetName As String
'Const DEF_PATH = "C:\Programme\MemBrain\Brains"
Const DEF_PATH = "C:"

Private Sub BuildResultSheetName()
    sResultSheetName = "Result " & sResultSheetIdx
End Sub



Private Sub HandleDllError()
    MsgBox ("Dll reported error! The program will terminate!")
    Unload Me
End Sub
'Delete all worksheets except for the first one
Private Sub CleanUpWorksheets()
    Dim sheetCount
    Dim i As Long
    
    sheetCount = Worksheets.count
    i = sheetCount
        
    While i >= 1
        If Worksheets(i).name <> "Main" Then
            Worksheets(i).Delete
        End If
        i = i - 1
    Wend
    
    Worksheets("Main").Cells(3, 2) = ""
    
    sResultSheetIdx = 0
    sResultSheetCount = 0
End Sub
' enter general information into first worksheet
Private Sub SetupGeneralInfo()
    Dim sheet As Worksheet
    
    Worksheets(1).Cells(3, 2) = sFileName
        
End Sub
Private Function SetupConfigData() As Boolean
    
    Dim ret As Boolean
    
    ret = True
    
    sStepCount = Worksheets("Main").Cells(6, 2)
    
    ret = (sStepCount >= 2)
    If (ret = False) Then
        MsgBox "Number of Activation Steps must be >= 2!"
    End If
    
    SetupConfigData = ret
End Function

Private Sub ApplyAverageInputs()
Dim min As Double
Dim max As Double
Dim act As Double
Dim ret As Long
Dim inIdx As Long

inIdx = 0
While inIdx < sInCount
    ret = MB_GetInputActRange(inIdx, min, max)
    If ret <> 0 Then
        HandleDllError
    End If
    act = (min + max) / 2
    ret = MB_ApplyInputAct(inIdx, act)
    If ret <> 0 Then
        HandleDllError
    End If
    
    inIdx = inIdx + 1
Wend

End Sub
'Analyse the input neuron with the given index
Private Sub AnalyseInputNeuron(ByVal idx As Long)
    Dim i As Long
    Dim j As Long
    Dim stepSize As Double
    Dim min As Double
    Dim max As Double
    Dim inAct As Double
    Dim ret As Long
    Dim outAct As Double
                  
    If (sColumn + 1 + sOutCount > 256) Then
        'Time to select a new results work sheet
        sResultSheetIdx = sResultSheetIdx + 1
        BuildResultSheetName
        sColumn = 1
    End If
    
    'Apply average values to all input neurons
    ApplyAverageInputs
    
    'Calculate activation adjustment step size
    ret = MB_GetInputActRange(idx, min, max)
    If ret <> 0 Then
        HandleDllError
    End If
    inAct = min
    stepSize = (max - min) / (sStepCount - 1)
    
    ' Apply activations, perform think steps and retrieve output values
    For i = 1 To sStepCount Step 1
        ret = MB_ApplyInputAct(idx, inAct)
        If ret <> 0 Then
            HandleDllError
        End If
        MB_ThinkStep
              
        Worksheets(sResultSheetName).Cells(i + 1, sColumn) = inAct
        sColumn = sColumn + 1
        
        For j = 0 To sOutCount - 1 Step 1
            ret = MB_GetOutputAct(j, outAct)
            Worksheets(sResultSheetName).Cells(i + 1, sColumn) = outAct
            sColumn = sColumn + 1
        
            If ret <> 0 Then
                HandleDllError
            End If
        Next
        sColumn = sColumn - 1 - sOutCount
              
        inAct = inAct + stepSize
    Next
    sColumn = sColumn + 2 + sOutCount
     
End Sub


Private Sub ButLoadNet_Click()
    Dim result As Long
    
    Dim Filter As String, Title As String
    Dim FilterIndex As Integer
    Dim fileName As Variant
    ' File filters
    Filter = "MemBrain Files (*.mbn),*.mbn," & _
             "All Files (*.*),*.*"
    ' Default Filter to *.mbn
    FilterIndex = 1
    ' Set Dialog Caption
    Title = "Select a MemBrain net File to Open"
    ' Select Start Drive & Path
    ChDrive ("C")
    ChDir (DEF_PATH)
    With Application
        ' Set File Name to selected File
        fileName = .GetOpenFilename(Filter, FilterIndex, Title)
        ' Reset Start Drive/Path
        ChDrive (Left(.DefaultFilePath, 1))
        ChDir (.DefaultFilePath)
    End With
    ' Exit on Cancel
    If fileName = False Then
        MsgBox "No file was selected."
        Exit Sub
    End If
    
    sFileName = fileName
    
    fileName = fileName + vbNullChar
    ' Open File
    result = MB_LoadNet(fileName)
    
    'result = MB_LoadNet("C:\Programme\MemBrain\Excel\Anlassnetz_Hrte_Zugversuche270307.mbn")
    If result <> 0 Then
        HandleDllError
    Else
        sInCount = 0
        sOutCount = 0
    End If
    
    CleanUpWorksheets
    SetupGeneralInfo

End Sub
' Add neuron names to the results worksheet
Private Sub AddNeuronNames()
    Dim inIdx As Long
    Dim outIdx As Long
    Dim name As String
    Const LENGTH = 100
    
    name = String$(LENGTH + 1, vbNullChar)
    sColumn = 1
             
         
    For inIdx = 0 To sInCount - 1
    
        If (sColumn + 1 + sOutCount > 256) Then
            'Time to create a new results work sheet
            Worksheets.Add
            sResultSheetCount = sResultSheetCount + 1
            sResultSheetIdx = sResultSheetIdx + 1
            BuildResultSheetName
            Worksheets(1).name = sResultSheetName
            sColumn = 1
        End If
        name = String$(LENGTH + 1, vbNullChar)
        If MB_GetInputName(inIdx, name, 100) <> 0 Then
            HandleDllError
        End If
        name = Trim(name)
        Worksheets(sResultSheetName).Cells(1, sColumn) = name
        sColumn = sColumn + 1
            For outIdx = 0 To sOutCount - 1
                name = String$(LENGTH + 1, vbNullChar)
                If MB_GetOutputName(outIdx, name, 100) <> 0 Then
                    HandleDllError
                End If
                name = Trim(name)
                Worksheets(sResultSheetName).Cells(1, sColumn) = name
                sColumn = sColumn + 1
            Next
        sColumn = sColumn + 1
        
    Next
        
End Sub

Private Sub ButRunAnalysis_Click()
    Dim inCount As Long
    Dim outCount As Long
    Dim inIdx As Long
    
    
    sInCount = MB_GetInputCount
    sOutCount = MB_GetOutputCount
    
    If (sInCount < 1) Then
        MsgBox "The loaded net does not have any inputs!"
        Exit Sub
    End If
    
    If (sOutCount < 1) Then
        MsgBox "The loaded net does not have any outputs!"
        Exit Sub
    End If
    
    If (sOutCount > 255) Then
        MsgBox "The number of output neurons exceeds 255!"
        Exit Sub
    End If
    
    CleanUpWorksheets
    
    If SetupConfigData() = False Then
        Exit Sub
    End If
    
    ' Add a new worksheet for the results
    Worksheets.Add
        
    sResultSheetCount = 1
    sResultSheetIdx = 1
    BuildResultSheetName
    Worksheets(1).name = sResultSheetName
    
    ' Now add the neuron names to the results sheet
    AddNeuronNames
    sResultSheetIdx = 1
    BuildResultSheetName
    sColumn = 1
    
    inIdx = 0
    While inIdx < sInCount
        AnalyseInputNeuron (inIdx)
        inIdx = inIdx + 1
    Wend
    
    MsgBox ("Analysis Finished!")
    
End Sub

Private Sub ButShowDllVersion_Click()

    Dim result As Long
    Dim Version As String
    Dim LENGTH As Long

    LENGTH = 50
    Version = String$(LENGTH + 1, vbNullChar)

    result = MB_GetVersionInfo(Version, LENGTH)
    If result = 0 Then
        Version = Trim(Version)
        MsgBox (Version)
    Else
        HandleDllError
    End If
    
    
End Sub


Private Sub UserForm_Click()

End Sub
