option('to') !== null ? Carbon::parse((string) $this->option('to')) : Carbon::now();
$from = $this->option('from') !== null
? Carbon::parse((string) $this->option('from'))
: $to->copy()->subMonths(max(1, (int) $this->option('months')));
$data = $report->build($from, $to);
if ($this->option('json')) {
$this->line((string) json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
return self::SUCCESS;
}
$this->info("Aufrufzahlen je Portal — veröffentlicht {$data['from']} bis {$data['to']}");
foreach ($data['portals'] as $portal) {
$this->newLine();
$this->line("{$portal['label']}");
$rows = [];
foreach ($portal['segments'] as $segment) {
$s = $segment['stats'];
if ($s['anzahl'] === 0) {
$rows[] = [$segment['segment'], 0, '–', '–', '–', '–', '–', '–', '–'];
continue;
}
$rows[] = [
$segment['segment'],
$s['anzahl'],
$s['min'],
$s['p10'],
$s['p25'],
$s['median'],
$s['p75'],
$s['p90'],
$s['max'],
];
}
$this->table(['Bestand', 'PMs', 'Min', 'P10', 'P25', 'Median', 'P75', 'P90', 'Max'], $rows);
$gesamt = $portal['segments'][0]['stats'];
if ($gesamt['anzahl'] === 0) {
continue;
}
$this->line(sprintf(
' Mittelwert %s gegenüber Median %d%s',
$gesamt['mittelwert'],
$gesamt['median'],
// Die Schiefe ist die eigentliche Antwort auf E2: Zieht eine
// Handvoll Ausreißer den Schnitt nach oben, liegt der typische
// Absender darunter und eine Rohzahl liest sich für ihn als
// Misserfolg.
$gesamt['mittelwert'] > $gesamt['median'] * 1.25
? ' ← rechtsschief, Rohzahlen wirken für die Mehrheit enttäuschend'
: '',
));
$verteilung = [];
foreach ($gesamt['verteilung'] as $klasse => $anzahl) {
$anteil = $gesamt['anzahl'] > 0 ? round($anzahl / $gesamt['anzahl'] * 100) : 0;
$verteilung[] = [$klasse.' Aufrufe', $anzahl, $anteil.' %'];
}
$this->table(['Klasse', 'PMs', 'Anteil'], $verteilung);
$kohorten = [];
foreach ($portal['cohorts'] as $cohort) {
$kohorten[] = [
$cohort['alter'],
$cohort['anzahl'],
$cohort['median'] ?? '–',
$cohort['mittelwert'] ?? '–',
];
}
if ($kohorten !== []) {
$this->line(" Aufrufe nach Alter am Stichtag {$data['stichtag']} (nur Meldungen seit dem Relaunch)");
$this->table(['Alter der Meldung', 'PMs', 'Median', 'Mittelwert'], $kohorten);
// Der Gesamtmedian oben hängt an der Altersmischung des
// Fensters und ist zwischen zwei Messzeitpunkten nicht
// vergleichbar. Die einzelne Kohorte ist es.
$this->line(' Als Basiswert die KOHORTE festhalten, nicht den Gesamtmedian — nur sie ist später identisch erhebbar.');
}
}
return self::SUCCESS;
}
}