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; } }