Files
RR-Graph-Auswertung/rr-auswertung.php
2026-02-07 13:08:18 +01:00

312 lines
14 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?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' ] );