import 'dart:ui'; import 'package:flutter_test/flutter_test.dart'; import 'package:pyramid/features/call_ui/inflated_layout.dart'; /// [seconds] lang simulieren (60 Schritte pro Sekunde). bool _run(InflatedLayout l, double seconds) { var moving = true; for (var i = 0; i < (seconds * 60).round(); i++) { moving = l.step(1 / 60); } return moving; } List _ids(int n) => [for (var i = 0; i < n; i++) 'p$i']; void main() { const phone = Size(390, 620); const desktop = Size(1200, 700); test('eine Person füllt den ganzen Bereich bis an die Ränder', () { final l = InflatedLayout()..sync(['solo'], {}, phone); _run(l, 1); final r = l.cellBounds('solo'); expect(r.left, closeTo(l.margin, 0.5)); expect(r.top, closeTo(l.margin, 0.5)); expect(r.right, closeTo(phone.width - l.margin, 0.5)); expect(r.bottom, closeTo(phone.height - l.margin, 0.5)); // Gerundete Ecken: der Umriss enthält die Ecke des Rechtecks nicht mehr. final path = l.outline('solo'); expect(path.contains(r.topLeft + const Offset(2, 2)), isFalse); expect(path.contains(r.center), isTrue); }); test('vier Personen: gleich große Zellen, zusammen fast die ganze Fläche', () { final l = InflatedLayout()..sync(_ids(4), {}, desktop); final moving = _run(l, 6); expect(moving, isFalse, reason: 'kommt nicht zur Ruhe'); final areas = l.cells.values.map((c) => c.area).toList(); final avg = areas.reduce((a, b) => a + b) / areas.length; for (final a in areas) { expect(a, closeTo(avg, avg * 0.08)); } final total = areas.reduce((a, b) => a + b); expect(total, greaterThan(l.bounds.width * l.bounds.height * 0.9)); }); test('wer spricht, bekommt deutlich mehr Fläche', () { final l = InflatedLayout()..sync(_ids(3), {}, phone); _run(l, 4); l.sync(_ids(3), {'p1'}, phone); _run(l, 5); final speaker = l.cells['p1']!.area; final other = l.cells['p0']!.area; expect(speaker / other, closeTo(InflatedLayout.speakingShare, InflatedLayout.speakingShare * 0.15)); }); test('je mehr Personen, desto kleiner die Zellen', () { double avgArea(int n) { final l = InflatedLayout()..sync(_ids(n), {}, phone); _run(l, 5); return l.cells.values.fold(0, (s, c) => s + c.area) / n; } final a2 = avgArea(2), a5 = avgArea(5), a9 = avgArea(9); expect(a5, lessThan(a2)); expect(a9, lessThan(a5)); }); test('Neue pumpen sich auf, Gehende verschwinden', () { final l = InflatedLayout()..sync(_ids(2), {}, phone); _run(l, 3); l.sync(_ids(3), {}, phone); expect(l.cells['p2']!.area, lessThan(l.cells['p0']!.area)); _run(l, 5); expect(l.cells['p2']!.area, closeTo(l.cells['p0']!.area, l.cells['p0']!.area * 0.1)); l.sync(['p0', 'p2'], {}, phone); _run(l, 3); expect(l.cells.keys.toSet(), {'p0', 'p2'}); }); test('Zellen überlappen nicht und jeder Mittelpunkt liegt in seiner Zelle', () { final l = InflatedLayout()..sync(_ids(7), {'p3'}, desktop); _run(l, 6); final paths = {for (final id in l.cells.keys) id: l.outline(id)}; for (final c in l.cells.values) { expect(paths[c.id]!.contains(c.centroid), isTrue, reason: '${c.id} Schwerpunkt'); for (final other in l.cells.values) { if (other.id == c.id) continue; expect(paths[other.id]!.contains(c.centroid), isFalse, reason: '${c.id} liegt in ${other.id}'); } } }); test('Drehen (hochkant → quer): zwei Personen nebeneinander', () { final l = InflatedLayout()..sync(_ids(2), {}, phone); _run(l, 3); final a = l.cells['p0']!.centroid, b = l.cells['p1']!.centroid; expect((a.dy - b.dy).abs(), greaterThan((a.dx - b.dx).abs()), reason: 'hochkant: übereinander'); l.sync(_ids(2), {}, desktop); _run(l, 3); final c = l.cells['p0']!.centroid, d = l.cells['p1']!.centroid; expect((c.dx - d.dx).abs(), greaterThan((c.dy - d.dy).abs()), reason: 'quer: nebeneinander'); }); }