chronogramm

This commit is contained in:
2025-07-26 18:41:41 +02:00
parent 31f55f13b3
commit 07dc37902b
2 changed files with 423 additions and 430 deletions

View File

@@ -218,7 +218,7 @@ def auswahl_verarbeiten():
st.session_state.output_text = output st.session_state.output_text = output
st.session_state.map_data = mapd st.session_state.map_data = mapd
elif auswahl == "Quadtree/Quadkey": elif auswahl == "Quadtree/Quadkey":
output, mapd = tools.quadtreekoordinaten(text) output, mapd = tools.quadtree_koordinaten(text)
st.session_state.output_text = output st.session_state.output_text = output
st.session_state.map_data = mapd st.session_state.map_data = mapd
elif auswahl == "REPLACE": elif auswahl == "REPLACE":

View File

@@ -2438,7 +2438,7 @@ def maptiles_kachelkoordinaten(eingabetext):
else: else:
return "Zahlen konnten nicht ermittelt werden!", None return "Zahlen konnten nicht ermittelt werden!", None
def quadtreekoordinaten(eingabetext): def quadtree_koordinaten(eingabetext):
hilfetext = ("### Quadtree-/Quadkeykoordinaten\n" hilfetext = ("### Quadtree-/Quadkeykoordinaten\n"
"Diese Koordinatenkodierung spielt in der alltäglichen Praxis eigentlich kaum noch ein Rolle, " "Diese Koordinatenkodierung spielt in der alltäglichen Praxis eigentlich kaum noch ein Rolle, "
"außer scheinbar bei bing-maps und beim Geocaching. Sie dient ähnlich wie das Maptiles-System dazu " "außer scheinbar bei bing-maps und beim Geocaching. Sie dient ähnlich wie das Maptiles-System dazu "
@@ -2487,35 +2487,27 @@ def quadtreekoordinaten(eingabetext):
return ("Es konnte keine gültige Quadtree-Koordinate erkannt werden. (eine Zahl die nur die Ziffern " return ("Es konnte keine gültige Quadtree-Koordinate erkannt werden. (eine Zahl die nur die Ziffern "
"0,1,2,3 enthält)"), None "0,1,2,3 enthält)"), None
''' def chronogramm(eingabetext):
def chronogramm(): hilfetext = ('### Chronogramm/ römische Ziffern zählen\n'
hilfetext = """HILFE: [Chronogramm/ römische Ziffern zählen] 'Ein Chronogramm (oder Eteostichon) ist ein Satzteil, ein Satz, ein Sinnspruch oder eine Inschrift, '
Ein Chronogramm (oder Eteostichon) ist ein Satzteil, ein Satz, ein Sinnspruch 'meist ein Vers in lateinischer Sprache, in dem diejenigen Buchstaben, die auch als römische '
oder eine Inschrift, meist ein Vers in lateinischer Sprache, in dem diejenigen 'Zahlzeichen gelesen werden können (I, V, X, L, C, D, M), in ihrer Summe die Jahreszahl des '
Buchstaben, die auch als römische Zahlzeichen gelesen werden können 'Ereignisses angeben, auf das sich der Text bezieht. Entscheidend ist allein die Summe der '
(I, V, X, L, C, D, M), in ihrer Summe die Jahreszahl des Ereignisses angeben, 'Zahlenwertbuchstaben, die sonst bei römischen Zahlen übliche Subtraktion kleinerer Zahlenwerte von '
auf das sich der Text bezieht. Entscheidend ist allein die Summe der 'folgenden größeren erfolgt nicht. Die Zahlbuchstaben sind meist hervorgehoben, etwa durch '
Zahlenwertbuchstaben, die sonst bei römischen Zahlen übliche Subtraktion 'Großschreibung oder Verdickung der Buchstaben bzw. durch farbliche Abhebung mittels Rötung oder '
kleinerer Zahlenwerte von folgenden größeren erfolgt nicht. 'Vergoldung. \n'
Die Zahlbuchstaben sind meist hervorgehoben, etwa durch Großschreibung oder 'Eine Besonderheit bilden Krypto(chrono)gramme, bei denen die Zahlbuchstaben nicht gekennzeichnet '
Verdickung der Buchstaben bzw. durch farbliche Abhebung mittels Rötung oder 'sind und "verborgen" bleiben. Bei der einfachen Analyse werden hier die Buchstaben I(1), V(5), '
Vergoldung. Eine Besonderheit bilden Krypto(chrono)gramme, bei denen die 'X(10), L(50), C(100), D(500), M(1000) berücksichtigt und addiert, bei der erweiterten Analyse wird '
Zahlbuchstaben nicht gekennzeichnet sind und "verborgen" bleiben. 'zunächst einmal berücksichtigt, daß im Lateinischen Alphabet der Buchstabe J als I und der '
'Buchstabe U als V geschrieben wird. Außerdem erfolgt wird in der extremen Variante auch noch '
Bei der einfachen Analyse werden hier die Buchstaben I(1),V(5),X(10),L(50), 'W=10(V+V) und Y=2(I+I) berücksichtigt. \n'
C(100), D(500), M(1000) berücksichtigt und addiert, bei der erweiterten 'Des Weiteren wird auch für jeden relevanten Buchstaben einzeln noch einmal die Anzahl und Summe'
Analyse wird zunächst einmal berücksichtigt, daß im Lateinischen Alphabet ' angezeigt. Eine Unterscheidung zwischen Klein- und Großschreibung findet nicht statt.')
der Buchstabe J als I und der Buchstabe U als V geschrieben wird. Außerdem
erfolgt wird in der extremen Variante auch noch W=10(V+V) und Y=2(I+I)
berücksichtigt. Desweiteren wird auch für jeden relevanten Buchstaben
einzeln noch einmal die Anzahl und Summe angezeigt.
Eine Unterscheidung zwischen Klein- und Großschreibung findet nicht statt.
"""
eingabetext = Eingabe.get(1.0, END)
text = eingabetext.rstrip() text = eingabetext.rstrip()
if text == "": if text == "":
Ausgabe.insert(1.0, hilfetext + "\n") return hilfetext
else: else:
text = text.upper() text = text.upper()
i, v, x, ll, c, d, m, y, w, u, j = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 i, v, x, ll, c, d, m, y, w, u, j = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
@@ -2545,20 +2537,324 @@ Eine Unterscheidung zwischen Klein- und Großschreibung findet nicht statt.
sum_einfach = i + (v * 5) + (x * 10) + (ll * 50) + (c * 100) + (d * 500) + (m * 1000) sum_einfach = i + (v * 5) + (x * 10) + (ll * 50) + (c * 100) + (d * 500) + (m * 1000)
sum_erweitert = sum_einfach + (u * 5) + j sum_erweitert = sum_einfach + (u * 5) + j
sum_extrem = sum_erweitert + (y * 2) + (w * 10) sum_extrem = sum_erweitert + (y * 2) + (w * 10)
Ausgabe.insert(1.0, "Summe extrem(inkl.J,U,Y,W): {}\n".format(sum_extrem)) ausgabetext = "|Buchstabe|Wert|Anzahl|Summe\n|-|-|-|-|\n"
Ausgabe.insert(1.0, "Summe erweitert(inkl. I,U): {}\n".format(sum_erweitert)) ausgabetext += f"|I|1|{i}|{i}|\n"
Ausgabe.insert(1.0, "Summe einfach(I,V,X,L,C,D,M): {}\n".format(sum_einfach)) ausgabetext += f"|V|5|{v}|{v*5}|\n"
Ausgabe.insert(1.0, "W(V+V=10):{:5}x \tSumme W: {}\n".format(w, w * 10), "gr") ausgabetext += f"|X|10|{x}|{x*10}|\n"
Ausgabe.insert(1.0, " Y(I+I=2):{:5}x \tSumme Y: {}\n".format(y, y * 2), "gr") ausgabetext += f"|L|50|{ll}|{ll*50}|\n"
Ausgabe.insert(1.0, " U(V=5):{:5}x \tSumme U: {}\n".format(u, u * 5), "gr") ausgabetext += f"|C|100|{c}|{c*100}|\n"
Ausgabe.insert(1.0, " J(I=1):{:5}x \tSumme U: {}\n".format(j, j), "gr") ausgabetext += f"|D|500|{d}|{d*500}|\n"
Ausgabe.insert(1.0, " M(1000):{:5}x \tSumme M: {}\n".format(m, m * 1000), "gr") ausgabetext += f"|M|1000|{m}|{m*1000}\n"
Ausgabe.insert(1.0, " D(500):{:5}x \tSumme D: {}\n".format(d, d * 500), "gr") ausgabetext += f"|J(=I)|1|{j}|{j}|\n"
Ausgabe.insert(1.0, " C(100):{:5}x \tSumme C: {}\n".format(c, c * 100), "gr") ausgabetext += f"|U(=V)|5|{u}|{u*5}|\n"
Ausgabe.insert(1.0, " L(50):{:5}x \tSumme L: {}\n".format(ll, ll * 50), "gr") ausgabetext += f"|Y(=I+I)|2|{y}|{y*2}|\n"
Ausgabe.insert(1.0, " X(10):{:5}x \tSumme X: {}\n".format(x, x * 10), "gr") ausgabetext += f"|W(=V+V)|10|{w}|{w*10}\n \n"
Ausgabe.insert(1.0, " V(5):{:5}x \tSumme V: {}\n".format(v, v * 5), "gr") ausgabetext += f"Summe einfach(I,V,X,L,C,D,M): {sum_einfach} \n"
Ausgabe.insert(1.0, " I(1):{:5}x \tSumme I: {}\n".format(i, i), "gr") ausgabetext += f"Summe erweitert(inkl. I,U): {sum_erweitert} \n"
ausgabetext += f"Summe extrem(inkl.J,U,Y,W): {sum_extrem}"
return ausgabetext
'''
def zahlen_roemisch_arabisch_umwandeln():
hilfetext = """HILFE: [Römische in Arabische Zahlen umwandeln und umgekehrt]
Es werden römische Zahlen in arabische umgewandelt und umgekehrt, die Funktion
arbeitet dabei bei der Umwandlung von arabisch zu römisch mit Werten bis
maximal 500000. Es werden folgende Zeichen verwendet: I=1, V=5, X=10, L=50,
C=100, D=500, M=1000, \u2181=5000, \u2182=10000, \u2187=50000, \u2188=100000
Etwas Vorsicht sollte bei einer Umwandlung von römischen in arabische Zahlen
geboten sein, wenn mit untypischen Schreibweisen gearbeitet wird bei welchen
mehr als ein Zeichen von dem nachfolgenden Zeichen abgezogen werden soll.
Die eigentlich inkorrekte Schreibweise IIX für die Zahl 8 wird hier die Zahl
10 als Ergebnis haben (+1-1+10), dafür wird aber allerdings die ebenfalls
falsche Schreibweise IM genauso als 999 wie die korrekte Schreibweise CMXCIX
erkannt.
"""
rza = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000, '\u2181': 5000, '\u2182': 10000,
'\u2187': 50000, '\u2188': 100000}
azr = [(100000, '\u2188'), (90000, '\u2182\u2188'), (50000, '\u2187'), (40000, '\u2182\u2187'),
(10000, '\u2182'), (9000, 'M\u2182'), (5000, '\u2181'), (4000, 'M\u2181'), (1000, 'M'), (900, 'CM'),
(500, 'D'),
(400, 'CD'), (100, 'C'), (90, 'XC'), (50, 'L'), (40, 'XL'), (10, 'X'), (9, 'IX'), (5, 'V'), (4, 'IV'),
(1, 'I')]
eingabetext = Eingabe.get(1.0, END)
rz = eingabetext.rstrip()
if rz == "":
Ausgabe.insert(1.0, hilfetext + "\n")
else:
rz = rz.upper()
try:
az = 0
for i in range(len(rz)):
if i == len(rz) - 1:
az += rza[rz[i]]
Ausgabe.insert(1.0, "{} = {}\n".format(rz, az))
else:
if rza[rz[i]] < rza[rz[i + 1]]:
az -= rza[rz[i]]
else:
az += rza[rz[i]]
except KeyError:
try:
zahl = int(rz)
if zahl > 500000:
Ausgabe.insert(1.0, "arabische Zahlen größer als 500000 mag ich nicht in römische Zahlen!\n", "re")
return
rom = ""
for az, romz in azr:
count = zahl // az
zahl -= az * count
rom += romz * count
Ausgabe.insert(1.0, "{} = {}\n".format(rz, rom))
except ValueError:
Ausgabe.insert(1.0, "Es konnte keine römische oder arabische Zahl erkannt werden!\n", "re")
def url_decode():
eingabetext = Eingabe.get(1.0, END)
eingabetext = eingabetext.rstrip()
if eingabetext == "":
Ausgabe.insert(1.0, """HILFE: [URL-decode]
Nachdem Groundspeak nun inzwischen sämtliche Bilddateien
über einen Proxy umleitet bevor sie im Listing erscheinen
wird es manchmal schwer die ursprüngliche URL und/oder
den Dateinamen des Bildes noch lesen zu können.
Die URL hat dort nun jeweils folgendes Muster:
https://imgproxy.geocaching.com/......?url=.....
wobei nach dem ?url= dann die ursprüngliche Bild-URL
folgt, allerdings wird dabei dann aus
http:// folgendes http%3A%2F%2F und um genau dieses
wieder normal lesbar zu machen dient diese Funktion\n\n""")
else:
atxt = urllib_parse_unquote(eingabetext)
Ausgabe.insert(1.0, atxt + "\n")
Ausgabe.insert(1.0, "dekodierte URL:\n", "bu")
def reversewig():
seperator = ("|,", "_", "/", ";", ",")
eingabetext = Eingabe.get(1.0, END)
eingabetext = eingabetext.rstrip()
if eingabetext == "":
Ausgabe.insert(1.0, """HILFE: [Reverse Wherigo zu Koordinaten]
Mit dem Reverse Wherigo hat -Waldmeister- eigentlich eine coole Sache
erfunden. Man hat anfangs keine Koordinaten sondern nur 3 Zahlen, welche
man nach Start des Wherigo-Cartridges eingibt und dann erfährt man wie weit
der Cache entfernt ist. Nun kann man immer wieder von unterschiedlichen
Positionen aus diese Entfernungsfragen durchführen und sich damit dem
Cache nähern. Je weniger Abfragen man braucht umso besser.
Leider gibt es inzwischen genügend Tools die genau wie diese Funktion
hier aus den 3 Zahlen direkt die Finalkoordinaten ermitteln können.
Leider??? Ja leider denn das führt auch dazu, das es inzwischen so extrem
viele dieser Reverse-Wherigos gibt wo sich die Owner anscheinend auch
denken "Die spielt doch sowieso keiner mehr normal..." anders kann ich
mir ganze Trails mit Reverse-Wherigos nicht erklären.
Um die Funktion zu nutzen braucht man nur die 3 Zahlen durch ein entsprechendes
Trennzeichen: | , _ / ; , oder Leerzeichen eingeben und auf den Knopp klicken
und bekommt Koordinaten.
""" + "\n\n")
else:
se = ""
for s in seperator:
if s in eingabetext:
se = s
if se == "" and " " in eingabetext:
se = " "
if se == "":
Ausgabe.insert(1.0, "Keine gültiges Trennzeichen (, ; / _ | oder Leerzeichen) erkannt!\n", "re")
else:
txt = eingabetext.split(se)
if len(txt) == 3:
error = 0
for z in txt:
try:
int(z)
except ValueError:
Ausgabe.insert(1.0, "Bitte die Eingabezahlen überprüfen\n", "re")
error += 1
if error == 0:
final = rwig_to_coords(txt[0], txt[1], txt[2])
Ausgabe.insert(1.0, "DEG: " + dec_to_deg(final[0], final[1]) + "\n")
Ausgabe.insert(1.0, "DEC: " + str(final[0]) + " " + str(final[1]) + "\n")
Ausgabe.insert(1.0, "WIG: " + txt[0] + ", " + txt[1] + ", " + txt[2] + "\n")
else:
Ausgabe.insert(1.0, "Es wurden nicht 3 Zahlen erkannt.\n", "re")
def base64_ascii():
eingabetext = Eingabe.get(1.0, END)
eingabetext = eingabetext.rstrip()
if eingabetext == "":
Ausgabe.insert(1.0, """HILFE: [Base64 <-> ASCII]
Base64 ist ein Kodierungsverfahren, welches dazu verwendet wird
um beliebige Binärdaten nur Hilfe einer Zeichenkette aus A-Z,
a-z, 0-9, +, / sowie am Ende = übertragen zu können. Ein Einsatzzweck
dafür ist z.B. wenn bei EMails Dateianhänge verwendet werden, dort
werden nahezu alle Dateiformate base64-kodiert übertragen.
Auch bei dem einem oder anderen Mystery sind mir solche kodierten
Zeichenketten schon begegnet. Wenn am Ende einer Zeichenkette ein
oder zwei "="-Zeichen stehen ist die Wahrscheinlichkeit recht groß,
das hier base64 verwendet wurde. Das "="-Zeichen dient hier nämlich
als "Lückenfüller" am Ende.
Die Funktion hier versucht zunächst eine Dekodierung Base64->ASCII
gelingt dies nicht, erscheint ein Hinweis und der eingegeben Text
wird dann Base64-kodiert ausgegeben.
""" + "\n\n")
else:
try:
ascii_string = binascii.a2b_base64(eingabetext).decode()
Ausgabe.insert(1.0, ascii_string + "\n")
Ausgabe.insert(1.0, "Base64 -> ASCII:\n", "bu")
except ValueError:
base64_string = binascii.b2a_base64(eingabetext.encode())
Ausgabe.insert(1.0, base64_string.decode() + "\n")
Ausgabe.insert(1.0, "ASCII -> Base64:\n", "bu")
Ausgabe.insert(1.0, "Umwandlung Base64 -> ASCII war nicht möglich.\n", "re")
def rail_encrypt(plain_text: str, rails: int):
arr = [["" for _ in range(len(plain_text))] for _ in range(rails)]
r = 0
z = 0
plus = True
for b in plain_text:
arr[r][z] = b
z += 1
if r + 1 == rails and plus:
plus = False
r -= 1
elif r - 1 < 0 and not plus:
plus = True
r += 1
elif plus:
r += 1
else:
r -= 1
out = ""
for i in range(rails):
for j in range(len(plain_text)):
out += arr[i][j]
return out
def jaegerzaun_encrypt():
eingabetext = Eingabe.get(1.0, END)
eingabetext = eingabetext.strip().replace("\n", " ")
pw = PW_Eingabe.get()
pw = pw.strip()
if eingabetext == "":
Ausgabe.insert(1.0, """HILFE: [encrypt Jägerzaun]
Jägerzaun (auch Railfence oder ZigZag-Chiffre genannt)
Bei dieser Chiffre wird kodiert, indem man einen Text im Zickzackmuster
in ein Feld aus z.B. 3 Zeilen und so vielen Spalten wie der Text lang ist
schreibt. Man beginnt in Spalte 1 - Zeile 1, dann geht es in Spalte 2 - Zeile 1
weiter danach Spalte 3 - Zeile 3, dann Spalte 4 - Zeile 2, Spalte 5 - Zeile 1 usw.
Danach werden die Buchstaben einfach Zeile für Zeile hintereinander geschrieben.
Unterschiedliche Varianten entstehen einfach dadurch, dass man mit unterschiedlich
vielen Zeilen arbeitet welche im Schlüsselfeld anzugeben ist.
Die Funktion erzeugt hierbei einmal eine Ausgabe bei welcher auch Leerzeichen
mitgeschrieben werden und eine Ausgabe wo zuvor die Leerzeichen entfernt werden.
""" + "\n\n")
elif pw == "" or not pw.isdigit():
Ausgabe.insert(1.0, "Bitte eine Zahl im Schlüsselfeld eingeben!!\n", "re")
else:
try:
if int(pw) < 2:
raise ValueError("Zahl zu klein")
Ausgabe.insert(1.0, rail_encrypt(eingabetext.replace(" ", ""), int(pw)) + "\n")
Ausgabe.insert(1.0, "ohne Leerzeichen\n", "bu")
Ausgabe.insert(1.0, rail_encrypt(eingabetext, int(pw)) + "\n")
Ausgabe.insert(1.0, "inkl. Leerzeichen\n", "bu")
except ValueError:
Ausgabe.insert(1.0, "Schlüsselzahl fehlerhaft oder kleiner als 2.\n", "re")
def rail_decrypt(cipher: str, rails: int):
arr = [["_" for _ in range(len(cipher))] for _ in range(rails)]
# cipher ins array reinbasteln
x, y = 0, 0
first_x = True
for b in cipher:
if x >= len(cipher) and y < rails:
y += 1
x = y
first_x = True
arr[y][x] = b
if y == 0 or (first_x and y != rails - 1):
x = x + (rails - y - 1) * 2
first_x = False
elif y == rails - 1 or first_x is False:
x = x + (y * 2)
first_x = True
# dekodierten Text aus array holen
out = ""
x, y = 0, 0
down = True
for _ in range(len(cipher)):
out += arr[y][x]
x += 1
if down and y + 1 == rails:
down = False
y -= 1
elif down:
y += 1
elif down is False and y == 0:
down = True
y += 1
elif down is False:
y -= 1
return out
def jaegerzaun_decrypt():
eingabetext = Eingabe.get(1.0, END)
eingabetext = eingabetext.strip().replace("\n", " ")
pw = PW_Eingabe.get()
pw = pw.strip()
if eingabetext == "":
Ausgabe.insert(1.0, """HILFE: [decrypt Jägerzaun]
Jägerzaun (auch Railfence oder ZigZag-Chiffre genannt)
Bei dieser Chiffre wird kodiert, indem man einen Text im Zickzackmuster
in ein Feld aus z.B. 3 Zeilen und so vielen Spalten wie der Text lang ist
schreibt. Man beginnt in Spalte 1 - Zeile 1, dann geht es in Spalte 2 - Zeile 1
weiter danach Spalte 3 - Zeile 3, dann Spalte 4 - Zeile 2, Spalte 5 - Zeile 1 usw.
Danach werden die Buchstaben einfach Zeile für Zeile hintereinander geschrieben.
Unterschiedliche Varianten entstehen einfach dadurch, dass man mit unterschiedlich
vielen Zeilen arbeitet welche im Schlüsselfeld angegeben werden kann.
Die Funktion erzeugt hierbei einmal eine Ausgabe bei welcher auch Leerzeichen
mitgeschrieben werden und eine Ausgabe wo zuvor die Leerzeichen entfernt werden.
Wird im Schlüsselfeld keine Zahl angegeben erfolgt automatisch die Dekodierung
für alle Zeilenanzahlen von 2-12.""" + "\n\n")
elif pw == "":
for i in range(12, 1, -1):
Ausgabe.insert(1.0, f'{i:02} - {rail_decrypt(eingabetext.replace(" ", ""), i)}\n')
Ausgabe.insert(1.0, "ohne Leerzeichen\n", "bu")
for i in range(12, 1, -1):
Ausgabe.insert(1.0, f'{i:02} - {rail_decrypt(eingabetext, i)}\n')
Ausgabe.insert(1.0, "inkl. Leerzeichen\n", "bu")
elif not pw.isdigit():
Ausgabe.insert(1.0, "Bitte eine Zahl im Schlüsselfeld eingeben!!\n", "re")
else:
try:
if int(pw) < 2:
raise ValueError("Zahl zu klein")
Ausgabe.insert(1.0, rail_decrypt(eingabetext.replace(" ", ""), int(pw)) + "\n")
Ausgabe.insert(1.0, "ohne Leerzeichen\n", "bu")
Ausgabe.insert(1.0, rail_decrypt(eingabetext, int(pw)) + "\n")
Ausgabe.insert(1.0, "inkl. Leerzeichen\n", "bu")
except ValueError:
Ausgabe.insert(1.0, "Schlüsselzahl fehlerhaft oder kleiner als 2.\n", "re")
def adfgx_kodieren(): def adfgx_kodieren():
@@ -2946,309 +3242,6 @@ wird (A->Z + 0->9 oder 9->0 + Z->A).
Ausgabe.insert(1.0, "Passwort 1: {}\n".format(pw[0]), "gr") Ausgabe.insert(1.0, "Passwort 1: {}\n".format(pw[0]), "gr")
def zahlen_roemisch_arabisch_umwandeln():
hilfetext = """HILFE: [Römische in Arabische Zahlen umwandeln und umgekehrt]
Es werden römische Zahlen in arabische umgewandelt und umgekehrt, die Funktion
arbeitet dabei bei der Umwandlung von arabisch zu römisch mit Werten bis
maximal 500000. Es werden folgende Zeichen verwendet: I=1, V=5, X=10, L=50,
C=100, D=500, M=1000, \u2181=5000, \u2182=10000, \u2187=50000, \u2188=100000
Etwas Vorsicht sollte bei einer Umwandlung von römischen in arabische Zahlen
geboten sein, wenn mit untypischen Schreibweisen gearbeitet wird bei welchen
mehr als ein Zeichen von dem nachfolgenden Zeichen abgezogen werden soll.
Die eigentlich inkorrekte Schreibweise IIX für die Zahl 8 wird hier die Zahl
10 als Ergebnis haben (+1-1+10), dafür wird aber allerdings die ebenfalls
falsche Schreibweise IM genauso als 999 wie die korrekte Schreibweise CMXCIX
erkannt.
"""
rza = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000, '\u2181': 5000, '\u2182': 10000,
'\u2187': 50000, '\u2188': 100000}
azr = [(100000, '\u2188'), (90000, '\u2182\u2188'), (50000, '\u2187'), (40000, '\u2182\u2187'),
(10000, '\u2182'), (9000, 'M\u2182'), (5000, '\u2181'), (4000, 'M\u2181'), (1000, 'M'), (900, 'CM'),
(500, 'D'),
(400, 'CD'), (100, 'C'), (90, 'XC'), (50, 'L'), (40, 'XL'), (10, 'X'), (9, 'IX'), (5, 'V'), (4, 'IV'),
(1, 'I')]
eingabetext = Eingabe.get(1.0, END)
rz = eingabetext.rstrip()
if rz == "":
Ausgabe.insert(1.0, hilfetext + "\n")
else:
rz = rz.upper()
try:
az = 0
for i in range(len(rz)):
if i == len(rz) - 1:
az += rza[rz[i]]
Ausgabe.insert(1.0, "{} = {}\n".format(rz, az))
else:
if rza[rz[i]] < rza[rz[i + 1]]:
az -= rza[rz[i]]
else:
az += rza[rz[i]]
except KeyError:
try:
zahl = int(rz)
if zahl > 500000:
Ausgabe.insert(1.0, "arabische Zahlen größer als 500000 mag ich nicht in römische Zahlen!\n", "re")
return
rom = ""
for az, romz in azr:
count = zahl // az
zahl -= az * count
rom += romz * count
Ausgabe.insert(1.0, "{} = {}\n".format(rz, rom))
except ValueError:
Ausgabe.insert(1.0, "Es konnte keine römische oder arabische Zahl erkannt werden!\n", "re")
def url_decode():
eingabetext = Eingabe.get(1.0, END)
eingabetext = eingabetext.rstrip()
if eingabetext == "":
Ausgabe.insert(1.0, """HILFE: [URL-decode]
Nachdem Groundspeak nun inzwischen sämtliche Bilddateien
über einen Proxy umleitet bevor sie im Listing erscheinen
wird es manchmal schwer die ursprüngliche URL und/oder
den Dateinamen des Bildes noch lesen zu können.
Die URL hat dort nun jeweils folgendes Muster:
https://imgproxy.geocaching.com/......?url=.....
wobei nach dem ?url= dann die ursprüngliche Bild-URL
folgt, allerdings wird dabei dann aus
http:// folgendes http%3A%2F%2F und um genau dieses
wieder normal lesbar zu machen dient diese Funktion\n\n""")
else:
atxt = urllib_parse_unquote(eingabetext)
Ausgabe.insert(1.0, atxt + "\n")
Ausgabe.insert(1.0, "dekodierte URL:\n", "bu")
def reversewig():
seperator = ("|,", "_", "/", ";", ",")
eingabetext = Eingabe.get(1.0, END)
eingabetext = eingabetext.rstrip()
if eingabetext == "":
Ausgabe.insert(1.0, """HILFE: [Reverse Wherigo zu Koordinaten]
Mit dem Reverse Wherigo hat -Waldmeister- eigentlich eine coole Sache
erfunden. Man hat anfangs keine Koordinaten sondern nur 3 Zahlen, welche
man nach Start des Wherigo-Cartridges eingibt und dann erfährt man wie weit
der Cache entfernt ist. Nun kann man immer wieder von unterschiedlichen
Positionen aus diese Entfernungsfragen durchführen und sich damit dem
Cache nähern. Je weniger Abfragen man braucht umso besser.
Leider gibt es inzwischen genügend Tools die genau wie diese Funktion
hier aus den 3 Zahlen direkt die Finalkoordinaten ermitteln können.
Leider??? Ja leider denn das führt auch dazu, das es inzwischen so extrem
viele dieser Reverse-Wherigos gibt wo sich die Owner anscheinend auch
denken "Die spielt doch sowieso keiner mehr normal..." anders kann ich
mir ganze Trails mit Reverse-Wherigos nicht erklären.
Um die Funktion zu nutzen braucht man nur die 3 Zahlen durch ein entsprechendes
Trennzeichen: | , _ / ; , oder Leerzeichen eingeben und auf den Knopp klicken
und bekommt Koordinaten.
""" + "\n\n")
else:
se = ""
for s in seperator:
if s in eingabetext:
se = s
if se == "" and " " in eingabetext:
se = " "
if se == "":
Ausgabe.insert(1.0, "Keine gültiges Trennzeichen (, ; / _ | oder Leerzeichen) erkannt!\n", "re")
else:
txt = eingabetext.split(se)
if len(txt) == 3:
error = 0
for z in txt:
try:
int(z)
except ValueError:
Ausgabe.insert(1.0, "Bitte die Eingabezahlen überprüfen\n", "re")
error += 1
if error == 0:
final = rwig_to_coords(txt[0], txt[1], txt[2])
Ausgabe.insert(1.0, "DEG: " + dec_to_deg(final[0], final[1]) + "\n")
Ausgabe.insert(1.0, "DEC: " + str(final[0]) + " " + str(final[1]) + "\n")
Ausgabe.insert(1.0, "WIG: " + txt[0] + ", " + txt[1] + ", " + txt[2] + "\n")
else:
Ausgabe.insert(1.0, "Es wurden nicht 3 Zahlen erkannt.\n", "re")
def base64_ascii():
eingabetext = Eingabe.get(1.0, END)
eingabetext = eingabetext.rstrip()
if eingabetext == "":
Ausgabe.insert(1.0, """HILFE: [Base64 <-> ASCII]
Base64 ist ein Kodierungsverfahren, welches dazu verwendet wird
um beliebige Binärdaten nur Hilfe einer Zeichenkette aus A-Z,
a-z, 0-9, +, / sowie am Ende = übertragen zu können. Ein Einsatzzweck
dafür ist z.B. wenn bei EMails Dateianhänge verwendet werden, dort
werden nahezu alle Dateiformate base64-kodiert übertragen.
Auch bei dem einem oder anderen Mystery sind mir solche kodierten
Zeichenketten schon begegnet. Wenn am Ende einer Zeichenkette ein
oder zwei "="-Zeichen stehen ist die Wahrscheinlichkeit recht groß,
das hier base64 verwendet wurde. Das "="-Zeichen dient hier nämlich
als "Lückenfüller" am Ende.
Die Funktion hier versucht zunächst eine Dekodierung Base64->ASCII
gelingt dies nicht, erscheint ein Hinweis und der eingegeben Text
wird dann Base64-kodiert ausgegeben.
""" + "\n\n")
else:
try:
ascii_string = binascii.a2b_base64(eingabetext).decode()
Ausgabe.insert(1.0, ascii_string + "\n")
Ausgabe.insert(1.0, "Base64 -> ASCII:\n", "bu")
except ValueError:
base64_string = binascii.b2a_base64(eingabetext.encode())
Ausgabe.insert(1.0, base64_string.decode() + "\n")
Ausgabe.insert(1.0, "ASCII -> Base64:\n", "bu")
Ausgabe.insert(1.0, "Umwandlung Base64 -> ASCII war nicht möglich.\n", "re")
def rail_encrypt(plain_text: str, rails: int):
arr = [["" for _ in range(len(plain_text))] for _ in range(rails)]
r = 0
z = 0
plus = True
for b in plain_text:
arr[r][z] = b
z += 1
if r + 1 == rails and plus:
plus = False
r -= 1
elif r - 1 < 0 and not plus:
plus = True
r += 1
elif plus:
r += 1
else:
r -= 1
out = ""
for i in range(rails):
for j in range(len(plain_text)):
out += arr[i][j]
return out
def jaegerzaun_encrypt():
eingabetext = Eingabe.get(1.0, END)
eingabetext = eingabetext.strip().replace("\n", " ")
pw = PW_Eingabe.get()
pw = pw.strip()
if eingabetext == "":
Ausgabe.insert(1.0, """HILFE: [encrypt Jägerzaun]
Jägerzaun (auch Railfence oder ZigZag-Chiffre genannt)
Bei dieser Chiffre wird kodiert, indem man einen Text im Zickzackmuster
in ein Feld aus z.B. 3 Zeilen und so vielen Spalten wie der Text lang ist
schreibt. Man beginnt in Spalte 1 - Zeile 1, dann geht es in Spalte 2 - Zeile 1
weiter danach Spalte 3 - Zeile 3, dann Spalte 4 - Zeile 2, Spalte 5 - Zeile 1 usw.
Danach werden die Buchstaben einfach Zeile für Zeile hintereinander geschrieben.
Unterschiedliche Varianten entstehen einfach dadurch, dass man mit unterschiedlich
vielen Zeilen arbeitet welche im Schlüsselfeld anzugeben ist.
Die Funktion erzeugt hierbei einmal eine Ausgabe bei welcher auch Leerzeichen
mitgeschrieben werden und eine Ausgabe wo zuvor die Leerzeichen entfernt werden.
""" + "\n\n")
elif pw == "" or not pw.isdigit():
Ausgabe.insert(1.0, "Bitte eine Zahl im Schlüsselfeld eingeben!!\n", "re")
else:
try:
if int(pw) < 2:
raise ValueError("Zahl zu klein")
Ausgabe.insert(1.0, rail_encrypt(eingabetext.replace(" ", ""), int(pw)) + "\n")
Ausgabe.insert(1.0, "ohne Leerzeichen\n", "bu")
Ausgabe.insert(1.0, rail_encrypt(eingabetext, int(pw)) + "\n")
Ausgabe.insert(1.0, "inkl. Leerzeichen\n", "bu")
except ValueError:
Ausgabe.insert(1.0, "Schlüsselzahl fehlerhaft oder kleiner als 2.\n", "re")
def rail_decrypt(cipher: str, rails: int):
arr = [["_" for _ in range(len(cipher))] for _ in range(rails)]
# cipher ins array reinbasteln
x, y = 0, 0
first_x = True
for b in cipher:
if x >= len(cipher) and y < rails:
y += 1
x = y
first_x = True
arr[y][x] = b
if y == 0 or (first_x and y != rails - 1):
x = x + (rails - y - 1) * 2
first_x = False
elif y == rails - 1 or first_x is False:
x = x + (y * 2)
first_x = True
# dekodierten Text aus array holen
out = ""
x, y = 0, 0
down = True
for _ in range(len(cipher)):
out += arr[y][x]
x += 1
if down and y + 1 == rails:
down = False
y -= 1
elif down:
y += 1
elif down is False and y == 0:
down = True
y += 1
elif down is False:
y -= 1
return out
def jaegerzaun_decrypt():
eingabetext = Eingabe.get(1.0, END)
eingabetext = eingabetext.strip().replace("\n", " ")
pw = PW_Eingabe.get()
pw = pw.strip()
if eingabetext == "":
Ausgabe.insert(1.0, """HILFE: [decrypt Jägerzaun]
Jägerzaun (auch Railfence oder ZigZag-Chiffre genannt)
Bei dieser Chiffre wird kodiert, indem man einen Text im Zickzackmuster
in ein Feld aus z.B. 3 Zeilen und so vielen Spalten wie der Text lang ist
schreibt. Man beginnt in Spalte 1 - Zeile 1, dann geht es in Spalte 2 - Zeile 1
weiter danach Spalte 3 - Zeile 3, dann Spalte 4 - Zeile 2, Spalte 5 - Zeile 1 usw.
Danach werden die Buchstaben einfach Zeile für Zeile hintereinander geschrieben.
Unterschiedliche Varianten entstehen einfach dadurch, dass man mit unterschiedlich
vielen Zeilen arbeitet welche im Schlüsselfeld angegeben werden kann.
Die Funktion erzeugt hierbei einmal eine Ausgabe bei welcher auch Leerzeichen
mitgeschrieben werden und eine Ausgabe wo zuvor die Leerzeichen entfernt werden.
Wird im Schlüsselfeld keine Zahl angegeben erfolgt automatisch die Dekodierung
für alle Zeilenanzahlen von 2-12.""" + "\n\n")
elif pw == "":
for i in range(12, 1, -1):
Ausgabe.insert(1.0, f'{i:02} - {rail_decrypt(eingabetext.replace(" ", ""), i)}\n')
Ausgabe.insert(1.0, "ohne Leerzeichen\n", "bu")
for i in range(12, 1, -1):
Ausgabe.insert(1.0, f'{i:02} - {rail_decrypt(eingabetext, i)}\n')
Ausgabe.insert(1.0, "inkl. Leerzeichen\n", "bu")
elif not pw.isdigit():
Ausgabe.insert(1.0, "Bitte eine Zahl im Schlüsselfeld eingeben!!\n", "re")
else:
try:
if int(pw) < 2:
raise ValueError("Zahl zu klein")
Ausgabe.insert(1.0, rail_decrypt(eingabetext.replace(" ", ""), int(pw)) + "\n")
Ausgabe.insert(1.0, "ohne Leerzeichen\n", "bu")
Ausgabe.insert(1.0, rail_decrypt(eingabetext, int(pw)) + "\n")
Ausgabe.insert(1.0, "inkl. Leerzeichen\n", "bu")
except ValueError:
Ausgabe.insert(1.0, "Schlüsselzahl fehlerhaft oder kleiner als 2.\n", "re")
def brainfuck_interpreter(): def brainfuck_interpreter():
eingabetext = Eingabe.get(1.0, END) eingabetext = Eingabe.get(1.0, END)
eingabetext = eingabetext.rstrip() eingabetext = eingabetext.rstrip()