Local $Score = 'Der Bub|1000;Der Lappen|900;Der Mensch|800;Der Komiker|700' Local $Spiel = 'Das Neue Spiel' Local $Version = '1' Local $T $Score = 'Der Bub|1000;Der Lappen|900;Der Mensch|800;Der Komiker|700' $Spiel = 'Das Neue Spiel' $Version = '1.07' ConsoleWrite(@CRLF) $T = TimerInit() ConsoleWrite('Highscore wird angelegt für "' & $Spiel & ' ' & $Version & '"' & @CRLF) ConsoleWrite('Kompression: ' & _Write('Highscore.dat', $Spiel & '|' & $Version, $Score) & ' %'& @CRLF) ConsoleWrite(Round(TimerDiff($T), 2) & ' ms' & @CRLF) $T = TimerInit() ConsoleWrite('Highscore wird gelesen...' & @CRLF) ConsoleWrite(_Read('Highscore.dat', $Spiel & '|' & $Version) & @CRLF) ConsoleWrite(Round(TimerDiff($T), 2) & ' ms' & @CRLF) ConsoleWrite(@CRLF) $Score = 'Der Bub|1000;Der Lappen|900;Der Mensch|800;Der Komiker|700;Der Bub|600;Der Lappen|500;Der Mensch|400;Der Komiker|300;Der Bub|200;Der Lappen|100' $Spiel = 'Das Neue Spiel' $Version = '1.27' $T = TimerInit() ConsoleWrite('Highscore wird angelegt für "' & $Spiel & ' ' & $Version & '"' & @CRLF) ConsoleWrite('Kompression: ' & _Write('Highscore.dat', $Spiel & '|' & $Version, $Score) & ' %'& @CRLF) ConsoleWrite(Round(TimerDiff($T), 2) & ' ms' & @CRLF) $T = TimerInit() ConsoleWrite('Highscore wird gelesen...' & @CRLF) ConsoleWrite(_Read('Highscore.dat', $Spiel & '|' & $Version) & @CRLF) ConsoleWrite(Round(TimerDiff($T), 2) & ' ms' & @CRLF) ConsoleWrite(@CRLF) $Score = 'Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;Der Statist mit der Nummer: 001;' $Spiel = 'The Spiel of keine Ahnung !' $Version = '2.75' $T = TimerInit() ConsoleWrite('Highscore wird angelegt für "' & $Spiel & ' ' & $Version & '"' & @CRLF) ConsoleWrite('Kompression: ' & _Write('Highscore.dat', $Spiel & '|' & $Version, $Score) & ' %'& @CRLF) ConsoleWrite(Round(TimerDiff($T), 2) & ' ms' & @CRLF) $T = TimerInit() ConsoleWrite('Highscore wird gelesen...' & @CRLF) ConsoleWrite(_Read('Highscore.dat', $Spiel & '|' & $Version) & @CRLF) ConsoleWrite(Round(TimerDiff($T), 2) & ' ms' & @CRLF) ConsoleWrite(@CRLF) ; #FUNCTION# ==================================================================================================================== ; Name...........: _Write ; Description ...: Schreibt einen spielspezifisch wieder abrufbaren String komprimiert in eine Datei ; Syntax.........: _Write($Pfad, $Spiel, $Score) ; Parameters ....: $Pfad - Der Pfad zur Datei in die geschrieben werden soll. ; $Spiel - String der den Namen des Spiels und die Versionsnummer enthält und mit | getrennt wird. (z.B. Spiel|1.05) ; $Score - Beliebiger String der komprimiert gespeichert werden soll. ; Return values .: Die Kompression in %. Alles über 100% bedeutet eine Vergrößerung der geschriebenen Daten ; Author ........: Mars ; Modified.......: ; Remarks .......: ; Related .......: _Read ; Link ..........: ; Example .......: ; =============================================================================================================================== Func _Write($Pfad, $Spiel, $Score) ; $Spiel 'Spielname|Spielversion' Local $Handle = FileOpen($Pfad), $Read = FileRead($Handle) ; Inhalt lesen FileClose($Handle) ; Schließen $Handle = FileOpen($Pfad, 2) ; Zum Schreiben Öffnen Local $Kurz = _Kurz($Spiel), $Ptr[2] = ['<'&$Kurz&'>',''], $CRLF = '', $P = '(?i)(?s)(.*?)', $CompStr = '' If Not StringInStr($Read, $Ptr[0]) Or Not StringInStr($Read, $Ptr[1]) Then If StringLeft(StringRight($Read, 4), 2) <> @CRLF Then $CRLF &= @CRLF $Read = $Read & $CRLF & $Ptr[0] & $Ptr[1] & ' - ' & _Name($Spiel) & @CRLF ; Abschnitt für den Highscore anlegen EndIf $CompStr = _Comp($Score) $Read = StringRegExpReplace($Read, $Ptr[0] & $P & $Ptr[1], $Ptr[0] & $CompStr & $Ptr[1]) ; Inhalt des Highscores Ersetzen FileWrite($Handle, $Read) ; Den Modifizierten Score Speichern FileClose($Handle) ; Alles auf die Platte schreiben Return Int(StringLen($CompStr)/StringLen($Score) * 100) EndFunc ; #FUNCTION# ==================================================================================================================== ; Name...........: _Read ; Description ...: Liest einen String aus einer mit _Write erstellten Datei. ; Syntax.........: _Read($Pfad, $Spiel) ; Parameters ....: $Pfad - Der Pfad zur Datei aus der gelesen werden soll ; $Spiel - String der den Namen des Spiels und die Versionsnummer enthält und mit | getrennt wird. (z.B. Spiel|1.05) ; Return values .: Der dekomprimierte String ; Author ........: Mars ; Modified.......: ; Remarks .......: ; Related .......: _Write ; Link ..........: ; Example .......: ; =============================================================================================================================== Func _Read($Pfad, $Spiel) ; $Spiel 'Spielname|Spielversion' Local $Kurz = _Kurz($Spiel), $Ptr[2] = ['<'&$Kurz&'>',''], $P = '(?i)(?s)(.*?)',$Read = FileRead($Pfad), $Split = StringRegExp($Read, $Ptr[0] & $P & $Ptr[1], 3) If Not IsArray($Split) Then Return 0 Return _DeComp($Split[0]) EndFunc #Region - Interne Benutzung Func _Kurz($Spiel) ; $Spiel 'Spielname|Spielversion' Local $Split = StringSplit($Spiel, '|', 2), $Spielname = $Split[0], $Spielversion = Number($Split[1]) Return _Hash($Spielname) & Floor($Spielversion*10) EndFunc ; Return Identifikation für das Spiel incl Version Func _Name($Spiel) ; $Spiel 'Spielname|Spielversion' Local $Split = StringSplit($Spiel, '|', 2) Return $Split[0] & ' ' & Number($Split[1]) EndFunc ; Spiel und Version mit Leerzeichen Func _Hash($String, $n = 3) ; N Stellige HashNummer für kurze Strings Local $len = StringLen($String), $Ret = 0 For $i = 1 To $len Step 1 $Ret += Asc(StringLeft($String, 1))^1.15 + $i $String = StringTrimLeft($String, 1) $Ret = $Ret^0.75 + $len Next $String = Int(($Ret - Int($Ret))* 2^32) ; Der String ist jetzt eine große Zahl $Ret = $len^2 $len = StringLen($String) For $i = 1 To $len Step 1 $Ret += Int(StringLeft($String, 2)) + Int(StringLeft($String, 1)) + Int(StringLeft($String, 3)) + Int(StringLeft($String, 4)) $String = StringTrimLeft($String, 2) Next $Ret = Int(($len + $Ret/$len)^2) While $Ret > 2^($n*4) - 1 $Ret -= 2^($n*4) - 1 WEnd Return Hex($Ret, $n) EndFunc Func _Comp($String) Return _Ersetzung_Comp(_LZ77_4096_16_Comp($String)) EndFunc ;==>_Comp Func _Decomp($String) Return _LZ77_4096_16_Decomp(_Ersetzung_DeComp($String)) EndFunc ;==>_Decomp Func _LZ77_4096_16_Comp($String) $String = StringReplace($String, Chr(0), '[N]', 0, 1) Local $WortBuchGroesse = 4096, $LexikonZeichen = StringLen($String) If $LexikonZeichen > $WortBuchGroesse Then $LexikonZeichen = $WortBuchGroesse Local $SuchFensterZeichen = 16, $Lexikon = _Nullen($LexikonZeichen), $SuchFenster = '', $len = StringLen($String), $OptimierterString = '', $Suchlaenge = $SuchFensterZeichen, $StrInStr = 0 $SuchFenster = StringLeft($String, $SuchFensterZeichen) $String = StringTrimLeft($String, $SuchFensterZeichen) For $i = 1 To $len Step 1 If $SuchFenster = '' Then ExitLoop For $o = $SuchFensterZeichen To 1 Step -1 $Suchlaenge = $o $StrInStr = StringInStr($Lexikon, StringLeft($SuchFenster, $Suchlaenge), 1, -1) If $StrInStr Then $Suchlaenge = StringLen(StringLeft($SuchFenster, $Suchlaenge)) ExitLoop EndIf Next If $StrInStr Then $OptimierterString &= Hex($StrInStr - 1, 3) & Hex($Suchlaenge - 1, 1) $Lexikon &= StringMid($Lexikon, $StrInStr, $Suchlaenge) $Lexikon = StringTrimLeft($Lexikon, $Suchlaenge) $SuchFenster = StringTrimLeft($SuchFenster, $Suchlaenge) $SuchFenster &= StringLeft($String, $Suchlaenge) $String = StringTrimLeft($String, $Suchlaenge) $OptimierterString &= Hex(Asc(StringLeft($SuchFenster, 1)), 2) $Lexikon &= StringLeft($SuchFenster, 1) $Lexikon = StringTrimLeft($Lexikon, 1) $SuchFenster = StringTrimLeft($SuchFenster, 1) $SuchFenster &= StringLeft($String, 1) $String = StringTrimLeft($String, 1) Else $OptimierterString &= '0000' & Hex(Asc(StringLeft($SuchFenster, 1)), 2) $Lexikon &= StringLeft($SuchFenster, 1) $Lexikon = StringTrimLeft($Lexikon, 1) $SuchFenster = StringTrimLeft($SuchFenster, 1) $SuchFenster &= StringLeft($String, 1) $String = StringTrimLeft($String, 1) EndIf Next Return Hex($LexikonZeichen - 1, 3) & Hex($SuchFensterZeichen - 1, 1) & $OptimierterString EndFunc Func _LZ77_4096_16_Decomp($String) Local $NeuerString = '', $LexikonZeichen = Int('0x' & StringLeft($String, 3)) + 1 $String = StringTrimLeft($String, 3) Local $SuchFensterZeichen = Int('0x' & StringLeft($String, 1)) + 1 ; Wird zwar nicht gebraucht, rundet aber die Ungrade Dateilänge ab $String = StringTrimLeft($String, 1) Local $Lexikon = _Nullen($LexikonZeichen), $lexNr = 0, $len = 0, $Asc = 0 For $i = 0 To StringLen($String) / 4 Step 1 If $String = '' Then ExitLoop $lexNr = Int('0x' & StringLeft($String, 3)) + 1 $String = StringTrimLeft($String, 3) $len = Int('0x' & StringLeft($String, 1)) + 1 $String = StringTrimLeft($String, 1) $Asc = Int('0x' & StringLeft($String, 2)) $String = StringTrimLeft($String, 2) If $lexNr = 1 And $len = 1 Then $NeuerString &= Chr($Asc) $Lexikon &= Chr($Asc) $Lexikon = StringTrimLeft($Lexikon, 1) Else $NeuerString &= StringMid($Lexikon, $lexNr, $len) $Lexikon &= StringMid($Lexikon, $lexNr, $len) $Lexikon = StringTrimLeft($Lexikon, $len) If $Asc Then $NeuerString &= Chr($Asc) $Lexikon &= Chr($Asc) $Lexikon = StringTrimLeft($Lexikon, 1) EndIf EndIf Next $NeuerString = StringReplace($NeuerString, '[N]', Chr(0), 0, 1) Return $NeuerString EndFunc ;==>_LZ77_4096_16_Decomp Func _Nullen($a) ; Damit das Lexikon voller Nullen ist. Local $n = '' For $i = 1 To $a Step 1 $n &= '0' Next Return $n EndFunc ;==>_Nullen Func _ZeichenArray() Local $sZ = '!"#%&,-/:;=@GHIJKLMNOPQRSTUVWXYZ_`abcdefghijklmnopqrstuvwxyz~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ', $UBound = StringLen($sZ), $b[$UBound] For $i = 0 To $UBound - 1 Step 1 $b[$i] = StringLeft($sZ, 1) $sZ = StringTrimLeft($sZ, 1) Next Return $b EndFunc ;==>_ZeichenArray Func _Ersetzung_DeComp($a) Local $n = Int('0x' & StringRight($a, 2)), $_____ZeichenReverse = _ZeichenArray(), $st = '' $a = StringTrimRight($a, 2) _ArrayReverse2($_____ZeichenReverse, 0, $n - 1) For $i = 0 To $n - 1 Step 1 $st = StringRight($a, 2) $a = StringTrimRight($a, 2) $a = StringReplace($a, $_____ZeichenReverse[$i], $st, 0, 1) Next Return $a EndFunc ;==>_Ersetzung_DeComp Func _Ersetzung_Comp($a) Local $l_alt = StringLen($a), $l_neu = 0, $st, $er, $n = 0, $_____Zeichen = _ZeichenArray(), $_____Zeichenmenge = UBound($_____Zeichen) While 1 $st = _Analyse($a) ; $st = Meist vorkommender String $a = StringReplace($a, $st, $_____Zeichen[$n], 0, 1) $a &= $st ; Und rechts an $a angehängt. $a = Urspringsstring $l_neu = StringLen($a) ; Neue Stringlänge $n += 1 ; Durchläufe If ($n = $_____Zeichenmenge Or $l_neu >= $l_alt) Then ;Nur Abbrechen, wenn tatsächlich nix geht. (nicht wenn der 8er nicht klappt...) ExitLoop EndIf $l_alt = $l_neu WEnd Return $a & Hex($n, 2) ; Rückgabe ist der Komprimierte String und die Anzahl ersetzungen EndFunc ;==>_Ersetzung_Comp Func _Analyse($sData, $l = 2) Local $StringLaenge = StringLen($sData), $Top[2], $StringPart, $Replacements, $BenutzteStrings[256][256] For $i = 0 To $StringLaenge - ($l - 1) Step 1 $StringPart = StringMid($sData, $i, $l) If Not $BenutzteStrings[Asc(StringLeft($StringPart, 1))][Asc(StringRight($StringPart, 1))]Then ; Damit keine Strings doppelt getestet werden... $BenutzteStrings[Asc(StringLeft($StringPart, 1))][Asc(StringRight($StringPart, 1))] = True StringReplace($sData, $StringPart, $StringPart, 0, 1) $Replacements = @extended If $Replacements >= $Top[0] Then $Top[0] = $Replacements $Top[1] = $StringPart EndIf EndIf Next Return $Top[1] EndFunc ;==>_Analyse Func _ArrayReverse2(ByRef $avArray, $iStart = 0, $iEnd = 0) Local $vTmp, $iUBound = UBound($avArray) - 1 For $i = $iStart To Int(($iStart + $iEnd - 1) / 2) $vTmp = $avArray[$i] $avArray[$i] = $avArray[$iEnd] $avArray[$iEnd] = $vTmp $iEnd -= 1 Next EndFunc ;==>_ArrayReverse #EndRegion - Interne Benutzung