703 lines
22 KiB
Python
703 lines
22 KiB
Python
#!/usr/bin/env python3
|
||
|
||
import random
|
||
import time
|
||
import json
|
||
import os
|
||
import subprocess
|
||
from datetime import datetime
|
||
|
||
|
||
# ============================================================
|
||
# EINSTELLUNGEN
|
||
# ============================================================
|
||
|
||
# Durchschnittlicher Abstand zwischen zwei Funfacts
|
||
AVERAGE_HOURS = 2
|
||
|
||
# Niemals kürzer als diese Zeit warten
|
||
MIN_WAIT_MINUTES = 5
|
||
|
||
# Wie viele bereits gezeigte Facts gespeichert werden
|
||
HISTORY_SIZE = 200
|
||
|
||
# Datei für die History
|
||
HISTORY_FILE = os.path.expanduser(
|
||
"~/.tech_funfacts_history.json"
|
||
)
|
||
|
||
|
||
# ============================================================
|
||
# FUNFACTS
|
||
# ============================================================
|
||
|
||
FUNFACTS = [
|
||
|
||
# ---------------- INTERNET ----------------
|
||
|
||
"Es gibt tatsächlich einen offiziellen Standard für Netzwerkpakete per Brieftaube: RFC 1149 aus dem Jahr 1990.",
|
||
|
||
"Die erste registrierte Domain der Welt war symbolics.com. Sie wurde am 15. März 1985 registriert.",
|
||
|
||
"Die erste E-Mail wurde 1971 von Ray Tomlinson verschickt.",
|
||
|
||
"Ray Tomlinson verwendete das @-Zeichen, um Benutzer und Computer voneinander zu trennen.",
|
||
|
||
"Das Internet und das World Wide Web sind nicht dasselbe. Das Web ist nur ein Dienst, der das Internet benutzt.",
|
||
|
||
"Das World Wide Web wurde 1989 von Tim Berners-Lee vorgeschlagen.",
|
||
|
||
"Die erste Website der Welt war info.cern.ch.",
|
||
|
||
"Die erste Webcam wurde benutzt, um den Füllstand einer Kaffeemaschine zu überwachen.",
|
||
|
||
"Das ARPANET war einer der wichtigsten Vorläufer des heutigen Internets.",
|
||
|
||
"Der erste ARPANET-Versuch zwischen UCLA und Stanford sollte das Wort LOGIN übertragen. Nach den ersten zwei Buchstaben stürzte das System ab.",
|
||
|
||
"IPv4 besitzt etwa 4,3 Milliarden mögliche Adressen.",
|
||
|
||
"IPv6 besitzt ungefähr 340 Sextillionen mögliche Adressen.",
|
||
|
||
"Eine IPv6-Adresse kann 128 Bit lang sein.",
|
||
|
||
"DNS übersetzt normalerweise Domainnamen wie example.com in IP-Adressen.",
|
||
|
||
"DNS steht für Domain Name System.",
|
||
|
||
"HTTP steht für Hypertext Transfer Protocol.",
|
||
|
||
"HTTPS verwendet normalerweise TLS, um die Verbindung zwischen Browser und Server zu verschlüsseln.",
|
||
|
||
"Ein Ping verwendet normalerweise ICMP und nicht TCP.",
|
||
|
||
"Der Begriff Spam für unerwünschte Nachrichten wurde durch Monty-Python-Sketches inspiriert.",
|
||
|
||
"Der erste große Internet-Wurm hieß Morris Worm und verbreitete sich 1988.",
|
||
|
||
|
||
# ---------------- COMPUTER-GESCHICHTE ----------------
|
||
|
||
"Der erste bekannte Computer-Bug war tatsächlich eine Motte. Sie wurde 1947 aus einem Relais eines Harvard-Mark-II-Computers entfernt.",
|
||
|
||
"Die erste Festplatte von IBM wurde 1956 vorgestellt.",
|
||
|
||
"Die IBM 350 Disk Storage Unit von 1956 konnte ungefähr 5 Megabyte speichern.",
|
||
|
||
"Die IBM 350 von 1956 wog ungefähr eine Tonne.",
|
||
|
||
"Ein modernes Smartphone besitzt mehr Rechenleistung als viele Computer aus der Apollo-Ära.",
|
||
|
||
"ENIAC wurde 1945 fertiggestellt und war einer der ersten großen elektronischen Universalcomputer.",
|
||
|
||
"ENIAC verwendete ungefähr 18.000 Elektronenröhren.",
|
||
|
||
"Die ersten Computer waren teilweise so groß, dass sie ganze Räume füllten.",
|
||
|
||
"Der Begriff Computer bezeichnete ursprünglich tatsächlich Menschen, die Berechnungen durchführten.",
|
||
|
||
"Konrad Zuse entwickelte mit der Z3 einen der ersten funktionsfähigen, programmierbaren Computer.",
|
||
|
||
"Die Z3 von Konrad Zuse wurde 1941 fertiggestellt.",
|
||
|
||
"Die Z3 verwendete Relais statt moderner Transistoren.",
|
||
|
||
"Der erste kommerziell erfolgreiche Mikroprozessor war der Intel 4004.",
|
||
|
||
"Der Intel 4004 erschien 1971.",
|
||
|
||
"Der Intel 4004 war ein 4-Bit-Prozessor.",
|
||
|
||
"Der Intel 4004 hatte nur etwa 2.300 Transistoren.",
|
||
|
||
"Moderne CPUs besitzen dagegen Milliarden von Transistoren.",
|
||
|
||
"Der Begriff CPU steht für Central Processing Unit.",
|
||
|
||
"RAM steht für Random Access Memory.",
|
||
|
||
"ROM steht für Read-Only Memory.",
|
||
|
||
|
||
# ---------------- HARDWARE ----------------
|
||
|
||
"Eine moderne CPU kann Milliarden Transistoren enthalten.",
|
||
|
||
"Ein Transistor kann vereinfacht als elektronischer Schalter betrachtet werden.",
|
||
|
||
"Moderne Prozessoren bestehen aus Milliarden winziger Schalter.",
|
||
|
||
"CPUs werden häufig in Nanometern gefertigt. Diese Zahl beschreibt heute nicht einfach die tatsächliche Größe eines einzelnen Transistors.",
|
||
|
||
"Eine CPU mit 3 GHz hat einen Takt von ungefähr drei Milliarden Zyklen pro Sekunde.",
|
||
|
||
"GHz bedeutet Gigahertz.",
|
||
|
||
"1 Gigahertz entspricht einer Milliarde Hertz.",
|
||
|
||
"RAM verliert seinen Inhalt normalerweise, wenn die Stromversorgung abgeschaltet wird.",
|
||
|
||
"SSDs besitzen keine beweglichen mechanischen Schreib-Leseköpfe.",
|
||
|
||
"HDDs speichern Daten magnetisch auf rotierenden Scheiben.",
|
||
|
||
"Eine klassische Festplatte kann mehrere rotierende Magnetscheiben enthalten.",
|
||
|
||
"SSDs verwenden Flash-Speicher.",
|
||
|
||
"Flash-Speicher kann Daten auch ohne permanente Stromversorgung behalten.",
|
||
|
||
"USB steht für Universal Serial Bus.",
|
||
|
||
"USB wurde unter anderem entwickelt, um die große Anzahl verschiedener PC-Anschlüsse zu reduzieren.",
|
||
|
||
"USB-C beschreibt hauptsächlich einen Stecker und nicht automatisch die Geschwindigkeit oder Leistung eines Geräts.",
|
||
|
||
"Ein USB-C-Anschluss kann je nach Gerät USB 2, USB 3, USB4, Thunderbolt oder andere Funktionen unterstützen.",
|
||
|
||
"PCI Express wird häufig verwendet, um Grafikkarten und andere schnelle Erweiterungskarten anzubinden.",
|
||
|
||
"NVMe wurde speziell für schnelle Speichergeräte über PCI Express entwickelt.",
|
||
|
||
"Eine NVMe-SSD kommuniziert nicht einfach über SATA, sondern verwendet normalerweise PCI Express.",
|
||
|
||
|
||
# ---------------- LINUX ----------------
|
||
|
||
"Linux wurde 1991 von Linus Torvalds begonnen.",
|
||
|
||
"Linux hieß ursprünglich nicht als fertiges Betriebssystem Linux. Linus Torvalds entwickelte zunächst den Kernel.",
|
||
|
||
"Android verwendet den Linux-Kernel.",
|
||
|
||
"Linux läuft auf Smartphones, Servern, Routern, Supercomputern, Fernsehern und vielen eingebetteten Geräten.",
|
||
|
||
"Ein großer Teil der weltweit leistungsstärksten Supercomputer verwendet Linux.",
|
||
|
||
"Der Linux-Kernel ist Open Source.",
|
||
|
||
"GNU und Linux sind technisch gesehen unterschiedliche Projekte.",
|
||
|
||
"Viele Linux-Distributionen verwenden GNU-Programme zusammen mit dem Linux-Kernel.",
|
||
|
||
"Arch Linux verwendet standardmäßig den Paketmanager pacman.",
|
||
|
||
"Der Linux-Befehl chmod kann die Zugriffsrechte einer Datei verändern.",
|
||
|
||
"Der Befehl ps kann laufende Prozesse anzeigen.",
|
||
|
||
"Der Befehl top kann laufende Prozesse und Systemauslastung anzeigen.",
|
||
|
||
"htop ist eine interaktive Alternative zu top.",
|
||
|
||
"Unter Linux wird nahezu alles als Datei oder über dateiähnliche Schnittstellen dargestellt.",
|
||
|
||
"Die Verzeichnisstruktur von Linux beginnt bei /.",
|
||
|
||
"Das Home-Verzeichnis eines Benutzers liegt normalerweise unter /home.",
|
||
|
||
"Der Linux-Kernel kann während des Betriebs Informationen über /proc bereitstellen.",
|
||
|
||
"Linux besitzt ein virtuelles Dateisystem namens sysfs.",
|
||
|
||
"Viele Hardwareinformationen können unter Linux über virtuelle Dateisysteme ausgelesen werden.",
|
||
|
||
"Ein Linux-System kann vollständig ohne grafische Oberfläche betrieben werden.",
|
||
|
||
|
||
# ---------------- NETZWERK ----------------
|
||
|
||
"Ein Ethernet-Kabel kann Daten übertragen, obwohl die Daten im Kabel als elektrische Signale dargestellt werden.",
|
||
|
||
"WLAN steht für Wireless Local Area Network.",
|
||
|
||
"LAN steht für Local Area Network.",
|
||
|
||
"WAN steht für Wide Area Network.",
|
||
|
||
"MAC-Adressen sind normalerweise 48 Bit lang.",
|
||
|
||
"Eine IPv4-Adresse besteht aus 32 Bit.",
|
||
|
||
"Eine IPv6-Adresse besteht aus 128 Bit.",
|
||
|
||
"Ein /24-IPv4-Netz enthält theoretisch 256 Adressen.",
|
||
|
||
"Bei einem normalen /24-Netz sind klassischerweise zwei Adressen für Netzwerk und Broadcast reserviert.",
|
||
|
||
"127.0.0.1 bezeichnet normalerweise den eigenen Computer.",
|
||
|
||
"Die Adresse 0.0.0.0 kann je nach Kontext eine besondere Bedeutung haben, beispielsweise als nicht spezifizierte Adresse.",
|
||
|
||
"192.168.0.0/16 gehört zu den privaten IPv4-Adressbereichen.",
|
||
|
||
"10.0.0.0/8 gehört zu den privaten IPv4-Adressbereichen.",
|
||
|
||
"172.16.0.0/12 gehört zu den privaten IPv4-Adressbereichen.",
|
||
|
||
"Router verbinden unterschiedliche Netzwerke miteinander.",
|
||
|
||
"Switches verbinden Geräte innerhalb eines lokalen Netzwerks.",
|
||
|
||
"Ein Switch arbeitet hauptsächlich auf Layer 2 des OSI-Modells.",
|
||
|
||
"Router arbeiten hauptsächlich auf Layer 3 des OSI-Modells.",
|
||
|
||
"TCP ist verbindungsorientiert.",
|
||
|
||
"UDP ist verbindungslos und besitzt weniger Overhead als TCP.",
|
||
|
||
|
||
# ---------------- PROGRAMMIERUNG ----------------
|
||
|
||
"Python wurde nach der Comedy-Gruppe Monty Python benannt und nicht nach einer Schlange.",
|
||
|
||
"Python wurde erstmals 1991 veröffentlicht.",
|
||
|
||
"C wurde in den frühen 1970er-Jahren bei Bell Labs entwickelt.",
|
||
|
||
"C++ entstand als Erweiterung der Programmiersprache C.",
|
||
|
||
"JavaScript und Java sind trotz ihrer Namen unterschiedliche Programmiersprachen.",
|
||
|
||
"HTML ist keine klassische Programmiersprache, sondern eine Auszeichnungssprache.",
|
||
|
||
"CSS wird hauptsächlich verwendet, um das Aussehen von Webseiten zu beschreiben.",
|
||
|
||
"SQL wird verwendet, um mit relationalen Datenbanken zu arbeiten.",
|
||
|
||
"Git wurde ursprünglich von Linus Torvalds entwickelt.",
|
||
|
||
"Git wurde ursprünglich für die Entwicklung des Linux-Kernels entwickelt.",
|
||
|
||
"Ein Compiler übersetzt Quellcode normalerweise in eine andere Form, beispielsweise Maschinencode oder Bytecode.",
|
||
|
||
"Ein Interpreter führt Code vereinfacht gesagt direkt bzw. über eine Laufzeitumgebung aus.",
|
||
|
||
"Ein Algorithmus ist eine eindeutig beschriebene Vorgehensweise zur Lösung eines Problems.",
|
||
|
||
"Ein Bit kann grundsätzlich zwei Zustände darstellen: 0 oder 1.",
|
||
|
||
"Ein Byte besteht normalerweise aus 8 Bit.",
|
||
|
||
"1 Kilobyte kann je nach Definition 1.000 oder 1.024 Bytes bedeuten.",
|
||
|
||
"1 Kibibyte entspricht exakt 1.024 Bytes.",
|
||
|
||
"1 Megabyte entspricht im SI-System 1.000.000 Bytes.",
|
||
|
||
"1 MiB entspricht exakt 1.048.576 Bytes.",
|
||
|
||
"Binärzahlen verwenden nur die Ziffern 0 und 1.",
|
||
|
||
|
||
# ---------------- ZEIT / DATEN ----------------
|
||
|
||
"Unix-Zeit zählt normalerweise Sekunden seit dem 1. Januar 1970.",
|
||
|
||
"Der sogenannte Year-2038-Bug betrifft Systeme, die Unix-Zeit in einem signierten 32-Bit-Wert speichern.",
|
||
|
||
"Am 19. Januar 2038 erreicht ein klassischer signierter 32-Bit-Unix-Zeitstempel sein Maximum.",
|
||
|
||
"Ein 64-Bit-Unix-Zeitstempel kann für sehr lange Zeiträume verwendet werden.",
|
||
|
||
"Computer speichern Zeit häufig nicht so, wie Menschen sie auf einer Uhr sehen.",
|
||
|
||
"Zeitzonen machen Zeitberechnungen in Computersystemen deutlich komplizierter.",
|
||
|
||
"UTC steht für Coordinated Universal Time.",
|
||
|
||
"NTP kann verwendet werden, um Computeruhren über Netzwerke zu synchronisieren.",
|
||
|
||
"GPS-Satelliten benötigen extrem genaue Zeitmessung.",
|
||
|
||
"Schaltsekunden können bei Computersystemen zu unerwarteten Problemen führen.",
|
||
|
||
|
||
# ---------------- SICHERHEIT ----------------
|
||
|
||
"Ein Passwort muss nicht nur lang, sondern auch möglichst einzigartig sein.",
|
||
|
||
"Passwort-Hashing ist etwas anderes als Verschlüsselung.",
|
||
|
||
"Ein guter Passwort-Hash soll nicht einfach wieder in das ursprüngliche Passwort zurückgerechnet werden können.",
|
||
|
||
"Salts werden beim Passwort-Hashing verwendet, damit identische Passwörter nicht denselben Hash erzeugen.",
|
||
|
||
"HTTPS bedeutet nicht automatisch, dass eine Website vertrauenswürdig ist. Es schützt hauptsächlich die Verbindung.",
|
||
|
||
"Ein Vorhängeschloss im Browser bedeutet nicht automatisch, dass eine Website seriös ist.",
|
||
|
||
"Zwei-Faktor-Authentifizierung kann einen zusätzlichen Schutz bieten, selbst wenn ein Passwort bekannt wird.",
|
||
|
||
"SSH steht für Secure Shell.",
|
||
|
||
"SSH wird häufig verwendet, um Linux-Server remote zu verwalten.",
|
||
|
||
"Ein SSH-Schlüssel kann zur Authentifizierung verwendet werden, ohne jedes Mal ein Passwort einzugeben.",
|
||
|
||
|
||
# ---------------- DATEIEN / SPEICHER ----------------
|
||
|
||
"Eine Datei mit der Endung .jpg muss nicht zwingend ein Bild sein. Die Endung ist nur eine Namenskonvention.",
|
||
|
||
"ZIP-Dateien können mehrere Dateien und Verzeichnisse in einem Archiv zusammenfassen.",
|
||
|
||
"Kompression kann Daten kleiner machen, ohne sie zu verändern, oder Informationen entfernen, um noch kleinere Dateien zu erzeugen.",
|
||
|
||
"PNG verwendet verlustfreie Kompression.",
|
||
|
||
"JPEG verwendet normalerweise verlustbehaftete Kompression.",
|
||
|
||
"FLAC ist ein verlustfreies Audioformat.",
|
||
|
||
"MP3 verwendet verlustbehaftete Audiokompression.",
|
||
|
||
"Eine Datei kann gelöscht werden, obwohl ihre Daten auf einem Datenträger noch nicht sofort überschrieben wurden.",
|
||
|
||
"Dateisysteme speichern zusätzliche Informationen wie Dateigröße, Besitzer und Änderungszeit.",
|
||
|
||
"ext4 ist ein weit verbreitetes Linux-Dateisystem.",
|
||
|
||
|
||
# ---------------- WEIRD / FUN ----------------
|
||
|
||
"Es gibt einen offiziellen Internetstandard für die Übertragung von IP-Paketen mit Brieftauben.",
|
||
|
||
"Ein Computer kann theoretisch eine komplette Festplatte mit Nullen überschreiben, obwohl diese Nullen keine sichtbaren Informationen enthalten.",
|
||
|
||
"Der Name CAPTCHA steht für Completely Automated Public Turing test to tell Computers and Humans Apart.",
|
||
|
||
"CAPTCHAs wurden entwickelt, um Menschen und automatisierte Programme voneinander zu unterscheiden.",
|
||
|
||
"QR-Codes können auch dann noch funktionieren, wenn ein Teil des Codes beschädigt ist.",
|
||
|
||
"QR-Codes wurden ursprünglich für die Automobilindustrie entwickelt.",
|
||
|
||
"Der erste Computermonitor war noch weit von heutigen 4K-Displays entfernt.",
|
||
|
||
"Frühe Computerspiele konnten mit wenigen Kilobyte auskommen.",
|
||
|
||
"Das Spiel DOOM von 1993 war klein genug, dass seine Größe nach heutigen Maßstäben geradezu lächerlich wirkt.",
|
||
|
||
"Tetris wurde ursprünglich 1984 von Alexei Paschitnow entwickelt.",
|
||
|
||
"Der Game-Boy-Prozessor lief nur mit wenigen Megahertz.",
|
||
|
||
"Moderne Grafikkarten besitzen tausende Recheneinheiten.",
|
||
|
||
"Eine GPU kann viele Berechnungen parallel durchführen und ist deshalb besonders gut für bestimmte mathematische Aufgaben geeignet.",
|
||
|
||
"Minecraft-Welten können extrem große Koordinatenbereiche besitzen.",
|
||
|
||
"Ein Pixel ist ein einzelnes Bildelement eines digitalen Bildes.",
|
||
|
||
"4K bedeutet bei Video nicht immer exakt dieselbe Auflösung. Im TV-Bereich ist 3840×2160 üblich.",
|
||
|
||
"Ein 1080p-Bild besitzt ungefähr zwei Millionen Pixel.",
|
||
|
||
"Ein 4K-UHD-Bild besitzt ungefähr acht Millionen Pixel.",
|
||
|
||
"Ein 8K-UHD-Bild besitzt ungefähr 33 Millionen Pixel.",
|
||
|
||
|
||
# ---------------- WEITERE TECH-FACTS ----------------
|
||
|
||
"Bluetooth und WLAN verwenden beide Funktechnik, sind aber für unterschiedliche Einsatzzwecke optimiert.",
|
||
|
||
"Bluetooth wurde ursprünglich nach Harald Blauzahn, einem dänischen König, benannt.",
|
||
|
||
"Das Bluetooth-Logo kombiniert Runen, die für Harald Blauzahn stehen.",
|
||
|
||
"ASCII verwendet ursprünglich 7 Bit pro Zeichen.",
|
||
|
||
"ASCII kann deshalb 128 verschiedene Werte darstellen.",
|
||
|
||
"Unicode wurde entwickelt, um Zeichen aus sehr vielen Schriftsystemen darstellen zu können.",
|
||
|
||
"UTF-8 kann ASCII-Zeichen direkt darstellen.",
|
||
|
||
"UTF-8 ist heute eine der wichtigsten Zeichenkodierungen im Internet.",
|
||
|
||
"Ein Emoji ist technisch gesehen nicht einfach nur ein einzelnes Byte.",
|
||
|
||
"Die Zahl 255 ist in Binärdarstellung 11111111.",
|
||
|
||
"Die Zahl 256 ist 2 hoch 8.",
|
||
|
||
"Ein 32-Bit-Wert kann 2 hoch 32 verschiedene Bitmuster darstellen.",
|
||
|
||
"Ein 64-Bit-Wert kann 2 hoch 64 verschiedene Bitmuster darstellen.",
|
||
|
||
"2 hoch 64 ist 18.446.744.073.709.551.616.",
|
||
|
||
"Ein einzelnes Bit ist die kleinste klassische Informationseinheit in einem Binärsystem.",
|
||
|
||
"Computer verwenden Binärlogik, weil elektronische Schaltungen besonders gut zwischen zwei Zuständen unterscheiden können.",
|
||
|
||
"Ein CPU-Cache ist deutlich schneller als der normale Arbeitsspeicher, aber auch wesentlich kleiner.",
|
||
|
||
"L1-Cache ist normalerweise kleiner und schneller als L2-Cache.",
|
||
|
||
"L3-Cache ist normalerweise größer und langsamer als L1-Cache.",
|
||
|
||
"Moderne CPUs können mehrere Cache-Ebenen besitzen.",
|
||
|
||
|
||
# ---------------- DYNAMIC FACTS ----------------
|
||
|
||
"Seit dem Start des Unix-Zeitstempels am 1. Januar 1970 sind bereits {unix_days} Tage vergangen.",
|
||
|
||
"Seit der ersten E-Mail von Ray Tomlinson sind ungefähr {email_days} Tage vergangen.",
|
||
|
||
"Die erste E-Mail wurde 1971 verschickt. Das ist inzwischen mehr als ein halbes Jahrhundert her.",
|
||
|
||
"Der Unix-Zeitstempel startete am 1. Januar 1970. Heute sind bereits {unix_seconds} Sekunden seit diesem Zeitpunkt vergangen.",
|
||
|
||
"Bis zum Year-2038-Problem sind es noch ungefähr {days_until_2038} Tage.",
|
||
|
||
"Der erste Webserver wurde am CERN betrieben. Das World Wide Web ist inzwischen Jahrzehnte alt.",
|
||
|
||
]
|
||
|
||
|
||
# ============================================================
|
||
# DYNAMISCHE FAKTEN
|
||
# ============================================================
|
||
|
||
def replace_dynamic(text):
|
||
|
||
now = datetime.now()
|
||
|
||
# Unix-Tage
|
||
unix_start = datetime(1970, 1, 1)
|
||
unix_seconds = int((now - unix_start).total_seconds())
|
||
unix_days = (now - unix_start).days
|
||
|
||
# Erste E-Mail
|
||
# Ray Tomlinsons erste Netzwerknachricht wird meist auf 1971 datiert.
|
||
email_date = datetime(1971, 10, 29)
|
||
email_days = (now - email_date).days
|
||
|
||
# Year 2038
|
||
y2038 = datetime(2038, 1, 19, 3, 14, 7)
|
||
days_until_2038 = (y2038 - now).days
|
||
|
||
replacements = {
|
||
"{unix_seconds}": f"{unix_seconds:,}".replace(",", "."),
|
||
"{unix_days}": f"{unix_days:,}".replace(",", "."),
|
||
"{email_days}": f"{email_days:,}".replace(",", "."),
|
||
"{days_until_2038}": f"{days_until_2038:,}".replace(",", "."),
|
||
}
|
||
|
||
for placeholder, value in replacements.items():
|
||
text = text.replace(placeholder, value)
|
||
|
||
return text
|
||
|
||
|
||
# ============================================================
|
||
# HISTORY LADEN
|
||
# ============================================================
|
||
|
||
def load_history():
|
||
|
||
if not os.path.exists(HISTORY_FILE):
|
||
return []
|
||
|
||
try:
|
||
with open(HISTORY_FILE, "r", encoding="utf-8") as file:
|
||
data = json.load(file)
|
||
|
||
if isinstance(data, list):
|
||
return data
|
||
|
||
except (json.JSONDecodeError, OSError):
|
||
pass
|
||
|
||
return []
|
||
|
||
|
||
# ============================================================
|
||
# HISTORY SPEICHERN
|
||
# ============================================================
|
||
|
||
def save_history(history):
|
||
|
||
try:
|
||
with open(HISTORY_FILE, "w", encoding="utf-8") as file:
|
||
json.dump(
|
||
history,
|
||
file,
|
||
ensure_ascii=False,
|
||
indent=2
|
||
)
|
||
|
||
except OSError as error:
|
||
print(f"Fehler beim Speichern der History: {error}")
|
||
|
||
|
||
# ============================================================
|
||
# NOTIFICATION
|
||
# ============================================================
|
||
|
||
def notify(text):
|
||
|
||
try:
|
||
|
||
subprocess.run(
|
||
[
|
||
"notify-send",
|
||
"IT Funfact",
|
||
text
|
||
],
|
||
check=False
|
||
)
|
||
|
||
except FileNotFoundError:
|
||
|
||
print(
|
||
"FEHLER: notify-send wurde nicht gefunden."
|
||
)
|
||
|
||
except Exception as error:
|
||
|
||
print(
|
||
f"Fehler beim Anzeigen der Notification: {error}"
|
||
)
|
||
|
||
|
||
# ============================================================
|
||
# ZUFÄLLIGE WARTEZEIT
|
||
# ============================================================
|
||
|
||
def random_wait():
|
||
|
||
# Exponentialverteilung:
|
||
#
|
||
# Durchschnitt = 6 Stunden
|
||
#
|
||
# Dadurch entstehen absichtlich sehr unterschiedliche
|
||
# Abstände.
|
||
#
|
||
# Beispiel:
|
||
# 20 Minuten
|
||
# 2 Stunden
|
||
# 7 Stunden
|
||
# 13 Stunden
|
||
# usw.
|
||
#
|
||
# Extrem lange/kürzere Abstände sind möglich.
|
||
|
||
average_seconds = AVERAGE_HOURS * 60 * 60
|
||
|
||
seconds = random.expovariate(
|
||
1 / average_seconds
|
||
)
|
||
|
||
minimum_seconds = MIN_WAIT_MINUTES * 60
|
||
|
||
return max(
|
||
seconds,
|
||
minimum_seconds
|
||
)
|
||
|
||
|
||
# ============================================================
|
||
# EINEN ZUFÄLLIGEN FACT AUSWÄHLEN
|
||
# ============================================================
|
||
|
||
def choose_fact(history):
|
||
|
||
# Bereits angezeigte Facts vermeiden
|
||
available = [
|
||
fact
|
||
for fact in FUNFACTS
|
||
if fact not in history
|
||
]
|
||
|
||
# Wenn alle Facts irgendwann angezeigt wurden:
|
||
# History zurücksetzen.
|
||
if not available:
|
||
|
||
print(
|
||
"Alle Funfacts wurden bereits angezeigt."
|
||
)
|
||
|
||
history.clear()
|
||
|
||
available = FUNFACTS
|
||
|
||
return random.choice(available)
|
||
|
||
|
||
# ============================================================
|
||
# HAUPTPROGRAMM
|
||
# ============================================================
|
||
|
||
def main():
|
||
|
||
print()
|
||
print("=" * 60)
|
||
print(" IT FUNFACTS")
|
||
print("=" * 60)
|
||
print()
|
||
print(f"Funfacts insgesamt: {len(FUNFACTS)}")
|
||
print(f"Durchschnittliches Intervall: {AVERAGE_HOURS} Stunden")
|
||
print(f"History: {HISTORY_FILE}")
|
||
print()
|
||
print("Programm läuft...")
|
||
print("Mit Ctrl+C beenden.")
|
||
print()
|
||
|
||
history = load_history()
|
||
|
||
try:
|
||
|
||
while True:
|
||
|
||
wait_time = random_wait()
|
||
|
||
print(
|
||
f"Nächster Funfact in "
|
||
f"{wait_time / 3600:.2f} Stunden."
|
||
)
|
||
|
||
time.sleep(wait_time)
|
||
|
||
fact = choose_fact(history)
|
||
|
||
fact = replace_dynamic(fact)
|
||
|
||
print()
|
||
print("FUNFACT:")
|
||
print(fact)
|
||
print()
|
||
|
||
notify(fact)
|
||
|
||
# Den fertigen Text speichern.
|
||
# Dadurch wird auch verhindert,
|
||
# dass derselbe dynamische Fact direkt
|
||
# wieder erscheint.
|
||
history.append(fact)
|
||
|
||
# History begrenzen
|
||
history = history[-HISTORY_SIZE:]
|
||
|
||
save_history(history)
|
||
|
||
except KeyboardInterrupt:
|
||
|
||
print()
|
||
print("Funfacts beendet.")
|
||
print()
|
||
|
||
|
||
# ============================================================
|
||
# START
|
||
# ============================================================
|
||
|
||
if __name__ == "__main__":
|
||
main()
|