1. Dashboard
  2. Mitglieder
    1. Letzte Aktivitäten
    2. Benutzer online
    3. Team
    4. Mitgliedersuche
  3. Forenregeln
  4. Forum
    1. Unerledigte Themen
  • Anmelden
  • Registrieren
  • Suche
Alles
  • Alles
  • Artikel
  • Seiten
  • Forum
  • Erweiterte Suche
  1. AutoIt.de - Das deutschsprachige Forum.
  2. Mitglieder
  3. Mars

Beiträge von Mars

  • Overheadarmes/Codearmes Keyboard capturing

    • Mars
    • 6. Oktober 2022 um 22:46

    Keyboardstate ist quasi "IsPressed" für alle Tasten gleichzeitig. Um das zu nutzen müsste man extrem oft Abfragen machen und quasi (hier 256) alle Keys andauernd abfragen um zu schauen ob etwas gedrückt wurde. Das ist für ein "paar wenige" Keys ggf eine gute Idee, aber wenn ich ca. 150 mögliche Keys überwachen muss, nur damit ab und zu einer davon gedrückt und erkannt wird, dann sind 99.9% der Abfragen nutzlos^^

    Damit auch schnelle Tastendrücke erfasst werden wäre man außerdem gezwungen mit hoher Frequenz zu prüfen (da die Events hier ungepuffert sind).

    Ich lass die Idee noch ein bisschen sacken, und dann wirds wahrscheinlich die Version von Oscar (Eigenes Window + Proc) mit sämtlichen Sachen die ich vergessen habe (wovon BugFix einige aufgezeigt hat). Wobei ich noch nicht ganz sicher bin, die WMs (ohne ein eigenes Window) sind auch verlockend, vermutlich weniger Komplexität in der Implementierung, dafür mehr Overhead. Allerdings ist laut der Hilfe WM_CHAR nicht immer nutzbar, wo das vermutlich am einfachsten wäre (auch in Bezug auf das Gedrückthalten von Tasten und Kombinationen von Tasten)...

    Da fällt mir direkt eine Frage ein: GUIRegisterMsg hat ja keinen Parameter für hWND. Hat ein Layered-Window dort einen eigenen Zugang (GuiSwitch und dann GUIRegisterMsg? Ich kenne mich damit leider nicht aus...), sodass ich z.B. WM_CHAR im Layered-Window registrieren kann (weil ich ja 100% sicher sein kann, dass ich kein Edit-Ctrl habe, also müsste WM_CHAR verfügbar sein)?


    Edit: Ich glaube ich bin da auf dem mentalen Holzweg. Kann es sein, dass die von RegisterMsg registrierten Funktionen mit den via SetWindowLong(..., WNDPROC, ...) registrierten Funktionen auf ein und dasselbe verweisen und diese Methode quasi die oben angesprochene GUIRegisterMsg Version "mit" HWND ist? Falls das so ist glaube ich es jetzt ansatzweise verstanden zu haben...

    Mensch, ein simples einfaches Texteingabefeld ist viel zu kompliziert... :rofl:

    lg

    M

  • Overheadarmes/Codearmes Keyboard capturing

    • Mars
    • 6. Oktober 2022 um 18:37

    Das sieht schon ziemlich gut aus. WindowProc und die benötigten Zusatzfunktionen (Pfeiltasten, etc) hatte ich komplett übersehen.

  • Overheadarmes/Codearmes Keyboard capturing

    • Mars
    • 6. Oktober 2022 um 16:47

    Moin,

    Um einem XY Problem vorzubeugen gleich vorweg das Ziel: Ich möchte ein GDI+ Ctrl basteln welches ähnlich zu einem Input-Ctrl arbeitet. (Texteingabe möglich). Außerdem soll es intern "keine" AutoIt-Ctrls verwenden, also kein "verstecktes" Ctrl das ausgelesen wird. Da das ganze angezeigt wird ist ein GUI vorhanden, RegisterMsg etc. funktioniert, GUIOnEventMode ist an. Die Tasten sollen nur gecaptured werden, wenn das GUI auch aktiv ist. Gedrückthalten von Tasten soll sich genauso verhalten wie man es vom InputCtrl gewohnt ist (also zunächst 1 Zeichen, dann kurze Pause, dann am laufenden Band neue Zeichen). Zu allem überfluss soll das ganze im Leerlauf möglichst wenig Performance brauchen, es wäre unschön, wenn ein Programm alleine 50% der Rechenzeit dafür aufwendet um ein InputCtrl zu verwalten.

    Anätze

    > IsPressed/Keyboardstate:

    - Sehr viel Code muss ausgeführt werden um anständig festzustellen was gedrückt wurde.

    - Kombinationen müssen von Hand ausgewertet werden (z.B. Shift + Taste)

    - Wird immer ausgeführt egal ob GUI aktiv ist, oder nicht.

    - Das Verhalten von "gedrückt halten einer Taste" muss manuell nachgebildet werden.

    > Hotkeys:

    - Unmengen Hotkeys müssen registriert werden.

    + Kombinationen wie Shift + Taste oder ähnliches ohne weitere Logik abrufbar.

    - Wird immer ausgeführt egal ob GUI aktiv ist, oder nicht.

    + Das Verhalten von "gedrückt halten einer Taste" wird unterstützt.

    > GUISetAccelerators:

    + Alle "Hotkeys" sind schnell und einfach initialisierbar (2D Array)

    + Kombinationen werden unterstützt.

    ? Belastet den GUIMessageLoop/EventLoop (wir sind im GUIOnEventMode, also werden die Accelerators -> Msgloop/Eventloop weitergeleitet) Keine ahnung "wie belastend" das ist, wenn da 150 Registrierungen drin sind.

    + Funktioniert nur wenn GUI aktiv.

    - Braucht "versteckte Ctrls" (DummyCtrl).

    ? Das Verhalten von "gedrückt halten einer Taste" wird unterstützt?

    > GUIRegisterMsg + Keymessages:

    + (glaube ich) Kombinationen werden unterstützt.
    + Belastet soweit ich weiß den Message/Eventloop nicht.

    ? Messages werden nur verschickt, wenn GUI aktiv?

    + (glaube ich) Man hat Zugriff auf zusätzliche Infos, weil lParam und wParam mehr als nur den Key der gedrückt wurde beinhaltet?

    ? Das Verhalten von "gedrückt halten einer Taste" wird unterstützt?

    Jetzt kommt die Frage: Was habe ich übersehen (gibt es noch weitere Wege?), und gibt es einen "richtigen" Weg bei der Sache?

    Einige Punkte habe ich mit Fragezeichen markiert, weil ich nicht genau weiß wie sich die Funktionen verhalten und weil ich nicht alles ausprobieren will.

    Hier braucht niemand irgendwelchen Code zu posten, alles was ich möchte ist (falls ihr etwas in der Art schonmal gemacht habt) eine Info wie man sowas richtig angeht.

    Meine Tendenz ist GUIRegisterMsg zu verwenden, aber vllt hat ja jemand hier mehr Erfahrung und kann mir einen Tipp geben.

    lg

    M

  • [Erledigt] Kann man bei SciTE den Compiler austauschen, der mit Ctrl+F7 aufgerufen wird?

    • Mars
    • 31. Juli 2022 um 17:46

    Mit der Macht des PU, habe ich das mal [Erledigt] :rofl:

  • [Erledigt] Kann man bei SciTE den Compiler austauschen, der mit Ctrl+F7 aufgerufen wird?

    • Mars
    • 31. Juli 2022 um 00:16

    Alina und Exit

    Klärt uns unwissende bitte auf. Ich bin mir fast sicher, dass ich Au3toCmd nicht verwenden werde, aber wenn jemand anderes mal ein Problem ähnlicher Art hat, wird er (sofern er weiß wie man die Suche benutzt) früher oder später hier landen (Keywords wurden in diesem Thread ja zu genüge verwendet). Dann wäre es schön, wenn hier ein Abschluss für offene Fragen steht.

    Was war das Problem?

    Was war der Bedienfehler?

    Wie vermeidet man den Bedienfehler?

  • [Erledigt] Kann man bei SciTE den Compiler austauschen, der mit Ctrl+F7 aufgerufen wird?

    • Mars
    • 24. Juli 2022 um 10:40
    Zitat von Alina

    Den habe ich mir damals irgendwo gezogen und weiß selber nicht mehr woher.

    Das klingt aber nicht sehr Vertrauenserweckend :D

  • [Erledigt] Kann man bei SciTE den Compiler austauschen, der mit Ctrl+F7 aufgerufen wird?

    • Mars
    • 23. Juli 2022 um 13:00
    Zitat von BugFix

    Hast du einen anderen AutoIt Compiler? ;)

    Insgeheim hat Alina die letzten Jahre an AutoIt4 gearbeitet und will nun endlich die Früchte ihrer Arbeit ernten. 8)

  • GUICtrlCreateIcon mit png-Datei

    • Mars
    • 9. Juli 2022 um 19:27

    Ich glaube oh-ha meint damit, dass du aus der .png ein .ico machen sollst. Eigentlich willst du ja aber die .png so wie sie ist in einem Ctrl verwenden.

    Ich vermute, dass UEZ dafür eine Funktion hat (wahrscheinlich sogar 5 verschiedene für jeden nur erdenklicken Ctrltyp + GUIs). Habe auch etwas gegoogelt, aber nicht die richtige gefunden (nur eine die das komplette Fenster benutzt um eine .png anzuzeigen). Ich bin leider nicht fit mit Winapi & Sendmessage, sonst würde ich die 3 Zeilen selbst aufschreiben...

    lg

    M

  • ArrayPlus-UDF - weitere Helferlein für den täglichen Umgang mit Arrays

    • Mars
    • 9. Juli 2022 um 17:18

    Vorab: Vielleicht habe ich einfach nicht gesehen, ob diese Funktionalität vorhanden ist. Dann ist dieser Beitrag obsolet.

    Vorallem wenn man mit z.B. Kugelkoordinaten, etc. arbeitet braucht man oft Intervalle (Range) mit inklusiven, oder exklusiven Rändern.

    z.B. Das Intervall [0, 2PI] ist NICHT dasselbe wie (0, 2PI). Dafür verwende ich gerne folgende Funktion:

    AutoIt
    #include-once
    
    If @ScriptName = 'Range.au3' Then __Range_Example()
    
    Func Range($sLeft = '[', $fMin = 0, $fMax = 1, $sRight = ']', $iSteps = 10)
        Local $a[$iSteps], $_[2], $l = $sLeft = '[' ? 0 : 1, $s = ($fMax - $fMin) / ($iSteps - 1 + ($sRight = ']' ? 0 : 1) + $l)
        For $i = 0 To $iSteps - 1 Step 1
            $_[0] = $i
            $_[1] = ($i + $l) * $s + $fMin
            $a[$i] = $_
        Next
        Return $a
    EndFunc
    
    Func __Range_Example()
    
        Local $2PI = 6.28318530717959
    
        ConsoleWrite(@CRLF & 'Intervall = (0, 2PI), Schritte = 9' & @CRLF)
        For $i In Range('(', 0, $2PI, ')', 9)
            ConsoleWrite($i[0] & ' ' & $i[1] & @CRLF)
        Next
    
        ConsoleWrite(@CRLF & 'Intervall = (0, 2PI], Schritte = 9' & @CRLF)
        For $i In Range('(', 0, $2PI, ']', 9)
            ConsoleWrite($i[0] & ' ' & $i[1] & @CRLF)
        Next
    
        ConsoleWrite(@CRLF & 'Intervall = [0, 2PI), Schritte = 9' & @CRLF)
        For $i In Range('[', 0, $2PI, ')', 9)
            ConsoleWrite($i[0] & ' ' & $i[1] & @CRLF)
        Next
    
        ConsoleWrite(@CRLF & 'Intervall = [0, 2PI], Schritte = 9' & @CRLF)
        For $i In Range('[', 0, $2PI, ']', 9)
            ConsoleWrite($i[0] & ' ' & $i[1] & @CRLF)
        Next
    
    EndFunc
    Alles anzeigen

    Das ermöglicht es einen kontinuierlichen Raum disket zu sampeln, während man gleichzeitig auswählen kann welchen Rand die Intervalle haben (Abgeschlossen, oder Offen).

    (Gilt natürlich in dieser Beispielfunktion nur für lineare Räume, wenn man hier eine Funktion anwendet wie x^2, dann stimmt das Sampling nicht mehr, sobald mindestens ein Rand offen ist)

    Das wäre ein Vorschlag für etwas das man hier ergänzen könnte (ich weiß aber nicht wie man das hier geschickt einbaut ohne unnötig viele Parameter zu haben, vielleicht wirklich via String parsing (also "(0, 1)" steht für das beidseitig offene Intervall, "[0, 1]" steht für das beidseitig abgeschlossene Intervall).

    lg

    M

  • AdlibRegister sinnvoll einsetzen

    • Mars
    • 13. Juni 2022 um 15:07

    Ich kann hier nur über meine persönliche Meinung dazu sprechen (mögen andere mich korrigieren).

    Ich halte AdlibRegister für weitestgehend nutzlos. Eine (meiner Meinung nach) bessere Methode sind Funktionen mit Static Timer, da diese an einem Ort ausgeführt werden den "ich" festlege, während AdlibRegister Funktionen "überall" aufgerufen werden können und den Programmablauf damit durcheinanderbringen (außer man hat seine Programmstruktur extra darauf ausgelegt).

    Beispiel:

    AutoIt
    #include <Misc.au3>
    
    FunktionNummerEins(Null, 1000)
    FunktionNummerZwei(Null, 2345)
    
    While Sleep(10) And Not _IsPressed('1B') ; ESC = exit
        FunktionNummerEins(1, 2, 3)
        FunktionNummerZwei(1, 2, 3)
    WEnd
    
    Func FunktionNummerEins($x = 0, $y = 0, $z = 0)
        Local Static $_t = TimerInit(), $_i = 100 ; $_t ist der static timer, $_i ist das Zeitintervall in Millisekunden
        If $x = Null Then $_i = $y ; Hier muss man sich irgendeine Konvention ausdenken um das Intervall einstellen zu können, z.B, wenn Param1 = Null
        If TimerDiff($_t) < $_i Then Return
        $_t = TimerInit()
        ; Hier beginnt die "eigentliche" Funktion
    
        ConsoleWrite('FunktionNummerEins: ['& $_i &'ms] Len(x,y,z) = ' & StringFormat('%.2f', Sqrt($x^2 + $y^2 + $z^2)) & @CRLF)
    
    EndFunc
    
    Func FunktionNummerZwei($x = 0, $y = 0, $z = 0)
        Local Static $_t = TimerInit(), $_i = 100 ; $_t ist der static timer, $_i ist das Zeitintervall in Millisekunden
        If $x = Null Then $_i = $y ; Hier muss man sich irgendeine Konvention ausdenken um das Intervall einstellen zu können
        If TimerDiff($_t) < $_i Then Return
        $_t = TimerInit()
        ; Hier beginnt die "eigentliche" Funktion
    
        ConsoleWrite('FunktionNummerZwei: ['& $_i &'ms] x + y + z = ' & ($x + $y + $z) & @CRLF)
    
    EndFunc
    Alles anzeigen

    Man kann diese Funktionalität auch Wrappen, sodass man z.B. eine Funktion hat die "SetTimer($xFunc, $ms)" hat, usw.

    Wenn du nicht willst, dass der Nutzer davon etwas mitbekommt musst du dafür sorgen, dass die Abfragen einzeln relativ schnell durchlaufen, dann kannst du im Mainloop z.B. immer ein paar Millisekunden zur Verfügung stellen um Abfragen abzuarbeiten. Sind diese Millisekunden aufgebraucht werden die restlichen Abfragen erst im nächsten Schleifendurchlauf angegangen. Sowas lässt sich mittels Queue + Timer regeln (z.B. Alle 5 Sekunden sollen 100 Abfragen gemacht werden, dann werden alle 5 Sekunden die 100 Abfragen in den Queue gesteckt (das geht sehr schnell), und in jedem Schleifendurchlauf werden ?? Millisekunden lang Abfragen bearbeitet bis der Queue leer ist. Da muss man aber aufpassen wenn Abfragen aus welchem Grund auch immer nicht abgearbeitet werden können, dann wird der Queue immer länger und das wollen wir ja nicht).

    lg

    M

  • Diskrete Fouriertransformation (DFT)

    • Mars
    • 10. Juni 2022 um 11:25
    Zitat von AspirinJunkie

    Plottest du das direkt aus AutoIt heraus? Falls ja - wie?

    Da muss ich dich direkt vorwarnen, das folgende ist keine UDF die es in die Öffentlichkeit geschafft hat. Sie ist in keinem guten Zustand und jedes Mal, wenn ich etwas plotten will baue ich genau die funktion die ich gerade brauche ein^^

    AutoIt
    #include-once
    #include <GDIPlus.au3>
    #include <Array.au3>
    
    Global $__AG_OPT_WITH_LINES = True
    Global $__AG_OPT_WITH_POINTS = True
    Global $__AG_OPT_LOGSCALE_Y = False
    
    Global $__AG_XMIN = 0
    Global $__AG_XMAX = 1
    
    Func _ArrayGraph_SetXRange($fMin, $fMax)
        $__AG_XMIN = $fMin
        $__AG_XMAX = $fMax
    EndFunc
    
    ;~ Local $a = [1, 2, 3, 2, 1.5, 6.3, 1, 0, 0, -2, 1.123, 2.345, 3, 2, 1, 2, 3, 5, 4, 3, 2, 1, 0, -1, -2, 5, 4, 3, 2, 1, 9, -2.22, -1, 3, 2.1, 4]
    ;~ ArrayGraph1D($a)
    
    ;~ Local $b = [1000, 1001, 998, 995, 1013.2, 995.5]
    ;~ ArrayGraph1D($b)
    If @ScriptName = 'ArrayGraph1D.au3' Then
        Local $c = CreateCosArray(4 * 8)
        _ArrayGraph($c, '', 0, 0, lin)
    EndIf
    
    
    Func lin($x)
        Return 2 + $x / 3
    EndFunc   ;==>lin
    
    Func CreateCosArray($iSize = 8, $xFunc = _Cos)
        Local $a[$iSize]
        For $i = 0 To $iSize - 1 Step 1
            $a[$i] = $xFunc($i / ($iSize - 1) * 6.28318530717959)
        Next
        Return $a
    EndFunc   ;==>CreateCosArray
    
    Func __Cos($x)
        Return _Cos($x / (4 * 8 - 1) * 6.28318530717959)
    EndFunc   ;==>__Cos
    
    Func _Cos($x)
        Local $a = 1
        Local $b = 2
        Local $c = 3
        Local $d = 1
        Return $a * (Cos($x) + 1) + $b * (Cos(2 * $x) + 1) + $c * (Cos(4 * $x) + 1) + $d * (Cos(8 * $x) + 1)
    EndFunc   ;==>_Cos
    
    Func __AG_ArrayMinMax(ByRef $aArray, $iFrom = 0, $iTo = 0)
        Local $iMax = Null, $iMin = Null
        If $iTo = 0 Then $iTo = UBound($aArray) - 1
        For $i = $iFrom To $iTo Step 1
            If __AG_IsInf($aArray[$i]) Then ContinueLoop
            If $iMin = Null Then $iMin = $aArray[$i]
            If $iMax = Null Then $iMax = $aArray[$i]
            If $aArray[$i] < $iMin Then $iMin = $aArray[$i]
            If $aArray[$i] > $iMax Then $iMax = $aArray[$i]
        Next
        Local $aRet = [$iMin, $iMax]
        Return $aRet
    EndFunc   ;==>__AG_ArrayMinMax
    
    
    Func __AG_FuncMinMax(ByRef $xFunc, $iFrom, $iTo)
        If Not IsFunc($xFunc) Then Return SetError(1, 0, '__Ag_FuncMinMax called, but $xFunc is no function.')
        Local $iMax = Null, $iMin = Null, $x
        For $i = $iFrom To $iTo Step 1
            $x = $__AG_OPT_LOGSCALE_Y ? Log($xFunc($i)) : $xFunc($i)
            If __AG_IsInf($xFunc($i)) Then ContinueLoop
            If $iMin = Null Then $iMin = $x
            If $iMax = Null Then $iMax = $x
            If $x < $iMin Then $iMin = $x
            If $x > $iMax Then $iMax = $x
        Next
        Local $aRet = [$iMin, $iMax]
        Return $aRet
    EndFunc   ;==>__AG_FuncMinMax
    
    Func __AG_IsInf($x)
        Return $x = -1 / 0 Or $x = 1 / 0
    EndFunc   ;==>__AG_IsInf
    
    Func __AG_BeautifyNumber($x)
        If $x > 999.9 Then Return StringTrimRight(StringFormat('%.2e', $x), 4) & StringTrimLeft(StringSplit(StringFormat('%.2e', $x), 'e', 2)[1], 2)
        If $x > 99.99 Then Return StringFormat('%.1f', $x)
        If $x > 9.999 Then Return StringFormat('%.2f', $x)
        If $x > 0.999 Then Return StringFormat('%.3f', $x)
    ;~     ConsoleWrite($x & ' ' & StringFormat('%.2e', $x) & @CRLF)
        Return StringTrimRight(StringFormat('%.2e', $x), 4) & '-' & StringTrimLeft(StringSplit(StringFormat('%.2e', $x), 'e', 2)[1], 2)
    EndFunc   ;==>__AG_BeautifyNumber
    
    Func __AG_PointDistance($x1, $y1, $x2, $y2)
        Return Sqrt(($x1 - $x2) ^ 2 + ($y1 - $y2) ^ 2)
    EndFunc   ;==>__AG_PointDistance
    
    Func Swap(ByRef $x, ByRef $y)
        Local $t = $x
        $x = $y
        $y = $t
    EndFunc   ;==>Swap
    
    Func _ArrayGraph($aArray, $sTitle = Default, $iFrom = 0, $iTo = 0, $xFunc = 0)
    
        If UBound($aArray) = 1 Then Return SetError(1, 0, 'Array contains only 1 element') ; TODO
        If UBound($aArray, 0) <> 1 Then Return SetError(2, 0, 'Array must be 1D')
    
        Local $bFunc = IsFunc($xFunc)
        Local $iUBound = UBound($aArray)
        If $iTo = 0 Then $iTo = $iUBound - 1
        If $iFrom < 0 Then $iFrom = 0
        If $iFrom > $iTo Then Swap($iFrom, $iTo)
    
    
        Local $sOldOpt = __AG_SetMultiOpt('GUIOnEventMode = 0; MouseCoordMode = 2')
    
        Local $iW = 800, $iH = 400
        Local $hGUI = GUICreate((($sTitle = Default) Or (Not $sTitle)) ? ('Array[' & $iUBound & '] Range: [' & $iFrom & ']-[' & $iTo & ']') : $sTitle, $iW, $iH)
        Local $hOldGUI = GUISwitch($hGUI)
    
    
        If $__AG_OPT_LOGSCALE_Y Then
            For $i = $iFrom To $iTo Step 1
                $aArray[$i] = Log($aArray[$i])
            Next
        EndIf
    
        Local $aPositions[$iUBound][2]
    
        _GDIPlus_Startup()
    
        Local $hGFX = _GDIPlus_GraphicsCreateFromHWND($hGUI)
        Local $hBMP = _GDIPlus_BitmapCreateFromGraphics($iW, $iH, $hGFX)
        Local $hBUF = _GDIPlus_ImageGetGraphicsContext($hBMP)
        Local $hBMP_BG = _GDIPlus_BitmapCreateFromGraphics($iW, $iH, $hGFX)
        Local $hBUF_BG = _GDIPlus_ImageGetGraphicsContext($hBMP_BG)
        _GDIPlus_GraphicsSetSmoothingMode($hBUF_BG, 2)
        _GDIPlus_GraphicsSetSmoothingMode($hBUF, 2)
    
        _GDIPlus_GraphicsClear($hBUF_BG, 0xFF383838)
    
        Local $hBRU = _GDIPlus_BrushCreateSolid(0xFF444444)
        Local $hBRU2 = _GDIPlus_BrushCreateSolid(0xFFCC5555)
        Local $hPEN = _GDIPlus_PenCreate(0xFFDDDDDD)
        Local $hPEN2 = _GDIPlus_PenCreate(0xFFFF8888)
    
        Local $aBorder = [90, 35, 10, 40] ; Layout
    
        _GDIPlus_GraphicsDrawRect($hBUF_BG, $aBorder[0], $aBorder[1], $iW - ($aBorder[0] + $aBorder[2]), $iH - ($aBorder[1] + $aBorder[3]), $hPEN)
        _GDIPlus_GraphicsFillRect($hBUF_BG, $aBorder[0], $aBorder[1], $iW - ($aBorder[0] + $aBorder[2]), $iH - ($aBorder[1] + $aBorder[3]), $hBRU)
    
        Local $aRange = __AG_ArrayMinMax($aArray, $iFrom, $iTo)
        Local $aRangeFunc = __AG_FuncMinMax($xFunc, $iFrom, $iTo)
        If $aRange[0] = $aRange[1] Then
            $aRange[0] -= 0.5
            $aRange[1] += 0.5
        EndIf
        If IsArray($aRangeFunc) Then
            If $aRangeFunc[0] = $aRangeFunc[1] Then
                $aRangeFunc[0] -= 0.5
                $aRangeFunc[1] += 0.5
            EndIf
            If $aRange[0] > $aRangeFunc[0] Then $aRange[0] = $aRangeFunc[0]
            If $aRange[1] < $aRangeFunc[1] Then $aRange[1] = $aRangeFunc[1]
        EndIf
    
        ;For $i = $iFrom To $iTo Step 1
        ;    If __AG_IsInf($aArray[$i]) Then $aArray[$i] = $aArray[$i] > 0 ? $aRange[1] : $aRange[0]
        ;Next
    
        Local $iRangeY = $aRange[1] - $aRange[0]
        Local $iDotDiameter = 3.12 ^ (-0.015 * (($iTo - $iFrom) - 136)) + 1.77 ; Wenige Punkte -> Große Punkte, Viele Punkte -> Kleine Punkte
        Local $tmpX, $tmpY, $tmpYFunc
        Local $tRect
    
        Local $hFAM = _GDIPlus_FontFamilyCreate('Arial')
        Local $hFON = _GDIPlus_FontCreate($hFAM, 16, 0, 2)
        Local $hFOR = _GDIPlus_StringFormatCreate()
        _GDIPlus_StringFormatSetLineAlign($hFOR, 1)
        _GDIPlus_StringFormatSetAlign($hFOR, 2)
    
        _GDIPlus_BrushSetSolidColor($hBRU, 0xFFAAAAAA)
        For $y = $aRange[0] To $aRange[1] + 0.0001 Step $iRangeY / 10
            $tmpX = $aBorder[0]
            $tmpY = (1 - ($y - $aRange[0]) / $iRangeY) * ($iH - ($aBorder[1] + $aBorder[3])) + $aBorder[1]
            _GDIPlus_GraphicsDrawLine($hBUF_BG, $tmpX - 5, $tmpY, $tmpX + 5, $tmpY, $hPEN)
            $tRect = _GDIPlus_RectFCreate($tmpX - 5, $tmpY + 1)
            _GDIPlus_GraphicsDrawStringEx($hBUF_BG, __AG_BeautifyNumber($__AG_OPT_LOGSCALE_Y ? Exp($y) : $y), $hFON, $tRect, $hFOR, $hBRU)
        Next
    
        _GDIPlus_StringFormatSetLineAlign($hFOR, 0)
        _GDIPlus_StringFormatSetAlign($hFOR, 1)
        Local $iCountXAxisNumbers = Int(5.85 ^ (-0.0065 * (($iTo - $iFrom) - 280)) + 12.4)
        Local $tmpXOld = -1, $tmpYOld = -1, $iCountPoints = 0, $tmpYOldFunc = -1
        For $x = $iFrom To $iTo Step 1
            $tmpX = ($x - $iFrom) / ($iTo - $iFrom) * ($iW - ($aBorder[0] + $aBorder[2])) + $aBorder[0]
            $tmpY = (1 - ($aArray[$x] - $aRange[0]) / $iRangeY) * ($iH - ($aBorder[1] + $aBorder[3])) + $aBorder[1]
            If $bFunc Then $tmpYFunc = (1 - (($__AG_OPT_LOGSCALE_Y ? Log($xFunc($x)) : $xFunc($x)) - $aRange[0]) / $iRangeY) * ($iH - ($aBorder[1] + $aBorder[3])) + $aBorder[1]
            $aPositions[$x][0] = $tmpX
            $aPositions[$x][1] = $tmpY
            If Not __AG_IsInf($aArray[$x]) Then
                $iCountPoints += 1
                If $__AG_OPT_WITH_LINES Then
                    If $iCountPoints > 1 And $x < $iTo + 1 Then
                        _GDIPlus_GraphicsDrawLine($hBUF_BG, $tmpXOld, $tmpYOld, $tmpX, $tmpY, $hPEN)
                        If $bFunc Then _GDIPlus_GraphicsDrawLine($hBUF_BG, $tmpXOld, $tmpYOldFunc, $tmpX, $tmpYFunc, $hPEN2)
                    EndIf
                    $tmpXOld = $tmpX
                    $tmpYOld = $tmpY
                    If $bFunc Then $tmpYOldFunc = $tmpYFunc
                EndIf
                If $__AG_OPT_WITH_POINTS Then
                    _GDIPlus_GraphicsDrawEllipse($hBUF_BG, $tmpX - $iDotDiameter / 2 - 2, $tmpY - $iDotDiameter / 2 - 2, $iDotDiameter + 4, $iDotDiameter + 4, $hPEN)
                    If $iDotDiameter > 2 Then
                        _GDIPlus_GraphicsFillEllipse($hBUF_BG, $tmpX - $iDotDiameter / 2, $tmpY - $iDotDiameter / 2, $iDotDiameter, $iDotDiameter, $hBRU)
                        If $bFunc Then _GDIPlus_GraphicsFillEllipse($hBUF_BG, $tmpX - $iDotDiameter / 2, $tmpYFunc - $iDotDiameter / 2, $iDotDiameter, $iDotDiameter, $hBRU2)
                    EndIf
                EndIf
            EndIf
            If IsInt($x / Ceiling(($iTo - $iFrom) / $iCountXAxisNumbers)) Then
                _GDIPlus_GraphicsDrawLine($hBUF_BG, $tmpX, $iH - $aBorder[3] + 5, $tmpX, $iH - $aBorder[3] - 5, $hPEN)
                $tRect = _GDIPlus_RectFCreate($tmpX, $iH - $aBorder[3] + 6)
                $tmpStr = Round($x / ($iTo - $iFrom) * ($__AG_XMAX - $__AG_XMIN) + $__AG_XMIN, 2)
                _GDIPlus_GraphicsDrawStringEx($hBUF_BG, $tmpStr, $hFON, $tRect, $hFOR, $hBRU)
            EndIf
        Next
    
        GUISetState(@SW_SHOW)
    
        Local $aPos = MouseGetPos()
        Local $div = ($iTo - $iFrom) / ($iW - ($aBorder[0] + $aBorder[2]))
    
        $tRect = _GDIPlus_RectFCreate(0, 0, $iW, $aBorder[1])
        _GDIPlus_FontDispose($hFON)
        _GDIPlus_FontFamilyDispose($hFAM)
        $hFAM = _GDIPlus_FontFamilyCreate('Consolas')
        $hFON = _GDIPlus_FontCreate($hFAM, Int($aBorder[1] * 0.7), 1, 2)
        _GDIPlus_StringFormatSetLineAlign($hFOR, 1)
    
        _GDIPlus_PenSetColor($hPEN, 0xDDFFFFFF)
    
        Local $rectX, $rectW
    
        While GUIGetMsg() <> -3
            Local $dist0 = 9999, $dist1 = 9999, $dist2 = 9999
            $aPos = MouseGetPos()
            _GDIPlus_GraphicsDrawImageRect($hBUF, $hBMP_BG, 0, 0, $iW, $iH)
            $tmpX = Round(($aPos[0] - $aBorder[0]) / ($iW - ($aBorder[0] + $aBorder[2])) * ($iTo - $iFrom), 0)
            If $tmpX >= 0 And $tmpX <= ($iTo - $iFrom) And $aPos[1] >= 0 And $aPos[1] <= $iH Then
                $tmpX = Abs($tmpX)
                $dist0 = __AG_PointDistance($aPos[0], $aPos[1], $aPositions[$tmpX + $iFrom][0], $aPositions[$tmpX + $iFrom][1])
                If $tmpX > $iFrom Then $dist1 = __AG_PointDistance($aPos[0], $aPos[1], $aPositions[$tmpX + $iFrom - 1][0], $aPositions[$tmpX + $iFrom - 1][1])
                If $tmpX < $iTo Then $dist2 = __AG_PointDistance($aPos[0], $aPos[1], $aPositions[$tmpX + $iFrom + 1][0], $aPositions[$tmpX + $iFrom + 1][1])
                If $dist1 < $dist0 / 3 And $dist1 < $dist2 Then $tmpX -= 1
                If $dist2 < $dist0 / 3 And $dist2 < $dist1 Then $tmpX += 1
                If $tmpX + $iFrom >= UBound($aPositions) Then ContinueLoop
                If $tmpX + $iFrom < 0 Then ContinueLoop
    
                _GDIPlus_BrushSetSolidColor($hBRU, 0x20000000)
                $rectX = ($tmpX - 0.5) / $div + $aBorder[0]
                $rectW = 1 / $div
                If $rectX < $aBorder[0] Then
                    $rectX = $aBorder[0]
                    $rectW /= 2
                EndIf
                If $rectX + $rectW > $iW - $aBorder[2] Then
                    $rectW /= 2
                    $rectX = $iW - $aBorder[2] - $rectW
                EndIf
                _GDIPlus_GraphicsFillRect($hBUF, $rectX, $aBorder[1], $rectW, $iH - ($aBorder[1] + $aBorder[3]), $hBRU)
                _GDIPlus_BrushSetSolidColor($hBRU, 0xDDFFFFFF)
    ;~             ConsoleWrite($tmpX + $iFrom & @CRLF)
                _GDIPlus_GraphicsDrawEllipse($hBUF, $aPositions[$tmpX + $iFrom][0] - $iDotDiameter / 2 - 4, $aPositions[$tmpX + $iFrom][1] - $iDotDiameter / 2 - 4, $iDotDiameter + 8, $iDotDiameter + 8, $hPEN)
                If $iDotDiameter > 2 Then _GDIPlus_GraphicsFillEllipse($hBUF, $aPositions[$tmpX + $iFrom][0] - $iDotDiameter / 2, $aPositions[$tmpX + $iFrom][1] - $iDotDiameter / 2, $iDotDiameter, $iDotDiameter, $hBRU)
                _GDIPlus_BrushSetSolidColor($hBRU, 0xFFDDDDDD)
                _GDIPlus_GraphicsDrawStringEx($hBUF, '[' & ($tmpX + $iFrom) & '] = ' & ($__AG_OPT_LOGSCALE_Y ? Exp($aArray[$tmpX + $iFrom]) : $aArray[$tmpX + $iFrom]), $hFON, $tRect, $hFOR, $hBRU)
            EndIf
            _GDIPlus_GraphicsDrawImageRect($hGFX, $hBMP, 0, 0, $iW, $iH)
        WEnd
    
        _GDIPlus_BrushDispose($hBRU)
        _GDIPlus_BrushDispose($hBRU2)
        _GDIPlus_StringFormatDispose($hFOR)
        _GDIPlus_FontDispose($hFON)
        _GDIPlus_FontFamilyDispose($hFAM)
        _GDIPlus_PenDispose($hPEN)
        _GDIPlus_PenDispose($hPEN2)
        _GDIPlus_GraphicsDispose($hBUF_BG)
        _GDIPlus_BitmapDispose($hBMP_BG)
        _GDIPlus_GraphicsDispose($hBUF)
        _GDIPlus_BitmapDispose($hBMP)
        _GDIPlus_GraphicsDispose($hGFX)
        _GDIPlus_Shutdown()
    
        __AG_SetMultiOpt($sOldOpt)
        GUISwitch($hOldGUI)
        GUIDelete($hGUI)
    
    EndFunc   ;==>_ArrayGraph
    
    Func __AG_SetMultiOpt($sParam)
        Local $aParam = StringSplit(StringStripWS($sParam, 8), ';', 2), $sRet, $aSplit
        For $i = 0 To UBound($aParam) - 1 Step 1
            $aSplit = StringSplit($aParam[$i], '=', 2)
            $sRet &= $aSplit[0] & '=' & Opt($aSplit[0], $aSplit[1]) & ';'
        Next
        Return StringTrimRight($sRet, 1)
    EndFunc   ;==>__AG_SetMultiOpt
    Alles anzeigen

    Die Funktion gibt es eigentlich nur, weil ich im Stil von _ArrayDisplay "schnell und einfach" eine Funktion haben wollte um Arrays anzusehen. Es gibt (auch hier im Forum) UDFs die Daten plotten können, ich schätze, wenn man es ernsthaft angeht sollte man mit so einer UDF eine Anzeige basteln...

    lg

    M

  • Diskrete Fouriertransformation (DFT)

    • Mars
    • 9. Juni 2022 um 15:58

    Was ich in der SB gepostet hatte: https://imgur.com/a/wrzZjAa

    Die Version hier (nach einigen kleinen Anpassungen) funktioniert schonmal deutlich besser. Peaks in den angeschauten Frequenzen sind sauber, deutlich und ohne übertriebenes Überschwingen.

    Inputdaten (mit dem bloßen Auge erkennt man hier höchstens, dass da "irgendwas schnell schwingt", die 2te Schwingung sieht man selbst mit scharfem Blick nicht):

    unnamed.png

    amplitude der DFT (angepasst, sodass man über Frequenzbereiche gezielt drüberlaufen kann, wobei "eine Arraylänge" immer 2PI entspricht)

    (die X-Achse ist etwas doof beschriftet, der erste Peak ist NICHT bei 0.85, sondern tatsächlich etwa bei 1.0, also da wo er hingehört)
    unnamed.png

    Danke nochmal für die Hilfe :thumbup:

    lg

    M

  • Diskrete Fouriertransformation (DFT)

    • Mars
    • 9. Juni 2022 um 13:20

    Achso, ich glaube ich habe den Unterschied zwischen FT und DFT immernoch nicht verstanden.

    Was ich dachte ist folgendes: Die Abtastfrequenz gibt an welche Frequenzen im Array überprüft werden, also dass ich z.B. soetwas wie "alle Frequenzen von 0 bis 5 in 0.1er Schritten" ablaufen kann. Vermutlich ergibt das im Grenzwert wieder eine kontinuierliche FT. Das muss ich wohl nachlesen :/

    Ein Glück, dass ich mit Signalverarbeitung nichts am Hut habe, sonst hätte man mich für so viel Blödheit bestimmt schon verprügelt :part:

    lg

    M

  • Diskrete Fouriertransformation (DFT)

    • Mars
    • 9. Juni 2022 um 12:47

    Vielen Dank, jetzt wo ich die Lösung sehe, sehe ich auch meine Fehler :D

    Mit der Abtastfrequenz kann aber etwas nicht stimmen (glaube ich). Die taucht im Code nur bei "$aRet[$k][$eFrequency] = $k * $nFs / $N" auf, hat aber keinen Einfluss auf die anderen Werte (oder ich habe da etwas missverstanden, was auch gut sein kann).

    lg

    M

  • Internet-Kommunikation - Nervige PopUp-Fenster

    • Mars
    • 30. Mai 2022 um 16:34

    Eine Idee:

    Es gibt ja einige CSS/JS Tricks mit denen man das Erscheinungsbild nahezu jeder Webseite ändern kann (Stylish, Greasemonkey, CSS-Injector, etc. Es gibt hunderte Wege nach Rom). Damit habe ich ausprobiert die Cookiepopups einfach garnicht erst anzeigen zu lassen, das ging nicht so gut wie erwartet... Einige Webseiten führen nach Betätigung des Popups ein Skript aus um die Webseite freizuschalten, wenn man das Popup garnicht erst bekommt bleibt die Seite unbenutzbar.

    Soweit ich weiß ist es laut Gesetz verpflichtend, dass der Nutzer zustimmt BEVOR die Cookies benutzt werden dürfen. Wenn man also eine Möglichkeit findet die Popups zu killen und gleichzeitig die Webseite zu aktivieren, hätte man es geschafft. Vermutlich ist das via CSS + JS (das Popup ist in der Lage die Webseite freizuschalten, mit JS muss das Clientseitig dementsprechend auch gehen) möglich. Vermutlich muss man für jeden Popuptyp/jede Webseite ein eigenes Skript und eigenes CSS basteln (und das auch häufig aktualisieren, die wollen ja deine Daten, also ändern die andauernd irgendwelche Kleinigkeiten).

    Da mein Wissen im Bereich HTML und CSS aber nur ganz knapp über NULL ist, habe ich nach 30 Minuten im Inspektor (Firefoxtool um Webseitencode einzusehen) aufgegeben. Jemand der sich hier auskennt sollte das aber hinbekommen.

    Edit: uBlock Origin hat einen Filter für Cookie-Banner unter Einstellungen -> Filterlisten -> Belästigungen -> "EasyList Cookie". Ob das hilft weiß ich nicht, hab es mal aktiviert und lasse mich überraschen.

    Edit2: Das Addon "idontcareaboutcookies" nimmt scheinbar automatisch alle cookies an. Ich verstehe nicht wieso dieses Addon so populär und gleichzeitig so fehlgeleitet sein kann.

    lg

    M

  • Häufigkeitsverteilung

    • Mars
    • 30. April 2022 um 18:12

    Eine "nicht sicherere" Methode um Text zu verschlüsseln habe ich irgendwann auch mal gebastelt. Der Code ist sogar Kommentiert, da hatte ich wohl zu viel Freizeit :rofl:

    Prinzip ist:

    1. Starte einen RNG (hier XORShift) und generiere damit ein "one time pad" (eigentlich ist es ja keins, weil die Zahlen nicht "zufällig" sind)

    2. Modifiziere den RNG andauernd mit einzelnen Buchstaben aus dem PW, sodass jedes PW ein einzigartiges OTP erzeugt.

    2.5. Lasse das OTP (+Modifikationen) noch ein paar mal durch den RNG laufen damit sich einzelne Änderungen (z.B. nur 1 Buchstabe im PW) besser auf das gesamte OTP verteilen.

    3. XOR mit dem OTP

    Vorteile:

    - Extrem einfach.

    - Vorallem in anderen Programmiersprachen unfassbar schnell (es sind hier nur Shift, XOR und Additionen im inner Loop)

    - Da XORShift ziemlich gleichverteilt läuft sind auch die verschlüsselten Strings ziemlich gleichverteilt.

    - Das Verfahren ist zum ver- und entschlüsseln identisch.

    Nachteile:

    - Jeder mit 5 Minuten Ahnung im Bereich Programmierung kann die Verschlüsselung knacken.

    - In AutoIt nicht so schnell, als dass man damit größere Dateien verschlüsseln kann.

    AutoIt
    #include-once
    
    #include <Array.au3>
    
    If @ScriptName = 'StringXorWithPW.au3' Then
        Local $sString = 'Ich Bin ein Test, hier könnte im Prinzip nahezu alles stehen. Ich schreibe hier einfach etwas lustiges hin :)' & @CRLF & _
        'Noch eine Zeile, damit der Text länger wird. So lob ich mir das. ABC die Katze läuft im Schnee.'
        Local $sPW = 'Hi' ; Das ist das Passwort
        Local $_ = StringCount($sString)
        _ArrayDisplay($_)
        Local $sEncrypted = StringXorWithPW($sString, $sPW)
        Local $_ = StringCount(BinaryToString($sEncrypted))
        _ArrayDisplay($_)
        ConsoleWrite($sEncrypted & @CRLF)
        Local $sDecrypted = BinaryToString(StringXorWithPW($sEncrypted, $sPW))
        ConsoleWrite($sDecrypted & @CRLF)
    EndIf
    
    Func StringCount($s)
        Local $a[256][2]
        For $i = 1 To StringLen($s) Step 1
            $a[Asc(StringMid($s, $i, 1))][0] = Asc(StringMid($s, $i, 1))
            $a[Asc(StringMid($s, $i, 1))][1] += 1
        Next
        _ArraySort($a, 1, 0, 0, 1)
        For $i = 0 To UBound($a) - 1 Step 1
            If Not $a[$i][0] Then ExitLoop
        Next
        ReDim $a[$i][2]
        Return $a
    EndFunc
    
    Func StringXorWithPW($sString, $sPW, $bReturnStruct = False)
        Local $iLen = IsBinary($sString) ? BinaryLen($sString) : StringLen($sString), $vStr = DllStructCreate('byte[' & $iLen & ']')
        DllStructSetData($vStr, 1, IsBinary($sString) ? BinaryToString($sString) : $sString)
        Local $vOtp = StringToOneTimePad($sPW, $iLen, True)
        For $i = 1 To $iLen Step 1
            DllStructSetData($vStr, 1, BitXOR(DllStructGetData($vStr, 1, $i), DllStructGetData($vOtp, 1, $i)), $i)
        Next
        Return $bReturnStruct ? $vStr : DllStructGetData($vStr, 1)
    EndFunc
    
    Func StringToOneTimePad($sPW, $iLen, $bReturnStruct = False)
        Local $vOtp = DllStructCreate('byte[' & $iLen & ']') ; Wir arbeiten in einer Struct.
        If StringLen($sPW) > $iLen Then ; Falls das Passwort länger als das zu generierende OTP ist.
            Local $a = StringToOneTimePad(StringLeft($sPW, StringLen($sPW) / 2), $iLen, True)
            Local $b = StringToOneTimePad(StringRight($sPW, StringLen($sPW) / 2), $iLen, True)
            For $i = 1 To $iLen Step 1 ; ein OTP in voller länger für beide Hälften des PW Ausrechnen -> XOR -> Fertig.
                DllStructSetData($vOtp, 1, BitXOR(DllStructGetData($a, 1, $i), DllStructGetData($b, 1, $i)), $i)
            Next ; Da Rekursiv werden automatisch alle Variationen abgefangen (z.B. wenn das PW nach 1 Rekursion immernoch zu kurz ist)
        Else
            While StringLen($sPW) < $iLen ; Erstmal die Struct komplett auffüllen.
                $sPW &= $sPW ; Hier ist das OTP noch ziemlich schwach weil einfach nur das PW wiederholt wird.
            WEnd
            DllStructSetData($vOtp, 1, StringLeft($sPW, $iLen))
            Local $z = 314159265 + StringLen($sPW) + $iLen ; Irgendeine Magic Number um XorShift zu starten
            ; Idee:
            ; Nutze XorShift um Pseudozufallszahlen zu generieren (ja ich weiß die sind nicht besonders "sicher").
            ; Modifiziere den Inneren Zustand in jedem Schritt mit einem Teil des Passworts.
            ; Nimm irgendeinen Teil des Zustands als Output (z.B. BitAND(BitShift($z, 7), 0xFF))
            ; Arbeite Inplace und laufe 2+ Mal die komplette Struct ab.
            ; Grund dafür ist, dass eine Änderung am PW (z.B. die letze Stelle wurde geändert) erstmal nur
            ; den Output beeinflusst der nach dem erstmaligen Auftreten dieser Stelle berechnet wird. Läuft
            ; man aber 2+ Runden und nimmt den Inneren Zustand mit, so wird der gesamte Output vom gesamten Input beeinflusst.
            For $e = 0 To 2 Step 1 ; 2 Runden (Editors note: 0, 1, 2 -> also 3 Runden... :D)
                For $i = 1 To $iLen Step 1
                    $z = BitXOR($z, BitShift($z, -13), DllStructGetData($vOtp, 1, $i)) ; Hier werden die Low8 Bit mit dem String geXORt.
                    $z = BitXOR($z, BitShift($z, 17))
                    $z = BitXOR($z, BitShift($z, 5))
                    DllStructSetData($vOtp, 1, BitAND(BitShift($z, 7), 0xFF), $i) ; Das shr7 ist ausgedacht. Hier kann jede Zahl stehen.
                Next
            Next
        EndIf
        Return $bReturnStruct ? $vOtp : DllStructGetData($vOtp, 1)
    EndFunc
    Alles anzeigen

    lg

    M

  • Der Stumpfsinn der Gewohnheit - oder - Weil man das immer so macht.

    • Mars
    • 28. April 2022 um 17:10
    Zitat von Velted

    Aber warum sollte das so einfach sein? :Face:

    Das musst du nicht uns fragen, sondern die Jungs im EN-Forum :D

    [rant] Wenn man die vielen Ideen (um AutoIt zu verbessern) aus dem Forum mal alle sammeln und auflisten würde, hätte man sicherlich locker 3 Seiten "Stichpunkte" (1Idee/Zeile). Mein aktueller Favorit ist ByRef im selben Scope, also z.B. Local $a = Byref $b, wenn ich $a ändere, ändert sich auch $b und umgekehrt. Das geht aktuell nur via ByRef im Funktionsaufruf. Benutzen könnte man das um verschachtelte Arrays effizient zu handhaben, LinkedLists (oder quasi "alle" Datenstrukturen die Pointer verwenden) zu basteln, etc. etc. Mal gucken was nächstes Jahr mein Favorit bei "missing features" ist^^ [/rant]

    M

  • Merkwürdige Meßergebnisse mit _Timer_Init() und _Timer_Diff()

    • Mars
    • 24. April 2022 um 00:28

    4 Hinweise:

    1. AutoIt führt Zeilen beim ersten Mal etwas langsamer aus (außer das wurde inzwischen geändert). Das heißt wenn du eine Funktion das erste Mal aufrufst ist sie langsamer als alle weiteren Male. Was dich eigentlich interessiert ist die durchschnittliche Geschwindigkeit mit der die Funktion läuft, und nicht die Zeit die sie beim ersten Mal braucht.

    2. Je nachdem was dein PC gerade macht (der macht immer irgendetwas, z.B. Windows laufen lassen, Festplatte lesen, etc.) läuft AutoIt manchmal sehr unterschiedlich schnell (es "ruckelt" dann im Interpreter). Einzelne Messergebnisse sind also nicht aussagekräftig.

    3. (klingt komisch, ist aber so): Die Reihenfolge in der Code aufgerufen wird bewirkt einen kleinen Geschwindigkeitsunterschied (manchmal vernachlässigbar klein, manchmal größer, ich habe leider kein Beispiel, das ist nur eine Beobachtung von mir als ich ziemlich viele Funktionen auf Geschwindigkeit überprüft habe).

    4. Seit Windows 10 Update XYZ (ich weiß nicht welches) ist das ausführen von PostMessageA extrem verlangsamt (wird Intern im Interpreter verwendet). Der Interpreter wird langsamer, falls vorher schonmal ein Windows-Fenster erzeugt wurde (z.B. ArrayDisplay, MsgBox, etc). Das wurde zwar in AutoIt "gefixt" (indem nur noch alle X Interpreterschritte PostMessageA aufgerufen wird), hat aber trotzdem eine kleine Auswirkung. Daher: Verwende beim Zeitmessen niemals irgendwelche Fenster als Ausgabe, sondern lieber die Konsole.

    Am Besten ist es, wenn du beide Funktionen in zufälliger Reihenfolge aufrufst und die Messwerte z.B. in ein Array mit N Einträgen einträgst. Der Median davon entspricht in etwa dem durchschnittlichen Messwert. (Median deshalb, damit Ausreißer abgefangen werden, ein einfacher Mittelwert kann durch einen einzigen "ruckler" komplett kaputtgemacht werden).

    PS: Ich habe das Skript nicht getestet, sondern nur kurz angeschaut.

    lg

    M

  • Klartext 2 AHL_Codiert

    • Mars
    • 3. April 2022 um 01:11

    Bei einer Verschlüsselung kommt es darauf an, dass der verschlüsselte Text gleichverteiltem Rauschen entspricht (je weniger der Text von Rauschen unterscheidbar ist, desto schwieriger ist es Muster zu erkennen). Außerdem ist wichtig, dass sich das entstehende Rauschen nicht ähnelt, selbst wenn man im Passwort nur ein Bit dreht. Ich bin kein Experte auf dem Gebiet, aber ich glaube eine Verteilung wo die allermeisten Zeichen nur 1x vorkommen ist nicht mehr "gleichverteilt" (in einer Gleichverteilung kommt es ja statistisch zu vielen Abweichungen, Wenn du 6x würfelst bekommst du ziemlich wahrscheinlich nicht 1, 2, 3, 4, 5, 6 heraus, sondern irgendwelche Zahlen doppelt oder sogar dreifach, und das waren jetzt nur 6 Würfe und nicht wie bei ca. 100) und daher vermutlich ungeeignet für "gute" Verschlüsselung.

    Aber ich kenne mich da nicht gut aus, da weiß jemand anderes bestimmt mehr^^

  • [Wettbewerb] String komprimieren

    • Mars
    • 1. April 2022 um 14:02

    Andy war wahrscheinlich verhindert, vielleicht kommt von ihm später noch etwas :)

    Code
    Mein Skript funktioniert wie folgt (falls der Spaghetticode keinen Sinn ergibt, hier die Zusammenfassung):
    - 1. Erzeuge ein Histogramm des gesamten Strings (256 Slots)
    - 2. Komprimiere das Histogramm bestmöglich
        - 1. Speichere MinIndex und MaxIndex (z.B. 20 und 150) jeweils als 8 Bit, betrachte ab jetzt nur noch den relevanten Teil.
        - 2. Quantisiere auf 2 Bit (0 = Zeichen Existiert, 1 = Kleiner Wert, 2, Mittlerer Wert, 3 = Großer Wert, Empirisch bestimmt)
        - 3. Speichere das Histogramm Layerweise:
        ; | MinIndex                                                                                                       MaxIndex |
        ; 100100000000000000000011100100110011111111111111110000011111111111111111111111101101000111111111111111111111111110000000001
        ; 1  1                  100  0  00  1010100000000000     000000000000000000000000 00 0   11111111101111100111111001         0
        ; 0  0                  1           0 0 0                                                100110011 01010  111100  0
        ;                       1                                                                0  01  01  0 1   1000
        - In Layer 0 steht also immer eine 1 für: "Zeichen existiert"
        - In Layer 1 steht eine 1 für alle Zeichen die einen kleinen Wert haben
        - usw. Im Endeffekt kann man so eine 2Bit Kodierung benutzen, und insgesamt nur wenige Bits dafür verbrauchen.
            Das sieht beim Beispiel hier ggf. nutzlos aus (zu dicht), wenn man aber 100 aufeinanderfolgende Nullen betrachtet ergibt das Sinn.
        - 4. Benutze eine Lauflängenkodierung. Aus dem 01-String werden jetzt RLE-Tokens (also sowas wie 0 0 1 5 100 4 1)
        - Die Wahrscheinlichkeiten (nicht normiert) der Tokens entsprechen in etwa p(Index) = 14.7/((x+0.344)^0.94), empirisch bestimmt.
        - 5. Benutze einen Huffmantree (aus den oben gegebenen Wahrscheinlichkeiten) um die RLE-Tokens zu encodieren.
        - 6. Setze die Anzahl Tokens binär kodiert an den Anfang (das braucht der Decoder später)
        - Jetzt hat man eine (grobe) Wahrscheinlichkeitstabelle mit ca. 100 Einträgen in 200 Bit.
        - Im Nachhinein betrachtet hätte man vermutlich direkt eine RLE nutzen können und wäre damit besser bedient...
    - 3. Erzeuge basierend auf dem (groben) Historgramm einen HuffmanTree
    - 4. Für jedes Symbol:
        - 1. Hole eine Prediction über das nächste Symbol ein (Top15 Liste in meinem Fall wo auch die Konfidenz angegeben wird)
            - z.B. "C": 15, "A": 5, " ": 2 (das würde sagen: "C" ist am Wahrscheinlichsten, dann kommt A und dann das Leerzeichen)
        - 2. Booste das Histogramm (temporär) mit den Werten aus dem Predictor.
        - 3. Baue einen Huffmantree aus dem Histogramm
        - 4. Kodiere EIN Symbol
        - 5. Füge das kodierte Symbol zum Histogramm und zum Predictor hinzu (damit beide wissen was dekodiert wurde)
    - 5. Return = Gesamte Stringlänge (braucht man für die Steuerung) & Komprimiertes Historgramm vom Anfang & Eigentliche Daten
    Alles anzeigen

    Der Trick an der Sache war bei mir das Finetuning (was aber eigentlich auch Informationen über den zu Komprimierenden Inhalt braucht, also die eingestellten Parameter funktionieren gut für deutschen Text, aber vermutlich nicht so gut für andere Sachen).

    z.B. Wie stark wird das Histogramm geboostet? (1 Parameter)

    z.B. Wird der boost im Verlauf der Kodierung stärker oder schwäche (1 Parameter)

    z.B. Wie arbeitet der Predictor intern? (2 Parameter (lässt sich zusammenfassen als Verhältnis))

    z.B. Wie stark wird das Histogramm aktualisiert nachdem dein Zeichen dekodiert wurde? (1 Parameter)

    Ich habe insgesamt 4 Magic Numbers die alle für gewisse Einstellungen verantwortlich sind. Die kann man auch so einstellen, dass der Text 5% schlechter Komprimiert wird und genaugenommen müsste ich diese Werte (die man quasi bruteforcen muss) mit in den kodierten String stecken was nochmal ca. 40 Bit braucht. Da ich aber ohnehin schon so knapp an den 50% war wollte ich das einfach nicht machen... Wenn man das berücksichtigt bin ich quasi gleichauf mit AspirinJunkie (nur noch ein paar Bytes besser), wobei sein Skript 50x schneller ist :D

Spenden

Jeder Euro hilft uns, Euch zu helfen.

Download

AutoIt Tutorial
AutoIt Buch
Onlinehilfe
AutoIt Entwickler
  1. Datenschutzerklärung
  2. Impressum
  3. Shoutbox-Archiv
Community-Software: WoltLab Suite™