Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
martin-bertele committed Aug 14, 2024
1 parent a1826aa commit 6250e11
Show file tree
Hide file tree
Showing 116 changed files with 7,789 additions and 0 deletions.
Binary file added .automation/assets/ftcon_banner.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 changes: 34 additions & 0 deletions .automation/generate_markdowns.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import 'models/models.dart';
import 'parse_jsons.dart';
import 'write_readme.dart';
import 'write_speakers.dart';
import 'write_socials.dart';
import 'write_levels.dart';
import 'write_formats.dart';
import 'write_companies.dart';
import 'write_rooms.dart';
import 'write_descriptions.dart';
import 'write_agenda.dart';

Future<void> main() async {
final List<Talk> talks = [];
final List<Speaker> speakers = [];
final List<Company> companies = [];

// speakers and companies are unique.
await parseJsons(talks, speakers, companies);

// sort alphabetically
talks.sort((a, b) => a.title.compareTo(b.title));
speakers.sort((a, b) => a.name.compareTo(b.name));
companies.sort((a, b) => a.name.compareTo(b.name));

writeReadme(talks);
writeSpeakers(speakers, talks);
writeSocials(speakers);
writeLevels(talks);
writeFormats(talks);
writeRooms(talks);
writeDescriptions(talks);
writeAgenda(talks);
}
13 changes: 13 additions & 0 deletions .automation/models/company.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import 'models.dart';

class Company {
final String name;
final String? url;
final List<Speaker> speakers;

Company({
required this.name,
this.url,
required this.speakers,
});
}
26 changes: 26 additions & 0 deletions .automation/models/helpers.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Utility class to hold the function
class UrlHelper {
static String toUrl(String handleOrUrl, String platform) {
String baseUrl;
switch (platform.toLowerCase()) {
case 'github':
baseUrl = 'https://github.com/';
break;
case 'linkedin':
baseUrl = 'https://www.linkedin.com/in/';
break;
case 'x':
baseUrl = 'https://x.com/';
break;
default:
throw ArgumentError('Unsupported platform: $platform');
}

// Check if the handleOrUrl already contains the base URL
if (handleOrUrl.contains(baseUrl)) {
return handleOrUrl;
} else {
return '$baseUrl$handleOrUrl';
}
}
}
14 changes: 14 additions & 0 deletions .automation/models/hyperlink.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class Hyperlink {
final String label;
final String url;

Hyperlink({
required this.label,
required this.url,
});

factory Hyperlink.fromJson(Map<String, dynamic> json) => Hyperlink(
label: json['label'],
url: json['url'],
);
}
6 changes: 6 additions & 0 deletions .automation/models/models.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export 'company.dart';
export 'helpers.dart';
export 'hyperlink.dart';
export 'recommendation.dart';
export 'speaker.dart';
export 'talk.dart';
17 changes: 17 additions & 0 deletions .automation/models/recommendation.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
class Recommendation {
final String tool;
final String? comment;
final String? url;

Recommendation({
required this.tool,
this.comment,
this.url,
});

factory Recommendation.fromJson(Map<String, dynamic> json) => Recommendation(
tool: json['tool'],
comment: json['comment'],
url: json['url'],
);
}
70 changes: 70 additions & 0 deletions .automation/models/speaker.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import 'helpers.dart';

class Speaker {
final String name;
final String? bio;
final String? companyName;
final String? companyUrl;
final String? githubUrlOrHandle;
final String? xUrlOrHandle;
final String? linkedinUrlOrHandle;
final String? webUrl;

Speaker({
required this.name,
this.bio,
this.companyName,
this.companyUrl,
this.githubUrlOrHandle,
this.xUrlOrHandle,
this.linkedinUrlOrHandle,
this.webUrl,
});

factory Speaker.fromJson(Map<String, dynamic> json) => Speaker(
name: json['name'],
bio: json['bio'],
companyName: json['companyName'],
companyUrl: json['companyUrl'],
githubUrlOrHandle: json['githubUrlOrHandle'],
xUrlOrHandle: json['xUrlOrHandle'],
linkedinUrlOrHandle: json['linkedinUrlOrHandle'],
webUrl: json['webUrl'],
);

String? get githubLink => githubUrlOrHandle != null
? UrlHelper.toUrl(githubUrlOrHandle!, 'github')
: null;

String? get xLink =>
xUrlOrHandle != null ? UrlHelper.toUrl(xUrlOrHandle!, 'x') : null;

String? get linkedinLink => linkedinUrlOrHandle != null
? UrlHelper.toUrl(linkedinUrlOrHandle!, 'linkedin')
: null;

String get mdLink =>
'[${this.name}](https://github.com/martin-bertele/ftcon24eu/blob/main/Speakers.md#${this.name.toLowerCase().replaceAll(' ', '-')})';

Speaker copyWith({
String? name,
String? bio,
String? companyName,
String? companyUrl,
String? githubUrlOrHandle,
String? xUrlOrHandle,
String? linkedinUrlOrHandle,
String? webUrl,
}) {
return Speaker(
name: name ?? this.name,
bio: bio ?? this.bio,
companyName: companyName ?? this.companyName,
companyUrl: companyUrl ?? this.companyUrl,
githubUrlOrHandle: githubUrlOrHandle ?? this.githubUrlOrHandle,
xUrlOrHandle: xUrlOrHandle ?? this.xUrlOrHandle,
linkedinUrlOrHandle: linkedinUrlOrHandle ?? this.linkedinUrlOrHandle,
webUrl: webUrl ?? this.webUrl,
);
}
}
77 changes: 77 additions & 0 deletions .automation/models/talk.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import 'models.dart';

class Talk {
final List<Speaker> speakers;
final String title;
final String? description;
final List<Hyperlink>? resources;
final List<Recommendation>? recommendations;
final String? day;
final String? time;
final DateTime? startsAt;
final DateTime? endsAt;
final String? room;
final String? format;
final String? level;
final String? videoUrl;
final List<String>? topics;

Talk({
required this.speakers,
required this.title,
this.description,
this.resources,
this.recommendations,
this.day,
this.time,
this.startsAt,
this.endsAt,
this.room,
this.format,
this.level,
this.videoUrl,
this.topics,
});

factory Talk.fromJson(Map<String, dynamic> json) => Talk(
speakers: List<Speaker>.from(
json['speakers'].map((model) => Speaker.fromJson(model))),
title: json['title'],
description: json['description'],
resources: (json['resources'] as List<dynamic>?)
?.map((r) => Hyperlink.fromJson(r))
.toList(),
recommendations: (json['recommendations'] as List<dynamic>?)
?.map((r) => Recommendation.fromJson(r))
.toList(),
day: json['day'],
time: json['time'],
startsAt: json['startsAt'] != null
? DateTime.parse(json['startsAt']).toLocal()
: null,
endsAt: json['endsAt'] != null
? DateTime.parse(json['endsAt']).toLocal()
: null,
room: json['room'],
format: json['format'],
level: json['level'],
videoUrl: json['videoUrl'],
topics: List<String>.from(json['topics']),
);

String get tableRow {
final titleColumn = this.videoUrl?.isNotEmpty == true
? '[${this.title}](${this.videoUrl})'
: this.title;
final speakersColumn = this.speakers.map((s) => s.mdLink).join(', ');
final resourcesColumn = this
.resources
?.where((r) => r.label != 'Slides/Blog/...')
.map((r) => '[${r.label}](${r.url})')
.join(', ');
final recommendationsColumn =
this.recommendations?.map((r) => '[${r.tool}](${r.url})').join('<br>');

return '| $titleColumn | $speakersColumn | $resourcesColumn | $recommendationsColumn |';
}
}
73 changes: 73 additions & 0 deletions .automation/parse_jsons.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import 'dart:convert';
import 'dart:io';
import 'models/models.dart';

Future<void> parseJsons(
List<Talk> talks,
List<Speaker> uniqueSpeakers,
List<Company> uniqueCompanies,
) async {
const dataDir = 'talks';
final directory = Directory(dataDir);
final files = await directory
.list()
.where((file) => file.path.endsWith('.json'))
.toList();

for (var file in files) {
final fileContent = await File(file.path).readAsString();
talks.add(Talk.fromJson(jsonDecode(fileContent)));
}

for (Talk talk in talks) {
for (Speaker speaker in talk.speakers) {
int existingIndex =
uniqueSpeakers.indexWhere((s) => s.name == speaker.name);

if (existingIndex > 0) {
// A speaker with the same name exists, compare the filled data
Speaker existingSpeaker = uniqueSpeakers[existingIndex];
uniqueSpeakers[existingIndex] = uniqueSpeakers[existingIndex].copyWith(
companyName: existingSpeaker.companyName?.isEmpty == true
? speaker.companyName
: existingSpeaker.companyName,
bio: existingSpeaker.bio?.isEmpty == true
? speaker.bio
: existingSpeaker.bio,
companyUrl: existingSpeaker.companyUrl?.isEmpty == true
? speaker.companyUrl
: existingSpeaker.companyUrl,
githubUrlOrHandle: existingSpeaker.githubUrlOrHandle?.isEmpty == true
? speaker.githubUrlOrHandle
: existingSpeaker.githubUrlOrHandle,
xUrlOrHandle: existingSpeaker.xUrlOrHandle?.isEmpty == true
? speaker.xUrlOrHandle
: existingSpeaker.xUrlOrHandle,
linkedinUrlOrHandle:
existingSpeaker.linkedinUrlOrHandle?.isEmpty == true
? speaker.linkedinUrlOrHandle
: existingSpeaker.linkedinUrlOrHandle,
webUrl: existingSpeaker.webUrl?.isEmpty == true
? speaker.webUrl
: existingSpeaker.webUrl,
);
} else {
// No speaker with the same name exists, add the new speaker
uniqueSpeakers.add(speaker);
}

int idx =
uniqueCompanies.indexWhere((c) => c.name == speaker.companyName);
if (idx < 0) {
if (speaker.companyName != null && speaker.companyName!.isNotEmpty)
uniqueCompanies.add(Company(
name: speaker.companyName!,
speakers: List.from(talk.speakers),
));
} else {
// add speaker to existing company
uniqueCompanies[idx].speakers.add(speaker);
}
}
}
}
47 changes: 47 additions & 0 deletions .automation/write_agenda.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import 'dart:io';
import 'dart:convert';
import 'models/models.dart';

void writeAgenda(List<Talk> talks) async {
final agendaContent = StringBuffer();

agendaContent.writeln('# Agenda\n\n');

// Define the agenda days
const days = ["Wednesday", "Thursday", "Friday"];

for (var day in days) {
// Add subheadline for each day
agendaContent.writeln('## $day\n');

// Generate table headers
agendaContent.writeln(
'| Time & Room | Title | Speakers | Resources | Recommendations |');
agendaContent.writeln(
'| ----------- | ----- | -------- | --------- | --------------- |');

// Filter talks by current day
var filteredTalks = List.from(talks.where((talk) => talk.day == day));
filteredTalks.sort((a, b) {
int compareTime = a.startsAt!.compareTo(b.startsAt!);
if (compareTime != 0) return compareTime;
const roomOrder = [
'Widget Way',
'Async Area',
'Dart Den',
'Flutter Forest'
];
return roomOrder.indexOf(a.room).compareTo(roomOrder.indexOf(b.room));
});

// Iterate over filtered talks to populate the table
filteredTalks.forEach((talk) => agendaContent
.writeln('| **${talk.time}**<br>*${talk.room}* ${talk.tableRow}'));

// Add a newline for spacing between days
agendaContent.writeln('\n');
}

// Write the accumulated content to Agenda.md
await File('Agenda.md').writeAsString(agendaContent.toString());
}
Empty file.
Loading

0 comments on commit 6250e11

Please sign in to comment.