Initial commit

This commit is contained in:
s4luorth
2026-02-07 13:08:18 +01:00
commit 68f683625d
6 changed files with 1024 additions and 0 deletions

311
rr-auswertung.php Normal file
View File

@@ -0,0 +1,311 @@
<?php
/**
* Plugin Name: RR Auswertung
* Description: Diagramme und Statistiken für Rosins Restaurants
* Version: 1.0.0
* Author: Netz-Orth
* Text Domain: rr-auswertung
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
define( 'RR_AUSWERTUNG_PATH', plugin_dir_path( __FILE__ ) );
define( 'RR_AUSWERTUNG_URL', plugin_dir_url( __FILE__ ) );
require_once RR_AUSWERTUNG_PATH . 'includes/class-rr-data.php';
require_once RR_AUSWERTUNG_PATH . 'includes/class-rr-charts.php';
final class RR_Auswertung {
private static $instance = null;
private $data;
private $charts;
public static function instance() {
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
private function __construct() {
$this->data = new RR_Data();
$this->charts = new RR_Charts( $this->data );
add_action( 'wp_enqueue_scripts', [ $this, 'register_assets' ] );
$this->register_shortcodes();
}
public function register_assets() {
wp_register_script(
'chartjs',
RR_AUSWERTUNG_URL . 'assets/js/chart.min.js',
[],
'4.4.7',
false
);
wp_register_script(
'chartjs-datalabels',
RR_AUSWERTUNG_URL . 'assets/js/chartjs-datalabels.min.js',
[ 'chartjs' ],
'2.2.0',
false
);
wp_register_style(
'rr-charts',
RR_AUSWERTUNG_URL . 'assets/css/rr-charts.css',
[],
'1.0.0'
);
// Perfmatters / WP Rocket / Autoptimize: chart.min.js von Delay/Defer ausschließen
add_filter( 'perfmatters_delay_js_exclusions', function( $exclusions ) {
$exclusions[] = 'chart.min.js';
$exclusions[] = 'chartjs-datalabels.min.js';
return $exclusions;
} );
add_filter( 'perfmatters_defer_js_exclusions', function( $exclusions ) {
$exclusions[] = 'chart.min.js';
$exclusions[] = 'chartjs-datalabels.min.js';
return $exclusions;
} );
}
private function register_shortcodes() {
$shortcodes = [
'rr_status_chart' => 'render_status_chart',
'rr_staffel_status_chart' => 'render_staffel_status_chart',
'rr_testessen_verbesserung_chart' => 'render_testessen_verbesserung_chart',
'rr_region_chart' => 'render_region_chart',
'rr_region_status_chart' => 'render_region_status_chart',
'rr_staffel_ergebnis_chart' => 'render_staffel_ergebnis_chart',
];
foreach ( $shortcodes as $tag => $method ) {
add_shortcode( $tag, [ $this->charts, $method ] );
}
// Text-Shortcodes mit dynamischen Zahlen
add_shortcode( 'rr_text_status', [ $this, 'render_text_status' ] );
add_shortcode( 'rr_text_staffel', [ $this, 'render_text_staffel' ] );
add_shortcode( 'rr_text_testessen', [ $this, 'render_text_testessen' ] );
add_shortcode( 'rr_text_region', [ $this, 'render_text_region' ] );
add_shortcode( 'rr_text_region_status', [ $this, 'render_text_region_status' ] );
add_shortcode( 'rr_text_staffel_ergebnis', [ $this, 'render_text_staffel_ergebnis' ] );
add_shortcode( 'rr_text_intro', [ $this, 'render_text_intro' ] );
// Debug-Shortcode: zeigt Rohdaten + Chart.js Status
add_shortcode( 'rr_debug', [ $this, 'render_debug' ] );
}
public function render_text_intro( $atts ) {
$counts = $this->data->get_status_counts();
$total = array_sum( $counts );
$staffel_data = $this->data->get_staffel_status();
$staffeln = count( $staffel_data );
$rate = $total > 0 ? round( $counts['geöffnet'] / $total * 100 ) : 0;
return sprintf(
'<p><strong>„Rosins Restaurants"</strong> gehört zu den bekanntesten deutschen TV-Formaten, wenn es um die Gastronomie geht. Seit der ersten Staffel hat Sternekoch <strong>Frank Rosin</strong> in <strong>%d Staffeln</strong> insgesamt <strong>%d Restaurants</strong> in ganz Deutschland besucht und den Betreibern unter die Arme gegriffen. Doch wie nachhaltig ist seine Hilfe wirklich? Aktuell sind noch <strong>%d Restaurants (%d%%)</strong> geöffnet. Auf dieser Seite findest du alle Zahlen, Daten und Fakten zur Sendung die Statistiken werden regelmäßig aktualisiert und spiegeln den aktuellen Stand der besuchten Betriebe wider.</p>',
$staffeln,
$total,
$counts['geöffnet'],
$rate
);
}
public function render_text_status( $atts ) {
$counts = $this->data->get_status_counts();
$total = array_sum( $counts );
$rate_open = $total > 0 ? round( $counts['geöffnet'] / $total * 100 ) : 0;
$rate_closed = $total > 0 ? round( $counts['geschlossen'] / $total * 100 ) : 0;
$rate_new = $total > 0 ? round( $counts['neuer Betreiber'] / $total * 100 ) : 0;
return sprintf(
'<p>Eine der häufigsten Fragen rund um die Sendung lautet: Wie viele der von Frank Rosin besuchten Restaurants existieren heute noch? Von insgesamt <strong>%d Restaurants</strong> sind aktuell noch <strong>%d geöffnet</strong> das entspricht einer Überlebensrate von <strong>%d%%</strong>. Dem gegenüber stehen <strong>%d Betriebe (%d%%)</strong>, die dauerhaft schließen mussten. Weitere <strong>%d Restaurants (%d%%)</strong> werden heute unter neuen Betreibern weitergeführt das ursprüngliche Konzept oder der Besitzer hat also gewechselt, der Standort ist aber weiterhin in Betrieb.</p>',
$total,
$counts['geöffnet'],
$rate_open,
$counts['geschlossen'],
$rate_closed,
$counts['neuer Betreiber'],
$rate_new
);
}
public function render_text_staffel( $atts ) {
$staffel_data = $this->data->get_staffel_status();
$best_staffel = '';
$best_rate = 0;
$worst_staffel = '';
$worst_rate = 100;
foreach ( $staffel_data as $s => $data ) {
$sum = array_sum( $data );
if ( $sum > 0 ) {
$rate = $data['geöffnet'] / $sum * 100;
if ( $rate > $best_rate ) {
$best_rate = $rate;
$best_staffel = $s;
}
if ( $rate < $worst_rate ) {
$worst_rate = $rate;
$worst_staffel = $s;
}
}
}
return sprintf(
'<p>Nicht jede Staffel von Rosins Restaurants war gleich erfolgreich. Über <strong>%d Staffeln</strong> hinweg zeigen sich deutliche Unterschiede bei der langfristigen Überlebensrate der besuchten Betriebe. Die erfolgreichste Staffel ist <strong>Staffel %s</strong> hier sind noch <strong>%d%%</strong> der Restaurants geöffnet. Am schlechtesten schneidet <strong>Staffel %s</strong> ab, wo nur noch <strong>%d%%</strong> der Betriebe existieren. Das folgende Diagramm schlüsselt die Verteilung von geöffneten, geschlossenen und unter neuer Führung stehenden Restaurants pro Staffel auf.</p>',
count( $staffel_data ),
$best_staffel,
round( $best_rate ),
$worst_staffel,
round( $worst_rate )
);
}
public function render_text_testessen( $atts ) {
$avg_data = $this->data->get_staffel_ergebnis_avg();
$total_avg1 = 0;
$total_avg2 = 0;
$count = 0;
foreach ( $avg_data as $s => $v ) {
if ( $v['avg1'] > 0 && $v['avg2'] > 0 ) {
$total_avg1 += $v['avg1'];
$total_avg2 += $v['avg2'];
$count++;
}
}
$avg1 = $count > 0 ? round( $total_avg1 / $count, 1 ) : 0;
$avg2 = $count > 0 ? round( $total_avg2 / $count, 1 ) : 0;
$diff = round( $avg2 - $avg1, 1 );
$pct = $avg1 > 0 ? round( $diff / $avg1 * 100 ) : 0;
return sprintf(
'<p>Ein zentrales Element jeder Folge ist das Testessen: Ein unabhängiges Team bewertet die Qualität der Restaurants auf einer normalisierten Skala von <strong>1 bis 5</strong>. Das erste Testessen findet vor Frank Rosins Eingreifen statt, das zweite nach der Umgestaltung. Im Durchschnitt über alle Staffeln verbessern sich die Restaurants von <strong>%.1f</strong> auf <strong>%.1f Punkte</strong> das ist eine Steigerung um <strong>%.1f Punkte (+%d%%)</strong>. Doch wie konstant ist diese Verbesserung über die Jahre? Das folgende Diagramm zeigt den Vorher-Nachher-Vergleich der durchschnittlichen Testessen-Ergebnisse, aufgeschlüsselt nach Staffel.</p>',
$avg1,
$avg2,
$diff,
$pct
);
}
public function render_text_region( $atts ) {
$regions = $this->data->get_region_counts();
$top_region = '';
$top_count = 0;
$second_region = '';
$second_count = 0;
foreach ( $regions as $name => $c ) {
if ( $c > $top_count ) {
$second_count = $top_count;
$second_region = $top_region;
$top_count = $c;
$top_region = $name;
} elseif ( $c > $second_count ) {
$second_count = $c;
$second_region = $name;
}
}
return sprintf(
'<p>Die von Frank Rosin besuchten Restaurants verteilen sich auf <strong>%d Bundesländer und Regionen</strong> darunter auch vereinzelte Einsätze im Ausland. Die regionale Verteilung ist dabei keineswegs gleichmäßig: Die meisten Hilferufe kamen aus <strong>%s</strong> mit <strong>%d Restaurants</strong>, gefolgt von <strong>%s</strong> mit <strong>%d Betrieben</strong>. Diese Verteilung spiegelt unter anderem die Dichte der Gastronomie-Szene und die wirtschaftliche Situation in den jeweiligen Regionen wider. Das horizontale Balkendiagramm zeigt die genaue Aufschlüsselung nach Bundesland und Region.</p>',
count( $regions ),
$top_region,
$top_count,
$second_region,
$second_count
);
}
public function render_text_region_status( $atts ) {
$region_status = $this->data->get_region_status();
$best_region = '';
$best_rate = 0;
$worst_region = '';
$worst_rate = 100;
foreach ( $region_status as $name => $data ) {
$sum = array_sum( $data );
if ( $sum >= 3 ) {
$rate = $data['geöffnet'] / $sum * 100;
if ( $rate > $best_rate ) {
$best_rate = $rate;
$best_region = $name;
}
if ( $rate < $worst_rate ) {
$worst_rate = $rate;
$worst_region = $name;
}
}
}
return sprintf(
'<p>Gibt es regionale Unterschiede beim langfristigen Erfolg der Restaurants? Die Daten zeigen: Ja. Betrachtet man nur Bundesländer und Regionen mit mindestens drei besuchten Restaurants, hat <strong>%s</strong> mit <strong>%d%%</strong> die höchste Überlebensrate. Am anderen Ende steht <strong>%s</strong> mit nur <strong>%d%%</strong> noch geöffneten Betrieben. Diese Unterschiede können auf verschiedene Faktoren zurückzuführen sein von der lokalen Wirtschaftslage über Mietpreise bis hin zur Wettbewerbssituation vor Ort.</p>',
$best_region,
round( $best_rate ),
$worst_region,
round( $worst_rate )
);
}
public function render_text_staffel_ergebnis( $atts ) {
$avg_data = $this->data->get_staffel_ergebnis_avg();
$keys = array_keys( $avg_data );
$first = reset( $keys );
$last = end( $keys );
$first_avg2 = $avg_data[ $first ]['avg2'] ?? 0;
$last_avg2 = $avg_data[ $last ]['avg2'] ?? 0;
$trend = $last_avg2 > $first_avg2 ? 'verbessert' : ( $last_avg2 < $first_avg2 ? 'verschlechtert' : 'kaum verändert' );
// Beste Staffel nach 2. Testessen finden
$best_s = '';
$best_avg2 = 0;
foreach ( $avg_data as $s => $v ) {
if ( $v['avg2'] > $best_avg2 ) {
$best_avg2 = $v['avg2'];
$best_s = $s;
}
}
return sprintf(
'<p>Wie haben sich die Testessen-Bewertungen im Laufe der Sendung entwickelt? Von Staffel %s bis Staffel %s hat sich das durchschnittliche Ergebnis nach Rosins Einsatz insgesamt <strong>%s</strong> von <strong>%.1f</strong> auf <strong>%.1f Punkte</strong>. Die stärkste Verbesserung nach dem Coaching erreichten die Restaurants in <strong>Staffel %s</strong> mit einem Durchschnitt von <strong>%.1f Punkten</strong> beim zweiten Testessen. Die beiden Linien im Diagramm zeigen den Trend der normalisierten Ergebnisse vor und nach Frank Rosins Einsatz über alle Staffeln hinweg.</p>',
$first,
$last,
$trend,
$first_avg2,
$last_avg2,
$best_s,
$best_avg2
);
}
public function render_debug( $atts ) {
if ( ! current_user_can( 'manage_options' ) ) {
return '<p>Debug nur für Admins sichtbar.</p>';
}
// Cache leeren für frische Daten
$this->data->clear_cache();
$info = $this->data->get_debug_info();
$out = '<div style="background:#f0f0f0;padding:20px;font-family:monospace;font-size:13px;overflow:auto;max-height:800px;">';
$out .= '<h3>RR Auswertung Debug</h3>';
$out .= '<pre>' . esc_html( print_r( $info, true ) ) . '</pre>';
$out .= '<h4>Chart.js Test</h4>';
$out .= '<p id="rr-debug-chartjs">Prüfe Chart.js...</p>';
$out .= '<script>document.addEventListener("DOMContentLoaded",function(){var el=document.getElementById("rr-debug-chartjs");if(typeof Chart!=="undefined"){el.innerHTML="Chart.js geladen: v"+Chart.version;}else{el.innerHTML="FEHLER: Chart.js NICHT geladen!";el.style.color="red";}});</script>';
$out .= '</div>';
return $out;
}
}
add_action( 'plugins_loaded', [ 'RR_Auswertung', 'instance' ] );