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

  • AutoIt-Hackathon #3 "alte Zeiten"

    • Mars
    • 11. Mai 2025 um 21:06
    AutoIt
    ; ================================= entferne alle Leer- und Kommentarzeilen und poste diesen Code-Block im Thread ==================================
    Func _IntegerToRoman($sInteger)
    	Local $Return
    	Local Static $M[], $K
    	If Not UBound($M) Then
    		$M[1] = 'I'
    		$M[5] = 'V'
    		$M[10] = 'X'
    		$M[50] = 'L'
    		$M[100] = 'C'
    		$M[500] = 'D'
    		$M[1000] = 'M'
    		$K = MapKeys($M)
    	EndIf
    	For $r = UBound($K) - 1 To 0 Step -1
    		While $sInteger >= $K[$r]
    			$Return &= $M[$K[$r]]
    			$sInteger -= $K[$r]
    		WEnd
    	Next
    	$Return = StringReplace($Return, 'IIII', 'IV')
    	$Return = StringReplace($Return, 'VIV' , 'IX')
    	$Return = StringReplace($Return, 'XXXX', 'XL')
    	$Return = StringReplace($Return, 'LXL' , 'XC')
    	$Return = StringReplace($Return, 'CCCC', 'CD')
    	$Return = StringReplace($Return, 'DCD' , 'CM')
    	Return $Return
    EndFunc   ;==>_IntegerToRoman
    Func _RomanToInteger($sRoman)
    	Local $Return
    	Local Static $M[], $K
    	If Not UBound($M) Then
    		$M['I'] = 1
    		$M['V'] = 5
    		$M['X'] = 10
    		$M['L'] = 50
    		$M['C'] = 100
    		$M['D'] = 500
    		$M['M'] = 1000
    		$K = MapKeys($M)
    	EndIf
    	$sRoman = StringReplace($sRoman, 'CM', 'DCD', 0, 1)
    	$sRoman = StringReplace($sRoman, 'CD', 'CCCC', 0, 1)
    	$sRoman = StringReplace($sRoman, 'XC', 'LXL', 0, 1)
    	$sRoman = StringReplace($sRoman, 'XL', 'XXXX', 0, 1)
    	$sRoman = StringReplace($sRoman, 'IX', 'VIV', 0, 1)
    	$sRoman = StringReplace($sRoman, 'IV', 'IIII', 0, 1)
    	For $c In StringSplit($sRoman, '', 2)
    		$Return += $M[$c]
    	Next
    	Return $Return
    EndFunc   ;==>_RomanToInteger
    
    ; Bonus-Aufgabe für Ambitionierte ;-)
    Func _DateToRoman($sDate) ;Input date in the format "YYYY/MM/DD[ HH:MM:SS]", Output in same date-format with roman sign
    	;If Not StringInStr($sDate, ' ', 0, 1) Then Return '' ; Das hier ist ein Joke. Natürlich muss diese Zeile weg :)
    	Local $Return, $aDate = StringSplit(StringReplace(StringReplace($sDate, ' ', ':', 0, 1), '/', ':', 0, 1), ':', 2)
    	For $i = 0 To UBound($aDate) - 1 Step 1
    		$Return &= _IntegerToRoman($aDate[$i]) & ($i < UBound($aDate) - 1 ? ($i < 2 ? '/' : $i = 2 ? ' ' : ':') : '')
    	Next
    	Return $Return
    EndFunc   ;==>_DateToRoman
    ; ================================= entferne alle Leer- und Kommentarzeilen und poste diesen Code-Block im Thread ==================================
    Alles anzeigen
  • AutoIt Hackathon #1 Mitarbeiter-ID abgeschlossen

    • Mars
    • 30. März 2025 um 21:44

    Das passiert, wenn man <Array.au3> nach _Check() included.

  • AutoIt Hackathon #1 Mitarbeiter-ID abgeschlossen

    • Mars
    • 30. März 2025 um 21:22

    Hinweis: Das ist die Lösung für die heruntergeladene Datei (die nur 14 Zeichen erfordert).

    AutoIt
    Func _CreateID($aUserdata)
    	Local $Return
    	$Return = StringLeft($aUserdata[2] & '99999', 5)
    	$Return &= StringLeft(StringRight(StringSplit($aUserdata[3], '.', 2)[2], 2), 1)
    	$Return &= StringRight('0' & StringSplit($aUserdata[3], '.', 2)[1] + 50 * ($aUserdata[4] = 'W'), 2)
    	$Return &= StringSplit($aUserdata[3], '.', 2)[0]
    	$Return &= StringRight(StringSplit($aUserdata[3], '.', 2)[2], 1)
    	$Return &= StringLeft($aUserdata[0], 1) & ($aUserdata[1] ? StringLeft($aUserdata[1], 1) : '9')
    	Local $q = 0, $a = StringSplit($Return, '', 2)
    	For $i = 0 To UBound($a) - 1 Step 1
    		$a[$i] = Asc($a[$i])
    	Next
    	While UBound($a) > 1
    		For $i = 0 To UBound($a) - 1 Step 1
    			$q += $a[$i]
    		Next
    		$a = StringSplit($q, '', 2)
    		$q = 0
    	WEnd
    	$Return &= $a[0]
    	Return $Return
    EndFunc
    Alles anzeigen
  • PackedIntegers (miniudf)

    • Mars
    • 2. März 2025 um 14:59

    Moin,

    das folgende ist eine mini UDF um Integerzahlen zusammenzupacken. Die Rechnung ist analog zur Umrechnung zwischen "Uhrzeit und Sekunden", sodass genau dieser Spezialfall auch als Beispiel im Code enthalten ist. Eine Einschränkung ist leider, dass AutoIt intern maximal uint63 unterstützt (also eigentlich int64). Mit einer BigInt-UDF (die es ja gibt, ich wollte aber keine Abhängigkeiten hier) könnte man also "sehr viel mehr" Zahlen zusammenfassen.

    Mein persönlicher Anwendungsfall ist (mal wieder) irgendwo einzelne Bits beim Speichern von Daten mit bekannten Intervallen herauszuholen. Ob es dafür andere (sinnvolle) Anwendungsfälle gibt weiß ich leider nicht. ^^

    Falls Fehler auftauchen, bitte hier melden. Ich habe die Sache nur kurz getestet und bin froh korrigiert zu werden.

    AutoIt: PackedIntegers.au3
    __PI_Test()
    
    Func __PI_Test()
    	; Uhrzeit Beispiel (Hier spart man keine Bits. Schade)
    	Local $structure = [[0,23],[0,59],[0,59]]
    	Local $values = [1, 30, 15]
    
    	; Uhrzeit Beispiel mit Tag und Millisekunden (1 Bit gespart)
    ;~ 	Local $structure = [[1,365],[0,23],[0,59],[0,59],[0,999]]
    ;~ 	Local $values = [234, 1, 30, 15, 789]
    
    	; Anderes Beispiel (2 Bit gespart)
    ;~ 	Local $structure = [[0, 3], [7, 16], [1000, 1500], [55, 88], [0, 2], [0, 1]]
    ;~ 	Local $values = [3, 16, 1500, 88, 1, 1]
    
    	; Klassenarbeitsergebnisse von 24 Personen (9 Bit gespart, ist aber auch absichtlich ein Extremfall)
    ;~ 	Local $structure = [[1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6], [1, 6]]
    ;~ 	Local $values = [1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6]
    
    	Local $packed = _PI_Create($structure)
    	_PI_SetValue($packed, $values) ; Set all values (can set single ones too via ($packed, $i, $iValue)
    	Local $iInt = _PI_GetInt($packed) ; Das ist der resultierende uint
    	_PI_Debug($packed) ; Nochmal reinschauen
    	ConsoleWrite(@CRLF)
    
    	Local $otherPacked = _PI_Create($structure)
    	_PI_SetInt($otherPacked, $iInt) ; Alle einzelnen Zahlen aus dem uint laden.
    	_PI_Debug($otherPacked)
    
    	Local $values = _PI_GetValue($otherPacked)
    	For $i = 0 To UBound($values) - 1 Step 1
    		ConsoleWrite(($i = 0 ? 'Values as array: [' : '') & $values[$i] & ($i < UBound($values) - 1 ? ', ' : ']' & @CRLF))
    	Next
    
    EndFunc
    
    ; e.g. $structure = [[0, 3], [7, 16], [1000, 1500], [55, 88]]
    ; -> 4 Integers
    ; -> 1st can be 0, 1, 2 or 3. Ränder inklusive!
    Func _PI_Create($aStructure)
    	Local $x[], $_[]
    	For $i = 0 To UBound($aStructure) - 1 Step 1
    		$x[$i] = $_
    		$x[$i][0] = $aStructure[$i][0]
    		$x[$i][1] = $aStructure[$i][1]
    		$x[$i][2] = 0 ; Default = min value
    	Next
    	Return $x
    EndFunc
    
    ; Output the contents + bonus info
    Func _PI_Debug($x)
    	Local $iSumBits = 0, $iSumBitsNaive = 0, $iValue, $iRange, $iMaxIntLen = 0, $sPadding = '                '
    	For $i = 0 To UBound($x) - 1 Step 1
    		$iValue = $x[$i][0] + $x[$i][2]
    		If StringLen($x[$i][0]) > $iMaxIntLen Then $iMaxIntLen = StringLen($x[$i][0])
    		If StringLen($x[$i][1]) > $iMaxIntLen Then $iMaxIntLen = StringLen($x[$i][1])
    		If StringLen($iValue) > $iMaxIntLen Then $iMaxIntLen = StringLen($iValue)
    	Next
    	ConsoleWrite('Debug packed integers in $x[' & UBound($x) & '][2]' & @CRLF)
    	For $i = 0 To UBound($x) - 1 Step 1
    		$iValue = $x[$i][0] + $x[$i][2]
    		$iRange = $x[$i][1] - $x[$i][0] + 1
    		ConsoleWrite('[' & StringRight($sPadding & $x[$i][0], $iMaxIntLen) & ', ' & StringRight($sPadding & $x[$i][1], $iMaxIntLen) & '] (Bit: ' & StringFormat('%5.2f', (Log($iRange) / Log(2))) & _
    		') -> $x[' & $i & '][2] = ' & StringRight($sPadding & $iValue, $iMaxIntLen) & ' (raw: ' & StringRight($sPadding & $x[$i][2], $iMaxIntLen) & ')' & @CRLF)
    		$iSumBits += Log($iRange) / Log(2)
    		$iSumBitsNaive += Ceiling(Log($iRange) / Log(2))
    	Next
    	ConsoleWrite('Overall bits needed: ' & StringFormat('%.2f', $iSumBits) & ' (' & Ceiling($iSumBits) & ' instead of '&$iSumBitsNaive&') for Integer ' & _PI_GetInt($x) & @CRLF)
    EndFunc
    
    ; set a value with _PI_SetValue($x, $i, $iValue), where $i is the index and $iValue is the value
    ; set all values with _PI_SetValue($x, $i), where $i = Array of values [1, 2, 3, ...]
    Func _PI_SetValue(ByRef $x, $i, $iValue = 0)
    	If IsArray($i) Then
    		If UBound($i) <> UBound($x) Then Return SetError(1, 0, 0 * ConsoleWrite('Num Values ('&UBound($i)&') does not match the size of $x (' & UBound($x) & ')' & @CRLF))
    		For $j = 0 To UBound($i) - 1 Step 1
    			_PI_SetValue($x, $j, $i[$j])
    		Next
    		Return
    	EndIf
    	If $iValue < $x[$i][0] Or $iValue > $x[$i][1] Then Return SetError(1, 0, 0 * ConsoleWrite('Value "'&$iValue&'" is outside the allowed range [' & $x[$i][0] & ', ' & $x[$i][1] & ']' & @CRLF))
    	If Not IsInt($iValue) Then SetError(2, 0, 0 * ConsoleWrite('Value "'&$iValue&'" is no integer but "'&VarGetType($iValue)&'"' & @CRLF))
    	$x[$i][2] = $iValue - $x[$i][0]
    EndFunc
    
    ; get a value with _PI_GetValue($x, $i), where $i is the index
    ; get all values with _PI_GetValue($x)
    Func _PI_GetValue(ByRef $x, $i = -1)
    	If $i = -1 Then
    		Local $aRet[UBound($x)]
    		For $j = 0 To UBound($x) - 1 Step 1
    			$aRet[$j] = _PI_GetValue($x, $j)
    		Next
    		Return $aRet
    	EndIf
    	Return $x[$i][0] + $x[$i][2]
    EndFunc
    
    ; get the uint value
    Func _PI_GetInt(ByRef $x)
    	Local $iInt = 0, $mul = 1
    	For $i = UBound($x) - 1 To 0 Step -1
    		$iInt += $x[$i][2] * $mul
    		$mul *= $x[$i][1] - $x[$i][0] + 1
    	Next
    	Return $iInt
    EndFunc
    
    ; set the uint value. This automatically sets all internal values
    Func _PI_SetInt(ByRef $x, $iInt)
    	Local $prefixMul[], $mul = 1
    	For $i = UBound($x) - 1 To 1 Step -1
    		$mul *= $x[$i][1] - $x[$i][0] + 1
    		$prefixMul[$i - 1] = $mul
    	Next
    	For $i = 0 To UBound($prefixMul) - 1 Step 1
    		$x[$i][2] = Int($iInt / $prefixMul[$i])
    		$iInt -= $x[$i][2] * $prefixMul[$i]
    	Next
    	$x[$i][2] = $iInt
    EndFunc
    Alles anzeigen

    lg

    M

  • Code Kata - Christmas Tree

    • Mars
    • 19. Dezember 2024 um 17:39
    Zitat von chesstiger

    Wer online testen möchte: https://gc.de/gc/brainfuck/

    Hat mich jetzt knappe 3 Stunden gekostet, das zu entwerfen. ^^

    Das erste Element auf dem Stack ist nebenbei die gesamte Baumhöhe. Heißt kurz gesagt, für jedes + was man der Baumspitze hinzufügt, wird der generierte Baum eine Ebene höher.

    Hat er nicht gemacht.... Das ist ja der Wahnsinn :D

  • Code Kata - Christmas Tree

    • Mars
    • 17. Dezember 2024 um 14:53

    Die Idee mit der Animation ist gar nicht mal so schlecht. Hoffentlich vergesse ich das nicht bis nächstes Jahr ^^

  • Code Kata - Christmas Tree

    • Mars
    • 16. Dezember 2024 um 22:31

    Neues Jahr, neuer Weihnachtsbaum!

    (Entspricht nicht den Vorgaben, aber ich wollte einfach Basteln)

    AutoIt
    P(15)
    
    Func P($h, $_ = Default)
    	If $_ <> Default Then
    		If $_ > 0 Then
    			Local $1 = $h = '.' ? '' : $h, $a = ['.', '.', ' ', '*', 'O'], $o = False
    			For $i = 0 To $_ - 2 Step 1
    				$h &= $1 ? $1 : $a[Random(0, UBound($a)-1-(StringInStr($h, 'O', 0, 1)?1:0), 1)]
    			Next
    			Return $h
    		Else
    			Return ''
    		EndIf
    	EndIf
    	Local $w = Int($h / 2) * 2 + 1, $r = 1, $s = '', $l = False, $k, $p
    	For $y = 0 To $h - 1 Step 1
    		$s &= ($y = 0 ? (P(' ', Int($w / 2 + 1)) & '*') : ($y < $h - 1) ? (P(' ', Int(($w - $r)/2) - 0) & '/' & P('.', $r) & '\') : ((($p/2 < $r/2 ? ' ' : '') & P('^', $p/2) & '[_]' & P('^', $p/2)))) & @CRLF
    		If Not ($y < $h - 1 And $y > 0) Then ContinueLoop
    		$p = $r
    		$k = ($h - $y - 2) > (($w - $r) / 2) And Not $l
    		$l = $k ? Random() > 0.5 : False
    		$r += $k ? (Not ($l And $y > 2) ? ((Random() > 0.5 ? 2 : ($r < $w / 2 ? 2 : ($y > 3 ? -2 : 2)))) : 0) : 2
    		$r = $r - 2 * ($r > $w)
    	Next
    	ConsoleWrite($s & @CRLF)
    EndFunc
    Alles anzeigen

    lg

    M

  • Persönliche Weiterbildung bzgl. IT, Programmierung und Co.

    • Mars
    • 23. Oktober 2024 um 19:28

    1. Meine Weiterbildung erfolgt meistens privat durch "irgendwelche Sachen die ich sehe" und durch "herumbasteln". Das macht sich natürlich auf dem Papier nicht gut, daher bekomme ich alle Halbjahr irgendeine Weiterbildung gesponsort (ist immer Themenbezogen).

    Trends sind mir persönlich vollkommen egal, ich mache was ich für richtig halte. Da ich aktuell am C++ lernen bin (bzw. es seit ~5 Jahren aktiv nutze, aber man lernt ja nie aus), will ich das erst "perfektionieren" bevor irgendwas anderes um die Ecke kommt. Sowas wie z.B. Rust gefällt mir überhaupt nicht, da es sich anfühlt als würde man mit angezogener Handbremse programmieren. Den "Mit Rust konnte ich meine alten Projekte 3x so schnell neu implementieren" Bias halte ich ebenfalls für lächerlich. Ja, wenn ich ein altes Projekt erneut programmiere, dann bin ich 3x so schnell, selbst wenn ich die Sprache nicht wechsele. Aber gut, das ist Ansichtssache. Jeder soll machen was er für richtig hält.

    2. Ich habe noch keine dollen Papers geschrieben, bin aber gerade dabei. Das scheint wohl gern gesehen zu sein, und da ich soweiso eine Quatschtüte bin ist das kein Problem auch mal ein paar "ordentliche" Sachen zu schreiben. Insgesamt halte ich aber das publizieren für gnadenlos überbewertet. Ja, es ist wichtig neuen Kram für die Welt zugänglich aufzuschreiben, sodass sich das Wissen verbreiten kann. Finde den Fehler im vorherigen Satz. "Für die Welt zugänglich", war der Fehler, da alles was ich "ordentlich" schreibe hinter einer Paywall landen wird (außer auf den sieben Weltmeeren, die ich in diesem Bezug tatsächlich empfehlen kann).
    Wenn es nach mir ginge, gäbe es ein weltweites community moderiertes "Wissenschafts Wikipedia" bei dem eben nur Profs bzw. "Leute aus der Forschung an einer Bildungs/Forschungseinrichtung" Schreibrechte, aber jeder auf der ganzen Welt Leserechte besitzt. Möchte man etwas veröffentlichen muss man sich an jemanden vom Fach wenden. Damit wird direkt 90% Unfug (der sich auch in aktuellen Veröffentlichungen wiederfindet) herausgefiltert. Außerdem kann man "in diesem Wiki" eine Analyse machen ob das eigene Thema dort schon vorhanden ist. (Such mal 50 Journals/Konferenzen weltweit über die letzten 50 Jahre nach etwas durch was du erfunden/gefunden hast. Viel Spaß. Die Wahrscheinlichkeit ist 95%, dass du es nicht findest, selbst wenn es schonmal irgendwo aufgetaucht ist. Vielleicht falsche Keywords? Vielleicht falsche Sprache? etc.). Falls ja (Thema existiert bereits), dann bekommt man schreibrechte für den dazugehörigen Artikel für eventuelle Ergänzungen, falls nein (Thema ist neu bzw. transformativ), dann bekommt man einen eigenen Artikel. Ein super Nebeneffekt sind "Verlinkungen" die es zwar auch jetzt schon gibt [Mar24], mit der unfassbar altertümlichen Methode ([...] verweist auf einen Text der im Anhang steht, den ich googeln muss um das dazugehörige Paper zu finden was ich dann lesen muss um herauszufinden welche Stelle überhaupt zitiert wurde) bin ich aber auf Kriegsfuß. Wie schön wäre es, wenn ich [Mar24] anklicke und in einer Sekunde bin ich im richtigen Artikel in der richtigen Zeile um nachzulesen wo etwas herkommt... Das wird es leider niemals geben, zumindest nicht mehr in meiner Lebenszeit.

    Aber gut, damit kann niemand Geld verdienen, und Wissen wäre ein Grundrecht. So eine Welt haben wir halt nicht.

    Over and Out :D

    M

  • Select Cas in einem Intervall

    • Mars
    • 18. September 2024 um 12:21

    Es bringt halt leider auch Granaten wie das Folgende:

    Halbe Seite Text

    Dauert also noch etwas bis wir ersetzt werden :D

    (Bei der Frage habe ich implizit gehofft, dass mein Thread aus dem PU-Bereich gelesen wurde. Da ist ein Beispiel wie man die Pointer von (Globalen) AutoIt-Variablen durch ein paar Tricks herausbekommen kann)

    lg

    M

  • Select Cas in einem Intervall

    • Mars
    • 18. September 2024 um 11:49

    Einfach aus Jux habe ich die Frage mal in die KI gefüttert, und siehe da, der Code ist technisch gesehen korrigiert worden.

    Irgendwann werden wir als Supporter überflüssig, es ist nur noch eine Frage der Zeit :)

    Edit: Habe noch nachgefragt, ob man an dem Code noch etwas ändern könnte, und tatsächlich, das zweimalige Verwenden von "left" wurde als potenzieller Fehler markiert.

    lg

    M

  • Ungefähre Funktionswerte Puffern

    • Mars
    • 1. Juli 2024 um 22:31

    Moin,

    wer kennt es nicht. Man hat eine Funktion die irgendetwas stochastisch berechnet (Monte-Carlo) und relativ lange braucht.

    Diese Funktion möchte man aber im Idealfall "oft" aufrufen (ggf. in einer anderen Funktion, die ebenfalls stochastisch arbeitet, usw usw). Im Endeffekt resultiert das in Abermillionen von Funktionsaufrufen, die sehr schnell sehr viel Zeit in Anspruch nehmen.

    Aber es gibt Abhilfe: Ein sich selbst füllender Puffer der Funktionswerte an einigen Stützstellen speichert und dann linear interpoliert (mit Unsicherheitsangabe).

    Vermutlich habe ich darin noch ein Paar Bugs versteckt, aber für meine bisherigen Anwendungsfälle hat es funktioniert, daher gibts jetzt ne "mini-UDF". Wie bei allen Methoden ist es wichtig "sinnvolle" Parameter zu wählen, ansonsten läuft sich der Algorithmus tot (mit Failsave -> MaxIter) oder produziert vollkommen falsche Ergebnisse (z.B. wenn man nur 10 Stützstellen verwendet, obwohl man eigentlich mindestens 100 braucht, oder wenn man eine Genauigkeit von 0.01 haben möchte, obwohl die Funktionswerte die Größenordnung 100 und eine große Streuung haben). Was die Ungenauigkeitsangabe im Returnwert angeht möchte ich meine Hand nicht ins Feuer legen. Da sich der Mittelwert ja mit jedem neuen Sample ändert und die vorherigen Varianzen nicht angepasst werden können (man will ja nicht "alles" speichern) ist dieser Wert nur "ungefähr richtig".

    Die Verwendung ist glaube ich intuitiv ersichtlich wenn man das Beispiel anschaut. FFB heißt "FuzzyFunctionBuffer"

    AutoIt
    Global Const $__FFB_MIN_SAMPLES = 17
    
    ; Beispielfunktion mit langer Rechenzeit die "nicht genau" arbeitet:
    ; Stochastisches abschätzen vom Volumen einer Kugel mir Radius $r
    Func myFunc($r)
    	Local Const $k = 1000
    	Local $n = 0, $r2 = $r ^ 2
    	For $i = 0 To $k - 1 Step 1
    		$n += Random(-$r, $r) ^ 2 + Random(-$r, $r) ^ 2 + Random(-$r, $r) ^ 2 < $r2
    	Next
    	Return $n / $k * (2 * $r) ^ 3
    EndFunc   ;==>myFunc
    
    ; Naiver Ansatz:
    ; Einfach Mittelwert bilden über N Versuche (hier mit N = 100)
    ; Probleme:
    ; - Wie genau ist das denn jetzt?
    ; - Wenn ich die Funktionswerte mehrfach brauche muss ich mich selbst um das Puffern kümmern.
    ; - Wenn ich "ähnliche" Funktionswerte brauche muss die Funktion komplett neu ausgewertet werden.
    Local $t = TimerInit()
    For $i = 80 To 90 Step 1
    	Local $v = 0
    	For $j = 0 To 99 Step 1
    		$v += myFunc($i / 100)
    	Next
    	$v /= 100
    	ConsoleWrite('r = ' & StringFormat('% 5.3f', $i / 100) & ' -> Vol = ' & StringFormat('% 6.4f', $v) & ' err = ' & StringFormat('% 6.4f', $v-4/3*(($i/100)^3)*3.141592654) & @CRLF)
    Next
    ConsoleWrite('Time: ' & TimerDiff($t) & @CRLF)
    ConsoleWrite(@CRLF)
    
    ;~ ; Ansatz mit Lookup-Table & linearer Interpolation
    Local $FFB = _FFB_Create1D(myFunc, 0, 5, 100)
    Local $t = TimerInit()
    For $i = 80 To 90 Step 1
    	Local $v = _FFB_Call1D($FFB, $i / 100, 0.01)
    	ConsoleWrite('r = ' & StringFormat('% 5.3f', $i / 100) & ' -> Vol = ' & StringFormat('% 6.4f +- % 6.4f', $v[0], $v[1]) & ' err = ' & StringFormat('% 6.4f', $v[0] - 4 / 3 * (($i / 100) ^ 3) * 3.141592654) & @CRLF)
    Next
    ConsoleWrite('Time: ' & TimerDiff($t) & @CRLF)
    ConsoleWrite(@CRLF)
    
    ; Der Trick ist jetzt, dass der LUT jetzt aufgebaut ist. Braucht man die Funktionswerte erneut ist das relativ schnell
    ; Auch für Funktionswerte die nicht "exakt" da liegen wo man schonmal gesampled hat. Je mehr sich der LUT füllt, desto schneller wird er.
    Local $t = TimerInit()
    For $i = 80 To 90 Step 1
    	Local $x = $i / 100 + Random(-0.05, 0.05)
    	Local $v = _FFB_Call1D($FFB, $x, 0.01)
    	ConsoleWrite('r = ' & StringFormat('% 5.3f', $x) & ' -> Vol = ' & StringFormat('% 6.4f +- % 6.4f', $v[0], $v[1]) & ' err = ' & StringFormat('% 6.4f', $v[0] - 4 / 3 * ($x ^ 3) * 3.141592654) & @CRLF)
    Next
    ConsoleWrite('Time: ' & TimerDiff($t) & @CRLF)
    ConsoleWrite(@CRLF)
    
    Func _FFB_Call1D(ByRef $FFB, $x, $nAccuracy = 0.01, $iIterMax = 100)
    	Local $iSteps = UBound($FFB) - 1
    	Local $k = ($x - $FFB[$iSteps][1]) / $FFB[$iSteps][2] * ($iSteps - 1)
    	Local $i = Int($k), $ix = ($i / ($iSteps - 1) * $FFB[$iSteps][2] + $FFB[$iSteps][1]) ; Unterer Slot
    	Local $j = $i + 1, $jx = ($j / ($iSteps - 1) * $FFB[$iSteps][2] + $FFB[$iSteps][1]) ; Oberer Slot
    	Local $alpha = $k - $i ; $alpha = Prozentsatz vom darüberliegenden Slot
    	Local $f = $FFB[$iSteps][0], $v = 0, $t = 0
    
    	If $i >= 0 And $i < $iSteps Then
    		If $FFB[$i][2] < $__FFB_MIN_SAMPLES Then
    			Local $p[]
    			For $_ = 0 To $__FFB_MIN_SAMPLES - 1 Step 1
    				$p[$_] = $f($ix)
    				$FFB[$i][0] += $p[$_]
    			Next
    			$FFB[$i][0] /= $__FFB_MIN_SAMPLES
    			For $_ = 0 To $__FFB_MIN_SAMPLES - 1 Step 1
    				$FFB[$i][1] += ($p[$_] - $FFB[$i][0]) ^ 2
    			Next
    			$FFB[$i][2] = $__FFB_MIN_SAMPLES
    		EndIf
    		$t = 0
    		While Sqrt($FFB[$i][1]) / ($FFB[$i][2] - 1) > $nAccuracy
    			$v = $f($ix)
    			$FFB[$i][0] = ($FFB[$i][0] * $FFB[$i][2] + $v) / ($FFB[$i][2] + 1)
    			$FFB[$i][1] += ($v - $FFB[$i][0]) ^ 2
    			$FFB[$i][2] += 1
    			$t += 1
    			If $t >= $iIterMax Then ExitLoop
    		WEnd
    	EndIf
    
    	If $j >= 0 And $j < $iSteps Then
    		If $FFB[$j][2] < $__FFB_MIN_SAMPLES Then
    			Local $p[]
    			For $_ = 0 To $__FFB_MIN_SAMPLES - 1 Step 1
    				$p[$_] = $f($jx)
    				$FFB[$j][0] += $p[$_]
    			Next
    			$FFB[$j][0] /= $__FFB_MIN_SAMPLES
    			For $_ = 0 To $__FFB_MIN_SAMPLES - 1 Step 1
    				$FFB[$j][1] += ($p[$_] - $FFB[$j][0]) ^ 2
    			Next
    			$FFB[$j][2] = $__FFB_MIN_SAMPLES
    		EndIf
    		$t = 0
    		While Sqrt($FFB[$j][1]) / ($FFB[$j][2] - 1) > $nAccuracy
    			$v = $f($jx)
    			$FFB[$j][0] = ($FFB[$j][0] * $FFB[$j][2] + $v) / ($FFB[$j][2] + 1)
    			$FFB[$j][1] += ($v - $FFB[$j][0]) ^ 2
    			$FFB[$j][2] += 1
    			$t += 1
    			If $t >= $iIterMax Then ExitLoop
    		WEnd
    	EndIf
    
    	Local $Ret[]
    	If Abs($alpha) < 1E-3 Then
    		$Ret[0] = $FFB[$i][0]
    		$Ret[1] = Sqrt($FFB[$i][1] / ($FFB[$i][2] - 1))
    	ElseIf Abs($alpha - 1) < 1E-3 Then
    		$Ret[0] = $FFB[$j][0]
    		$Ret[1] = Sqrt($FFB[$j][1] / ($FFB[$j][2] - 1))
    	Else
    		$Ret[0] = $FFB[$i][0] * (1 - $alpha) + $FFB[$j][0] * $alpha
    		$Ret[1] = (Sqrt($FFB[$i][1]) / ($FFB[$i][2] - 1)) * (1 - $alpha) + (Sqrt($FFB[$j][1]) / ($FFB[$j][2] - 1)) * $alpha
    	EndIf
    
    	Return $Ret ; [0] = Wert, [1] = Unsicherheit
    
    EndFunc   ;==>_FFB_Call1D
    
    Func _FFB_Create1D($xFunc, $fMinInclusive = 0, $fMaxInclusive = 1, $iSteps = 100)
    	Local $_[$iSteps + 1][3]
    	$_[$iSteps][0] = $xFunc
    	$_[$iSteps][1] = $fMinInclusive
    	$_[$iSteps][2] = $fMaxInclusive - $fMinInclusive
    	; [0] = Mittelwert
    	; [1] = VarianzSumme
    	; [2] = NumSamples
    	Return $_
    EndFunc   ;==>_FFB_Create1D
    Alles anzeigen


    Edit: Hier noch eine Überarbeitung mit quadratischer Interpolation (so kann man den LUT etwas kleiner wählen, oder man möchte eine sehr weiche Kurve. Die gab es bei der linearen Version nicht).

    AutoIt
    #include <Array.au3>
    
    Global Const $__FFB_MIN_SAMPLES = 17
    Global Const $__FFB_NUM_MAXITER = 100
    
    ; Anwendungsfall: Funktionswerte entstören
    Func myFunc($r)
    	Return Sin($r) + Random() / 3 ; sin ist im Bereich -1 bis 1, mit 1/3 plusminus rauschen ist das schon ziemlich viel.
    EndFunc   ;==>myFunc
    
    Local $FFB = _FFB_Create1D(myFunc, -10, 10, 100) ; Hat 100 Slots zwischen -10 und 10
    For $i In __FFB_Range('[', -3.141, 3.141, ']', 200) ; Die 200 Samples brauchen nur ca. 33 Slots. Durch die quadratische Interpolation kommt trotzdem eine gute Kurve heraus.
    	Local $v = _FFB_Call1D($FFB, $i[1], 0.0005, 1e9, 100000) ; Wenn man es wirklich ganz genau haben will. (0.0005 Sigma, da will man schon 3 richtige Nachkommastellen haben)
    	ConsoleWrite(StringFormat('% 5.3f', $i[1]) & ', ' & StringFormat('% 6.4f', $v[0])  & @CRLF)
    Next
    _ArrayDisplay($FFB) ; Nachschauen was im LUT eigentlich drin steht.
    
    Func _FFB_Train1D(ByRef $FFB, $nAbsAccuracy = 1e9, $nRelAccuracy = 1e9)
    	Local $iSteps = UBound($FFB) - 1
    	Local $fMin = $FFB[$iSteps][1]
    	Local $fMax = $FFB[$iSteps][2] + $FFB[$iSteps][1]
    	Local $bTargetMet = True, $v = 0
    	Do
    		$bTargetMet = True
    		For $i In __FFB_Range('[', $fMin, $fMax, ']', $iSteps)
    			$v = _FFB_Call1D($FFB, $i[1], $nAbsAccuracy, $nRelAccuracy)
    			If $v[1] > $nAbsAccuracy Then $bTargetMet = False
    			If $v[0] > 1E-9 And $v[1] / $v[0] > $nRelAccuracy Then $bTargetMet = False
    		Next
    	Until $bTargetMet
    EndFunc   ;==>_FFB_Train1D
    
    Func _FFB_Call1D(ByRef $FFB, $x, $nAbsAccuracy = 1e9, $nRelAccuracy = 1e9, $iIterMax = $__FFB_NUM_MAXITER, $bQuadraticInterpolation = True)
    	Local $iSteps = UBound($FFB) - 1, $s5 = $iSteps - 5, $s5d = $s5 / $FFB[$iSteps][2]
    	Local $k = ($x - $FFB[$iSteps][1]) * $s5d + 2, $ik = Int($k) ; Slots: [ik-1, ik, ik+1, ik+2] <- diese 4 sind immer vorhanden.
    	Local $alpha = $k - $ik ; $alpha = Prozentsatz vom darüberliegenden Slot
    	Local $f = $FFB[$iSteps][0], $v = 0, $t = 0
    	For $i = $ik - 1 To $ik + 2 Step 1 ; from -1 to 2 -> Für 4 Slots.
    		Local $ix = ($i - 2) / $s5d + $FFB[$iSteps][1]
    		If $FFB[$i][2] < $__FFB_MIN_SAMPLES Then
    			Local $p[]
    			For $_ = 0 To $__FFB_MIN_SAMPLES - 1 Step 1
    				$p[$_] = $f($ix)
    				$FFB[$i][0] += $p[$_]
    			Next
    			$FFB[$i][0] /= $__FFB_MIN_SAMPLES
    			For $_ = 0 To $__FFB_MIN_SAMPLES - 1 Step 1
    				$FFB[$i][1] += ($p[$_] - $FFB[$i][0]) ^ 2
    			Next
    			$FFB[$i][2] = $__FFB_MIN_SAMPLES
    		EndIf
    		$t = 0
    		While Sqrt($FFB[$i][1]) / ($FFB[$i][2] - 1) > $nAbsAccuracy Or ($FFB[$i][0] > 1E-9 And Sqrt($FFB[$i][1]) / ($FFB[$i][2] - 1) / $FFB[$i][0] > $nRelAccuracy)
    			$v = $f($ix)
    			$FFB[$i][0] = ($FFB[$i][0] * $FFB[$i][2] + $v) / ($FFB[$i][2] + 1)
    			$FFB[$i][1] += ($v - $FFB[$i][0]) ^ 2
    			$FFB[$i][2] += 1
    			$t += 1
    			If $t >= $iIterMax Then ExitLoop
    		WEnd
    	Next
    	Local $Ret[]
    	If $bQuadraticInterpolation Then
    		Local $ixa = ($ik - 3) / $s5d + $FFB[$iSteps][1], $ixb = ($ik - 2) / $s5d + $FFB[$iSteps][1], $ixc = ($ik - 1) / $s5d + $FFB[$iSteps][1], $ixd = $ik / $s5d + $FFB[$iSteps][1]
    		Local $P3L = __FFB_Func3P($ixa, $FFB[$ik - 1][0], $ixb, $FFB[$ik - 0][0], $ixc, $FFB[$ik + 1][0])
    		Local $P3H = __FFB_Func3P($ixb, $FFB[$ik - 0][0], $ixc, $FFB[$ik + 1][0], $ixd, $FFB[$ik + 2][0])
    		$Ret[0] = ($P3L[0] * $x^2 + $P3L[1] * $x + $P3L[2]) * (1 - $alpha) + ($P3H[0] * $x^2 + $P3H[1] * $x + $P3H[2]) * $alpha
    	Else
    		$Ret[0] = $FFB[$ik][0] * (1 - $alpha) + $FFB[$ik + 1][0] * $alpha
    	EndIf
    	$Ret[1] = (Sqrt($FFB[$ik][1]) / ($FFB[$ik][2] - 1)) * (1 - $alpha) + (Sqrt($FFB[$ik + 1][1]) / ($FFB[$ik + 1][2] - 1)) * $alpha
    	Return $Ret ; [0] = Wert, [1] = Unsicherheit
    EndFunc   ;==>_FFB_Call1D
    
    Func _FFB_Create1D($xFunc, $fMinInclusive = 0, $fMaxInclusive = 1, $iSteps = 100, $nBorderEpsilon = 1E-6)
    	$fMinInclusive -= $nBorderEpsilon
    	$fMaxInclusive += $nBorderEpsilon
    	Local $_[$iSteps + 1][3]
    	$_[$iSteps][0] = $xFunc
    	$_[$iSteps][1] = $fMinInclusive
    	$_[$iSteps][2] = $fMaxInclusive - $fMinInclusive
    	; [i][0] = Mittelwert
    	; [i][1] = VarianzSumme
    	; [i][2] = NumSamples
    	Return $_
    EndFunc   ;==>_FFB_Create1D
    
    Func __FFB_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   ;==>__FFB_Range
    
    Func __FFB_Func2P($x0, $y0, $x1, $y1)
    	Local $_[] ; f(x) = ax + b
    	$_[0] = ($y1 - $y0) / ($x1 - $x0)
    	$_[1] = $y0 - $_[0] * $x0
    	Return $_
    EndFunc
    
    Func __FFB_Func3P($x0, $y0, $x1, $y1, $x2, $y2)
    	Local $_[] ; f(x) = ax² + bx + c
    	$_[0] = ($x2 * ($y1 - $y0) + $x1 * ($y0 - $y2) + $x0 * ($y2 - $y1)) / (($x0 - $x1) * ($x0 - $x2) * ($x1 - $x2)) ; a
    	$_[1] = (($y1 - $y0) + $_[0] * ($x0 ^ 2 - $x1 ^ 2)) / ($x1 - $x0) ; b
    	$_[2] = $y0 - $_[0] * $x0 ^ 2 - $_[1] * $x0 ; c
    	Return $_
    EndFunc
    Alles anzeigen


    lg

    M

  • RAM-Typ auslesen

    • Mars
    • 25. Juni 2024 um 17:12
    Zitat von water

    In der deutschen Übersetzung fälschlich "Blitz"

    Jedes Mal, wenn ich auf der MS Seite etwas nachschlage und diese furchtbaren deutschen Übersetzungen (teilweise von Naturkonstanten wie "BLACKNESS" beim BitBlt) sehe, klicke ich "diese Seite war nicht hilfreich" an und schreibe in den Kommentar rein, dass sämtliche Wörter die mit Programmcode zu tun haben bitte nicht übersetzt werden sollen. Ich hab schon Tabellen mit Enums gesehen die man von Start bis Ende in die Tonne treten konnte weil fast alle Bezeichnungen falsch waren X/

    Ist denen aber egal. Wenn ich nicht 90% der Namen von Sachen die ich dort suche schonmal gehört hätte wäre ich echt sauer, aus genanntem Grund bin ich nur "genervt" von sowas...

    M

  • [GDI+] Kurve zeichnen (3 Methoden)

    • Mars
    • 4. Juni 2024 um 15:45

    Moin,

    wer kennt es nicht: Ich möchte eine Funktion f(t) -> (x(t),y(t)) zeichnen und wähle einfach 100 gleichverteilte Punkte in t um das zu tun. Das Ergebnis sieht mies aus. Ich wähle 200 Punkte. Immernoch mies. 1000 vielleicht? Okay, jetzt sieht es OK aus, aber weil meine Kurve irgendwo ein paar fiese Kanten & Peaks hat ist das Ergebnis immernoch nicht Pixelgenau... Also 10000 Punkte?

    Anbei ist ein Skript mit 3 Methoden um eine Kurve zu zeichnen.

    1. Linear (das was oben beschrieben wurde, 1 f(t) call pro Punkt)

    2. Adaptiv (Zunächst mit niedriger Auflösung Linear, dann "schätzen" wo gute Orte für weitere Punkte sind, 1 f(t) call pro Punkt)

    3. Adaptiv2 (Es wird mehr oder weniger via BruteForce herausgefunden wo gute Orte für weitere Punkte sind, "viele" f(t) calls pro Punkt)

    Es sei angemerkt, dass nicht jede Funktion für jeden Anwendungsfall sinnvoll ist. 1 & 2 eignen sich für Echtzeitanwendungen (sie brauchen für ~100 Punkte nur ein paar Millisekunden, je nach PC). 3 ist dafür geeignet wenn man die Funktion mit den wenigst möglichen Punkten "nahezu" bestmöglich abbilden will und die benötigte Zeit keine Rolle spielt (z.B. wenn man die Punkte irgendwo puffert, dann muss man sie nur 1x berechnen und kann sie anschließend relativ performant anzeigen, weil es so wenige sind).

    Die Geschwindigkeit ist leider ziemlich mies, da ich an einigen Stellen faul war (z.B. lineare Liniensuche statt Newton, etc.). Außerdem fehlen mir gewisse Datenstrukturen in AutoIt die ich, mangels Pointersupport, auch nicht nachbauen konnte (bzw. ich war einfach zu faul alles via DllStruct zu machen).

    PS: Jede Funktion f(x) = ... lässt sich als f(x) = (x, y(x)) umschreiben, wie auch im Beispiel verwendet. Man muss also nicht zwingend f:R->R² Funktionen verwenden :)


    Edit: Um zu demonstrieren, dass es auch mit "echten" R² Funktionen klappt kann man z.B. sowas hier verwenden:

    Code
    Func F($t)
    	Local $__[]
    	$__[0] = $t * $iGuiW * 0.9 + $iGuiW * 0.05
    	$__[1] = 50 * ManyGauss($t * 100 - 60) + 100*(2*$t-1)^2
    	Local $a = 0.1, $cx = $iGuiW / 2, $cy = 0
    	Local $_[]
    	$_[0] = $cx + ($__[0] - $cx) * Cos($a) - ($__[1] - $cy) * Sin($a)
    	$_[1] = $cy + ($__[0] - $cx) * Sin($a) + ($__[1] - $cy) * Cos($a)
    	Return $_
    EndFunc

    Eine gewöhnliche f(x) -> R Funktion könnte soetwas nicht abbilden, da einige x-Werte mehrere y-Werte besitzen. Fälle die in diesem Skript "nicht" abgedeckt sind, sind unstetige Funktionen. Falls es irgendwo einen "echten" Sprung in der Funktion gibt (z.B. Funktionen die aus mehreren Teilen bestehen die in einem Plot zu mehreren Linien führen), kann die hier gezeigte Methode nicht verwendet werden.


    lg

    M

    Dateien

    AdaptiveDiscretization.au3 14,53 kB – 210 Downloads
  • Zeitreihe Regressionsanalyse Trendberechnung

    • Mars
    • 30. Mai 2024 um 22:47

    Meine Frage wäre: Was möchtest du konkret aus den Daten herauslesen?
    Soweit ich das verstehe sind die Daten wie folgt: Eintrag1 = [#Artikelnummer1 #Ankaufszahl1 #Verkaufszahl1, #DatumBzwZeitraum1, #WeitereInfos1], ... usw. für tausende Produkte und verschiedene Zeitpunkte/Zeiträume.

    Eine übliche Methode um ein Gefühl für Große Datenmengen zu bekommen ist erstmal die Ansicht verschiedener Scatterplots/Heatmaps (z.B. x-Achse = Datum, y-Achse = Verkaufszahl, Fabcode = Produkttyp. Hier muss man einiges an Kombinationen durchprobieren). Darin ergeben sich dann eindeutige Muster (je nachdem wie man den Plot parametrisiert), die man anschließend weiter auswerten kann.

    Bin aber nicht sicher, ob dir hier AutoIt weiterhelfen kann... Also einen Scatterplot kann man schnell und einfach basteln, aber das kann z.B. Gnuplot ebenfalls (ganz ohne Programmieraufwand). Die "Analyse" wird sich bei AutoIt auch auf lineare Regression einzelner Plotabschnitte beschränken (siehe oben), der Informationsgewinn hält sich dabei aber in Grenzen. Den Trend erkennt man ja schon am Plot.

    Edit: Falls du Trends extrapolieren willst wird es auch eher knifflig und ich vermute da bist du bei Machine-Learning-Leuten besser aufgehoben. Die kennen sich mit Voodoo aus :D

    lg
    M

  • _ConsoleWriteMap

    • Mars
    • 21. Mai 2024 um 12:32

    Sieht fast genauso aus wie etwas das ich immer verwende um Maps in die Konsole zu verfrachten :D

    Falls gemischte Keys (Integer-Keys & String-Keys) verwendet werden ist hier noch eine kleine Ergänzung:

    $sOut &= StringFormat('%s%-20s%s%s\n', $aC[$n], (IsString($k) And StringIsInt($k)) ? '"' & $k & '"' : $k, $vValue).

    Damit sieht man eindeutig womit man es zu tun hat.

    lg

    M

  • Rollende Kugel mit Textur

    • Mars
    • 18. Mai 2024 um 11:21

    Das ist ein super Beispiel. Hier wird Die Kugel einfach "Scheibchenweise" mit einer linearen Matrix gezeichnet, sodass insgesamt der Eindruck entsteht man hätte es irgendwie nichtlinear gelöst. Dafür muss man aber ein Sleep(100) einbauen und $iStep = 15 setzen, sonst sieht man das nicht weil es zu schnell und zu fein aufgelöst ist :D

  • Rollende Kugel mit Textur

    • Mars
    • 18. Mai 2024 um 01:58

    Sehr interessant. Hier noch eine Idee: Finde eine Transformation um die Einzelpixelrechnung komplett aus dem Spiel zu nehmen.

    Der Texturabdruck dieser Formel ist auch nicht ganz richtig für eine "korrekte" perspektivische Projektion einer Ebene auf eine Kugeloberfläche (Das Abbild ist eine um 45° gedrehte Raute). Da ich hier kein Profi bin ist Folgendes nur eine Vermutung: Die 3x2 Matrizen aus GDI+ werden hierfür wahrscheinlich nicht reichen, weil sie die Verzerrung nicht abbilden können. Dafür müsste man dann doch wieder nichtlineare Elemente einbringen die GDI+ nicht abbilden kann sodass man sie doch von Hand ausrechnen muss... Ist wahrscheinlich im Endeffekt kein Vorteil, aber ganz kurz dachte ich "vielleicht reicht die GDI+ übliche Matrix ja doch". Bin da kein Profi, von daher: Vielleicht bringt die Idee ja irgendwen weiter :D

    Den Texturfootprint kann man mit folgendem Skript einsehen:

    AutoIt
    #include <GDIPlus.au3>
    #include <GUIConstantsEx.au3>
    
    OnAutoItExitRegister(_exit)
    Opt("GUIOnEventMode", 1)
    
    Global Const $PI = ACos(-1), $PI_2 = ASin(1), $PI_4 = ATan(1), $_2PI = $PI + $PI
    
    main()
    
    
    
    Func main()
    	Local $mC = _b3d_createCanvas(1000, 750)
    
    	; start moving textured ball
    	Local $mTexture = _b3d_importTexture(@ScriptDir & "\13h_310x156.bmp")
    	_b3d_ballMoving($mC, 50, 1000/2, 750/2, 0, 0, $mTexture)
    
    	; GUI endless loop
    	While Sleep(100)
    	WEnd
    
    EndFunc
    
    ; demo function for drawing a moving ball
    Func _b3d_ballMoving(ByRef $mCanvas, Const $iRadius, Const $iXStart, Const $iYStart, $fVx, $fVy, $mTexture, Const $fRotX0 = 0, Const $fRotY0 = 0)
    	Local $iXPos = $iXStart, $iYPos = $iYStart
    	Local $fRotX = $fRotX0, $fRotY = $fRotY0
    	Local $fU = 2 * $PI * $iRadius
    
    	Local $hBitmap = _GDIPlus_BitmapCreateFromFile(@ScriptDir & "\13h_310x156.bmp")
    	Local $aSize = _GDIPlus_ImageGetDimension($hBitmap)
    	Local $hCopy = _GDIPlus_BitmapCloneArea($hBitmap, 0, 0, $aSize[0], $aSize[1])
    	Local $hGFX = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    	Local $i = 0
    	Local $hPEN = _GDIPlus_PenCreate(0xFF808080, 3)
    	Do
    		$fVx = Sin($i/30)
    		$fVy = Cos($i/30)
    		$i += 1
    		; clear old image
    		_GDIPlus_GraphicsClear($mCanvas.Context, 0xFF303030)
    
    		_GDIPlus_GraphicsDrawImageRect($hGFX, $hCopy, 0, 0, $aSize[0], $aSize[1])
    
    		; draw textured sphere
    		_b3d_drawTexturedSphere($mCanvas, $iXPos, $iYPos, $iRadius, $mTexture, $fRotX, $fRotY, $hBitmap)
    
    		_GDIPlus_GraphicsDrawImage($mCanvas.Context, $hBitmap, 10, 550)
    
    
    		_b3d_canvasShow($mCanvas)
    
    		$iXPos += $fVx
    		$iYPos += $fVy
    		$fRotX += __b3d_modPos($fVy, $fU) / $fU * $_2PI
    		$fRotY -= __b3d_modPos($fVx, $fU) / $fU * $_2PI
    
    
    	Until $iXPos > 90000
    	_GDIPlus_PenDispose($hPEN)
    	_GDIPlus_BitmapDispose($hBitmap)
    	_GDIPlus_BitmapDispose($hCopy)
    EndFunc
    
    
    ; draws a sphere and map a texture on it
    Func _b3d_drawTexturedSphere(ByRef $mCanvas, $iMx, $iMy, $iR, $mTexture, $iRotX = 0, $iRotY = 0, $hTexture = 0)
    	Local $iTexWidth = $mTexture.width
    	Local $iTexHeight = $mTexture.height
    	Local $iX, $iY, $iHalfChord, $iSegmentHeight
    	Local $fXTex, $fYTex
    	Local $iColor
    	Local $aBitmap = $mTexture.Pixels ; faster than _GDIPlus_BitmapGetPixel
    	Local $hBitmap = $mCanvas.Bitmap
    
    	; Koordinaten-Transformation als LUT um Doppelberechnung zu vermeiden
    	; Zum jeweiligen aktuellen Kreissegment (Radius - aktuelle Position im Kreis) wird die dazugehörige Koordinate im Texturraum berechnet
    	Local $aTexCoordsY[$iR + 1][2]
    	Local $aTexCoordsX[$iR + $iR + 1]
    	Local $fRad, $fRadX, $fRadY, $fRadYBottom
    	For $iH = 0 To $iR
    		; der Kreisbogenabstand vom Zenitpunkt (=Kugelwinkel in rad)
    		$fRad = ASin(($iR-$iH) / $iR)
    
    		; upper half
    		$fRadY = $fRad + $iRotX
    		$aTexCoordsY[$iH][0] = Round(__b3d_modPos($PI_2 - $fRadY, $Pi) / $Pi * ($iTexHeight - 1))
    
    		; lower half
    		$fRadYBottom = $fRadY - $fRad - $fRad
    		$aTexCoordsY[$iH][1] = Round(__b3d_modPos($PI_2 - $fRadYBottom, $Pi) / $Pi * ($iTexHeight - 1))
    
    		; left half
    		$fRadX = $PI - $fRad + $iRotY ; "+ $PI": um 0-Punkt auf Texturmitte zu platzieren
    		$aTexCoordsX[$iH] = Round(__b3d_modPos($fRadX , $_2PI) / $_2PI * ($iTexWidth - 1))
    
    		; right half
    		$fRadXRight = $fRad + $PI + $iRotY ; "+ $PI": um 0-Punkt auf Texturmitte zu platzieren
    		$aTexCoordsX[$iR + $iR - $iH] = Round(__b3d_modPos($fRadXRight, $_2PI) / $_2PI * ($iTexWidth - 1))
    	Next
    
    	; middle line (extra to avoid double processing):
    	$iYTexMid = $aTexCoordsY[$iR][0]
    	For $iX = $iMx - $iR To $iMx + $iR
    		$fXTex = $aTexCoordsX[$iX - $iMx + $iR]
    		$iColor = $aBitmap[$fXTex][$iYTexMid]
    		DllCall($__g_hGDIPDll, "int", "GdipBitmapSetPixel", "handle", $hTexture, "int", $fXTex, "int", $iYTexMid , "uint", 0xFF00FFFF)
    		DllCall($__g_hGDIPDll, "int", "GdipBitmapSetPixel", "handle", $hBitmap, "int", $iX, "int", $iMy, "uint", $iColor) ; faster than extra _GDIPlus_BitmapSetPixel()
    	Next
    
    	; rest of circle area
    	For $iSegmentHeight = 0 To $iR - 1
    
    		; halbe Sehnenlänge
    		$iHalfChord = Int(Round(Sqrt(2*$iR*$iSegmentHeight - ($iSegmentHeight*$iSegmentHeight))))
    
    		; Koordinaten des Quellpixels aus dem Texturbitmap
    		$fYTex = $aTexCoordsY[$iSegmentHeight][0]
    		$fYTexBottom = $aTexCoordsY[$iSegmentHeight][1]
    
    		For $iX = $iMx - $iHalfChord To $iMx + $iHalfChord
    			$fXTex = $aTexCoordsX[$iX - $iMx + $iR]
    
    			; draw top case
    			$iColor = $aBitmap[$fXTex][$fYTex]
    			$iY = $iMy + $iSegmentHeight - $iR
    			DllCall($__g_hGDIPDll, "int", "GdipBitmapSetPixel", "handle", $hTexture, "int", $fXTex, "int", $fYTex , "uint", 0xFF00FFFF)
    			DllCall($__g_hGDIPDll, "int", "GdipBitmapSetPixel", "handle", $hBitmap, "int", $iX, "int", $iY, "uint", $iColor)
    
    			; draw bottom case
    			$iColor = $aBitmap[$fXTex][$fYTexBottom]
    			$iY = $iMy - $iSegmentHeight + $iR
    			DllCall($__g_hGDIPDll, "int", "GdipBitmapSetPixel", "handle", $hTexture, "int", $fXTex, "int", $fYTexBottom , "uint", 0xFF00FFFF)
    			DllCall($__g_hGDIPDll, "int", "GdipBitmapSetPixel", "handle", $hBitmap, "int", $iX, "int", $iY, "uint", $iColor)
    		Next
    	Next
    EndFunc
    
    
    Func _b3d_importTexture($sPath)
    	Local $mTexture[]
    	Local $hBitmap = _GDIPlus_BitmapCreateFromFile($sPath)
    	$mTexture.Bitmap = $hBitmap
    	If @error Then Return SetError(@error, @extended, Null)
    
    	$mTexture.width = _GDIPlus_ImageGetWidth($hBitmap)
    	$mTexture.height = _GDIPlus_ImageGetHeight($hBitmap)
    
    	; convert to AutoIt-Array for faster pixel access
    	Local $aBitmap[$mTexture.width][$mTexture.height], $x, $y
    	For $x = 0 To $mTexture.width - 1
    		For $y = 0 To $mTexture.height - 1
    			$aBitmap[$x][$y] = _GDIPlus_BitmapGetPixel($hBitmap, $x, $y)
    		Next
    	Next
    	$mTexture.Pixels = $aBitmap
    
    	Return $mTexture
    EndFunc
    
    ; function to draw a filled circle on a bitmap
    Func _b3d_drawCircleFilled(ByRef $mCanvas, $iMx, $iMy, $iR, $sColor = "0xFFFFFFFF")
    	Local $iX, $iY, $iHalfChord, $iSegmentHeight
    
    	; middle line (extra to avoid double processing):
    	For $iX = $iMx - $iR To $iMx + $iR
    		_GDIPlus_BitmapSetPixel($mCanvas.Bitmap, $iX, $iMy, $sColor)
    	Next
    
    	; rest of circle area
    	For $iSegmentHeight = 0 To $iR - 1
    		$iHalfChord = Round(Sqrt(2*$iR*$iSegmentHeight - ($iSegmentHeight*$iSegmentHeight)))
    
    		For $iX = $iMx - $iHalfChord To $iMx + $iHalfChord
    			$iY = $iMy + $iSegmentHeight - $iR
    			_GDIPlus_BitmapSetPixel($mCanvas.Bitmap, $iX, $iY, $sColor)
    			$iY = $iMy - $iSegmentHeight + $iR
    			_GDIPlus_BitmapSetPixel($mCanvas.Bitmap, $iX, $iY, $sColor)
    		Next
    	Next
    EndFunc
    
    ; zeigt den aktuellen Zustand der Canvas (des Zeichnungsbitmaps an)
    Func _b3d_canvasShow(ByRef $mCanvas)
    	_GDIPlus_GraphicsDrawImage($mCanvas.Graphic, $mCanvas.Bitmap, 0, 0)
    EndFunc
    
    Func _b3d_createCanvas($iWidth, $iHeight)
    	; map which holds all the necessary parameters
    	Local $mCanvas[]
    	$mCanvas.width = $iWidth
    	$mCanvas.height = $iHeight
    
    	; Initialize GDI+ library
        _GDIPlus_Startup()
    
    	; create GUI
        $mCanvas.GUI = GUICreate("Ball 3D", $iWidth, $iHeight)
    	GUISetBkColor(0x303030, $mCanvas.GUI) ;set GUI background color
    	GUISetOnEvent($GUI_EVENT_CLOSE, _exit)
    	GUISetState(@SW_SHOW, $mCanvas.GUI)
    
    	; create Canvas
    	$mCanvas.Graphic = _GDIPlus_GraphicsCreateFromHWND($mCanvas.GUI)
    	$mCanvas.Bitmap = _GDIPlus_BitmapCreateFromGraphics($iWidth, $iHeight, $mCanvas.Graphic)
    	$mCanvas.Context = _GDIPlus_ImageGetGraphicsContext($mCanvas.Bitmap)
    
    	Return $mCanvas
    EndFunc
    
    ; positive modulo
    Func __b3d_modPos($divident, $divisor)
    	Local $m = Mod($divident, $divisor)
    	Return $m < 0 ? $m + $divisor : $m
    EndFunc
    
    Func _exit()
    	_GDIPlus_Shutdown()
    	Exit
    EndFunc
    Alles anzeigen

    lg

    M

  • Frage zu seltsamen Verhalten von _WinAPI_CopyFileEx

    • Mars
    • 16. Mai 2024 um 21:37
    Zitat von hipfzwirgel

    p.s. für einen Hook hat MS ja 4ms als Wert festgelegt. Also müsste schon bei 10ms eigentlich die Progressproc abbrechen...

    Hinweis: Das "Sleep()" von AutoIt kann keine kleineren Schritte als 10ms verwenden. Du kannst zum Spaß mal 1000x Sleep(4) laufen lassen und jeweils mit TimerInit & Timerdiff stoppen wie viel Zeit tatsächlich geschlafen wurde. Leider funktionieren auch alternative Methoden wie delayexecution oder nanosleep mit AutoIt nicht zuverlässig (manchmal schon, manchmal aber auch nicht... Zumindest nach meiner Erfahrung).

    Das hilft dir jetzt nicht bei deinem Problem, aber die Info wollte ich loswerden, nicht dass du versuchst "Sleep(4)" anzuwenden und dich dann wunderst was hier eigentlich los ist :D


    lg

    M

  • Holen Sie sich aus den Ressourcen der ausführbaren Dateien Daten in Form einer Zeile ab

    • Mars
    • 13. April 2024 um 13:08

    The problem is:
    - This is impossible as long as noone knows everything about map/struct itself (what exactly is TdlgDXImages2, Font, TcxImageList, etc.). You cannot assemble a mapping without knowing all members.
    - This looks like a "map" from another programming language. If "everything" is known one might construct something with nested maps (in AutoIt) to represent the data but the memory layout will be vastly different. Also AutoIt does not allow to reinterpret_cast<map*>(ptr), so noone will be able to even get a memory dump of a map here (and vice versa) :D. A dedicated function to r/w is needed.
    - Wrapping this into a "struct" requires the knowledge of the whole memory layout. This is impossible, especially for maps with variant datatypes or other "unknown inner workings" like: What exactly is "[]" in memory? This looks like an empty list but only god knows how this is represented in RAM (assuming the shown binary data is a memory dump).
    - etc.

    Most people here are skilled in reading/writing code but I fear your request cannot be fulfilled by anyone without "the whole picture".

    To sum it up:
    - If "everything" about this map is known, it is possible to write a "ReadBinaryToNestedMap/WriteNestedMapToBinary" function.
    - If you find someone who wants to do this (after "everything" is known) is another story.

    M

  • Einfaches Preprocessing zum Komprimieren (nur eine Spielerei)

    • Mars
    • 3. April 2024 um 01:17

    Mit Ausgangspunkt ist gemeint, dass man das als Vorstufe für einen Kompressionsalgorithmus verwenden kann. Üblicherweise bekommt man eine bessere Kompression, wenn irgendeine Struktur in den Daten vorliegt die man ausnutzen kann. In diesem Fall: Sehr viel mehr Nullen als Einsen, dafür aber etwas unstrukturierter. (Ist also für einen Kodierer der Muster erkennt ungeeignet, die Muster wurden ja quasi in Nullen umgewandelt)

    Mögliche Folgeschritte wären:
    - Lauflängenkodierung (ist intuitiv das erste was mir einfällt)
    - Falls Lauflängenkodierung im Binärformat -> Arithmetische Entropiekodierung als Folgeschritt (huffman geht hier nicht besonders gut, da die Symbole nicht mehr aligned sind).
    - Falls Lauflängenkodierung mit Tokens -> Irgendeine Entropiekodierung (hier hat man die Symbole einzeln -> Jede Methode geht) als Folgeschritt -> Fertig.

    Probleme der aktuellen Methode:
    - Je größer der LUT, desto länger ist die Warmlaufphase, da der LUT erstmal gefüllt werden muss
    - Je größer der LUT, desto besser das Ergebnis nach der Warmlaufphase, aber man ist auf 16 Bit beschränkt.

    Lösungsansatz den ich irgendwann ausprobiere:
    - Baue einen beliebig großen "pseudo" LUT aus mehreren 8Bit Blöcken zusammen.
    - So siehts aus: [Block n-2][Block n-1][Block n][Bit x] -> Akuell wird nur [Block n] verwendet um x vorherzusagen. Man könnte allerdings auch alle anderen Blöcke einbeziehen. Da hier (aus Stochastik-Sicht) keine Unabhängigkeit vorliegt (es ist also ein Unterschied ob ich ausgehend von [Block n-1 (8Bit)] und [Block n (8Bit)] das x vorhersage, oder ob ich einen einzigen 16Bit Block nehme) muss man für halbwegs gute Ergebnisse vermutlich eine Art Interleaving verwenden.

    Trivialbeispiel mit 4 x 8Bit Blöcken -> [aaaaaaaa][bbbbbbbb][cccccccc][dddddddd][x] -> 4 Vorhersagen mit den Blöcken ohne Änderung (habe keine Nummern drangeschrieben, die aaaaaaaa sind eigentlich a1a2a3...usw)
    Zusätzlich mit Interleaving [abcdabcd][abcdabcd][abcdabcd][abcdabcd][x] -> 4 Weitere Vorhersagen für x
    Eine Linearkombination (mit irgendwelchen Koeffizienten die ich nicht kenne) dieser 8 Vorhersagen dient als Approximation der Vorhersage die ein einziger 32Bit Block liefern könnte. Je mehr Vorhersagen mit verschieden Verwobenenen 8 Bit Blöcken man verwendet, desto besser die Approximation. Gleichzeitig sinkt die Warmlaufphase, da man nicht 2^32 Zustände, sondern (im Beispielfall) nur 8 * 2^8 = 2048 Zustände vollmachen muss. Ich schätze damit sind auch bei "normalem Text" 90%+ Nullen möglich (statt 79%). Wäre zumindest lustig, wenn das gehen würde :)

    Danach kommt die "swap Methode" (aus dem Permutationen Komprimieren Thread) zum Einsatz (wobei hier die Nullen und Einsen geswappt werden um sie zu sortieren). Dann sind die Daten in folgender Form: [Bits zur Steuerung der Swaps][alle Einsen][alle Nullen]. Alle Einsen und Alle Nullen können als 2 Integer gespeichert werden, sodass die komprimierten Daten nur noch aus Swap-Positionen + 2 Int bestehen. Hehehe. Damit werde ich die Welt erobern.

    M

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™