Skip to content

Commit

Permalink
feat: Transcript for team matches (#50)
Browse files Browse the repository at this point in the history
  • Loading branch information
Gustl22 committed Sep 8, 2024
1 parent 9020dfb commit 8e1a0af
Show file tree
Hide file tree
Showing 14 changed files with 929 additions and 245 deletions.
19 changes: 18 additions & 1 deletion wrestling_scoreboard_client/lib/l10n/app_de.arb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{
"appName": "Ringerkampf-Anzeige",
"home": "Start",
"start": "Start",
"home": "Heim",
"guest": "Gast",
"explore": "Erkunden",
"more": "Mehr",
"settings": "Einstellungen",
Expand Down Expand Up @@ -100,7 +102,18 @@
"endDate": "Ende",

"wrestlingRulesPdf": "https://www.ringen.de/wp-content/uploads/2019/01/Internationales-Regelwerk_Januar-2019_.pdf",
"transcriptTeamMatches": "Protokoll für Mannschaftskämpfe",
"scoreSheetSingleCompetitions": "Punktzettel für Einzelmeisterschaften",
"signature": "Unterschrift",
"pool": "Pool",
"round": "Runde",
"mat": "Matte",
"status": "Status",
"visitors": "Besucher",
"numberAbbreviation": "Nr.",
"total": "Gesamt",
"participantVacant": "unbesetzt",

"weight": "Gewicht",
"weightClass": "Gewichtsklasse",
"weightClasses": "Gewichtsklassen",
Expand Down Expand Up @@ -166,6 +179,10 @@
"boutResultDsqAbbr": "DQ",
"boutResultDsq2Abbr": "DQ2",
"actions": "Aktionen",
"point": "Punkt",
"points": "Punkte",
"technicalPoints": "Technische Punkte",
"classificationPoints": "Gruppen-Punkte",
"participations": "Teilnahmen",
"boutConfig": "Kampf-Konfiguration",

Expand Down
17 changes: 17 additions & 0 deletions wrestling_scoreboard_client/lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
"@appName": {
"description": "The internationalized app name"
},
"start": "Start",
"home": "Home",
"guest": "Guest",
"explore": "Explore",
"more": "More",
"settings": "Settings",
Expand Down Expand Up @@ -103,7 +105,18 @@
"endDate": "End",

"wrestlingRulesPdf": "https://uww.org/sites/default/files/2019-12/wrestling_rules.pdf",
"transcriptTeamMatches": "Transcript for Team Matches",
"scoreSheetSingleCompetitions": "Score sheet for Single Competitions",
"signature": "Signature",
"pool": "Pool",
"round": "Round",
"mat": "Mat",
"status": "Status",
"visitors": "Visitors",
"numberAbbreviation": "No.",
"total": "Total",
"participantVacant": "vacant",

"weight": "Weight",
"weightClass": "Weight Class",
"weightClasses": "Weight Classes",
Expand Down Expand Up @@ -169,6 +182,10 @@
"boutResultDsqAbbr": "DSQ",
"boutResultDsq2Abbr": "DSQ2",
"actions": "Actions",
"point": "point",
"points": "Points",
"technicalPoints": "Technical Points",
"classificationPoints": "Classification Points",
"participations": "Participations",
"boutConfig": "Bout configuration",

Expand Down
67 changes: 60 additions & 7 deletions wrestling_scoreboard_client/lib/services/print/pdf/components.dart
Original file line number Diff line number Diff line change
@@ -1,13 +1,36 @@
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart';
import 'package:wrestling_scoreboard_client/services/print/pdf/pdf_sheet.dart';
import 'package:wrestling_scoreboard_common/common.dart';

buildCheckBox({
bool isChecked = false,
PdfColor pencilColor = PdfColors.blue800,
PdfColor? checkBoxColor,
}) =>
Container(
color: checkBoxColor,
margin: const EdgeInsets.all(4),
height: 20,
width: 20,
foregroundDecoration: BoxDecoration(
border: Border.all(
color: PdfColors.grey,
width: .5,
),
),
alignment: Alignment.center,
child: isChecked ? Text('×', style: TextStyle(fontSize: 20, color: pencilColor)) : null,
);

Widget buildTextCell(
String title, {
double? height = 60,
double? width,
double? fontSize,
PdfColor borderColor = PdfColors.grey,
PdfColor textColor = PdfColors.black,
PdfColor? borderColor,
double? borderWidth,
PdfColor? textColor,
PdfColor? color,
EdgeInsets? margin,
Alignment alignment = Alignment.centerLeft,
Expand All @@ -19,19 +42,39 @@ Widget buildTextCell(
alignment: alignment,
foregroundDecoration: BoxDecoration(
border: Border.all(
color: borderColor,
width: .5,
color: borderColor ?? PdfColors.grey,
width: borderWidth ?? .5,
),
),
height: height,
width: width,
child: Text(title, style: TextStyle(fontSize: fontSize, color: textColor)));
child: Text(title, style: TextStyle(fontSize: fontSize, color: textColor ?? PdfColors.black)));
}

Widget buildFormCell({
String? title,
String? content,
double height = 60,
double height = 40,
double? width,
PdfColor borderColor = PdfColors.grey,
PdfColor? color,
PdfColor pencilColor = PdfColors.blue800,
}) {
return buildFormCellWidget(
title: title,
content: content == null ? null : Text(content, style: TextStyle(fontSize: 11, color: pencilColor)),
height: height,
width: width,
borderColor: borderColor,
color: color,
pencilColor: pencilColor,
);
}

Widget buildFormCellWidget({
String? title,
Widget? content,
double height = 40,
double? width,
PdfColor borderColor = PdfColors.grey,
PdfColor? color,
Expand Down Expand Up @@ -59,9 +102,19 @@ Widget buildFormCell({
Expanded(
child: Container(
alignment: Alignment.center,
child: Text(content, style: TextStyle(fontSize: 12, color: pencilColor)),
child: content,
)),
],
),
);
}

extension BoutRolePdfColor on BoutRole {
PdfColor? get pdfColor {
return this == BoutRole.red ? PdfSheet.homeColor : PdfSheet.guestColor;
}

PdfColor? get textPdfColor {
return PdfColors.white;
}
}
197 changes: 197 additions & 0 deletions wrestling_scoreboard_client/lib/services/print/pdf/pdf_sheet.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
import 'dart:typed_data';

import 'package:flutter/material.dart' show BuildContext;
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart';
import 'package:printing/printing.dart';
import 'package:wrestling_scoreboard_client/localization/date_time.dart';
import 'package:wrestling_scoreboard_client/services/print/pdf/components.dart';
import 'package:wrestling_scoreboard_common/common.dart';

abstract class PdfSheet {
static const PdfPageFormat a4 =
PdfPageFormat(21.0 * PdfPageFormat.cm, 29.7 * PdfPageFormat.cm, marginAll: 1.0 * PdfPageFormat.cm);
static const PdfPageFormat a4Cross =
PdfPageFormat(29.7 * PdfPageFormat.cm, 21.0 * PdfPageFormat.cm, marginAll: 1.0 * PdfPageFormat.cm);

static const horizontalGap = 8.0;
static const verticalGap = 8.0;

static const pencilColor = PdfColors.blue900;
static const homeColor = PdfColors.red;
static const guestColor = PdfColors.blue;

final PdfColor baseColor;
final PdfColor accentColor;
late final AppLocalizations localizations;
final BuildContext buildContext;

PdfSheet({
this.baseColor = PdfColors.blueGrey500,
this.accentColor = PdfColors.blueGrey900,
required this.buildContext,
}) {
localizations = AppLocalizations.of(buildContext)!;
}

Future<Uint8List> buildPdf({PdfPageFormat? pageFormat});

Widget buildFooter(Context context) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
'© ${DateTime.now().year} - August Oberhauser',
style: const TextStyle(fontSize: 6, color: PdfColors.grey500),
),
Text(
'Page ${context.pageNumber}/${context.pagesCount}',
style: const TextStyle(fontSize: 8, color: PdfColors.grey800),
),
],
);
}

Future<PageTheme> buildTheme({
PdfPageFormat pageFormat = PdfSheet.a4,
Font? base,
Font? bold,
Font? italic,
}) async {
return PageTheme(
pageFormat: pageFormat,
theme: ThemeData.withFont(
base: base ?? await PdfGoogleFonts.robotoRegular(),
bold: bold ?? await PdfGoogleFonts.robotoBold(),
italic: italic ?? await PdfGoogleFonts.robotoItalic(),
),
);
}

Widget buildInfo(Context context, WrestlingEvent wrestlingEvent) {
return Table(columnWidths: {
0: const FlexColumnWidth(2),
1: const FlexColumnWidth(1),
2: const FlexColumnWidth(1),
3: const FlexColumnWidth(1),
4: const FixedColumnWidth(120),
}, children: [
TableRow(
children: [
buildFormCell(
title: 'Event-${localizations.name}',
// ?? localizations.location,
content: wrestlingEvent is TeamMatch
? ('${wrestlingEvent.home.team.name} – ${wrestlingEvent.guest.team.name}')
: (wrestlingEvent as Competition).name,
color: PdfColors.grey100,
pencilColor: PdfSheet.pencilColor,
height: 40),
if (wrestlingEvent is TeamMatch)
buildFormCell(
title: localizations.league,
// ?? localizations.location,
content: wrestlingEvent.league?.fullname,
color: PdfColors.grey100,
pencilColor: PdfSheet.pencilColor,
height: 40),
if (wrestlingEvent is! TeamMatch)
buildFormCell(
title: 'Competition',
// ?? localizations.location,
content: 'Competition',
color: PdfColors.grey100,
pencilColor: PdfSheet.pencilColor,
height: 40),
buildFormCell(
title: localizations.date,
content: wrestlingEvent.date.toDateTimeStringFromLocaleName(localizations.localeName),
color: PdfColors.grey100,
pencilColor: PdfSheet.pencilColor,
height: 40),
buildFormCell(
title: 'Ort',
// ?? localizations.location,
content: wrestlingEvent.location,
color: PdfColors.grey100,
pencilColor: PdfSheet.pencilColor,
height: 40),
],
),
]);
}

Widget buildPerson({required String title, String? no, double? width}) {
const cellHeight = 30.0;
return buildFormCell(title: '$title (Name/Nr.)', content: no, height: cellHeight, width: width);
}

List<Widget> buildStaff(Context context, WrestlingEvent wrestlingEvent, {double? width}) {
Person? timeKeeper;
Person? transcriptWriter;
if (wrestlingEvent is TeamMatch) {
timeKeeper = wrestlingEvent.timeKeeper;
transcriptWriter = wrestlingEvent.transcriptWriter;
} else if (wrestlingEvent is Competition) {}

return [
buildPerson(
title: localizations.timeKeeper.toUpperCase(),
no: timeKeeper == null ? '' : '${timeKeeper.id} / ${timeKeeper.fullName}',
width: width),
buildPerson(
title: localizations.transcriptionWriter.toUpperCase(),
no: transcriptWriter == null ? '' : '${transcriptWriter.id} / ${transcriptWriter.fullName}',
width: width),
];
}

List<Widget> buildStewards(Context context, WrestlingEvent wrestlingEvent, {double? width}) {
List<Person?> stewards = [];
// TODO: stewards from list
if (stewards.length < 3) {
stewards.addAll(Iterable.generate(3 - stewards.length, (i) => null));
}
return stewards
.map(
(steward) => buildPerson(
title: localizations.steward.toUpperCase(),
no: steward == null ? '' : '${steward.id} / ${steward.fullName}',
width: width),
)
.toList();
}

List<Widget> buildReferees(Context context, WrestlingEvent wrestlingEvent, {double? width}) {
Person? matChairman;
Person? referee;
Person? judge;
if (wrestlingEvent is TeamMatch) {
matChairman = wrestlingEvent.matChairman;
referee = wrestlingEvent.referee;
judge = wrestlingEvent.judge;
} else if (wrestlingEvent is Competition) {
// TODO: get referees from bout
// matChairman = bout.matChairman;
// referee = bout.referee;
// judge = bout.judge;
}

return [
buildPerson(
title: localizations.matChairman.toUpperCase(),
no: matChairman == null ? '' : '${matChairman.id} / ${matChairman.fullName}',
width: width),
buildPerson(
title: localizations.referee.toUpperCase(),
no: referee == null ? '' : '${referee.id} / ${referee.fullName}',
width: width),
buildPerson(
title: localizations.judge.toUpperCase(),
no: judge == null ? '' : '${judge.id} / ${judge.fullName}',
width: width),
];
}
}
Loading

0 comments on commit 8e1a0af

Please sign in to comment.