]*>(.*?)<\/p>/s', $text, $p_matches);
$replacements_done = 0;
if (!empty($p_matches[0])) {
$paragraphs_count = count($p_matches[0]);
// Indizes für ersten und vorletzten Absatz
$first_index = 0;
$last_index = max(0, $paragraphs_count - 2); // Vorletzter Absatz statt letzter
// Positionen für die Ersetzung
$positions_to_process = array($first_index, $last_index);
foreach ($positions_to_process as $index) {
// Aktueller Absatz
$p_tag = $p_matches[0][$index];
$p_content = $p_matches[1][$index];
// Wörter mit Großbuchstaben im Absatz finden
if (preg_match_all('/\b([A-ZÄÖÜ][a-zäöüß]{2,})\b/u', $p_content, $word_matches)) {
if (!empty($word_matches[0])) {
// Ein Wort aus der Mitte nehmen, nicht das erste
$word_count = count($word_matches[0]);
$middle_index = intval($word_count / 2); // Wort aus der Mitte nehmen
$word = $word_matches[0][$middle_index > 0 ? $middle_index : 0];
// Durchstreichen und groß daneben schreiben
$replacement = '' . $word . ' ' . strtoupper($word) . '';
$new_content = preg_replace('/\b' . preg_quote($word, '/') . '\b/u', $replacement, $p_content, 1);
// Im Text ersetzen
$new_p_tag = str_replace($p_content, $new_content, $p_tag);
$text = str_replace($p_tag, $new_p_tag, $text);
$replacements_done++;
} else {
// Wenn keine Wörter mit Großbuchstaben, nimm ein längeres Wort aus der Mitte
if (preg_match_all('/\b([a-zA-ZäöüÄÖÜß]{4,})\b/u', $p_content, $alt_word_matches)) {
if (!empty($alt_word_matches[0])) {
// Ein Wort aus der Mitte nehmen, nicht das erste
$word_count = count($alt_word_matches[0]);
$middle_index = intval($word_count / 2); // Wort aus der Mitte nehmen
$word = $alt_word_matches[0][$middle_index > 0 ? $middle_index : 0];
// Durchstreichen und groß daneben schreiben
$replacement = '' . $word . ' ' . strtoupper($word) . '';
$new_content = preg_replace('/\b' . preg_quote($word, '/') . '\b/u', $replacement, $p_content, 1);
// Im Text ersetzen
$new_p_tag = str_replace($p_content, $new_content, $p_tag);
$text = str_replace($p_tag, $new_p_tag, $text);
$replacements_done++;
}
}
}
}
}
}
// NEU: 0.2 JAHRESZAHL-KORREKTUR - DURCHSTREICHEN UND "ACH QUATSCH" (1x pro Text)
$year_corrected = false; // Flag zur Kontrolle, ob bereits korrigiert wurde
$date_pattern = '/\b(20\d\d|19\d\d)\b/'; // Findet Jahreszahlen wie 2024, 1999, etc.
if (!$year_corrected && preg_match_all($date_pattern, $text, $matches, PREG_OFFSET_CAPTURE)) {
if (!empty($matches[0])) {
// Zufällige Jahreszahl auswählen
$random_match_index = array_rand($matches[0]);
$year = $matches[0][$random_match_index][0];
$position = $matches[0][$random_match_index][1];
// Ein Jahr weniger für die "falsche" Jahreszahl
$wrong_year = $year - 1;
// Selbstkorrektur-Text erstellen (immer mit originalem Jahr am Ende)
$correction = $year . " " . $wrong_year . " ach quatsch " . $year;
// Ersetzen der Jahreszahl durch die Selbstkorrektur
$text = substr_replace($text, $correction, $position, strlen($year));
$year_corrected = true; // Markieren, dass bereits korrigiert wurde
}
}
// NEU: 0.5 NACH BINDESTRICH GROSSSCHREIBUNG BIS ZUM NÄCHSTEN SATZZEICHEN (2x pro Text)
$all_positions = array();
$offset = 0;
// Alle " – " oder " - " Positionen finden (Bindestrich mit Leerzeichen)
while (($pos = strpos($text, ' – ', $offset)) !== false || ($pos = strpos($text, ' - ', $offset)) !== false) {
$all_positions[] = $pos + 3; // Position nach dem Bindestrich und Leerzeichen
$offset = $pos + 3;
}
if (!empty($all_positions)) {
// 2 zufällige Positionen auswählen
shuffle($all_positions);
$selected_positions = array_slice($all_positions, 0, min(2, count($all_positions)));
foreach ($selected_positions as $pos) {
// Finde das nächste Satzzeichen (.!?:;)
$next_period = strpos($text, '.', $pos);
$next_exclamation = strpos($text, '!', $pos);
$next_question = strpos($text, '?', $pos);
$next_colon = strpos($text, ':', $pos);
$next_semicolon = strpos($text, ';', $pos);
// Sammle alle gefundenen Positionen (ohne false-Werte)
$punctuation_positions = array();
if ($next_period !== false) $punctuation_positions[] = $next_period;
if ($next_exclamation !== false) $punctuation_positions[] = $next_exclamation;
if ($next_question !== false) $punctuation_positions[] = $next_question;
if ($next_colon !== false) $punctuation_positions[] = $next_colon;
if ($next_semicolon !== false) $punctuation_positions[] = $next_semicolon;
if (!empty($punctuation_positions)) {
// Die nächste Satzzeichen-Position finden
$next_punctuation = min($punctuation_positions);
// Den Text zwischen Bindestrich und nächstem Satzzeichen extrahieren
$text_to_uppercase = substr($text, $pos, $next_punctuation - $pos);
// In Großbuchstaben umwandeln
$uppercase_text = strtoupper($text_to_uppercase);
// Ersetzen
$text = substr_replace($text, $uppercase_text, $pos, strlen($text_to_uppercase));
}
}
}
// 1. PUNKTE → ..., :, -, .... (70%) - ABER NICHT BEI ZAHLEN/DATUM
$all_positions = array();
for ($i = 0; $i < strlen($text); $i++) {
if ($text[$i] === '.') {
// Prüfen ob vor oder nach dem Punkt eine Zahl steht
$before_is_digit = ($i > 0 && is_numeric($text[$i-1]));
$after_is_digit = ($i < strlen($text)-1 && is_numeric($text[$i+1]));
// NICHT bei Zahlen/Datum
if (!$before_is_digit && !$after_is_digit) {
$all_positions[] = $i;
}
}
}
if (!empty($all_positions)) {
// 95% der Punkte ersetzen - völlig zufällig
shuffle($all_positions);
shuffle($all_positions); // Doppelt mischen für mehr Chaos
$replace_count = intval(count($all_positions) * 0.70);
$selected_positions = array_slice($all_positions, 0, max(1, $replace_count));
// Von hinten nach vorne ersetzen
rsort($selected_positions);
foreach ($selected_positions as $pos) {
$replacements = ['...', ':', '-', '....'];
$replacement = $replacements[array_rand($replacements)];
$text = substr_replace($text, $replacement, $pos, 1);
}
}
// 2. KOMMAS → ; (50% gewürfelt)
$all_positions = array();
for ($i = 0; $i < strlen($text); $i++) {
if ($text[$i] === ',') {
$all_positions[] = $i;
}
}
if (!empty($all_positions)) {
// 50% zufällig auswählen - völlig gewürfelt
shuffle($all_positions);
shuffle($all_positions); // Doppelt würfeln
$replace_count = intval(count($all_positions) * 0.50);
$selected_positions = array_slice($all_positions, 0, max(1, $replace_count));
// Von hinten nach vorne ersetzen
rsort($selected_positions);
foreach ($selected_positions as $pos) {
$text = substr_replace($text, ';', $pos, 1);
}
}
// 3. FRAGEZEICHEN → ?!, ???, ?!? (31% gewürfelt)
$all_positions = array();
for ($i = 0; $i < strlen($text); $i++) {
if ($text[$i] === '?') {
$all_positions[] = $i;
}
}
if (!empty($all_positions)) {
// 31% zufällig auswählen - völlig gewürfelt
shuffle($all_positions);
shuffle($all_positions); // Doppelt würfeln
$replace_count = intval(count($all_positions) * 0.31);
$selected_positions = array_slice($all_positions, 0, max(1, $replace_count));
$replacements = ['?!', '???', '?!?', '??!', '?...', '!?'];
// Von hinten nach vorne ersetzen
rsort($selected_positions);
foreach ($selected_positions as $pos) {
$replacement = $replacements[array_rand($replacements)];
$text = substr_replace($text, $replacement, $pos, 1);
}
}
// 4. AUSRUFEZEICHEN → !!, !!!, !?! (25% gewürfelt)
$all_positions = array();
for ($i = 0; $i < strlen($text); $i++) {
if ($text[$i] === '!') {
$all_positions[] = $i;
}
}
if (!empty($all_positions)) {
// 25% zufällig auswählen - völlig gewürfelt
shuffle($all_positions);
shuffle($all_positions); // Doppelt würfeln
$replace_count = intval(count($all_positions) * 0.25);
$selected_positions = array_slice($all_positions, 0, max(1, $replace_count));
$replacements = ['!!', '!!!', '!?!', '!!?', '!...', '!?'];
// Von hinten nach vorne ersetzen
rsort($selected_positions);
foreach ($selected_positions as $pos) {
$replacement = $replacements[array_rand($replacements)];
$text = substr_replace($text, $replacement, $pos, 1);
}
}
// 5. GROSSBUCHSTABEN - Wörter chaotisch über verschiedene Absätze verteilen, erweiterte Wortliste
$words = ['gut', 'schlecht', 'heute', 'morgen', 'zeit', 'leben', 'arbeit', 'schön', 'wichtig', 'neu', 'alt', 'groß', 'klein', 'richtig', 'falsch', 'schnell', 'langsam',
'welt', 'mensch', 'thema', 'idee', 'geld', 'macht', 'liebe', 'haus', 'stadt', 'land', 'wasser', 'feuer', 'erde', 'luft', 'tier', 'pflanze', 'farbe', 'musik'];
shuffle($words);
// Liste mit Absatzindizes erstellen
preg_match_all('/
]*>(.*?)<\/p>/s', $text, $p_matches); if (!empty($p_matches[0])) { $paragraph_indices = range(0, count($p_matches[0]) - 1); shuffle($paragraph_indices); // Absatzreihenfolge zufällig mischen // Anzahl der zu ersetzenden Wörter (2-5, je nach Textlänge) $num_words_to_replace = min(count($paragraph_indices), rand(2, 5)); // Zufällige Absätze auswählen $selected_paragraphs = array_slice($paragraph_indices, 0, $num_words_to_replace); $replaced = 0; foreach ($selected_paragraphs as $p_index) { $p_tag = $p_matches[0][$p_index]; $p_content = $p_matches[1][$p_index]; // Suche nach einem passenden Wort im aktuellen Absatz $word_found = false; foreach ($words as $word_index => $word) { if (preg_match('/\b' . preg_quote($word, '/') . '\b/i', $p_content)) { // Wort in Großbuchstaben umwandeln $new_content = preg_replace('/\b' . preg_quote($word, '/') . '\b/i', strtoupper($word), $p_content, 1); // Im Text ersetzen $new_p_tag = str_replace($p_content, $new_content, $p_tag); $text = str_replace($p_tag, $new_p_tag, $text); // Wort aus Liste entfernen und Zähler erhöhen unset($words[$word_index]); $replaced++; $word_found = true; break; } } // Falls kein passendes Wort gefunden wurde, versuche mit einem zufälligen längeren Wort (4+ Buchstaben) if (!$word_found) { if (preg_match_all('/\b([a-zA-ZäöüÄÖÜß]{4,})\b/u', $p_content, $long_word_matches)) { if (!empty($long_word_matches[0])) { // Zufälliges Wort auswählen $rand_index = array_rand($long_word_matches[0]); $long_word = $long_word_matches[0][$rand_index]; // Wort in Großbuchstaben umwandeln $new_content = preg_replace('/\b' . preg_quote($long_word, '/') . '\b/u', strtoupper($long_word), $p_content, 1); // Im Text ersetzen $new_p_tag = str_replace($p_content, $new_content, $p_tag); $text = str_replace($p_tag, $new_p_tag, $text); $replaced++; } } } // Wenn genug Wörter ersetzt wurden, beenden if ($replaced >= $num_words_to_replace) { break; } } } // 6. UMBRÜCHE - 10 Stück, ZUFÄLLIG über ALLE Absätze verteilt // Alle Absätze identifizieren preg_match_all('/
(.*?)<\/p>/s', $text, $all_paragraphs, PREG_OFFSET_CAPTURE); if (!empty($all_paragraphs[0])) { // Mögliche Umbruch-Positionen in allen Absätzen sammeln $possible_breakpoints = []; foreach ($all_paragraphs[0] as $paragraph_index => $paragraph) { $paragraph_content = $paragraph[0]; $paragraph_offset = $paragraph[1]; // Nach Punkten im Satz suchen (". " oder ". " oder "." + Zeilenumbruch) $patterns = ['. ', '. ', ".\n", ".\r"]; foreach ($patterns as $pattern) { $position = 0; while (($pos = strpos($paragraph_content, $pattern, $position)) !== false) { // Sicherstellen, dass vor dem Punkt keine Zahl steht (um Dezimalzahlen/Datumsangaben zu vermeiden) $valid_sentence_end = true; if ($pos > 0 && is_numeric($paragraph_content[$pos-1])) { $valid_sentence_end = false; } if ($valid_sentence_end) { // Absolute Position im Text berechnen $abs_pos = $paragraph_offset + $pos; // Mit Paragraph-Index speichern für spätere Identifikation $possible_breakpoints[] = [ 'pos' => $abs_pos, 'paragraph_index' => $paragraph_index, 'paragraph_pos' => $pos, 'pattern' => $pattern ]; } $position = $pos + 1; } } } // Umbrüche zufällig verteilen (max. 10 Stück) if (!empty($possible_breakpoints)) { // Zufällig mischen, dann Paragraph-Index gruppieren, um zu vermeiden, dass zu viele Umbrüche im selben Absatz sind shuffle($possible_breakpoints); // Nach Absatz gruppieren $grouped_by_paragraph = []; foreach ($possible_breakpoints as $point) { $p_idx = $point['paragraph_index']; if (!isset($grouped_by_paragraph[$p_idx])) { $grouped_by_paragraph[$p_idx] = []; } $grouped_by_paragraph[$p_idx][] = $point; } // Aus jedem Absatz maximal 2 Umbruchpunkte nehmen, um eine bessere Verteilung zu erreichen $selected_breakpoints = []; $paragraphs_with_breaks = 0; // Erste Runde: Ein Umbruch pro Absatz foreach ($grouped_by_paragraph as $p_idx => $points) { if (count($selected_breakpoints) >= 10) break; if (!empty($points)) { $selected_breakpoints[] = $points[0]; $paragraphs_with_breaks++; } } // Zweite Runde: Wenn noch Umbrüche übrig, erneut durch die Absätze gehen if (count($selected_breakpoints) < 10) { foreach ($grouped_by_paragraph as $p_idx => $points) { if (count($selected_breakpoints) >= 10) break; if (count($points) > 1) { $selected_breakpoints[] = $points[1]; } } } // Nach Position sortieren (absteigend), um von hinten nach vorne zu ersetzen usort($selected_breakpoints, function($a, $b) { return $b['pos'] - $a['pos']; }); // Umbrüche einfügen (10 Stück oder weniger, falls nicht genug Absätze) $max_breaks = min(10, count($selected_breakpoints)); $selected_breakpoints = array_slice($selected_breakpoints, 0, $max_breaks); foreach ($selected_breakpoints as $point) { $pattern = $point['pattern']; $replacement = '.'; // Erst den Punkt ohne Leerzeichen/Zeilenumbruch ersetzen if ($pattern === '. ' || $pattern === '. ') { $replacement .= '
'; // Dann den Absatzumbruch einfügen } else { $replacement .= '
'; // Bei Zeilenumbrüchen direkt ersetzen } // Die Länge des zu ersetzenden Musters bestimmen $pattern_length = strlen($pattern); // Ersetzen an der Position $text = substr_replace($text, $replacement, $point['pos'], $pattern_length); } } } // NEU: 7. MODUL 11 - FORMATIERTE WÖRTER (unterstrichen, fett, kursiv) IN ZUFÄLLIGEN ABSÄTZEN (12-20x) // Absätze wieder identifizieren preg_match_all('/
]*>(.*?)<\/p>/s', $text, $p_matches); if (!empty($p_matches[0])) { $paragraphs_count = count($p_matches[0]); // Zufällig 8 bis 10 unterschiedliche Absatzindizes auswählen (oder alle, wenn weniger als 8 Absätze vorhanden) $paragraph_indices = range(0, $paragraphs_count - 1); shuffle($paragraph_indices); $max_formats = min(rand(8, 10), $paragraphs_count); $selected_paragraph_indices = array_slice($paragraph_indices, 0, $max_formats); // Formatierungsoptionen $format_options = [ 'u' => ['', ''], // Unterstrichen 'b' => ['', ''], // Fett 'i' => ['', ''] // Kursiv ]; $format_keys = array_keys($format_options); // Zähler für tatsächlich formatierte Wörter $formatted_count = 0; $max_formatted_words = rand(12, 20); // Zuerst versuchen, in den ausgewählten Absätzen zu formatieren foreach ($selected_paragraph_indices as $index) { // Aktueller Absatz $p_tag = $p_matches[0][$index]; $p_content = $p_matches[1][$index]; // Wörter mit mindestens 4 Buchstaben im Absatz finden if (preg_match_all('/\b([a-zA-ZäöüÄÖÜß]{4,})\b/u', $p_content, $word_matches)) { if (!empty($word_matches[0])) { // Mehrere Wörter pro Absatz finden, aber nicht direkt nebeneinander $word_count = count($word_matches[0]); $words_to_format = min(max(1, ceil($word_count / 3)), 3); // Max 3 Wörter pro Absatz, mehr bei sehr langen Absätzen for ($i = 0; $i < $words_to_format; $i++) { if ($formatted_count >= $max_formatted_words) break; // Sicherstellen, dass wir nicht mehr als 20 Wörter formatieren // Wort aus der Mitte auswählen, nicht das erste oder letzte if ($word_count < 3) { $word_index = array_rand($word_matches[0]); // Wenn weniger als 3 Wörter, einfach zufällig } else { // Zufällige Position, vermeide bereits formatierte Wörter $available_indices = array_diff(range(0, $word_count - 1), [$word_index ?? -1]); if (empty($available_indices)) break; $word_index = $available_indices[array_rand($available_indices)]; } $word = $word_matches[0][$word_index]; // Zufällige Formatierung wählen $format_key = $format_keys[array_rand($format_keys)]; $format_tags = $format_options[$format_key]; // Formatierung anwenden $formatted_word = $format_tags[0] . $word . $format_tags[1]; $new_content = preg_replace('/\b' . preg_quote($word, '/') . '\b/u', $formatted_word, $p_content, 1); if ($new_content !== $p_content) { // Nur ersetzen, wenn sich etwas geändert hat // Im Text ersetzen $p_content = $new_content; // Aktualisiere den Absatzinhalt für den nächsten Durchlauf $formatted_count++; } } // Absatz im Gesamttext ersetzen, falls Änderungen vorgenommen wurden if ($p_content !== $p_matches[1][$index]) { $new_p_tag = str_replace($p_matches[1][$index], $p_content, $p_tag); $text = str_replace($p_tag, $new_p_tag, $text); } } } } // Falls wir noch nicht genug Wörter formatiert haben, versuche es mit weiteren Absätzen if ($formatted_count < $max_formatted_words) { // Noch nicht verwendete Absätze durchsuchen $remaining_indices = array_diff(range(0, $paragraphs_count - 1), $selected_paragraph_indices); shuffle($remaining_indices); foreach ($remaining_indices as $index) { if ($formatted_count >= $max_formatted_words) break; // Absatz verarbeiten (ähnlich wie oben) $p_tag = $p_matches[0][$index]; $p_content = $p_matches[1][$index]; if (preg_match_all('/\b([a-zA-ZäöüÄÖÜß]{4,})\b/u', $p_content, $word_matches)) { if (!empty($word_matches[0])) { $word_index = array_rand($word_matches[0]); $word = $word_matches[0][$word_index]; $format_key = $format_keys[array_rand($format_keys)]; $format_tags = $format_options[$format_key]; $formatted_word = $format_tags[0] . $word . $format_tags[1]; $new_content = preg_replace('/\b' . preg_quote($word, '/') . '\b/u', $formatted_word, $p_content, 1); if ($new_content !== $p_content) { $new_p_tag = str_replace($p_content, $new_content, $p_tag); $text = str_replace($p_tag, $new_p_tag, $text); $formatted_count++; } } } } } } // NEU: 8. MODUL 12 - KLEINGESCHRIEBENE BINDEWÖRTER (UND, ABER, ODER) (20% Wahrscheinlichkeit) $conjunction_pattern = '/\b(UND|ABER|ODER)\b/'; if (preg_match_all($conjunction_pattern, $text, $matches, PREG_OFFSET_CAPTURE)) { if (!empty($matches[0])) { // Bei Tests immer mindestens ein Wort ersetzen, sonst zufällig 20% $min_replacements = 1; // Mindestens ein Wort ersetzen $replacement_count = max($min_replacements, ceil(count($matches[0]) * 0.2)); // Zufällig Positionen auswählen (sicherstellen, dass genug vorhanden sind) if (count($matches[0]) <= $replacement_count) { // Wenn weniger oder gleich viele Bindewörter wie gewünschte Ersetzungen, alle ersetzen $random_indices = array_keys($matches[0]); } else { // Sonst zufällig auswählen $random_indices = array_rand($matches[0], $replacement_count); // Wenn nur ein Index zurückgegeben wird (bei nur einer Ersetzung), in Array umwandeln if (!is_array($random_indices)) { $random_indices = [$random_indices]; } } // Von hinten nach vorne durchlaufen für korrekte Positionen $positions = []; foreach ($random_indices as $idx) { $positions[] = [ 'pos' => $matches[0][$idx][1], 'len' => strlen($matches[0][$idx][0]), 'word' => strtolower($matches[0][$idx][0]) ]; } // Nach Position sortieren (absteigend) usort($positions, function($a, $b) { return $b['pos'] - $a['pos']; }); // Ersetzen foreach ($positions as $pos_data) { $text = substr_replace($text, $pos_data['word'], $pos_data['pos'], $pos_data['len']); } } } // NEU: Horizontale Linien (1x) preg_match_all('/
]*>(.*?)<\/p>/s', $text, $p_matches); if (!empty($p_matches[0])) { $paragraph_indices = range(0, count($p_matches[0]) - 1); $last_paragraph_index = end($paragraph_indices); // Letzter Absatz $p_tag = $p_matches[0][$last_paragraph_index]; $new_p_tag = $p_tag . '