#include "MultiGraph.au3"
#include <Array.au3>
#include <File.au3>
#include <Date.au3>

Global $GraphHeight = 280
Global $aColors[10] = [0xf8ff23, 0xff0023, 0x94ff07, 0x0088ff, 0xff8902, 0xc107ff, 0x69fff3, 0xffffff, 0xff4b6f, 0x006a00]
Global $iDataPlotted = 0, $iHResolution = 250
Global $iVMin = 40, $iVMax = 50
Global $MainLineDiffY = $GraphHeight / 5
Global $iHMin = 0, $iHMax = $iHResolution
Global $DatResolutionLabel = " #", $DatResolution = -250
Global $bDrawGraph = False
Global $sVUnit = " mV"
Global $aData[1][3] = [[@YEAR & @MON & @MDAY & @HOUR & @MIN & @SEC, 42,48]]
Global $IDBtStartStop, $bInitStart, $hGUI


;Beispiel Logdatei einlesen NEU !!!
; $aData = _ReadLogToArray(@ScriptDir &"\dmm.log", 2, 0)
; _ArrayDisplay($aData)

Opt("MustDeclareVars", 1)
Opt("GUIOnEventMode", 1)

$hGUI = GUICreate("DMM Graph Test" & FileGetVersion(@ScriptFullPath, $FV_PRODUCTVERSION), 600, 430)
GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit", $hGUI)
$IDBtStartStop = GUICtrlCreateButton("Start/Stop", 20, 20)
GUICtrlSetOnEvent($IDBtStartStop, "_StartStop")
GUISetState()

_MG_Graph_erstellen (1, $hGUI, 80, 80, 500, $GraphHeight)
_MG_Graph_optionen_allgemein (1, $iHResolution, $iVMin, $iVMax, 0x000000, 0)
_MG_Graph_optionen_Plottmodus (1, 1, 1, 1, True)
_MG_Graph_optionen_Rahmen (1, True, 0x000000, 1)
_MG_Graph_optionen_Hauptgitterlinien (1, 1, 20, $MainLineDiffY, 1,0xFFFFFF, 190)
_MG_Graph_optionen_Hilfsgitterlinien (1, 1, -1, $MainLineDiffY / 2, 1,0xFFFFFF, 220)
_MG_Graph_Achse_links (1, True,  $iVMin, $iVMax, 1, $sVUnit, 0x000000, Default, 9, 60, 0.5)
_MG_Graph_Achse_unten (1, True,  $iHMin, $DatResolution, 0, $DatResolutionLabel, 0x000000, Default, 9, 70, 5)
_MG_Graph_initialisieren (1)

If _CalcHorAxis($aData) Then
	_MG_Graph_Achse_unten_update (1, $iHMin, $DatResolution, 0, $DatResolutionLabel)
EndIf

$bInitStart = True
While 1

	If $bDrawGraph = True Then
		; Horizontale Achse bei Bedarf skalieren
        If _CalcHorAxis($aData) Then _MG_Graph_Achse_unten_update (1, $iHMin, $DatResolution, 0, $DatResolutionLabel)
                   
        ; Vertikale Achse bei Bedarf skalieren
        _CalcVMinVMax($aData, -1, 1) ; VMin & VMAx neu berechnen
        If @extended = 1 Then ; Vertikale Auflösung muss geändert werden
        	_MG_Graph_optionen_allgemein (1, $iHResolution, $iVMin, $iVMax, 0x000000, 0)
        	_MG_Graph_Achse_links_update (1, $iVMin, $iVMax, 1, $sVUnit)
        	$iDataPlotted = _DrawGraphFromArray($aData, 1, -1, 1, True)
        EndIf
        
		If $bInitStart = True Then
			$iDataPlotted = _DrawGraphFromArray($aData, 1, $iDataPlotted, 1, True)
			$bInitStart = False
		Else
			$iDataPlotted = _DrawGraphFromArray($aData, 1, $iDataPlotted, 1)
		EndIf
	EndIf
	
	; Arraygröße überwachen
	If UBound($aData) >= 864000 Then ; Array auf 10 Tage, 1x pro Sekunde begrenzen. (Max. 16777216 Elemente möglich)
		_ArrayDelete($aData, "0-10000") ; ältesten Werte löschen
	EndIf
	
	; Für Demo: Array mit Zufallswerten füllen	
	ReDim $aData[UBound($aData) +1][UBound($aData, 2)]
	$aData[UBound($aData) -1][0] = @YEAR & @MON & @MDAY & @HOUR & @MIN & @SEC
	For $i = 1 To UBound($aData, 2) -1
		$aData[UBound($aData) -1][$i] = $aData[UBound($aData) -2][$i] + Random(-3, 3, 1)
	Next
	
	
	Sleep(1000)
WEnd


Func _StartStop()
	If $bDrawGraph = False then
		$bDrawGraph = True
	Else
		$bDrawGraph = False
	EndIf
EndFunc


Func _Exit()
	GUIDelete ($hGUI)
    Exit
EndFunc

	
Func _ReadLogToArray($sLogName, $iValueCol = 0, $iChannelCol = -1)
	Local $aLogFile, $aLogItems, $aLogData [0][0], $aOutData[0][0]
	Local $sKnownChannels = "", $aChannels[1], $j
	$aChannels[0] = 1
	If Not FileExists($sLogName) Then Return SetError(1,0,0)
	$aLogFile = FileReadToArray ($sLogName)

    ; Elemente der Logdatei in einzelne Spalten separieren und auf Wunsch Array der Kanäle erstellen
    If Not IsArray($aLogFile) Then Return SetError(2,0,0)
    For $i = $i To UBound($aLogFile) -1
        $aLogItems = StringSplit($aLogFile[$i], ";")
		ReDim $aLogData[UBound($aLogData) +1][$aLogItems[0]]
        For $j = 1 To $aLogItems[0]
        	If $j -1 = $iChannelCol And Not StringInStr($sKnownChannels, "$" & $aLogItems[$j] & "$") Then $sKnownChannels &= "$" & $aLogItems[$j] & "$" & "|"
            If $j = $aLogItems[0] Then
                $aLogData[$i][$j -1] = StringReplace($aLogItems[$j], ",", ".")
            Else
                $aLogData[$i][$j -1] = $aLogItems[$j]
            EndIf
        Next
    Next
    If $sKnownChannels <> "" Then $aChannels = StringSplit(StringMid($sKnownChannels,2,StringLen($sKnownChannels) -3), "$|$", 1)
    
    ; Messwerte (ggf. kanalbasierend) in Array-Spalten sortieren
    $j = 0
    For $i = 0 To UBound($aLogData) -1
    	If $i = 0 Then ReDim $aOutData[UBound($aOutData) +1][$aChannels[0]]
    	If $aOutData[$j][_ArraySearch($aChannels, $aLogData[$i][$iChannelCol], 1) -1] <> "" Then
    		ReDim $aOutData[UBound($aOutData) +1][$aChannels[0]]
    		$j += 1
    	EndIf
    	$aOutData[$j][_ArraySearch($aChannels, $aLogData[$i][$iChannelCol], 1) -1] = $aLogData[$i][$iValueCol]
    Next
    Return ($aOutData)
EndFunc


Func _CalcHorAxis(ByRef $aData, $iIntervalColumn = 0, $iCalcStart = -1)
	; Versuch eine horizontale Zeitauflösung zu berechnen
	; Format der Datum/Zeit-Spalte: YYYYMMDDhhmmss !
	If $iCalcStart = -1 Then $iCalcStart = UBound($aData) - $iHResolution
    If $iCalcStart < 0 Then $iCalcStart = 0
	Local $DatStart = StringLeft($aData[$iCalcStart][$iIntervalColumn], 4) & "/" & StringMid($aData[$iCalcStart][$iIntervalColumn], 5, 2) & "/" & StringMid($aData[$iCalcStart][$iIntervalColumn], 7, 2) & " " & StringMid($aData[$iCalcStart][$iIntervalColumn], 9, 2) & ":" & StringMid($aData[$iCalcStart][$iIntervalColumn], 11, 2) & ":" & StringMid($aData[$iCalcStart][$iIntervalColumn], 13, 2)
	Local $DatEnd = StringLeft($aData[UBound($aData) -1][$iIntervalColumn], 4) & "/" & StringMid($aData[UBound($aData) -1][$iIntervalColumn], 5, 2) & "/" & StringMid($aData[UBound($aData) -1][$iIntervalColumn], 7, 2) & " " & StringMid($aData[UBound($aData) -1][$iIntervalColumn], 9, 2) & ":" & StringMid($aData[UBound($aData) -1][$iIntervalColumn], 11, 2) & ":" & StringMid($aData[UBound($aData) -1][$iIntervalColumn], 13, 2)
	Local $DatResolutionLabelOld = $DatResolutionLabel
	Local $DatResolutionOld = $DatResolution
	$DatResolution = _DateDiff("s", $DatEnd, $DatStart)
	If $DatResolution <> 0 Then
		$DatResolutionLabel = " Sek"
		If $iHResolution / (UBound($aData) -1) > 1 Then $DatResolution = $DatResolution * ($iHResolution / (UBound($aData) -1))
		If Abs($DatResolution) > $iHResolution Then
			$DatResolutionLabel = " Min"
			$DatResolution = Round($DatResolution / 60)
		EndIf
		If Abs($DatResolution) > $iHResolution Then
			$DatResolutionLabel = " Std"
			$DatResolution = Round($DatResolution / 60)
		EndIf
		If Abs($DatResolution) > $iHResolution Then
			$DatResolutionLabel = " Tage"
			$DatResolution = Round($DatResolution / 24)
		EndIf
	Else
		$DatResolution = $DatResolutionOld
	EndIf
	If $DatResolutionOld = $DatResolution And $DatResolutionLabelOld = $DatResolutionLabel Then Return 0
	Return 1
EndFunc


Func _CalcVMinVmax(ByRef $aData, $iCalcStart = -1, $iColumnStart = 0)
	Local $iVMinOld = $iVMin
	Local $iVMaxOld = $iVMax
	Local $iIdxRow, $iVMinTemp, $iVMaxTemp
	If $iCalcStart = -1 Then $iCalcStart = UBound($aData) - $iHResolution
    If $iCalcStart < 0 Then $iCalcStart = 0
    
    For $i = $iColumnStart To UBound($aData, 2) -1
    	$iVMinTemp = Int(_ArrayMin($aData, 1, $iCalcStart, -1, $i) -0.5)
    	If $iVMinTemp < $iVMin Then $iVmin = $iVMinTemp
    	$iVMaxTemp = Int(_ArrayMax($aData, 1, $iCalcStart, -1, $i) +1)
    	If $iVMaxTemp > $iVMax Then $iVMax = $iVMaxTemp
    Next
    If $iVMinOld <> $iVmin Or $iVMaxOld <> $iVMax Then
    	Return SetExtended(1,1)
    Else
    	Return SetExtended(0,1)
    EndIf
EndFunc


Func _DrawGraphFromArray(ByRef $aData, $iGraph, $iPlotStart = -1, $iColumnStart = 0, $bInit = False)
	; Plotindex: -1 = die letzten um die Graphbreite zu füllen, 0 = alle alten
	If Not IsArray($aData) Then Return SetError(1,0,0)
	If $iGraph < 1 Then Return SetError(2,0,0)
	
	Local $iXResolution = $MG_aGraph[$iGraph][0][$MG_a_iAufloesung] ; Get X-Resolution from UDF-Variable

	If $iPlotStart = -1 Or $bInit = True Then
		$iPlotStart = UBound($aData) - $iXResolution
		If $iPlotStart < 0 Then $iPlotStart = 0
	EndIf
	
	If $bInit = True Then
		_MG_Graph_clear ($iGraph)
		;Kanale in Abhängigkeit des Array initialisieren
        For $i = 1 + $iColumnStart To UBound($aData, 2)
        	_MG_Kanal_optionen (1, $i - $iColumnStart, 1, 1, $aColors[Mod($i - 1 - $iColumnStart,10)], 0)
			If $i - $iColumnStart <= 10  Then
				GUICtrlCreateLabel($i - $iColumnStart, 60 + ($i - 1 - $iColumnStart) *15, 400, 14, 14, $SS_CENTER)
        		GUICtrlSetBKColor(-1, $aColors[Mod($i - 1 - $iColumnStart,10)])
            EndIf
        Next	
		_MG_Graph_optionen_Plottmodus ($iGraph, 1, 0, 1, True)
	EndIf

	$i = $iPlotStart
	While $i  < UBound($aData) -1
		For $j = $iColumnStart To UBound($aData, 2) -1
			_MG_Wert_setzen ($iGraph, $j + 1 - $iColumnStart, $aData[$i][$j])
		Next
		_MG_Graph_plotten($iGraph)
		$i += 1
	Wend
	
	If $bInit = True Then
		_MG_Graph_optionen_Plottmodus ($iGraph, 1, 1, 1, True)
		_MG_Graph_plotten($iGraph)
	EndIf
	
	Return $i
EndFunc