From 29e962be69cb24bd2b5d3f61bd3d1b1a81656baa Mon Sep 17 00:00:00 2001 From: David Scandurra Date: Fri, 19 May 2023 16:08:56 +0200 Subject: [PATCH 1/8] Cleanup dapp --- docs/team/translate/de.properties | 85 ++++++++ docs/team/translate/en.properties | 86 ++++++++ .../src/main/java/de/timolia/howto/Dapp.java | 143 ++---------- .../java/de/timolia/howto/LanguageUtil.java | 205 ------------------ .../src/main/java/de/timolia/howto/Utils.java | 38 ---- .../howto/conversion/InitialConversion.java | 62 ++++++ .../timolia/howto/conversion/JsonBuilder.java | 4 - .../howto/conversion/RankConversion.java | 14 +- .../de/timolia/howto/conversion/SQLApi.java | 84 +++---- .../howto/conversion/SqlUserConnection.java | 71 ++++++ .../conversion/models/TeamlerRankChange.java | 2 - .../models/TeamlerResponsibilities.java | 2 - .../timolia/howto/generator/FileWriter.java | 36 +++ .../howto/generator/PageRankChange.java | 10 +- .../howto/generator/PageResponsibilities.java | 135 +++++------- .../howto/generator/PageTeamMembers.java | 19 +- .../de/timolia/howto/models/Language.java | 8 - .../java/de/timolia/howto/models/Rank.java | 15 +- .../java/de/timolia/howto/models/Sex.java | 2 - .../java/de/timolia/howto/models/Teamler.java | 13 +- .../howto/responsibility/Responsibility.java | 32 +++ .../responsibility/ResponsibilityType.java | 12 + .../de/timolia/howto/translate/Language.java | 12 + .../de/timolia/howto/translate/Translate.java | 53 +++++ .../Translation.java} | 16 +- .../howto/translate/TranslationContext.java | 5 + 26 files changed, 585 insertions(+), 579 deletions(-) create mode 100644 docs/team/translate/de.properties create mode 100644 docs/team/translate/en.properties delete mode 100644 howto-dapp/src/main/java/de/timolia/howto/LanguageUtil.java delete mode 100644 howto-dapp/src/main/java/de/timolia/howto/Utils.java create mode 100644 howto-dapp/src/main/java/de/timolia/howto/conversion/InitialConversion.java create mode 100644 howto-dapp/src/main/java/de/timolia/howto/conversion/SqlUserConnection.java create mode 100644 howto-dapp/src/main/java/de/timolia/howto/generator/FileWriter.java delete mode 100644 howto-dapp/src/main/java/de/timolia/howto/models/Language.java create mode 100644 howto-dapp/src/main/java/de/timolia/howto/responsibility/Responsibility.java create mode 100644 howto-dapp/src/main/java/de/timolia/howto/responsibility/ResponsibilityType.java create mode 100644 howto-dapp/src/main/java/de/timolia/howto/translate/Language.java create mode 100644 howto-dapp/src/main/java/de/timolia/howto/translate/Translate.java rename howto-dapp/src/main/java/de/timolia/howto/{models/LanguageString.java => translate/Translation.java} (65%) create mode 100644 howto-dapp/src/main/java/de/timolia/howto/translate/TranslationContext.java diff --git a/docs/team/translate/de.properties b/docs/team/translate/de.properties new file mode 100644 index 00000000..c5e9f0db --- /dev/null +++ b/docs/team/translate/de.properties @@ -0,0 +1,85 @@ +rank.builder.description= Das Bauteam kreiert neue Maps und Lobbys für alle Gelegenheiten und Spielmodi auf Timolia. \ +Sie betreuen die architektonische Gestaltung neuer Modi und betreuen externe Mapeinsendungen. +rank.builder_plus.description= Builder+ übernehmen zusätzliche organisatorische Verantwortung durch ihre hohe Erfahrung sowohl im Level Design als auch im Team. \ +So leiten sie beispielsweise Projekte oder sind Ansprechpartner für neue Builder. +rank.content.description= Als kreative Ader sind sie für die verschiedensten Belange von Grafikdesign bis Übersetzung zuständig. +rank.developer.description= Developer kümmern sich um die Timolia Plugins, entwickeln neue Features und Spielmodi und kümmern sich um die Bugs, pardon, Features auf Timolia. +rank.developer_plus.description= Sie verfügen über langjährige Erfahrung als Entwickler auf Timolia und stehen bei internen Fragen zum Development zur Verfügung. \ +Auch kümmern sie sich um Timolia Plugins, entwickeln neue Features und Spielmodi und beheben mögliche Spielfehler. +rank.head_builder.description= Sie leiten und organisieren das Bauteam und dienen als erste Ansprechpartner für alle Builder. \ +Außerdem kümmern sie sich um die Auswahl und Einarbeitung neuer Builder und sind die Schnittstelle zwischen dem Bauteam und der allgemeinen Projektorganisation. +rank.administrator.description= Diese Teamler bilden die Leitung Timolias. Sie kümmern sich um die Verwaltung, Organisation und die Teamleitung. +rank.moderator.description= Moderatoren sind langjährige und besonders erfahrene Teamler, die einzigartige Expertise in ihrem jeweiligen Fachgebiet aufweisen. \ +Sie dienen als interne Ansprechpartner bei Fragen und koordinieren häufig einzelne Aufgabengebiete. +rank.supporter.description= Supporter stehen für alle grundlegenden Fragen und Reports zur Verfügung und sind die ersten, an die sich Spieler mit ihren Anliegen wenden können. +rank.supporter_plus.description= Sie verfügen über ein umfassendes Fachwissen und stehen für alle Fragen und Reports zur Verfügung. \ +Sie sind die ersten, an die sich Spieler mit ihren Anliegen wenden können. +rank.sysadmin.description= Systemadministratoren planen, installieren, konfigurieren und warten die technischen Systeme Timolias. \ +Sie führen Updates durch und sorgen für ein reibungsloses Spielerlebnis im Alltag. +page.rank-change.first= Hier werden alle Aus- und Eintritte bzw. Beförderungen und Degradierungen aufgelistet. +player= Spieler +page.rank-change.rank-previous= Vorheriger Rang +page.rank-change.rank-new= Jetziger Rang +date= Datum +page.members.first-1= Das Timolia-Team besteht aktuell aus +page.members.first-2= Mitgliedern und ist in die Ränge +and= und +page.members.first-3= aufgeteilt. +page.members.first-4= Nachfolgend findet ihr eine Liste aller Teammitglieder von Timolia sowie deren Aufgabenbereiche und Verantwortlichkeiten. Diese Zuteilung heißt nicht, dass ausschießlich diese Teamler in diesem Bereich aktiv sind. \ +Die Planung und Entwicklung von neuen Modi, Updates, Events und Ähnlichem liegt ausdrücklich nicht bei einem festen Teammitglied oder einer festen Gruppe von Teammitgliedern sondern unterscheidet sich von Projekt zu Projekt oder ändert sich zum Teil im Laufe des Projekts. +page.members.first-5= Die Ränge auf Timolia +page.members.rank-ingame= Rang (ingame) +page.members.hv= Hauptverantwortlich +page.members.nv= Nebenverantwortlich +page.members.fields= Bereiche +page.responsibilities.project-team-orga= Projekt- und Teamorganisation +page.responsibilities.teamleader= Team-Leiter +page.responsibilities.teamleader.desc= Im Timolia Team gibt es kleinere Teams, welche unter anderem durch diese Verantwortlichen organisiert werden. +page.responsibilities.project-team-orga.apply.builder= Teamlerauswahl Builder und Timolia Creative +page.responsibilities.project-team-orga.apply.content= Teamlerauswahl Content +page.responsibilities.project-team-orga.apply.development= Teamlerauswahl Development +page.responsibilities.project-team-orga.apply.support= Teamlerauswahl Support +page.responsibilities.project-team-orga.apply.support.desc= Wenn es wieder daran geht, neue Teammitglieder für den Support in unsere Reihen zu holen, kümmern sich diese Verantwortlichen darum. +page.responsibilities.project-team-orga.howto= Timolia HowTo +page.responsibilities.project-team-orga.howto.desc= Diese Teamler kümmern sich um's Aktualisieren und Erstellen des HowTos Timolias. +page.responsibilities.project-team-orga.tournament= Timolia Turnier Organisation +page.responsibilities.project-team-orga.tournament.desc= Dieses Team entscheidet über die Turniereinstellungen bei den Freitagsturnieren. +page.responsibilities.project-team-orga.uhc= UHC +page.responsibilities.project-team-orga.uhc.desc= Diese Teammitglieder kümmern sich um die Organisation und den reibungslosen Ablauf aller Timolia UHCs. +page.responsibilities.project-team-orga.youtuber= Youtuber-Ränge +page.responsibilities.project-team-orga.youtuber.desc= Wenn sich ein YouTuber für einen Rang auf Timolia interessiert, werden die Anfragen von diesem Team bearbeitet. +page.responsibilities.communication-platforms= Kommunikationsplattformen +page.responsibilities.communication-platforms.community-discord= Community-Discord +page.responsibilities.communication-platforms.community-discord.desc= Der Community-Discord von Timolia ist unter [https://timolia.de/discord](https://timolia.de/discord) zu erreichen. Er wird betreut von diesen Teamlern. +page.responsibilities.communication-platforms.bug-reports= Bug Reports +page.responsibilities.communication-platforms.appeal= Entschuldigungen +page.responsibilities.communication-platforms.falsely-banned= Zu Unrecht gebannt +page.responsibilities.communication-platforms.socialmedia= Social Media +page.responsibilities.communication-platforms.socialmedia.desc= Für einen ständigen Support und Content auf Twitter und anderen sozialen Medien sorgen diese Teamler. +page.responsibilities.communication-platforms.teamspeak= TeamSpeak +page.responsibilities.communication-platforms.teamspeak.desc= Der TeamSpeak von Timolia ist unter `ts.timolia.de` zu erreichen. Er wird betreut von diesen Teamlern. +page.responsibilities.other-responsibilities= Sonstige Aufgaben +page.responsibilities.other-responsibilities.translation= Translation und Content creation +page.responsibilities.other-responsibilities.map-submissions= Map-Einsendungen +page.responsibilities.other-responsibilities.graphicdesign= Grafikdesign +page.responsibilities.other-responsibilities.announcements= Ankündigungen +page.responsibilities.other-responsibilities.monthly-winner= Monatssieger +page.responsibilities.info= Hier werden die verschiedenen Aufgabenbereiche der Timolia Teamler aufgelistet. +page.responsibilities.custom.bug-reports.modsanddevs= Moderatoren und Developer +page.responsibilities.custom.sm.title= Projekte u. Verantwortungsgrad +page.responsibilities.custom.sm.twitter= Twitter +page.responsibilities.custom.sm.twitter-builder= Bauteam-Twitter +page.responsibilities.custom.sm.twitter.hv= Twitter HV +page.responsibilities.custom.sm.twitter.nv= Twitter NV +page.responsibilities.custom.sm.twitter-builder.hv= Bauteam-Twitter MR +page.responsibilities.custom.sm.twitter-builder.nv= Bauteam-Twitter SR +page.responsibilities.custom.teamleader.title= Zuständigkeit +page.responsibilities.custom.teamleader.whole-team= Management des Timolia-Teams +page.responsibilities.custom.teamleader.builder= Management des Bau-Teams +page.responsibilities.custom.teamleader.content= Management des Content-Teams +page.responsibilities.custom.teamleader.development= Management des Dev-Teams +page.responsibilities.custom.yter.title= Zuständigkeit +page.responsibilities.teamler= Teamler +page.responsibilities.responsib= Verantwortungsgrad +page.responsibilities.hv= Hauptverantwortlich +page.responsibilities.nv= Nebenverantwortlich diff --git a/docs/team/translate/en.properties b/docs/team/translate/en.properties new file mode 100644 index 00000000..a8dafd02 --- /dev/null +++ b/docs/team/translate/en.properties @@ -0,0 +1,86 @@ +rank.builder.description= The builder team creates new maps and lobbies for all occasions and game modes on Timolia. \ +They supervise the architectural design of new game modes and manage external map submissions. +rank.builder_plus.description= Builder+ take on additional organizational responsibility through their high level of experience in both level design and the team. \ +For example, they manage projects or are the contact person for new builders. +rank.content.description= As a creative streak, they are responsible for a wide range of interests from graphic design to translation. +rank.developer.description= Developers take care of Timolia plugins, develop new features and game modes and fix bugs (oh sorry, we really mean features) features on Timolia. +rank.developer_plus.description= They have many years of experience as a developer on Timolia and are available to answer internal questions about development. \ +They also take care of Timolia plugins, develop new features and game modes and fix possible bugs in games. +rank.head_builder.description= They lead and organize the builder team and act as the first point of contact for all builders. \ +Moreover, they take care of the selection and training of new builders and are the link between the builder team and the general project organization. +rank.administrator.description= These team members form the leadership of Timolia. They take care of administration, organization and team management. +rank.moderator.description= Moderators are long-term and outstandingly experienced team members who have unique knowledge in their respective fields. \ +They serve as internal contacts for questions and often coordinate individual areas of responsibility. +rank.supporter.description= Supporters are available for all basic questions and reports and \ +are the first to whom players can address their concerns. +rank.supporter_plus.description= They have comprehensive specialized knowledge and are available for all questions and reports. \ +They are the first to whom players can turn with their concerns. +rank.sysadmin.description= System administrators plan, install, configure and maintain Timolia's technical systems. \ +They carry out updates and ensure a smooth gaming experience in everyday life. +page.rank-change.first= Here, all team entries and resignations as well as promotions and demotions are listed. +player= Name +page.rank-change.rank-previous= Previous rank +page.rank-change.rank-new= Current Rank +date= Date +page.members.first-1= The Timolia team currently consists of +page.members.first-2= team members and is divided into the ranks +and= and +page.members.first-3= . +page.members.first-4= Below you will find a list of all team members of Timolia and their responsibilities aswell as their fields of operation. This does not mean that these team members alone are active in that specific field. \ +Planning and developing new game modes, updates and events is not assigned to one specific team member or a specific group of team members. It rather differs from one project to another and may change during the course of the project. +page.members.first-5= The ranks on Timolia +page.members.rank-ingame= Rang (ingame) +page.members.hv= Main responsibilities +page.members.nv= Secondary responsibilities +page.members.fields= Fields +page.responsibilities.project-team-orga= Project- and Teamorganization +page.responsibilities.teamleader= Team Leader +page.responsibilities.teamleader.desc= In the Timolia team, there are smaller teams, which are organized among others by these responsible persons. +page.responsibilities.project-team-orga.apply.builder= Staff selection builder and Timolia Creative +page.responsibilities.project-team-orga.apply.content= Staff selection content +page.responsibilities.project-team-orga.apply.development= Staff selection development +page.responsibilities.project-team-orga.apply.support= Staff selection support +page.responsibilities.project-team-orga.apply.support.desc= When it comes to recruiting new supporters, those team members will take care of it. +page.responsibilities.project-team-orga.howto= Timolia HowTo +page.responsibilities.project-team-orga.howto.desc= These team members are responsible for updating and creating Timolia's HowTos. +page.responsibilities.project-team-orga.tournament= Timolia Tournament Organization +page.responsibilities.project-team-orga.tournament.desc= This team decides on the tournament settings for the Friday tournaments. +page.responsibilities.project-team-orga.uhc= UHC +page.responsibilities.project-team-orga.uhc.desc= These team members take care of the organization and seamless experience of all Timolia UHCs. +page.responsibilities.project-team-orga.youtuber= YouTuber Ranks +page.responsibilities.project-team-orga.youtuber.desc= If a YouTuber is interested in a rank on Timolia, the requests are processed by this team. +page.responsibilities.communication-platforms= Communication platforms +page.responsibilities.communication-platforms.community-discord= Community-Discord +page.responsibilities.communication-platforms.community-discord.desc= The Community-Discord of Timolia can be reached at [https://timolia.de/discord](https://timolia.de/discord). It is maintained by these team members. +page.responsibilities.communication-platforms.bug-reports= Bug Reports +page.responsibilities.communication-platforms.appeal= Appeals +page.responsibilities.communication-platforms.falsely-banned= Falsely banned +page.responsibilities.communication-platforms.socialmedia= Social Media +page.responsibilities.communication-platforms.socialmedia.desc= These team members provide ongoing support and content on Twitter and other social media. +page.responsibilities.communication-platforms.teamspeak= TeamSpeak +page.responsibilities.communication-platforms.teamspeak.desc= The TeamSpeak of Timolia can be reached at `ts.timolia.de`. It is supervised by these team members. +page.responsibilities.other-responsibilities= Other responsibilites +page.responsibilities.other-responsibilities.translation= Translation and Content creation +page.responsibilities.other-responsibilities.map-submissions= Map submissions +page.responsibilities.other-responsibilities.graphicdesign= Graphic design +page.responsibilities.other-responsibilities.announcements= Announcements +page.responsibilities.other-responsibilities.monthly-winner= Monthly winner +page.responsibilities.info= The various areas of responsibility of the Timolia team members are listed here. +page.responsibilities.custom.bug-reports.modsanddevs= Moderators and Developers +page.responsibilities.custom.sm.title= Projects and level of responsibility +page.responsibilities.custom.sm.twitter= Twitter +page.responsibilities.custom.sm.twitter-builder= Builder Team-Twitter +page.responsibilities.custom.sm.twitter.hv= Twitter MR +page.responsibilities.custom.sm.twitter.nv= Twitter SR +page.responsibilities.custom.sm.twitter-builder.hv= Builder Team-Twitter MR +page.responsibilities.custom.sm.twitter-builder.nv= Builder Team-Twitter SR +page.responsibilities.custom.teamleader.title= Responsibility +page.responsibilities.custom.teamleader.whole-team= Management of the Timolia team +page.responsibilities.custom.teamleader.builder= Management of the builder team +page.responsibilities.custom.teamleader.content= Management of the content team +page.responsibilities.custom.teamleader.development= Management of the development team +page.responsibilities.custom.yter.title= Responsibility +page.responsibilities.teamler= Team member +page.responsibilities.responsib= Level of responsibility +page.responsibilities.hv= Main responsibility +page.responsibilities.nv= Secondary responsibility diff --git a/howto-dapp/src/main/java/de/timolia/howto/Dapp.java b/howto-dapp/src/main/java/de/timolia/howto/Dapp.java index 97f259ca..7564bf26 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/Dapp.java +++ b/howto-dapp/src/main/java/de/timolia/howto/Dapp.java @@ -3,142 +3,39 @@ import com.google.gson.FieldNamingPolicy; import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import de.timolia.howto.conversion.JsonBuilder; -import de.timolia.howto.conversion.models.TeamlerRankChange; -import de.timolia.howto.conversion.models.TeamlerResponsibilities; +import de.timolia.howto.conversion.InitialConversion; +import de.timolia.howto.generator.FileWriter; import de.timolia.howto.generator.PageRankChange; import de.timolia.howto.generator.PageResponsibilities; import de.timolia.howto.generator.PageTeamMembers; -import de.timolia.howto.models.Language; -import de.timolia.howto.models.Rank; -import de.timolia.howto.models.Sex; import de.timolia.howto.models.Teamler; +import de.timolia.howto.translate.Translate; -import java.io.IOException; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.StandardOpenOption; -import java.text.ParseException; -import java.util.ArrayList; import java.util.Arrays; -import java.util.LinkedHashMap; import java.util.List; -import java.util.stream.Collectors; -public class Dapp { // D. Application - - private static final Gson gson = new GsonBuilder() +public class Dapp { + public static final Translate translate = new Translate(); + public static final Gson gson = new GsonBuilder() .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) .create(); - public static boolean isDevEnv = false; - public static String MYSQL_USER = null; - public static String MYSQL_PASS = null; - public static String MYSQL_CON_STR = null; - - public static void main(String[] args) { - - if (System.getenv("MYSQL_USER_LIVE") != null) { - // live - MYSQL_USER = System.getenv("MYSQL_USER_LIVE"); - MYSQL_PASS = System.getenv("MYSQL_PASS_LIVE"); - MYSQL_CON_STR = System.getenv("MYSQL_CON_STR_LIVE"); - } else { - // dev - isDevEnv = true; - MYSQL_USER = System.getenv("MYSQL_USER_DEV"); - MYSQL_PASS = System.getenv("MYSQL_PASS_DEV"); - MYSQL_CON_STR = System.getenv("MYSQL_CON_STR_DEV"); - } - - - try { - - String json = Files.readString(Path.of("docs", "team", "teamler.json"), Charset.defaultCharset()); - Teamler[] teamlers = gson.fromJson(json, Teamler[].class); - List teamlerList = Arrays.asList(teamlers); - teamlerList.forEach(Teamler::updateName); - -// for(Teamler teamler : teamlerList) { -// String name = SQLApi.getName(teamler.getUuid()); -// if(!name.equals(teamler.getName())) { -// System.out.println("!!! " + teamler.getName() + " -> " + name); -// } -// } - - String changesMD = PageRankChange.generate(teamlerList); - String membersMD = PageTeamMembers.generate(teamlerList); - String responsibilitiesMD = PageResponsibilities.generate(teamlerList); - - writeFile(Path.of("docs", "team", "changes.de.md"), LanguageUtil.translate(Language.DE, changesMD)); - writeFile(Path.of("docs", "team", "members.de.md"), LanguageUtil.translate(Language.DE, membersMD)); - writeFile(Path.of("docs", "team", "responsibilities.de.md"), LanguageUtil.translate(Language.DE, responsibilitiesMD)); - - writeFile(Path.of("docs", "team", "changes.en.md"), LanguageUtil.translate(Language.EN, changesMD)); - writeFile(Path.of("docs", "team", "members.en.md"), LanguageUtil.translate(Language.EN, membersMD)); - writeFile(Path.of("docs", "team", "responsibilities.en.md"), LanguageUtil.translate(Language.EN, responsibilitiesMD)); - - } catch (Exception e) { - e.printStackTrace(); - System.exit(1); + public static void main(String[] args) throws Exception { + Path path = Path.of("docs", "team"); + translate.loadDirectory(path.resolve("translate")); + String json = Files.readString(path.resolve("teamler.json"), StandardCharsets.UTF_8); + Teamler[] teamlers = gson.fromJson(json, Teamler[].class); + List teamlerList = Arrays.asList(teamlers); + teamlerList.forEach(Teamler::updateName); + FileWriter fileWriter = new FileWriter(path, translate); + fileWriter.writeFile("changes", PageRankChange.generate(teamlerList)); + fileWriter.writeFile("members", PageTeamMembers.generate(teamlerList)); + fileWriter.writeFile("responsibilities", PageResponsibilities.generate(teamlerList)); + if (args.length == 1 && args[0].equalsIgnoreCase("init")) { + InitialConversion.convert(); } - - // used for initial conversion only - //convert(); - - - System.exit(0); } - - private static void writeFile(Path path, String text) throws IOException { - path.toFile().getParentFile().mkdirs(); - Files.writeString(path, text, Charset.defaultCharset(), StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE); - System.out.println("Wrote file '" + path.toString() + "'"); - } - - private static void convert() throws IOException, ParseException { - - List teamlers = new ArrayList<>(); - List teamlerRankChanges = JsonBuilder.getTeamlerRankChanges(); - - - teamlerRankChanges.stream().map(TeamlerRankChange::getUuid).sorted().distinct().forEach(uuid -> { - List changes = teamlerRankChanges.stream().filter(teamlerRankChange -> teamlerRankChange.getUuid().equals(uuid)).collect(Collectors.toList()); - - LinkedHashMap rankHistory = new LinkedHashMap<>(); - for (TeamlerRankChange teamlerRankChange : changes) { - if (rankHistory.isEmpty()) { - rankHistory.put("initial", teamlerRankChange.getRankFrom()); - } - rankHistory.put(teamlerRankChange.getReadableDate(), teamlerRankChange.getRankTo()); - } - - Teamler teamler = new Teamler(uuid, Sex.undefined, null, null, null, rankHistory); - teamlers.add(teamler); - }); - - List teamlerResponsibilitiesList = JsonBuilder.getTeamlerResponsibilities(); - teamlerResponsibilitiesList.forEach(teamlerResponsibilities -> { - Teamler teamler = teamlers.stream().filter(teamler1 -> teamler1.getUuid().equals(teamlerResponsibilities.getUuid())).findFirst().orElse(null); - - if (teamler == null) { - teamler = new Teamler(teamlerResponsibilities.getUuid(), Sex.undefined, null, null, null, null); - } - - System.out.println("teamler: " + teamler); - if (teamlerResponsibilities.getHv() != null) { - System.out.println("teamlerResponsibilities.getHv(): " + teamlerResponsibilities.getHv()); - teamler.setResponsibilitiesMain(Arrays.asList(teamlerResponsibilities.getHv().split(", "))); - } - if (teamlerResponsibilities.getNv() != null) { - teamler.setResponsibilitiesSecondary(Arrays.asList(teamlerResponsibilities.getNv().split(", "))); - } - }); - - - System.out.println(gson.toJson(teamlers)); - - } - } diff --git a/howto-dapp/src/main/java/de/timolia/howto/LanguageUtil.java b/howto-dapp/src/main/java/de/timolia/howto/LanguageUtil.java deleted file mode 100644 index 0c332a61..00000000 --- a/howto-dapp/src/main/java/de/timolia/howto/LanguageUtil.java +++ /dev/null @@ -1,205 +0,0 @@ -package de.timolia.howto; - -import de.timolia.howto.models.Language; -import de.timolia.howto.models.LanguageString; - -import java.util.ArrayList; -import java.util.stream.Collectors; - -public class LanguageUtil { - - public static String translate(Language language, String s) { - for(LanguageString languageString : getTranslations().stream().filter(languageString -> languageString.getLanguage().equals(language)).collect(Collectors.toList())) { - s = s.replaceAll("%" + languageString.getKey() + "%", languageString.getValue()); - } - return s; - } - - private static ArrayList getTranslations() { - return new ArrayList<>() {{ - add(new LanguageString(Language.DE, "rank.builder.description", "Das Bauteam kreiert neue Maps und Lobbys für alle Gelegenheiten und Spielmodi auf Timolia. \n" + - "Sie betreuen die architektonische Gestaltung neuer Modi und betreuen externe Mapeinsendungen.")); - add(new LanguageString(Language.EN, "rank.builder.description", "The builder team creates new maps and lobbies for all occasions and game modes on Timolia. \n" + - "They supervise the architectural design of new game modes and manage external map submissions.")); - add(new LanguageString(Language.DE, "rank.builder_plus.description", "Builder+ übernehmen zusätzliche organisatorische Verantwortung durch ihre hohe Erfahrung sowohl im Level Design als auch im Team. \n" + - "So leiten sie beispielsweise Projekte oder sind Ansprechpartner für neue Builder.")); - add(new LanguageString(Language.EN, "rank.builder_plus.description", "Builder+ take on additional organizational responsibility through their high level of experience in both level design and the team. \n" + - "For example, they manage projects or are the contact person for new builders.")); - add(new LanguageString(Language.DE, "rank.content.description", "Als kreative Ader sind sie für die verschiedensten Belange von Grafikdesign bis Übersetzung zuständig.")); - add(new LanguageString(Language.EN, "rank.content.description", "As a creative streak, they are responsible for a wide range of interests from graphic design to translation.")); - add(new LanguageString(Language.DE, "rank.developer.description", "Developer kümmern sich um die Timolia Plugins, entwickeln neue Features und Spielmodi und kümmern sich um die Bugs, pardon, Features auf Timolia.")); - add(new LanguageString(Language.EN, "rank.developer.description", "Developers take care of Timolia plugins, develop new features and game modes and fix bugs (oh sorry, we really mean features) features on Timolia.")); - add(new LanguageString(Language.DE, "rank.developer_plus.description", "Sie verfügen über langjährige Erfahrung als Entwickler auf Timolia und stehen bei internen Fragen zum Development zur Verfügung. \n" + - "Auch kümmern sie sich um Timolia Plugins, entwickeln neue Features und Spielmodi und beheben mögliche Spielfehler.")); - add(new LanguageString(Language.EN, "rank.developer_plus.description", "They have many years of experience as a developer on Timolia and are available to answer internal questions about development. \n" + - "They also take care of Timolia plugins, develop new features and game modes and fix possible bugs in games.")); - add(new LanguageString(Language.DE, "rank.head_builder.description", "Sie leiten und organisieren das Bauteam und dienen als erste Ansprechpartner für alle Builder. \n" + - "Außerdem kümmern sie sich um die Auswahl und Einarbeitung neuer Builder und sind die Schnittstelle zwischen dem Bauteam und der allgemeinen Projektorganisation.")); - add(new LanguageString(Language.EN, "rank.head_builder.description", "They lead and organize the builder team and act as the first point of contact for all builders. \n" + - "Moreover, they take care of the selection and training of new builders and are the link between the builder team and the general project organization.")); - add(new LanguageString(Language.DE, "rank.administrator.description", "Diese Teamler bilden die Leitung Timolias. " + - "Sie kümmern sich um die Verwaltung, Organisation und die Teamleitung.")); - add(new LanguageString(Language.EN, "rank.administrator.description", "These team members form the leadership of Timolia. " + - "They take care of administration, organization and team management.")); - add(new LanguageString(Language.DE, "rank.moderator.description", "Moderatoren sind langjährige und besonders erfahrene Teamler, die einzigartige Expertise in ihrem jeweiligen Fachgebiet aufweisen. \n" + - "Sie dienen als interne Ansprechpartner bei Fragen und koordinieren häufig einzelne Aufgabengebiete.")); - add(new LanguageString(Language.EN, "rank.moderator.description", "Moderators are long-term and outstandingly experienced team members who have unique knowledge in their respective fields. \n" + - "They serve as internal contacts for questions and often coordinate individual areas of responsibility.")); - add(new LanguageString(Language.DE, "rank.supporter.description", "Supporter stehen für alle grundlegenden Fragen und Reports zur Verfügung und sind die ersten, an die sich Spieler mit ihren Anliegen wenden können. ")); - add(new LanguageString(Language.EN, "rank.supporter.description", "Supporters are available for all basic questions and reports and \n" + - "are the first to whom players can address their concerns.")); - add(new LanguageString(Language.DE, "rank.supporter_plus.description", "Sie verfügen über ein umfassendes Fachwissen und stehen für alle Fragen und Reports zur Verfügung. \n" + - "Sie sind die ersten, an die sich Spieler mit ihren Anliegen wenden können.")); - add(new LanguageString(Language.EN, "rank.supporter_plus.description", "They have comprehensive specialized knowledge and are available for all questions and reports. \n" + - "They are the first to whom players can turn with their concerns.")); - add(new LanguageString(Language.DE, "rank.sysadmin.description", "Systemadministratoren planen, installieren, konfigurieren und warten die technischen Systeme Timolias. \n" + - "Sie führen Updates durch und sorgen für ein reibungsloses Spielerlebnis im Alltag.")); - add(new LanguageString(Language.EN, "rank.sysadmin.description", "System administrators plan, install, configure and maintain Timolia's technical systems. \n" + - "They carry out updates and ensure a smooth gaming experience in everyday life.")); - - add(new LanguageString(Language.DE, "page.rank-change.first", "Hier werden alle Aus- und Eintritte bzw. Beförderungen und Degradierungen aufgelistet.")); - add(new LanguageString(Language.EN, "page.rank-change.first", "Here, all team entries and resignations as well as promotions and demotions are listed.")); - add(new LanguageString(Language.DE, "player", "Spieler")); - add(new LanguageString(Language.EN, "player", "Name")); - add(new LanguageString(Language.DE, "page.rank-change.rank-previous", "Vorheriger Rang")); - add(new LanguageString(Language.EN, "page.rank-change.rank-previous", "Previous rank")); - add(new LanguageString(Language.DE, "page.rank-change.rank-new", "Jetziger Rang")); - add(new LanguageString(Language.EN, "page.rank-change.rank-new", "Current Rank")); - add(new LanguageString(Language.DE, "date", "Datum")); - add(new LanguageString(Language.EN, "date", "Date")); - - add(new LanguageString(Language.DE, "page.members.first-1", "Das Timolia-Team besteht aktuell aus ")); - add(new LanguageString(Language.EN, "page.members.first-1", "The Timolia team currently consists of ")); - add(new LanguageString(Language.DE, "page.members.first-2", " Mitgliedern und ist in die Ränge ")); - add(new LanguageString(Language.EN, "page.members.first-2", " team members and is divided into the ranks")); - add(new LanguageString(Language.DE, "and", "und")); - add(new LanguageString(Language.EN, "and", "and")); - add(new LanguageString(Language.DE, "page.members.first-3", " aufgeteilt.")); - add(new LanguageString(Language.EN, "page.members.first-3", ".")); - add(new LanguageString(Language.DE, "page.members.first-4", "Nachfolgend findet ihr eine Liste aller Teammitglieder von Timolia sowie deren Aufgabenbereiche und Verantwortlichkeiten. Diese Zuteilung heißt nicht, dass ausschießlich diese Teamler in diesem Bereich aktiv sind. \n" + - "Die Planung und Entwicklung von neuen Modi, Updates, Events und Ähnlichem liegt ausdrücklich nicht bei einem festen Teammitglied oder einer festen Gruppe von Teammitgliedern sondern unterscheidet sich von Projekt zu Projekt oder ändert sich zum Teil im Laufe des Projekts.")); - add(new LanguageString(Language.EN, "page.members.first-4", "Below you will find a list of all team members of Timolia and their responsibilities aswell as their fields of operation. This does not mean that these team members alone are active in that specific field. \n" + - "Planning and developing new game modes, updates and events is not assigned to one specific team member or a specific group of team members. It rather differs from one project to another and may change during the course of the project.")); - add(new LanguageString(Language.DE, "page.members.first-5", "Die Ränge auf Timolia")); - add(new LanguageString(Language.EN, "page.members.first-5", "The ranks on Timolia")); - add(new LanguageString(Language.DE, "page.members.rank-ingame", "Rang (ingame)")); - add(new LanguageString(Language.EN, "page.members.rank-ingame", "Rang (ingame)")); - add(new LanguageString(Language.DE, "page.members.hv", "Hauptverantwortlich")); - add(new LanguageString(Language.EN, "page.members.hv", "Main responsibilities")); - add(new LanguageString(Language.DE, "page.members.nv", "Nebenverantwortlich")); - add(new LanguageString(Language.EN, "page.members.nv", "Secondary responsibilities")); - add(new LanguageString(Language.DE, "page.members.fields", "Bereiche")); - add(new LanguageString(Language.EN, "page.members.fields", "Fields")); - - add(new LanguageString(Language.DE, "page.responsibilities.project-team-orga", "Projekt- und Teamorganisation")); - add(new LanguageString(Language.EN, "page.responsibilities.project-team-orga", "Project- and Teamorganization")); - add(new LanguageString(Language.DE, "page.responsibilities.teamleader", "Team-Leiter")); - add(new LanguageString(Language.EN, "page.responsibilities.teamleader", "Team Leader")); - add(new LanguageString(Language.DE, "page.responsibilities.teamleader.desc", "Im Timolia Team gibt es kleinere Teams, welche unter anderem durch diese Verantwortlichen organisiert werden.")); - add(new LanguageString(Language.EN, "page.responsibilities.teamleader.desc", "In the Timolia team, there are smaller teams, which are organized among others by these responsible persons.")); - add(new LanguageString(Language.DE, "page.responsibilities.project-team-orga.apply.builder", "Teamlerauswahl Builder und Timolia Creative")); - add(new LanguageString(Language.EN, "page.responsibilities.project-team-orga.apply.builder", "Staff selection builder and Timolia Creative")); - add(new LanguageString(Language.DE, "page.responsibilities.project-team-orga.apply.content", "Teamlerauswahl Content")); - add(new LanguageString(Language.EN, "page.responsibilities.project-team-orga.apply.content", "Staff selection content")); - add(new LanguageString(Language.DE, "page.responsibilities.project-team-orga.apply.development", "Teamlerauswahl Development")); - add(new LanguageString(Language.EN, "page.responsibilities.project-team-orga.apply.development", "Staff selection development")); - add(new LanguageString(Language.DE, "page.responsibilities.project-team-orga.apply.support", "Teamlerauswahl Support")); - add(new LanguageString(Language.EN, "page.responsibilities.project-team-orga.apply.support", "Staff selection support")); - add(new LanguageString(Language.DE, "page.responsibilities.project-team-orga.apply.support.desc", "Wenn es wieder daran geht, neue Teammitglieder für den Support in unsere Reihen zu holen, kümmern sich diese Verantwortlichen darum.")); - add(new LanguageString(Language.EN, "page.responsibilities.project-team-orga.apply.support.desc", "When it comes to recruiting new supporters, those team members will take care of it.")); - add(new LanguageString(Language.DE, "page.responsibilities.project-team-orga.howto", "Timolia HowTo")); - add(new LanguageString(Language.EN, "page.responsibilities.project-team-orga.howto", "Timolia HowTo")); - add(new LanguageString(Language.DE, "page.responsibilities.project-team-orga.howto.desc", "Diese Teamler kümmern sich um's Aktualisieren und Erstellen des HowTos Timolias.")); - add(new LanguageString(Language.EN, "page.responsibilities.project-team-orga.howto.desc", "These team members are responsible for updating and creating Timolia's HowTos.")); - add(new LanguageString(Language.DE, "page.responsibilities.project-team-orga.tournament", "Timolia Turnier Organisation")); - add(new LanguageString(Language.EN, "page.responsibilities.project-team-orga.tournament", "Timolia Tournament Organization")); - add(new LanguageString(Language.DE, "page.responsibilities.project-team-orga.tournament.desc", "Dieses Team entscheidet über die Turniereinstellungen bei den Freitagsturnieren.")); - add(new LanguageString(Language.EN, "page.responsibilities.project-team-orga.tournament.desc", "This team decides on the tournament settings for the Friday tournaments.")); - add(new LanguageString(Language.DE, "page.responsibilities.project-team-orga.uhc", "UHC")); - add(new LanguageString(Language.EN, "page.responsibilities.project-team-orga.uhc", "UHC")); - add(new LanguageString(Language.DE, "page.responsibilities.project-team-orga.uhc.desc", "Diese Teammitglieder kümmern sich um die Organisation und den reibungslosen Ablauf aller Timolia UHCs.")); - add(new LanguageString(Language.EN, "page.responsibilities.project-team-orga.uhc.desc", "These team members take care of the organization and seamless experience of all Timolia UHCs.")); - add(new LanguageString(Language.DE, "page.responsibilities.project-team-orga.youtuber", "Youtuber-Ränge")); - add(new LanguageString(Language.EN, "page.responsibilities.project-team-orga.youtuber", "YouTuber Ranks")); - add(new LanguageString(Language.DE, "page.responsibilities.project-team-orga.youtuber.desc", "Wenn sich ein YouTuber für einen Rang auf Timolia interessiert, werden die Anfragen von diesem Team bearbeitet.")); - add(new LanguageString(Language.EN, "page.responsibilities.project-team-orga.youtuber.desc", "If a YouTuber is interested in a rank on Timolia, the requests are processed by this team.")); - - add(new LanguageString(Language.DE, "page.responsibilities.communication-platforms", "Kommunikationsplattformen")); - add(new LanguageString(Language.EN, "page.responsibilities.communication-platforms", "Communication platforms")); - add(new LanguageString(Language.DE, "page.responsibilities.communication-platforms.community-discord", "Community-Discord")); - add(new LanguageString(Language.EN, "page.responsibilities.communication-platforms.community-discord", "Community-Discord")); - add(new LanguageString(Language.DE, "page.responsibilities.communication-platforms.community-discord.desc", "Der Community-Discord von Timolia ist unter [https://timolia.de/discord](https://timolia.de/discord) zu erreichen. Er wird betreut von diesen Teamlern.")); - add(new LanguageString(Language.EN, "page.responsibilities.communication-platforms.community-discord.desc", "The Community-Discord of Timolia can be reached at [https://timolia.de/discord](https://timolia.de/discord). It is maintained by these team members.")); - add(new LanguageString(Language.DE, "page.responsibilities.communication-platforms.bug-reports", "Bug Reports")); - add(new LanguageString(Language.EN, "page.responsibilities.communication-platforms.bug-reports", "Bug Reports")); - add(new LanguageString(Language.DE, "page.responsibilities.communication-platforms.appeal", "Entschuldigungen")); - add(new LanguageString(Language.EN, "page.responsibilities.communication-platforms.appeal", "Appeals")); - add(new LanguageString(Language.DE, "page.responsibilities.communication-platforms.falsely-banned", "Zu Unrecht gebannt")); - add(new LanguageString(Language.EN, "page.responsibilities.communication-platforms.falsely-banned", "Falsely banned")); - add(new LanguageString(Language.DE, "page.responsibilities.communication-platforms.socialmedia", "Social Media")); - add(new LanguageString(Language.EN, "page.responsibilities.communication-platforms.socialmedia", "Social Media")); - add(new LanguageString(Language.DE, "page.responsibilities.communication-platforms.socialmedia.desc", "Für einen ständigen Support und Content auf Twitter und anderen sozialen Medien sorgen diese Teamler.")); - add(new LanguageString(Language.EN, "page.responsibilities.communication-platforms.socialmedia.desc", "These team members provide ongoing support and content on Twitter and other social media.")); - add(new LanguageString(Language.DE, "page.responsibilities.communication-platforms.teamspeak", "TeamSpeak")); - add(new LanguageString(Language.EN, "page.responsibilities.communication-platforms.teamspeak", "TeamSpeak")); - add(new LanguageString(Language.DE, "page.responsibilities.communication-platforms.teamspeak.desc", "Der TeamSpeak von Timolia ist unter `ts.timolia.de` zu erreichen. Er wird betreut von diesen Teamlern.")); - add(new LanguageString(Language.EN, "page.responsibilities.communication-platforms.teamspeak.desc", "The TeamSpeak of Timolia can be reached at `ts.timolia.de`. It is supervised by these team members.")); - - add(new LanguageString(Language.DE, "page.responsibilities.other-responsibilities", "Sonstige Aufgaben")); - add(new LanguageString(Language.EN, "page.responsibilities.other-responsibilities", "Other responsibilites")); - add(new LanguageString(Language.DE, "page.responsibilities.other-responsibilities.translation", "Translation und Content creation")); - add(new LanguageString(Language.EN, "page.responsibilities.other-responsibilities.translation", "Translation and Content creation")); - add(new LanguageString(Language.DE, "page.responsibilities.other-responsibilities.map-submissions", "Map-Einsendungen")); - add(new LanguageString(Language.EN, "page.responsibilities.other-responsibilities.map-submissions", "Map submissions")); - add(new LanguageString(Language.DE, "page.responsibilities.other-responsibilities.graphicdesign", "Grafikdesign")); - add(new LanguageString(Language.EN, "page.responsibilities.other-responsibilities.graphicdesign", "Graphic design")); - add(new LanguageString(Language.DE, "page.responsibilities.other-responsibilities.announcements", "Ankündigungen")); - add(new LanguageString(Language.EN, "page.responsibilities.other-responsibilities.announcements", "Announcements")); - add(new LanguageString(Language.DE, "page.responsibilities.other-responsibilities.monthly-winner", "Monatssieger")); - add(new LanguageString(Language.EN, "page.responsibilities.other-responsibilities.monthly-winner", "Monthly winner")); - -// add(new LanguageString(Language.DE, "page.responsibilities.broadcasts.desc", "Um auch ingame immer auf dem neusten Stand zu bleiben, wird sich hier um Broadcast Mitteilungen gekümmert.")); -// add(new LanguageString(Language.EN, "page.responsibilities.broadcasts.desc", "To always stay up to date in-game, here is it taken care of broadcast messages.")); - - add(new LanguageString(Language.DE, "page.responsibilities.info", "Hier werden die verschiedenen Aufgabenbereiche der Timolia Teamler aufgelistet.")); - add(new LanguageString(Language.EN, "page.responsibilities.info", "The various areas of responsibility of the Timolia team members are listed here.")); - add(new LanguageString(Language.DE, "page.responsibilities.custom.bug-reports.modsanddevs", "Moderatoren und Developer")); - add(new LanguageString(Language.EN, "page.responsibilities.custom.bug-reports.modsanddevs", "Moderators and Developers")); - add(new LanguageString(Language.DE, "page.responsibilities.custom.sm.title", "Projekte u. Verantwortungsgrad")); - add(new LanguageString(Language.EN, "page.responsibilities.custom.sm.title", "Projects and level of responsibility")); - add(new LanguageString(Language.DE, "page.responsibilities.custom.sm.twitter", "Twitter")); - add(new LanguageString(Language.EN, "page.responsibilities.custom.sm.twitter", "Twitter")); - add(new LanguageString(Language.DE, "page.responsibilities.custom.sm.twitter-builder", "Bauteam-Twitter")); - add(new LanguageString(Language.EN, "page.responsibilities.custom.sm.twitter-builder", "Builder Team-Twitter")); - add(new LanguageString(Language.DE, "page.responsibilities.custom.sm.twitter.hv", "Twitter HV")); - add(new LanguageString(Language.EN, "page.responsibilities.custom.sm.twitter.hv", "Twitter MR")); - add(new LanguageString(Language.DE, "page.responsibilities.custom.sm.twitter.nv", "Twitter NV")); - add(new LanguageString(Language.EN, "page.responsibilities.custom.sm.twitter.nv", "Twitter SR")); - add(new LanguageString(Language.DE, "page.responsibilities.custom.sm.twitter-builder.hv", "Bauteam-Twitter MR")); - add(new LanguageString(Language.EN, "page.responsibilities.custom.sm.twitter-builder.hv", "Builder Team-Twitter MR")); - add(new LanguageString(Language.DE, "page.responsibilities.custom.sm.twitter-builder.nv", "Bauteam-Twitter SR")); - add(new LanguageString(Language.EN, "page.responsibilities.custom.sm.twitter-builder.nv", "Builder Team-Twitter SR")); - add(new LanguageString(Language.DE, "page.responsibilities.custom.teamleader.title", "Zuständigkeit")); - add(new LanguageString(Language.EN, "page.responsibilities.custom.teamleader.title", "Responsibility")); - add(new LanguageString(Language.DE, "page.responsibilities.custom.teamleader.whole-team", "Management des Timolia-Teams")); - add(new LanguageString(Language.EN, "page.responsibilities.custom.teamleader.whole-team", "Management of the Timolia team")); - add(new LanguageString(Language.DE, "page.responsibilities.custom.teamleader.builder", "Management des Bau-Teams")); - add(new LanguageString(Language.EN, "page.responsibilities.custom.teamleader.builder", "Management of the builder team")); - add(new LanguageString(Language.DE, "page.responsibilities.custom.teamleader.content", "Management des Content-Teams")); - add(new LanguageString(Language.EN, "page.responsibilities.custom.teamleader.content", "Management of the content team")); - add(new LanguageString(Language.DE, "page.responsibilities.custom.teamleader.development", "Management des Dev-Teams")); - add(new LanguageString(Language.EN, "page.responsibilities.custom.teamleader.development", "Management of the development team")); - add(new LanguageString(Language.DE, "page.responsibilities.custom.yter.title", "Zuständigkeit")); - add(new LanguageString(Language.EN, "page.responsibilities.custom.yter.title", "Responsibility")); - add(new LanguageString(Language.DE, "page.responsibilities.teamler", "Teamler")); - add(new LanguageString(Language.EN, "page.responsibilities.teamler", "Team member")); - add(new LanguageString(Language.DE, "page.responsibilities.responsib", "Verantwortungsgrad")); - add(new LanguageString(Language.EN, "page.responsibilities.responsib", "Level of responsibility")); - add(new LanguageString(Language.DE, "page.responsibilities.hv", "Hauptverantwortlich")); - add(new LanguageString(Language.EN, "page.responsibilities.hv", "Main responsibility")); - add(new LanguageString(Language.DE, "page.responsibilities.nv", "Nebenverantwortlich")); - add(new LanguageString(Language.EN, "page.responsibilities.nv", "Secondary responsibility")); - }}; - } - -} diff --git a/howto-dapp/src/main/java/de/timolia/howto/Utils.java b/howto-dapp/src/main/java/de/timolia/howto/Utils.java deleted file mode 100644 index 6779649d..00000000 --- a/howto-dapp/src/main/java/de/timolia/howto/Utils.java +++ /dev/null @@ -1,38 +0,0 @@ -package de.timolia.howto; - -import de.timolia.howto.models.Teamler; - -import java.util.Arrays; -import java.util.List; -import java.util.UUID; -import java.util.stream.Collectors; - -public class Utils { - - public static List getTeamler(List teamlers, UUID... uuid) { - List uuids = Arrays.asList(uuid); - return teamlers.stream().filter(teamler -> uuids.contains(teamler.getUuid())).collect(Collectors.toList()); - } - - public static class KeyValuePair { - - private final T key; - private final U value; - - public KeyValuePair(T key, U value) { - this.key = key; - this.value = value; - } - - - public T getKey() { - return key; - } - - public U getValue() { - return value; - } - - } - -} diff --git a/howto-dapp/src/main/java/de/timolia/howto/conversion/InitialConversion.java b/howto-dapp/src/main/java/de/timolia/howto/conversion/InitialConversion.java new file mode 100644 index 00000000..87067753 --- /dev/null +++ b/howto-dapp/src/main/java/de/timolia/howto/conversion/InitialConversion.java @@ -0,0 +1,62 @@ +package de.timolia.howto.conversion; + +import de.timolia.howto.Dapp; +import de.timolia.howto.conversion.models.TeamlerRankChange; +import de.timolia.howto.conversion.models.TeamlerResponsibilities; +import de.timolia.howto.models.Rank; +import de.timolia.howto.models.Sex; +import de.timolia.howto.models.Teamler; + +import java.io.IOException; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.stream.Collectors; + +public class InitialConversion { + public static void convert() throws IOException, ParseException { + + List teamlers = new ArrayList<>(); + List teamlerRankChanges = JsonBuilder.getTeamlerRankChanges(); + + + teamlerRankChanges.stream().map(TeamlerRankChange::getUuid).sorted().distinct().forEach(uuid -> { + List changes = teamlerRankChanges.stream().filter(teamlerRankChange -> teamlerRankChange.getUuid().equals(uuid)).collect(Collectors.toList()); + + LinkedHashMap rankHistory = new LinkedHashMap<>(); + for (TeamlerRankChange teamlerRankChange : changes) { + if (rankHistory.isEmpty()) { + rankHistory.put("initial", teamlerRankChange.getRankFrom()); + } + rankHistory.put(teamlerRankChange.getReadableDate(), teamlerRankChange.getRankTo()); + } + + Teamler teamler = new Teamler(uuid, Sex.undefined, null, null, null, rankHistory); + teamlers.add(teamler); + }); + + List teamlerResponsibilitiesList = JsonBuilder.getTeamlerResponsibilities(); + teamlerResponsibilitiesList.forEach(teamlerResponsibilities -> { + Teamler teamler = teamlers.stream().filter(teamler1 -> teamler1.getUuid().equals(teamlerResponsibilities.getUuid())).findFirst().orElse(null); + + if (teamler == null) { + teamler = new Teamler(teamlerResponsibilities.getUuid(), Sex.undefined, null, null, null, null); + } + + System.out.println("teamler: " + teamler); + if (teamlerResponsibilities.getHv() != null) { + System.out.println("teamlerResponsibilities.getHv(): " + teamlerResponsibilities.getHv()); + teamler.setResponsibilitiesMain(Arrays.asList(teamlerResponsibilities.getHv().split(", "))); + } + if (teamlerResponsibilities.getNv() != null) { + teamler.setResponsibilitiesSecondary(Arrays.asList(teamlerResponsibilities.getNv().split(", "))); + } + }); + + + System.out.println(Dapp.gson.toJson(teamlers)); + + } +} diff --git a/howto-dapp/src/main/java/de/timolia/howto/conversion/JsonBuilder.java b/howto-dapp/src/main/java/de/timolia/howto/conversion/JsonBuilder.java index 9d8374ed..802c006e 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/conversion/JsonBuilder.java +++ b/howto-dapp/src/main/java/de/timolia/howto/conversion/JsonBuilder.java @@ -37,10 +37,6 @@ public static List getTeamlerRankChanges() throws IOException String rankTo = split[3]; String date = split[4]; -// if(rankTo.contains("Supporter+")) { -// Thread.dumpStack(); -// } - TeamlerRankChange teamlerRankChange = new TeamlerRankChange(name, rankFrom, rankTo, date); teamlerRankChanges.add(teamlerRankChange); System.out.println(teamlerRankChange); diff --git a/howto-dapp/src/main/java/de/timolia/howto/conversion/RankConversion.java b/howto-dapp/src/main/java/de/timolia/howto/conversion/RankConversion.java index ad0461db..f886c4cd 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/conversion/RankConversion.java +++ b/howto-dapp/src/main/java/de/timolia/howto/conversion/RankConversion.java @@ -11,22 +11,14 @@ public class RankConversion { public static Rank getRank(String text) { - Map.Entry result = Arrays.stream(Rank.values()) + return Arrays.stream(Rank.values()) .collect(Collectors.toMap(Function.identity(), rank -> Math.max(getSimilarity(text, rank.getFemale()), getSimilarity(text, rank.getMale())))) .entrySet() .stream() .max(Comparator.comparingDouble(Map.Entry::getValue)) .filter(e -> e.getValue() > 0.1) - .orElse(null); - //System.out.println(result.getValue() + ": " + result.getKey().getName()); - - if (result == null) { - return null; - } - return result.getKey(); - - // < 0.1 - //return Arrays.stream(Scenarios.values()).min((o1, o2) -> Double.compare(TextUtils.getSimilarity(text, o2.getName()), TextUtils.getSimilarity(text, o1.getName()))).orElse(null); + .map(Map.Entry::getKey) + .orElse(null); } /** diff --git a/howto-dapp/src/main/java/de/timolia/howto/conversion/SQLApi.java b/howto-dapp/src/main/java/de/timolia/howto/conversion/SQLApi.java index 3f45f48b..19ac14ed 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/conversion/SQLApi.java +++ b/howto-dapp/src/main/java/de/timolia/howto/conversion/SQLApi.java @@ -3,43 +3,43 @@ import de.timolia.howto.Dapp; import java.sql.*; -import java.util.HashMap; -import java.util.Map; import java.util.UUID; public class SQLApi { + private static volatile SqlUserConnection connection; + private static volatile boolean triedConnect; - private static Connection connection; - private static final Map usernames = new HashMap<>(); - private static final Map uuids = new HashMap<>(); - - private static void establishConnection() throws SQLException { + private static SqlUserConnection establishConnection() { + if (!triedConnect) { + synchronized (SQLApi.class) { + if (!triedConnect) { + tryGuardedConnect(); + } + } + } + SqlUserConnection connection = SQLApi.connection; if (connection == null) { - connection = DriverManager.getConnection(Dapp.MYSQL_CON_STR, Dapp.MYSQL_USER, Dapp.MYSQL_PASS); + throw new RuntimeException("Earlier attempt connecting to sql failed"); } + return connection; } - - public static UUID getUuid(String name) { - if (usernames.containsKey(name)) { - return usernames.get(name); + private static void tryGuardedConnect() { + try { + connection = SqlUserConnection.connect(); + } catch (SQLException exception) { + throw new RuntimeException("Unable to establish sql connection", exception); + } finally { + triedConnect = true; } + } - System.out.print("Fetching UUID of '" + name + "'... "); + public static UUID getUuid(String name) { try { - establishConnection(); - PreparedStatement prepareStatement = connection.prepareStatement("SELECT uuid FROM timolia_user_names WHERE name=? ORDER BY last_played DESC LIMIT 1"); - prepareStatement.setString(1, name); - ResultSet resultSet = prepareStatement.executeQuery(); - resultSet.next(); - - UUID uuid = UUID.fromString(resultSet.getString("uuid")); - usernames.put(name, uuid); - System.out.println("'" + uuid + "'"); - return uuid; - } catch (SQLException e) { - e.printStackTrace(); - throw new RuntimeException("Cannot find UUID of '" + name + "'"); + return establishConnection().getUuid(name); + } catch (RuntimeException exception) { + exception.printStackTrace(); + throw exception; } } @@ -48,33 +48,17 @@ public static String getName(UUID uuid) { } public static String getName(UUID uuid, String fallback) { - if (uuids.containsKey(uuid)) { - return uuids.get(uuid); - } - - System.out.print("Fetching name of '" + uuid + "'... "); + SqlUserConnection connection; try { - establishConnection(); - //PreparedStatement prepareStatement = connection.prepareStatement("SELECT * FROM timolia_user_names WHERE uuid=? ORDER BY last_played DESC LIMIT 1"); - PreparedStatement prepareStatement = connection.prepareStatement("SELECT * FROM timolia_user WHERE uuid=?"); - prepareStatement.setString(1, uuid.toString()); - ResultSet resultSet = prepareStatement.executeQuery(); - resultSet.next(); - - String name = resultSet.getString("name"); - uuids.put(uuid, name); - System.out.println(name); - return name; - } catch (SQLException e) { - if (Dapp.isDevEnv && fallback != null) { - System.err.println("Cannot find name of '" + uuid + "', using '" + fallback + "'"); - uuids.put(uuid, fallback); + connection = establishConnection(); + } catch (RuntimeException exception) { + if (fallback != null && SqlUserConnection.isDevEnv()) { + System.err.println("Unable to establish sql connection for " + uuid + " fallback to " + fallback); + exception.printStackTrace(); return fallback; } - - e.printStackTrace(); - throw new RuntimeException("Cannot find name of '" + uuid + "'"); + throw new RuntimeException("Unable to establish sql connection", exception); } + return connection.getName(uuid, fallback); } - } diff --git a/howto-dapp/src/main/java/de/timolia/howto/conversion/SqlUserConnection.java b/howto-dapp/src/main/java/de/timolia/howto/conversion/SqlUserConnection.java new file mode 100644 index 00000000..74afc8e6 --- /dev/null +++ b/howto-dapp/src/main/java/de/timolia/howto/conversion/SqlUserConnection.java @@ -0,0 +1,71 @@ +package de.timolia.howto.conversion; + +import de.timolia.howto.Dapp; + +import java.sql.*; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class SqlUserConnection { + public static SqlUserConnection connect() throws SQLException { + String environmentSuffix = isDevEnv() ? "DEV" : "LIVE"; + String user = System.getenv("MYSQL_USER_" + environmentSuffix); + String password = System.getenv("MYSQL_PASS_" + environmentSuffix); + String connectionString = System.getenv("MYSQL_CON_STR_" + environmentSuffix); + Connection connection = DriverManager.getConnection(connectionString, user, password); + return new SqlUserConnection(connection); + } + + public static boolean isDevEnv() { + return System.getenv("MYSQL_USER_LIVE") == null; + } + + private final Connection connection; + private final Map usernames = new HashMap<>(); + private final Map uuids = new HashMap<>(); + + private SqlUserConnection(Connection connection) { + this.connection = connection; + } + + public UUID getUuid(String name) { + return usernames.computeIfAbsent(name, this::resolveUniqueId); + } + + public UUID resolveUniqueId(String name) { + try { + PreparedStatement prepareStatement = connection.prepareStatement("SELECT uuid FROM timolia_user_names WHERE name=? ORDER BY last_played DESC LIMIT 1"); + prepareStatement.setString(1, name); + ResultSet resultSet = prepareStatement.executeQuery(); + if (!resultSet.next()) { + throw new RuntimeException("Cannot find UUID of '" + name + "'"); + } + return UUID.fromString(resultSet.getString("uuid")); + } catch (SQLException exception) { + throw new RuntimeException("Failed to fetch uuid for name=" + name + "'", exception); + } + } + + public String getName(UUID uuid, String fallback) { + return uuids.computeIfAbsent(uuid, uniqueId -> resolveName(uniqueId, fallback)); + } + + private String resolveName(UUID uuid, String fallback) { + try { + PreparedStatement prepareStatement = connection.prepareStatement("SELECT * FROM timolia_user WHERE uuid=?"); + prepareStatement.setString(1, uuid.toString()); + ResultSet resultSet = prepareStatement.executeQuery(); + if (resultSet.next()) { + return resultSet.getString("name"); + } + if (fallback != null) { + System.out.println("No name for uuid " + uuid + " falling back to " + fallback); + return fallback; + } + throw new RuntimeException("Cannot find name of '" + uuid + "'"); + } catch (SQLException exception) { + throw new RuntimeException("Failed to fetch uuid for uuid=" + uuid + "'", exception); + } + } +} diff --git a/howto-dapp/src/main/java/de/timolia/howto/conversion/models/TeamlerRankChange.java b/howto-dapp/src/main/java/de/timolia/howto/conversion/models/TeamlerRankChange.java index 3ab94a2f..97a89022 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/conversion/models/TeamlerRankChange.java +++ b/howto-dapp/src/main/java/de/timolia/howto/conversion/models/TeamlerRankChange.java @@ -11,7 +11,6 @@ import java.util.UUID; public class TeamlerRankChange { - private static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd.MM.yyyy"); private final String name; @@ -108,5 +107,4 @@ public String toString() { ", date=" + simpleDateFormat.format(date) + '}'; } - } diff --git a/howto-dapp/src/main/java/de/timolia/howto/conversion/models/TeamlerResponsibilities.java b/howto-dapp/src/main/java/de/timolia/howto/conversion/models/TeamlerResponsibilities.java index c4c452d7..d1a5196c 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/conversion/models/TeamlerResponsibilities.java +++ b/howto-dapp/src/main/java/de/timolia/howto/conversion/models/TeamlerResponsibilities.java @@ -5,7 +5,6 @@ import java.util.UUID; public class TeamlerResponsibilities { - private final String name; private final UUID uuid; private final String hv; @@ -45,5 +44,4 @@ public String toString() { ", nv='" + nv + '\'' + '}'; } - } diff --git a/howto-dapp/src/main/java/de/timolia/howto/generator/FileWriter.java b/howto-dapp/src/main/java/de/timolia/howto/generator/FileWriter.java new file mode 100644 index 00000000..136a5cf2 --- /dev/null +++ b/howto-dapp/src/main/java/de/timolia/howto/generator/FileWriter.java @@ -0,0 +1,36 @@ +package de.timolia.howto.generator; + +import de.timolia.howto.translate.Language; +import de.timolia.howto.translate.Translate; +import de.timolia.howto.translate.TranslationContext; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; + +public class FileWriter { + private final Translate translate; + private final Path path; + + public FileWriter(Path path, Translate translate) { + this.path = path; + this.translate = translate; + } + + public void writeFile(String name, String text) throws IOException { + for (Language language : Language.values()) { + TranslationContext translation = translate.forLanguage(language); + String fileName = name + "." + language.key() + ".md"; + String content = translation.replaceAll(text); + writeFile(path.resolve(fileName), content); + } + } + + private static void writeFile(Path path, String text) throws IOException { + path.toFile().getParentFile().mkdirs(); + Files.writeString(path, text, Charset.defaultCharset(), StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE); + System.out.println("Wrote file '" + path + "'"); + } +} diff --git a/howto-dapp/src/main/java/de/timolia/howto/generator/PageRankChange.java b/howto-dapp/src/main/java/de/timolia/howto/generator/PageRankChange.java index 8e4a08a3..3b1c2036 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/generator/PageRankChange.java +++ b/howto-dapp/src/main/java/de/timolia/howto/generator/PageRankChange.java @@ -9,9 +9,7 @@ import java.util.Locale; public class PageRankChange { - public static String generate(List teamlers) { - ArrayList rankChanges = new ArrayList<>(); for (Teamler teamler : teamlers) { rankChanges.addAll(teamler.getRankChanges(false)); @@ -21,11 +19,6 @@ public static String generate(List teamlers) { if (!t1.getDate().equals(t2.getDate())) { return t2.getDate().compareTo(t1.getDate()); } -// if(t1.getRankFrom().equals(t2.getRankFrom())) { -// Teamler teamler1 = teamlers.stream().filter(t -> t.getUuid().equals(t1.getUuid())).findFirst().orElse(null); -// Teamler teamler2 = teamlers.stream().filter(t -> t.getUuid().equals(t2.getUuid())).findFirst().orElse(null); -// return t1.getRankFrom().getString(teamler1.getSex()).compareToIgnoreCase(t2.getRankFrom().getString(teamler2.getSex())); -// } if (!t1.getRankTo().equals(t2.getRankTo())) { Teamler teamler1 = teamlers.stream().filter(t -> t.getUuid().equals(t1.getUuid())).findFirst().orElse(null); Teamler teamler2 = teamlers.stream().filter(t -> t.getUuid().equals(t2.getUuid())).findFirst().orElse(null); @@ -48,7 +41,7 @@ public static String generate(List teamlers) { Calendar cal = Calendar.getInstance(); cal.setTime(teamlerRankChange.getDate()); String month = cal.getDisplayName(Calendar.MONTH, Calendar.LONG, Locale.GERMAN) + " " + cal.get(Calendar.YEAR); - String year = cal.get(Calendar.YEAR) + ""; + String year = String.valueOf(cal.get(Calendar.YEAR)); if (!year.equals(lastYear)) { lastYear = year; @@ -73,7 +66,6 @@ public static String generate(List teamlers) { .append(teamlerRankChange.getReadableDate()) .append(" |") .append("\n"); - //sb.append(teamlerRankChange).append("\n"); } sb.append("\n"); diff --git a/howto-dapp/src/main/java/de/timolia/howto/generator/PageResponsibilities.java b/howto-dapp/src/main/java/de/timolia/howto/generator/PageResponsibilities.java index 65f196c9..aa1dd43f 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/generator/PageResponsibilities.java +++ b/howto-dapp/src/main/java/de/timolia/howto/generator/PageResponsibilities.java @@ -1,9 +1,12 @@ package de.timolia.howto.generator; -import de.timolia.howto.LanguageUtil; -import de.timolia.howto.Utils; -import de.timolia.howto.models.Language; +import de.timolia.howto.Dapp; +import de.timolia.howto.responsibility.Responsibility; +import de.timolia.howto.responsibility.ResponsibilityType; +import de.timolia.howto.translate.Language; import de.timolia.howto.models.Teamler; +import de.timolia.howto.translate.Translate; +import de.timolia.howto.translate.TranslationContext; import java.util.LinkedHashMap; import java.util.LinkedList; @@ -12,9 +15,7 @@ import java.util.stream.Collectors; public class PageResponsibilities { - public static String generate(List teamlers) { - LinkedHashMap> responsibilities = new LinkedHashMap<>() {{ put("%page.responsibilities.project-team-orga%", new LinkedHashMap<>() {{ put("%page.responsibilities.teamleader%", "%page.responsibilities.teamleader.desc%"); @@ -48,15 +49,14 @@ public static String generate(List teamlers) { for (Map.Entry> categories : responsibilities.entrySet()) { String categoryName = categories.getKey(); LinkedHashMap subcategories = categories.getValue(); - sb .append("\n") .append("\n").append("# ").append(categoryName); + TranslationContext nameConverter = Dapp.translate.forLanguage(Language.DE); for (Map.Entry e : subcategories.entrySet()) { - String name = LanguageUtil.translate(Language.DE, e.getKey()); + String name = nameConverter.replaceAll(e.getKey()); String description = e.getValue(); - sb .append("\n") .append("\n").append("### **").append(name).append("**"); @@ -75,97 +75,78 @@ public static String generate(List teamlers) { String titleCustom = null; - LinkedList> hvCustom = new LinkedList<>(); - LinkedList> nvCustom = new LinkedList<>(); + LinkedList hvCustom = new LinkedList<>(); + LinkedList nvCustom = new LinkedList<>(); // custom stuff - if (e.getKey().equals("%page.responsibilities.bug-reports%")) { - nvCustom.add(new Utils.KeyValuePair<>("%page.responsibilities.custom.bug-reports.modsanddevs%", null)); - } else if (e.getKey().equals("%page.responsibilities.sm%")) { - titleCustom = "Projekte u. Verantwortungsgrad"; - for (Teamler teamler : teamlers.stream().filter(teamler -> teamler.hasResponsibilityMain("Twitter")).sorted(Teamler::compare).collect(Collectors.toList())) { - nvCustom.add(new Utils.KeyValuePair<>("|" + teamler.getNameForMarkdown() + "", "%page.responsibilities.custom.sm.twitter.hv%")); - } - for (Teamler teamler : teamlers.stream().filter(teamler -> teamler.hasResponsibilitySecondary("Twitter")).sorted(Teamler::compare).collect(Collectors.toList())) { - nvCustom.add(new Utils.KeyValuePair<>("|" + teamler.getNameForMarkdown() + "", "%page.responsibilities.custom.sm.twitter.nv%")); - } - for (Teamler teamler : teamlers.stream().filter(teamler -> teamler.hasResponsibilityMain("Bauteam-Twitter")).sorted(Teamler::compare).collect(Collectors.toList())) { - nvCustom.add(new Utils.KeyValuePair<>("|" + teamler.getNameForMarkdown() + "", "%page.responsibilities.custom.sm.twitter-builder.hv%")); - } - for (Teamler teamler : teamlers.stream().filter(teamler -> teamler.hasResponsibilitySecondary("Bauteam-Twitter")).sorted(Teamler::compare).collect(Collectors.toList())) { - nvCustom.add(new Utils.KeyValuePair<>("|" + teamler.getNameForMarkdown() + "", "%page.responsibilities.custom.sm.twitter-builder.nv%")); - } - } else if (e.getKey().equals("%page.responsibilities.teamleader%")) { - titleCustom = "%page.responsibilities.custom.teamleader.title%"; - // |J4mPr0 | Management des gesamten Timolia-Teams | - // |Jukplays | Management des Bau-Teams | - for (Teamler teamler : teamlers.stream().filter(teamler -> teamler.hasResponsibilityMain("Management des Timolia-Teams")).sorted(Teamler::compare).collect(Collectors.toList())) { - hvCustom.add(new Utils.KeyValuePair<>("|" + teamler.getNameForMarkdown() + "", "%page.responsibilities.custom.teamleader.whole-team%")); - } - for (Teamler teamler : teamlers.stream().filter(teamler -> teamler.hasResponsibilityMain("Management des Bau-Teams")).sorted(Teamler::compare).collect(Collectors.toList())) { - hvCustom.add(new Utils.KeyValuePair<>("|" + teamler.getNameForMarkdown() + "", "%page.responsibilities.custom.teamleader.builder%")); - } - for (Teamler teamler : teamlers.stream().filter(teamler -> teamler.hasResponsibilityMain("Management des Content-Teams")).sorted(Teamler::compare).collect(Collectors.toList())) { - hvCustom.add(new Utils.KeyValuePair<>("|" + teamler.getNameForMarkdown() + "", "%page.responsibilities.custom.teamleader.content%")); - } - for (Teamler teamler : teamlers.stream().filter(teamler -> teamler.hasResponsibilityMain("Management des Development-Teams")).sorted(Teamler::compare).collect(Collectors.toList())) { - hvCustom.add(new Utils.KeyValuePair<>("|" + teamler.getNameForMarkdown() + "", "%page.responsibilities.custom.teamleader.development%")); - } - } else if (e.getKey().equals("%page.responsibilities.yter%")) { - titleCustom = "%page.responsibilities.custom.yter.title%"; + switch (e.getKey()) { + case "%page.responsibilities.bug-reports%": + nvCustom.add(Responsibility.simple(ResponsibilityType.NV, "%page.responsibilities.custom.bug-reports.modsanddevs%")); + break; + case "%page.responsibilities.sm%": + titleCustom = "Projekte u. Verantwortungsgrad"; + for (Teamler teamler : teamlers.stream().filter(teamler -> teamler.hasResponsibilityMain("Twitter")).sorted(Teamler::compare).collect(Collectors.toList())) { + nvCustom.add(Responsibility.concreteTeamster(teamler, "%page.responsibilities.custom.sm.twitter.hv%")); + } + for (Teamler teamler : teamlers.stream().filter(teamler -> teamler.hasResponsibilitySecondary("Twitter")).sorted(Teamler::compare).collect(Collectors.toList())) { + nvCustom.add(Responsibility.concreteTeamster(teamler, "%page.responsibilities.custom.sm.twitter.nv%")); + } + for (Teamler teamler : teamlers.stream().filter(teamler -> teamler.hasResponsibilityMain("Bauteam-Twitter")).sorted(Teamler::compare).collect(Collectors.toList())) { + nvCustom.add(Responsibility.concreteTeamster(teamler, "%page.responsibilities.custom.sm.twitter-builder.hv%")); + } + for (Teamler teamler : teamlers.stream().filter(teamler -> teamler.hasResponsibilitySecondary("Bauteam-Twitter")).sorted(Teamler::compare).collect(Collectors.toList())) { + nvCustom.add(Responsibility.concreteTeamster(teamler, "%page.responsibilities.custom.sm.twitter-builder.nv%")); + } + break; + case "%page.responsibilities.teamleader%": + titleCustom = "%page.responsibilities.custom.teamleader.title%"; + for (Teamler teamler : teamlers.stream().filter(teamler -> teamler.hasResponsibilityMain("Management des Timolia-Teams")).sorted(Teamler::compare).collect(Collectors.toList())) { + hvCustom.add(Responsibility.concreteTeamster(teamler, "%page.responsibilities.custom.teamleader.whole-team%")); + } + for (Teamler teamler : teamlers.stream().filter(teamler -> teamler.hasResponsibilityMain("Management des Bau-Teams")).sorted(Teamler::compare).collect(Collectors.toList())) { + hvCustom.add(Responsibility.concreteTeamster(teamler, "%page.responsibilities.custom.teamleader.builder%")); + } + for (Teamler teamler : teamlers.stream().filter(teamler -> teamler.hasResponsibilityMain("Management des Content-Teams")).sorted(Teamler::compare).collect(Collectors.toList())) { + hvCustom.add(Responsibility.concreteTeamster(teamler, "%page.responsibilities.custom.teamleader.content%")); + } + for (Teamler teamler : teamlers.stream().filter(teamler -> teamler.hasResponsibilityMain("Management des Development-Teams")).sorted(Teamler::compare).collect(Collectors.toList())) { + hvCustom.add(Responsibility.concreteTeamster(teamler, "%page.responsibilities.custom.teamleader.development%")); + } + break; + case "%page.responsibilities.yter%": + titleCustom = "%page.responsibilities.custom.yter.title%"; + break; } - - if (titleCustom == null) { sb.append("\n").append("| %page.responsibilities.teamler% | %page.responsibilities.responsib% |"); } else { sb.append("\n").append("| %page.responsibilities.teamler% | ").append(titleCustom).append(" |"); } - sb.append("\n").append("| ------ | ------ |"); - if (hvCustom.isEmpty()) { for (Teamler teamler : hv) { - sb.append("\n").append("|").append(teamler.getNameForMarkdown()).append(" | %page.responsibilities.hv% |"); - } - } else { - for (Utils.KeyValuePair hvEntry : hvCustom) { - String k = hvEntry.getKey(); - String v = hvEntry.getValue(); - if (v == null) { - sb.append("\n").append(k).append(" | %page.responsibilities.hv% |"); - } else { - sb.append("\n").append(k).append(" | ").append(v).append(" |"); - } + hvCustom.add(Responsibility.concreteTeamster(ResponsibilityType.HV, teamler)); } } - + for (Responsibility hvEntry : hvCustom) { + sb.append("\n"); + hvEntry.renderTo(sb); + } if (!nv.isEmpty() || !nvCustom.isEmpty()) { sb.append("\n").append("| | |"); if (nvCustom.isEmpty()) { for (Teamler teamler : nv) { - sb.append("\n").append("|").append(teamler.getNameForMarkdown()).append(" | %page.responsibilities.nv% |"); - } - } else { - for (Utils.KeyValuePair nvEntry : nvCustom) { - String k = nvEntry.getKey(); - String v = nvEntry.getValue(); - if (v == null) { - sb.append("\n").append("|").append(k).append(" | %page.responsibilities.nv% |"); - } else { - sb.append("\n").append(k).append(" | ").append(v).append(" |"); - } + hvCustom.add(Responsibility.concreteTeamster(ResponsibilityType.NV, teamler)); } } + for (Responsibility nvEntry : nvCustom) { + sb.append("\n"); + nvEntry.renderTo(sb); + } } - - } } - sb.append("\n"); - return sb.toString(); } - -} +} diff --git a/howto-dapp/src/main/java/de/timolia/howto/generator/PageTeamMembers.java b/howto-dapp/src/main/java/de/timolia/howto/generator/PageTeamMembers.java index 8164e085..cddc0530 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/generator/PageTeamMembers.java +++ b/howto-dapp/src/main/java/de/timolia/howto/generator/PageTeamMembers.java @@ -10,22 +10,11 @@ import java.util.stream.Collectors; public class PageTeamMembers { - public static String generate(List teamlers) { - teamlers = teamlers.stream().filter(teamler -> teamler.getRankCurrent().isInTeam()).collect(Collectors.toList()); - - //return t1.getName().compareToIgnoreCase(t2.getName()); teamlers.sort(Teamler::compare); - - List> a = teamlers.stream().collect(Collectors.groupingBy(Teamler::getRankCurrent, Collectors.counting())) - .entrySet().stream().sorted((e1, e2) -> e1.getKey().compare(e2.getKey())).collect(Collectors.toList()); - - List ranks = Arrays.stream(Rank.values()).filter(rank -> rank.getDescription() != null).sorted(Rank::compare).collect(Collectors.toList()); - StringBuilder sb = new StringBuilder(); - sb.append("%page.members.first-1%").append(teamlers.size()).append("%page.members.first-2%\n"); List rankStrings = ranks.stream().map(rank -> "" + rank.getMale() + "").collect(Collectors.toList()); for (int i = 0; i < rankStrings.size(); i++) { @@ -44,7 +33,6 @@ public static String generate(List teamlers) { .append("\n").append("![%page.members.first-5%](img/content-ranks.png)"); for (Rank rank : ranks) { - sb .append("\n") .append("\n") @@ -71,25 +59,20 @@ public static String generate(List teamlers) { sb .append("\n") .append("- %page.members.hv%: ").append(teamler.getResponsibilitiesMain().stream().sorted(String::compareToIgnoreCase).collect(Collectors.joining(", "))); - //.append("- Hauptverantwortlich: ").append(String.join(", ", teamler.getResponsibilitiesMain())); } if (teamler.getResponsibilitiesSecondary() != null) { sb .append("\n") .append("- %page.members.nv%: ").append(teamler.getResponsibilitiesSecondary().stream().sorted(String::compareToIgnoreCase).collect(Collectors.joining(", "))); - //.append("- Nebenverantwortlich: ").append(String.join(", ", teamler.getResponsibilitiesSecondary())); } - if(teamler.getFields() != null){ + if (teamler.getFields() != null){ sb .append("\n") .append("- %page.members.fields%: ").append(teamler.getFields().stream().sorted(String::compareToIgnoreCase).collect(Collectors.joining(", "))); } } } - sb.append("\n"); - return sb.toString(); } - } diff --git a/howto-dapp/src/main/java/de/timolia/howto/models/Language.java b/howto-dapp/src/main/java/de/timolia/howto/models/Language.java deleted file mode 100644 index 1a8be8ae..00000000 --- a/howto-dapp/src/main/java/de/timolia/howto/models/Language.java +++ /dev/null @@ -1,8 +0,0 @@ -package de.timolia.howto.models; - -public enum Language { - - DE, - EN - -} diff --git a/howto-dapp/src/main/java/de/timolia/howto/models/Rank.java b/howto-dapp/src/main/java/de/timolia/howto/models/Rank.java index acdf46b6..78f2584c 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/models/Rank.java +++ b/howto-dapp/src/main/java/de/timolia/howto/models/Rank.java @@ -1,7 +1,6 @@ package de.timolia.howto.models; public enum Rank { - administrator( 161, true, "administrator", "Administrator", "Administratorin", "%rank.administrator.description%"), administrator_city( 160, true, "administrator", "Administrator City", null), builder( 80, true, "builder", "Builder", "Builderin", "%rank.builder.description%"), @@ -60,20 +59,12 @@ public enum Rank { } public String getString(Sex sex) { - if (sex.equals(Sex.female)) { - if (this.female != null) { - return this.female; - } else { - return this.male; - } - } else if (sex.equals(Sex.male)) { - return this.male; - } else { - return this.male; + if (sex == Sex.female && this.female != null) { + return this.female; } + return this.male; } - public int getValue() { return value; } diff --git a/howto-dapp/src/main/java/de/timolia/howto/models/Sex.java b/howto-dapp/src/main/java/de/timolia/howto/models/Sex.java index c4b3ad61..56662377 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/models/Sex.java +++ b/howto-dapp/src/main/java/de/timolia/howto/models/Sex.java @@ -1,9 +1,7 @@ package de.timolia.howto.models; public enum Sex { - female, male, undefined - } diff --git a/howto-dapp/src/main/java/de/timolia/howto/models/Teamler.java b/howto-dapp/src/main/java/de/timolia/howto/models/Teamler.java index 5397bc77..e32bd879 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/models/Teamler.java +++ b/howto-dapp/src/main/java/de/timolia/howto/models/Teamler.java @@ -21,7 +21,6 @@ public class Teamler { private final List responsibilitiesSecondaryHidden; private final List fields; private final LinkedHashMap rankHistory; - private transient List rankChanges = null; private transient Rank rankCurrent = null; public Teamler(UUID uuid, Sex sex, List responsibilitiesMain, List responsibilitiesSecondary, List fields, LinkedHashMap rankHistory) { @@ -85,8 +84,7 @@ public HashMap getRankHistory() { } public List getRankChanges(boolean includeHidden) { - //if(rankChanges == null) { - rankChanges = new ArrayList<>(); + List rankChanges = new ArrayList<>(); if (rankHistory == null || rankHistory.isEmpty()) { return rankChanges; } @@ -102,28 +100,20 @@ public List getRankChanges(boolean includeHidden) { String rankOldKey = TeamlerRankChange.toString(dates.get(Math.max(i - 1, 0))); if (!rankHistory.containsKey(rankOldKey) && rankHistory.containsKey("hidden-" + rankOldKey)) { rankOldKey = "hidden-" + rankOldKey; - //hidden = true; } Rank rank_old = rankHistory.get(rankOldKey); -// if(Math.max(i - 1, 0) + 1 > dates.size() - 1) { -// System.out.println("asd"); -// } - String rankNewKey = TeamlerRankChange.toString(dates.get(i)); if (!rankHistory.containsKey(rankNewKey) && rankHistory.containsKey("hidden-" + rankNewKey)) { rankNewKey = "hidden-" + rankNewKey; hidden = true; } Rank rank_new = rankHistory.get(rankNewKey); - if (includeHidden || !hidden && !rankNewKey.equals("initial")) { TeamlerRankChange teamlerRankChange = new TeamlerRankChange(name, uuid, rank_old, rank_new, TeamlerRankChange.toString(dates.get(i)), hidden); rankChanges.add(teamlerRankChange); } } - //} - return rankChanges; } @@ -184,5 +174,4 @@ public String toString() { ", rankHistory=" + rankHistory + '}'; } - } diff --git a/howto-dapp/src/main/java/de/timolia/howto/responsibility/Responsibility.java b/howto-dapp/src/main/java/de/timolia/howto/responsibility/Responsibility.java new file mode 100644 index 00000000..ed7cddc8 --- /dev/null +++ b/howto-dapp/src/main/java/de/timolia/howto/responsibility/Responsibility.java @@ -0,0 +1,32 @@ +package de.timolia.howto.responsibility; + +import de.timolia.howto.models.Teamler; + +public interface Responsibility { + void renderTo(StringBuilder builder); + + static Responsibility simple(ResponsibilityType type, String teamler) { + return builder -> builder + .append("|") + .append(teamler) + .append(" | ") + .append(type.defaultKey()) + .append(" |"); + } + + static Responsibility concreteTeamster(ResponsibilityType type, Teamler teamler) { + return concreteTeamster(teamler, type.defaultKey()); + } + + static Responsibility concreteTeamster(Teamler teamler, String translationKey) { + return builder -> builder + .append("|") + .append(teamler.getNameForMarkdown()) + .append("") + .append(" | ") + .append(translationKey) + .append(" |"); + } +} diff --git a/howto-dapp/src/main/java/de/timolia/howto/responsibility/ResponsibilityType.java b/howto-dapp/src/main/java/de/timolia/howto/responsibility/ResponsibilityType.java new file mode 100644 index 00000000..a708833a --- /dev/null +++ b/howto-dapp/src/main/java/de/timolia/howto/responsibility/ResponsibilityType.java @@ -0,0 +1,12 @@ +package de.timolia.howto.responsibility; + +import java.util.Locale; + +public enum ResponsibilityType { + HV, + NV; + + public String defaultKey() { + return "%page.responsibilities." + name().toLowerCase(Locale.ROOT) + "%"; + } +} diff --git a/howto-dapp/src/main/java/de/timolia/howto/translate/Language.java b/howto-dapp/src/main/java/de/timolia/howto/translate/Language.java new file mode 100644 index 00000000..6fc10247 --- /dev/null +++ b/howto-dapp/src/main/java/de/timolia/howto/translate/Language.java @@ -0,0 +1,12 @@ +package de.timolia.howto.translate; + +import java.util.Locale; + +public enum Language { + DE, + EN; + + public String key() { + return name().toLowerCase(Locale.ROOT); + } +} diff --git a/howto-dapp/src/main/java/de/timolia/howto/translate/Translate.java b/howto-dapp/src/main/java/de/timolia/howto/translate/Translate.java new file mode 100644 index 00000000..f27eeb82 --- /dev/null +++ b/howto-dapp/src/main/java/de/timolia/howto/translate/Translate.java @@ -0,0 +1,53 @@ +package de.timolia.howto.translate; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.*; +import java.util.stream.Collectors; + +public class Translate { + private final Map> translations = new HashMap<>(); + + public void loadDirectory(Path path) throws IOException { + Files.list(path).forEach(file -> { + try { + mayLoadFile(file); + } catch (IOException e) { + throw new UncheckedIOException("Failed to load translation from " + file, e); + } + }); + } + + private void mayLoadFile(Path path) throws IOException { + String name = path.getFileName().toString(); + System.out.println(name); + if (!name.endsWith(".properties")) { + return; + } + String languageName = name.substring(0, name.length() - ".properties".length()); + Language language = Language.valueOf(languageName.toUpperCase(Locale.ROOT)); + System.out.println(languageName); + Properties properties = new Properties(); + properties.load(Files.newBufferedReader(path, StandardCharsets.UTF_8)); + translations.put(language, properties.entrySet() + .stream() + .map(property -> new Translation(language, property.getKey().toString(), property.getValue().toString())) + .collect(Collectors.toList())); + } + + public TranslationContext forLanguage(Language language) { + List translations = this.translations.get(language); + if (translations == null) { + throw new IllegalArgumentException("No translations for language " + language); + } + return content -> { + for (Translation translation : translations) { + content = translation.replace(content); + } + return content; + }; + } +} diff --git a/howto-dapp/src/main/java/de/timolia/howto/models/LanguageString.java b/howto-dapp/src/main/java/de/timolia/howto/translate/Translation.java similarity index 65% rename from howto-dapp/src/main/java/de/timolia/howto/models/LanguageString.java rename to howto-dapp/src/main/java/de/timolia/howto/translate/Translation.java index bfce2a6b..721eec06 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/models/LanguageString.java +++ b/howto-dapp/src/main/java/de/timolia/howto/translate/Translation.java @@ -1,17 +1,23 @@ -package de.timolia.howto.models; - -public class LanguageString { +package de.timolia.howto.translate; +public class Translation { private final Language language; private final String key; private final String value; - public LanguageString(Language language, String key, String value) { + public Translation(Language language, String key, String value) { this.language = language; this.key = key; this.value = value; } + public String replace(String text) { + return text.replace(replacementKey(), getValue()); + } + + private String replacementKey() { + return "%" + getKey() + "%"; + } public Language getLanguage() { return language; @@ -25,7 +31,6 @@ public String getValue() { return value; } - @Override public String toString() { return "LanguageString{" + @@ -34,5 +39,4 @@ public String toString() { ", value='" + value + '\'' + '}'; } - } diff --git a/howto-dapp/src/main/java/de/timolia/howto/translate/TranslationContext.java b/howto-dapp/src/main/java/de/timolia/howto/translate/TranslationContext.java new file mode 100644 index 00000000..56b0b909 --- /dev/null +++ b/howto-dapp/src/main/java/de/timolia/howto/translate/TranslationContext.java @@ -0,0 +1,5 @@ +package de.timolia.howto.translate; + +public interface TranslationContext { + String replaceAll(String content); +} From 681f361a3b9bd833b5b74228d0e658e33f12acee Mon Sep 17 00:00:00 2001 From: David Scandurra Date: Fri, 19 May 2023 17:42:15 +0200 Subject: [PATCH 2/8] Rename .java to .kt --- howto-dapp/src/main/java/de/timolia/howto/{Dapp.java => Dapp.kt} | 0 .../conversion/{InitialConversion.java => InitialConversion.kt} | 0 .../timolia/howto/conversion/{JsonBuilder.java => JsonBuilder.kt} | 0 .../TeamlerResponsibilities.java => TeamlerResponsibilities.kt} | 0 .../timolia/howto/{conversion/SQLApi.java => database/SQLApi.kt} | 0 .../SqlUserConnection.java => database/SqlUserConnection.kt} | 0 .../de/timolia/howto/generator/{FileWriter.java => FileWriter.kt} | 0 .../howto/generator/{PageRankChange.java => PageRankChange.kt} | 0 .../{PageResponsibilities.java => PageResponsibilities.kt} | 0 .../howto/generator/{PageTeamMembers.java => PageTeamMembers.kt} | 0 .../main/java/de/timolia/howto/{models/Rank.java => rank/Rank.kt} | 0 .../{conversion/RankConversion.java => rank/RankConversion.kt} | 0 .../models/TeamlerRankChange.java => rank/TeamlerRankChange.kt} | 0 .../responsibility/{Responsibility.java => Responsibility.kt} | 0 .../{ResponsibilityType.java => ResponsibilityType.kt} | 0 .../java/de/timolia/howto/{models/Sex.java => teamler/Sex.kt} | 0 .../de/timolia/howto/{models/Teamler.java => teamler/Teamler.kt} | 0 .../de/timolia/howto/translate/{Language.java => Language.kt} | 0 .../de/timolia/howto/translate/{Translate.java => Translate.kt} | 0 .../timolia/howto/translate/{Translation.java => Translation.kt} | 0 .../translate/{TranslationContext.java => TranslationContext.kt} | 0 21 files changed, 0 insertions(+), 0 deletions(-) rename howto-dapp/src/main/java/de/timolia/howto/{Dapp.java => Dapp.kt} (100%) rename howto-dapp/src/main/java/de/timolia/howto/conversion/{InitialConversion.java => InitialConversion.kt} (100%) rename howto-dapp/src/main/java/de/timolia/howto/conversion/{JsonBuilder.java => JsonBuilder.kt} (100%) rename howto-dapp/src/main/java/de/timolia/howto/conversion/{models/TeamlerResponsibilities.java => TeamlerResponsibilities.kt} (100%) rename howto-dapp/src/main/java/de/timolia/howto/{conversion/SQLApi.java => database/SQLApi.kt} (100%) rename howto-dapp/src/main/java/de/timolia/howto/{conversion/SqlUserConnection.java => database/SqlUserConnection.kt} (100%) rename howto-dapp/src/main/java/de/timolia/howto/generator/{FileWriter.java => FileWriter.kt} (100%) rename howto-dapp/src/main/java/de/timolia/howto/generator/{PageRankChange.java => PageRankChange.kt} (100%) rename howto-dapp/src/main/java/de/timolia/howto/generator/{PageResponsibilities.java => PageResponsibilities.kt} (100%) rename howto-dapp/src/main/java/de/timolia/howto/generator/{PageTeamMembers.java => PageTeamMembers.kt} (100%) rename howto-dapp/src/main/java/de/timolia/howto/{models/Rank.java => rank/Rank.kt} (100%) rename howto-dapp/src/main/java/de/timolia/howto/{conversion/RankConversion.java => rank/RankConversion.kt} (100%) rename howto-dapp/src/main/java/de/timolia/howto/{conversion/models/TeamlerRankChange.java => rank/TeamlerRankChange.kt} (100%) rename howto-dapp/src/main/java/de/timolia/howto/responsibility/{Responsibility.java => Responsibility.kt} (100%) rename howto-dapp/src/main/java/de/timolia/howto/responsibility/{ResponsibilityType.java => ResponsibilityType.kt} (100%) rename howto-dapp/src/main/java/de/timolia/howto/{models/Sex.java => teamler/Sex.kt} (100%) rename howto-dapp/src/main/java/de/timolia/howto/{models/Teamler.java => teamler/Teamler.kt} (100%) rename howto-dapp/src/main/java/de/timolia/howto/translate/{Language.java => Language.kt} (100%) rename howto-dapp/src/main/java/de/timolia/howto/translate/{Translate.java => Translate.kt} (100%) rename howto-dapp/src/main/java/de/timolia/howto/translate/{Translation.java => Translation.kt} (100%) rename howto-dapp/src/main/java/de/timolia/howto/translate/{TranslationContext.java => TranslationContext.kt} (100%) diff --git a/howto-dapp/src/main/java/de/timolia/howto/Dapp.java b/howto-dapp/src/main/java/de/timolia/howto/Dapp.kt similarity index 100% rename from howto-dapp/src/main/java/de/timolia/howto/Dapp.java rename to howto-dapp/src/main/java/de/timolia/howto/Dapp.kt diff --git a/howto-dapp/src/main/java/de/timolia/howto/conversion/InitialConversion.java b/howto-dapp/src/main/java/de/timolia/howto/conversion/InitialConversion.kt similarity index 100% rename from howto-dapp/src/main/java/de/timolia/howto/conversion/InitialConversion.java rename to howto-dapp/src/main/java/de/timolia/howto/conversion/InitialConversion.kt diff --git a/howto-dapp/src/main/java/de/timolia/howto/conversion/JsonBuilder.java b/howto-dapp/src/main/java/de/timolia/howto/conversion/JsonBuilder.kt similarity index 100% rename from howto-dapp/src/main/java/de/timolia/howto/conversion/JsonBuilder.java rename to howto-dapp/src/main/java/de/timolia/howto/conversion/JsonBuilder.kt diff --git a/howto-dapp/src/main/java/de/timolia/howto/conversion/models/TeamlerResponsibilities.java b/howto-dapp/src/main/java/de/timolia/howto/conversion/TeamlerResponsibilities.kt similarity index 100% rename from howto-dapp/src/main/java/de/timolia/howto/conversion/models/TeamlerResponsibilities.java rename to howto-dapp/src/main/java/de/timolia/howto/conversion/TeamlerResponsibilities.kt diff --git a/howto-dapp/src/main/java/de/timolia/howto/conversion/SQLApi.java b/howto-dapp/src/main/java/de/timolia/howto/database/SQLApi.kt similarity index 100% rename from howto-dapp/src/main/java/de/timolia/howto/conversion/SQLApi.java rename to howto-dapp/src/main/java/de/timolia/howto/database/SQLApi.kt diff --git a/howto-dapp/src/main/java/de/timolia/howto/conversion/SqlUserConnection.java b/howto-dapp/src/main/java/de/timolia/howto/database/SqlUserConnection.kt similarity index 100% rename from howto-dapp/src/main/java/de/timolia/howto/conversion/SqlUserConnection.java rename to howto-dapp/src/main/java/de/timolia/howto/database/SqlUserConnection.kt diff --git a/howto-dapp/src/main/java/de/timolia/howto/generator/FileWriter.java b/howto-dapp/src/main/java/de/timolia/howto/generator/FileWriter.kt similarity index 100% rename from howto-dapp/src/main/java/de/timolia/howto/generator/FileWriter.java rename to howto-dapp/src/main/java/de/timolia/howto/generator/FileWriter.kt diff --git a/howto-dapp/src/main/java/de/timolia/howto/generator/PageRankChange.java b/howto-dapp/src/main/java/de/timolia/howto/generator/PageRankChange.kt similarity index 100% rename from howto-dapp/src/main/java/de/timolia/howto/generator/PageRankChange.java rename to howto-dapp/src/main/java/de/timolia/howto/generator/PageRankChange.kt diff --git a/howto-dapp/src/main/java/de/timolia/howto/generator/PageResponsibilities.java b/howto-dapp/src/main/java/de/timolia/howto/generator/PageResponsibilities.kt similarity index 100% rename from howto-dapp/src/main/java/de/timolia/howto/generator/PageResponsibilities.java rename to howto-dapp/src/main/java/de/timolia/howto/generator/PageResponsibilities.kt diff --git a/howto-dapp/src/main/java/de/timolia/howto/generator/PageTeamMembers.java b/howto-dapp/src/main/java/de/timolia/howto/generator/PageTeamMembers.kt similarity index 100% rename from howto-dapp/src/main/java/de/timolia/howto/generator/PageTeamMembers.java rename to howto-dapp/src/main/java/de/timolia/howto/generator/PageTeamMembers.kt diff --git a/howto-dapp/src/main/java/de/timolia/howto/models/Rank.java b/howto-dapp/src/main/java/de/timolia/howto/rank/Rank.kt similarity index 100% rename from howto-dapp/src/main/java/de/timolia/howto/models/Rank.java rename to howto-dapp/src/main/java/de/timolia/howto/rank/Rank.kt diff --git a/howto-dapp/src/main/java/de/timolia/howto/conversion/RankConversion.java b/howto-dapp/src/main/java/de/timolia/howto/rank/RankConversion.kt similarity index 100% rename from howto-dapp/src/main/java/de/timolia/howto/conversion/RankConversion.java rename to howto-dapp/src/main/java/de/timolia/howto/rank/RankConversion.kt diff --git a/howto-dapp/src/main/java/de/timolia/howto/conversion/models/TeamlerRankChange.java b/howto-dapp/src/main/java/de/timolia/howto/rank/TeamlerRankChange.kt similarity index 100% rename from howto-dapp/src/main/java/de/timolia/howto/conversion/models/TeamlerRankChange.java rename to howto-dapp/src/main/java/de/timolia/howto/rank/TeamlerRankChange.kt diff --git a/howto-dapp/src/main/java/de/timolia/howto/responsibility/Responsibility.java b/howto-dapp/src/main/java/de/timolia/howto/responsibility/Responsibility.kt similarity index 100% rename from howto-dapp/src/main/java/de/timolia/howto/responsibility/Responsibility.java rename to howto-dapp/src/main/java/de/timolia/howto/responsibility/Responsibility.kt diff --git a/howto-dapp/src/main/java/de/timolia/howto/responsibility/ResponsibilityType.java b/howto-dapp/src/main/java/de/timolia/howto/responsibility/ResponsibilityType.kt similarity index 100% rename from howto-dapp/src/main/java/de/timolia/howto/responsibility/ResponsibilityType.java rename to howto-dapp/src/main/java/de/timolia/howto/responsibility/ResponsibilityType.kt diff --git a/howto-dapp/src/main/java/de/timolia/howto/models/Sex.java b/howto-dapp/src/main/java/de/timolia/howto/teamler/Sex.kt similarity index 100% rename from howto-dapp/src/main/java/de/timolia/howto/models/Sex.java rename to howto-dapp/src/main/java/de/timolia/howto/teamler/Sex.kt diff --git a/howto-dapp/src/main/java/de/timolia/howto/models/Teamler.java b/howto-dapp/src/main/java/de/timolia/howto/teamler/Teamler.kt similarity index 100% rename from howto-dapp/src/main/java/de/timolia/howto/models/Teamler.java rename to howto-dapp/src/main/java/de/timolia/howto/teamler/Teamler.kt diff --git a/howto-dapp/src/main/java/de/timolia/howto/translate/Language.java b/howto-dapp/src/main/java/de/timolia/howto/translate/Language.kt similarity index 100% rename from howto-dapp/src/main/java/de/timolia/howto/translate/Language.java rename to howto-dapp/src/main/java/de/timolia/howto/translate/Language.kt diff --git a/howto-dapp/src/main/java/de/timolia/howto/translate/Translate.java b/howto-dapp/src/main/java/de/timolia/howto/translate/Translate.kt similarity index 100% rename from howto-dapp/src/main/java/de/timolia/howto/translate/Translate.java rename to howto-dapp/src/main/java/de/timolia/howto/translate/Translate.kt diff --git a/howto-dapp/src/main/java/de/timolia/howto/translate/Translation.java b/howto-dapp/src/main/java/de/timolia/howto/translate/Translation.kt similarity index 100% rename from howto-dapp/src/main/java/de/timolia/howto/translate/Translation.java rename to howto-dapp/src/main/java/de/timolia/howto/translate/Translation.kt diff --git a/howto-dapp/src/main/java/de/timolia/howto/translate/TranslationContext.java b/howto-dapp/src/main/java/de/timolia/howto/translate/TranslationContext.kt similarity index 100% rename from howto-dapp/src/main/java/de/timolia/howto/translate/TranslationContext.java rename to howto-dapp/src/main/java/de/timolia/howto/translate/TranslationContext.kt From 1c01c3bc580faabe88a58708070d1bb7c2e7b88c Mon Sep 17 00:00:00 2001 From: David Scandurra Date: Fri, 19 May 2023 17:42:15 +0200 Subject: [PATCH 3/8] Migrate to kotlin --- howto-dapp/build.gradle | 13 +- howto-dapp/gradle/wrapper/gradle-wrapper.jar | Bin 59203 -> 59536 bytes .../gradle/wrapper/gradle-wrapper.properties | 4 +- howto-dapp/{ => src}/gradlew | 2 +- howto-dapp/{ => src}/gradlew.bat | 2 +- .../src/main/java/de/timolia/howto/Dapp.kt | 69 +++--- .../howto/conversion/InitialConversion.kt | 99 ++++---- .../timolia/howto/conversion/JsonBuilder.kt | 134 +++++----- .../conversion/TeamlerResponsibilities.kt | 48 +--- .../java/de/timolia/howto/database/SQLApi.kt | 74 +++--- .../howto/database/SqlUserConnection.kt | 97 ++++---- .../de/timolia/howto/generator/FileWriter.kt | 53 ++-- .../timolia/howto/generator/PageRankChange.kt | 97 ++++---- .../howto/generator/PageResponsibilities.kt | 228 ++++++++--------- .../howto/generator/PageTeamMembers.kt | 86 +++---- .../main/java/de/timolia/howto/rank/Rank.kt | 144 +++++------ .../de/timolia/howto/rank/RankConversion.kt | 93 +++---- .../timolia/howto/rank/TeamlerRankChange.kt | 150 +++++------- .../howto/responsibility/Responsibility.kt | 56 +++-- .../responsibility/ResponsibilityType.kt | 10 +- .../main/java/de/timolia/howto/teamler/Sex.kt | 4 +- .../java/de/timolia/howto/teamler/Teamler.kt | 230 +++++++----------- .../de/timolia/howto/translate/Language.kt | 10 +- .../de/timolia/howto/translate/Translate.kt | 90 +++---- .../de/timolia/howto/translate/Translation.kt | 39 +-- .../howto/translate/TranslationContext.kt | 6 +- 26 files changed, 795 insertions(+), 1043 deletions(-) rename howto-dapp/{ => src}/gradlew (99%) mode change 100644 => 100755 rename howto-dapp/{ => src}/gradlew.bat (97%) diff --git a/howto-dapp/build.gradle b/howto-dapp/build.gradle index 140e0016..aedcece8 100644 --- a/howto-dapp/build.gradle +++ b/howto-dapp/build.gradle @@ -1,6 +1,7 @@ plugins { id 'java' id 'com.github.johnrengelman.shadow' version '6.1.0' + id 'org.jetbrains.kotlin.jvm' version '1.8.21' } group 'de.timolia.howto' @@ -13,19 +14,19 @@ repositories { dependencies { testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.2' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.2' - implementation 'com.google.code.gson:gson:2.8.8' - implementation 'mysql:mysql-connector-java:8.0.25' + implementation 'com.google.code.gson:gson:2.8.9' + implementation 'mysql:mysql-connector-java:8.0.28' // https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.11' -} - -test { - useJUnitPlatform() + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" } jar { manifest { attributes 'Main-Class': 'de.timolia.howto.Dapp' } +} +kotlin { + jvmToolchain(11) } \ No newline at end of file diff --git a/howto-dapp/gradle/wrapper/gradle-wrapper.jar b/howto-dapp/gradle/wrapper/gradle-wrapper.jar index e708b1c023ec8b20f512888fe07c5bd3ff77bb8f..7454180f2ae8848c63b8b4dea2cb829da983f2fa 100644 GIT binary patch delta 18435 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 B8dv}T delta 17845 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 X49Luk)baa85H9$5YCsTPT`SVRWMtMW diff --git a/howto-dapp/gradle/wrapper/gradle-wrapper.properties b/howto-dapp/gradle/wrapper/gradle-wrapper.properties index 4d9ca164..afef0da9 100644 --- a/howto-dapp/gradle/wrapper/gradle-wrapper.properties +++ b/howto-dapp/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists +zipStorePath=wrapper/dists \ No newline at end of file diff --git a/howto-dapp/gradlew b/howto-dapp/src/gradlew old mode 100644 new mode 100755 similarity index 99% rename from howto-dapp/gradlew rename to howto-dapp/src/gradlew index 4f906e0c..744e882e --- a/howto-dapp/gradlew +++ b/howto-dapp/src/gradlew @@ -72,7 +72,7 @@ case "`uname`" in Darwin* ) darwin=true ;; - MINGW* ) + MSYS* | MINGW* ) msys=true ;; NONSTOP* ) diff --git a/howto-dapp/gradlew.bat b/howto-dapp/src/gradlew.bat similarity index 97% rename from howto-dapp/gradlew.bat rename to howto-dapp/src/gradlew.bat index 107acd32..e18c03ce 100644 --- a/howto-dapp/gradlew.bat +++ b/howto-dapp/src/gradlew.bat @@ -33,7 +33,7 @@ set APP_HOME=%DIRNAME% for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" "-Dfile.encoding=UTF-8" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome diff --git a/howto-dapp/src/main/java/de/timolia/howto/Dapp.kt b/howto-dapp/src/main/java/de/timolia/howto/Dapp.kt index 7564bf26..408213a7 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/Dapp.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/Dapp.kt @@ -1,41 +1,42 @@ -package de.timolia.howto; +package de.timolia.howto -import com.google.gson.FieldNamingPolicy; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import de.timolia.howto.conversion.InitialConversion; -import de.timolia.howto.generator.FileWriter; -import de.timolia.howto.generator.PageRankChange; -import de.timolia.howto.generator.PageResponsibilities; -import de.timolia.howto.generator.PageTeamMembers; -import de.timolia.howto.models.Teamler; -import de.timolia.howto.translate.Translate; +import com.google.gson.FieldNamingPolicy +import com.google.gson.GsonBuilder +import de.timolia.howto.conversion.InitialConversion +import de.timolia.howto.generator.FileWriter +import de.timolia.howto.generator.PageRankChange +import de.timolia.howto.generator.PageResponsibilities +import de.timolia.howto.generator.PageTeamMembers +import de.timolia.howto.teamler.Teamler +import de.timolia.howto.translate.Translate +import java.nio.charset.StandardCharsets +import java.nio.file.Files +import java.nio.file.Path +import java.util.* +import kotlin.Throws +import kotlin.jvm.JvmStatic -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Arrays; -import java.util.List; - -public class Dapp { - public static final Translate translate = new Translate(); - public static final Gson gson = new GsonBuilder() +object Dapp { + val translate: Translate = Translate() + val gson = GsonBuilder() .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) - .create(); + .create() - public static void main(String[] args) throws Exception { - Path path = Path.of("docs", "team"); - translate.loadDirectory(path.resolve("translate")); - String json = Files.readString(path.resolve("teamler.json"), StandardCharsets.UTF_8); - Teamler[] teamlers = gson.fromJson(json, Teamler[].class); - List teamlerList = Arrays.asList(teamlers); - teamlerList.forEach(Teamler::updateName); - FileWriter fileWriter = new FileWriter(path, translate); - fileWriter.writeFile("changes", PageRankChange.generate(teamlerList)); - fileWriter.writeFile("members", PageTeamMembers.generate(teamlerList)); - fileWriter.writeFile("responsibilities", PageResponsibilities.generate(teamlerList)); - if (args.length == 1 && args[0].equalsIgnoreCase("init")) { - InitialConversion.convert(); + @Throws(Exception::class) + @JvmStatic + fun main(args: Array) { + val path = Path.of("docs", "team") + translate.loadDirectory(path.resolve("translate")) + val json = Files.readString(path.resolve("teamler.json"), StandardCharsets.UTF_8) + val teamlers = gson.fromJson(json, Array::class.java) + val teamlerList = Arrays.asList(*teamlers) + teamlerList.forEach { obj: Teamler -> obj.updateName() } + val fileWriter = FileWriter(path, translate) + fileWriter.writeFile("changes", PageRankChange.generate(teamlerList)) + fileWriter.writeFile("members", PageTeamMembers.generate(teamlerList)) + fileWriter.writeFile("responsibilities", PageResponsibilities.generate(teamlerList)) + if (args.size == 1 && args[0].equals("init", ignoreCase = true)) { + InitialConversion.convert() } } } diff --git a/howto-dapp/src/main/java/de/timolia/howto/conversion/InitialConversion.kt b/howto-dapp/src/main/java/de/timolia/howto/conversion/InitialConversion.kt index 87067753..b50dae04 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/conversion/InitialConversion.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/conversion/InitialConversion.kt @@ -1,62 +1,45 @@ -package de.timolia.howto.conversion; - -import de.timolia.howto.Dapp; -import de.timolia.howto.conversion.models.TeamlerRankChange; -import de.timolia.howto.conversion.models.TeamlerResponsibilities; -import de.timolia.howto.models.Rank; -import de.timolia.howto.models.Sex; -import de.timolia.howto.models.Teamler; - -import java.io.IOException; -import java.text.ParseException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.stream.Collectors; - -public class InitialConversion { - public static void convert() throws IOException, ParseException { - - List teamlers = new ArrayList<>(); - List teamlerRankChanges = JsonBuilder.getTeamlerRankChanges(); - - - teamlerRankChanges.stream().map(TeamlerRankChange::getUuid).sorted().distinct().forEach(uuid -> { - List changes = teamlerRankChanges.stream().filter(teamlerRankChange -> teamlerRankChange.getUuid().equals(uuid)).collect(Collectors.toList()); - - LinkedHashMap rankHistory = new LinkedHashMap<>(); - for (TeamlerRankChange teamlerRankChange : changes) { - if (rankHistory.isEmpty()) { - rankHistory.put("initial", teamlerRankChange.getRankFrom()); - } - rankHistory.put(teamlerRankChange.getReadableDate(), teamlerRankChange.getRankTo()); - } - - Teamler teamler = new Teamler(uuid, Sex.undefined, null, null, null, rankHistory); - teamlers.add(teamler); - }); - - List teamlerResponsibilitiesList = JsonBuilder.getTeamlerResponsibilities(); - teamlerResponsibilitiesList.forEach(teamlerResponsibilities -> { - Teamler teamler = teamlers.stream().filter(teamler1 -> teamler1.getUuid().equals(teamlerResponsibilities.getUuid())).findFirst().orElse(null); - - if (teamler == null) { - teamler = new Teamler(teamlerResponsibilities.getUuid(), Sex.undefined, null, null, null, null); - } - - System.out.println("teamler: " + teamler); - if (teamlerResponsibilities.getHv() != null) { - System.out.println("teamlerResponsibilities.getHv(): " + teamlerResponsibilities.getHv()); - teamler.setResponsibilitiesMain(Arrays.asList(teamlerResponsibilities.getHv().split(", "))); +package de.timolia.howto.conversion + +import de.timolia.howto.Dapp +import de.timolia.howto.rank.Rank +import de.timolia.howto.teamler.Sex +import de.timolia.howto.teamler.Teamler +import java.io.IOException +import java.text.ParseException + +object InitialConversion { + @Throws(IOException::class, ParseException::class) + fun convert() { + val teamlers: MutableList = ArrayList() + val teamlerRankChanges = JsonBuilder.getTeamlerRankChanges() + teamlerRankChanges.map { obj -> obj.uuid }.sorted().distinct().forEach { uuid -> + val rankHistory = LinkedHashMap() + teamlerRankChanges + .filter { teamlerRankChange -> teamlerRankChange.uuid == uuid } + .forEach { + if (rankHistory.isEmpty()) { + rankHistory["initial"] = it.rankFrom + } + rankHistory[it.getReadableDate()] = it.rankTo + } + val teamler = Teamler(uuid, Sex.undefined, null, null, null, rankHistory) + teamlers.add(teamler) + } + val teamlerResponsibilitiesList = JsonBuilder.getTeamlerResponsibilities() + teamlerResponsibilitiesList.forEach { teamlerResponsibilities -> + val teamler = teamlers.stream() + .filter { teamler1 -> teamler1.uuid == teamlerResponsibilities.uuid } + .findFirst() + .orElseGet { Teamler(teamlerResponsibilities.uuid, Sex.undefined, null, null, null, null) } + println("teamler: $teamler") + if (teamlerResponsibilities.hv != null) { + println("teamlerResponsibilities.getHv(): " + teamlerResponsibilities.hv) + teamler.responsibilitiesMain = mutableListOf(*teamlerResponsibilities.hv.split(", ").toTypedArray()) } - if (teamlerResponsibilities.getNv() != null) { - teamler.setResponsibilitiesSecondary(Arrays.asList(teamlerResponsibilities.getNv().split(", "))); + if (teamlerResponsibilities.nv != null) { + teamler.responsibilitiesSecondary = mutableListOf(*teamlerResponsibilities.nv.split(", ").toTypedArray()) } - }); - - - System.out.println(Dapp.gson.toJson(teamlers)); - + } + println(Dapp.gson.toJson(teamlers)) } } diff --git a/howto-dapp/src/main/java/de/timolia/howto/conversion/JsonBuilder.kt b/howto-dapp/src/main/java/de/timolia/howto/conversion/JsonBuilder.kt index 802c006e..78d36dfc 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/conversion/JsonBuilder.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/conversion/JsonBuilder.kt @@ -1,86 +1,72 @@ -package de.timolia.howto.conversion; - -import de.timolia.howto.conversion.models.TeamlerRankChange; -import de.timolia.howto.conversion.models.TeamlerResponsibilities; - -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.text.ParseException; -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Pattern; - -public class JsonBuilder { - - public static List getTeamlerRankChanges() throws IOException, ParseException { - String content = Files.readString(Path.of("src/main/resources", "changes.md"), StandardCharsets.UTF_8); - content = Pattern.compile("^([^|]|\\| ------|\\| Spieler).*$", Pattern.MULTILINE).matcher(content).replaceAll(""); - content = Pattern.compile("(\r\n)+", Pattern.MULTILINE).matcher(content).replaceAll("\n"); - content = Pattern.compile("[ \t]*\\|[ \t]*", Pattern.MULTILINE).matcher(content).replaceAll("|"); - content = Pattern.compile("", Pattern.MULTILINE).matcher(content).replaceAll(""); - content = Pattern.compile("", Pattern.MULTILINE).matcher(content).replaceAll(""); - - List teamlerRankChanges = new ArrayList<>(); - String[] lines = content.split("\n"); - for (int i = lines.length - 1; i >= 0; i--) { - String line = lines[i]; - +package de.timolia.howto.conversion + +import de.timolia.howto.rank.TeamlerRankChange +import java.io.IOException +import java.nio.charset.StandardCharsets +import java.nio.file.Files +import java.nio.file.Path +import java.text.ParseException +import java.util.* +import java.util.regex.Pattern +import kotlin.Throws + +object JsonBuilder { + @Throws(IOException::class, ParseException::class) + fun getTeamlerRankChanges(): MutableList { + var content = Files.readString(Path.of("src/main/resources", "changes.md"), StandardCharsets.UTF_8) + content = Pattern.compile("^([^|]|\\| ------|\\| Spieler).*$", Pattern.MULTILINE).matcher(content).replaceAll("") + content = Pattern.compile("(\r\n)+", Pattern.MULTILINE).matcher(content).replaceAll("\n") + content = Pattern.compile("[ \t]*\\|[ \t]*", Pattern.MULTILINE).matcher(content).replaceAll("|") + content = Pattern.compile("", Pattern.MULTILINE).matcher(content).replaceAll("") + content = Pattern.compile("", Pattern.MULTILINE).matcher(content).replaceAll("") + val teamlerRankChanges: MutableList = ArrayList() + val lines: Array = content.split("\n".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() + for (i in lines.indices.reversed()) { + val line = lines[i]!! if (line.isEmpty()) { - continue; + continue } - - String[] split = line.split("\\|"); - String name = split[1].replaceAll("\\\\", ""); - String rankFrom = split[2]; - String rankTo = split[3]; - String date = split[4]; - - TeamlerRankChange teamlerRankChange = new TeamlerRankChange(name, rankFrom, rankTo, date); - teamlerRankChanges.add(teamlerRankChange); - System.out.println(teamlerRankChange); + val split: List = line.split("|") + val name: String = split[1].replace("\\", "") + val rankFrom = split[2] + val rankTo = split[3] + val date = split[4] + val teamlerRankChange = TeamlerRankChange(name, rankFrom, rankTo, date) + teamlerRankChanges.add(teamlerRankChange) + println(teamlerRankChange) } - - return teamlerRankChanges; + return teamlerRankChanges } - public static List getTeamlerResponsibilities() throws IOException { - String content = Files.readString(Path.of("src/main/resources", "members.md"), StandardCharsets.UTF_8); - content = Pattern.compile("^(?!-|###).*$", Pattern.MULTILINE).matcher(content).replaceAll(""); - content = Pattern.compile("^- Rang \\(ingame\\):.*$", Pattern.MULTILINE).matcher(content).replaceAll(""); - content = Pattern.compile("(\r\n)+", Pattern.MULTILINE).matcher(content).replaceAll("\n"); - - List teamlerResponsibilitiesList = new ArrayList<>(); - for (String s : content.split("###")) { - if (s.isEmpty() || (!s.contains("Hauptverantwortlich") && !s.contains("Nebenverantwortlich"))) continue; - - s = s.substring(s.indexOf("'") + 1); - s = s.substring(s.indexOf("'") + 2); - - String name = s.substring(0, s.indexOf("<")).replaceAll("\\\\_", "_"); - String hv = null; - String nv = null; - - s = s.substring(s.indexOf("-")); - + @Throws(IOException::class) + fun getTeamlerResponsibilities(): MutableList { + var content = Files.readString(Path.of("src/main/resources", "members.md"), StandardCharsets.UTF_8) + content = Pattern.compile("^(?!-|###).*$", Pattern.MULTILINE).matcher(content).replaceAll("") + content = Pattern.compile("^- Rang \\(ingame\\):.*$", Pattern.MULTILINE).matcher(content).replaceAll("") + content = Pattern.compile("(\r\n)+", Pattern.MULTILINE).matcher(content).replaceAll("\n") + val teamlerResponsibilitiesList = ArrayList() + for (s in content.split("###")) { + var s = s + if (s.isEmpty() || !s.contains("Hauptverantwortlich") && !s.contains("Nebenverantwortlich")) continue + s = s.substring(s.indexOf("'") + 1) + s = s.substring(s.indexOf("'") + 2) + val name: String = s.substring(0, s.indexOf("<")).replace("\\\\_".toRegex(), "_") + var hv: String? = null + var nv: String? = null + s = s.substring(s.indexOf("-")) if (s.contains("Hauptverantwortlich")) { - hv = s.substring(s.indexOf("Hauptverantwortlich") + "Hauptverantwortlich".length() + 6, s.indexOf("\n")); - s = s.substring(s.indexOf("Hauptverantwortlich") + "Hauptverantwortlich\n".length() + 6 + hv.length()); + hv = s.substring(s.indexOf("Hauptverantwortlich") + "Hauptverantwortlich".length + 6, s.indexOf("\n")) + s = s.substring(s.indexOf("Hauptverantwortlich") + "Hauptverantwortlich\n".length + 6 + hv.length) } if (s.contains("Nebenverantwortlich")) { - nv = s.substring(s.indexOf("Nebenverantwortlich") + "Nebenverantwortlich".length() + 6, s.indexOf("\n")); + nv = s.substring(s.indexOf("Nebenverantwortlich") + "Nebenverantwortlich".length + 6, s.indexOf("\n")) } - - System.out.println("name: " + name); - System.out.println("hv: " + hv); - System.out.println("nv: " + nv); - - TeamlerResponsibilities teamlerResponsibilities = new TeamlerResponsibilities(name, hv, nv); - teamlerResponsibilitiesList.add(teamlerResponsibilities); + println("name: $name") + println("hv: $hv") + println("nv: $nv") + val teamlerResponsibilities = TeamlerResponsibilities(name, hv, nv) + teamlerResponsibilitiesList.add(teamlerResponsibilities) } - - return teamlerResponsibilitiesList; + return teamlerResponsibilitiesList } - } diff --git a/howto-dapp/src/main/java/de/timolia/howto/conversion/TeamlerResponsibilities.kt b/howto-dapp/src/main/java/de/timolia/howto/conversion/TeamlerResponsibilities.kt index d1a5196c..562f37be 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/conversion/TeamlerResponsibilities.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/conversion/TeamlerResponsibilities.kt @@ -1,47 +1,21 @@ -package de.timolia.howto.conversion.models; +package de.timolia.howto.conversion -import de.timolia.howto.conversion.SQLApi; +import de.timolia.howto.database.SQLApi +import java.util.* -import java.util.UUID; +class TeamlerResponsibilities( + private val name: String?, + val hv: String?, + val nv: String? +) { + val uuid: UUID = SQLApi.getUuid(name)!! -public class TeamlerResponsibilities { - private final String name; - private final UUID uuid; - private final String hv; - private final String nv; - - public TeamlerResponsibilities(String name, String hv, String nv) { - this.name = name; - this.uuid = SQLApi.getUuid(name); - this.hv = hv; - this.nv = nv; - } - - - public String getName() { - return name; - } - - public UUID getUuid() { - return uuid; - } - - public String getHv() { - return hv; - } - - public String getNv() { - return nv; - } - - - @Override - public String toString() { + override fun toString(): String { return "TeamlerResponsibilities{" + "name='" + name + '\'' + ", uuid=" + uuid + ", hv='" + hv + '\'' + ", nv='" + nv + '\'' + - '}'; + '}' } } diff --git a/howto-dapp/src/main/java/de/timolia/howto/database/SQLApi.kt b/howto-dapp/src/main/java/de/timolia/howto/database/SQLApi.kt index 19ac14ed..d8aaee6f 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/database/SQLApi.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/database/SQLApi.kt @@ -1,64 +1,60 @@ -package de.timolia.howto.conversion; +package de.timolia.howto.database -import de.timolia.howto.Dapp; +import java.sql.SQLException +import java.util.* +import kotlin.jvm.Volatile -import java.sql.*; -import java.util.UUID; +object SQLApi { + @Volatile + private var connection: SqlUserConnection? = null -public class SQLApi { - private static volatile SqlUserConnection connection; - private static volatile boolean triedConnect; - - private static SqlUserConnection establishConnection() { + @Volatile + private var triedConnect = false + private fun establishConnection(): SqlUserConnection { if (!triedConnect) { - synchronized (SQLApi.class) { + synchronized(SQLApi::class.java) { if (!triedConnect) { - tryGuardedConnect(); + tryGuardedConnect() } } } - SqlUserConnection connection = SQLApi.connection; - if (connection == null) { - throw new RuntimeException("Earlier attempt connecting to sql failed"); - } - return connection; + return connection ?: throw RuntimeException("Earlier attempt connecting to sql failed") } - private static void tryGuardedConnect() { + private fun tryGuardedConnect() { try { - connection = SqlUserConnection.connect(); - } catch (SQLException exception) { - throw new RuntimeException("Unable to establish sql connection", exception); + connection = SqlUserConnection.connect() + } catch (exception: SQLException) { + throw RuntimeException("Unable to establish sql connection", exception) } finally { - triedConnect = true; + triedConnect = true } } - public static UUID getUuid(String name) { - try { - return establishConnection().getUuid(name); - } catch (RuntimeException exception) { - exception.printStackTrace(); - throw exception; + fun getUuid(name: String?): UUID? { + return try { + establishConnection().getUuid(name) + } catch (exception: RuntimeException) { + exception.printStackTrace() + throw exception } } - public static String getName(UUID uuid) { - return getName(uuid, null); + fun getName(uuid: UUID?): String? { + return getName(uuid, null) } - public static String getName(UUID uuid, String fallback) { - SqlUserConnection connection; - try { - connection = establishConnection(); - } catch (RuntimeException exception) { + fun getName(uuid: UUID?, fallback: String?): String? { + val connection: SqlUserConnection = try { + establishConnection() + } catch (exception: RuntimeException) { if (fallback != null && SqlUserConnection.isDevEnv()) { - System.err.println("Unable to establish sql connection for " + uuid + " fallback to " + fallback); - exception.printStackTrace(); - return fallback; + System.err.println("Unable to establish sql connection for $uuid fallback to $fallback") + exception.printStackTrace() + return fallback } - throw new RuntimeException("Unable to establish sql connection", exception); + throw RuntimeException("Unable to establish sql connection", exception) } - return connection.getName(uuid, fallback); + return connection.getName(uuid, fallback) } } diff --git a/howto-dapp/src/main/java/de/timolia/howto/database/SqlUserConnection.kt b/howto-dapp/src/main/java/de/timolia/howto/database/SqlUserConnection.kt index 74afc8e6..3f71c1b4 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/database/SqlUserConnection.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/database/SqlUserConnection.kt @@ -1,71 +1,64 @@ -package de.timolia.howto.conversion; +package de.timolia.howto.database -import de.timolia.howto.Dapp; +import java.sql.* +import java.util.* -import java.sql.*; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -public class SqlUserConnection { - public static SqlUserConnection connect() throws SQLException { - String environmentSuffix = isDevEnv() ? "DEV" : "LIVE"; - String user = System.getenv("MYSQL_USER_" + environmentSuffix); - String password = System.getenv("MYSQL_PASS_" + environmentSuffix); - String connectionString = System.getenv("MYSQL_CON_STR_" + environmentSuffix); - Connection connection = DriverManager.getConnection(connectionString, user, password); - return new SqlUserConnection(connection); - } - - public static boolean isDevEnv() { - return System.getenv("MYSQL_USER_LIVE") == null; - } - - private final Connection connection; - private final Map usernames = new HashMap<>(); - private final Map uuids = new HashMap<>(); - - private SqlUserConnection(Connection connection) { - this.connection = connection; - } - - public UUID getUuid(String name) { - return usernames.computeIfAbsent(name, this::resolveUniqueId); +class SqlUserConnection private constructor(private val connection: Connection) { + private val usernames: MutableMap = HashMap() + private val uuids: MutableMap = HashMap() + fun getUuid(name: String?): UUID? { + return usernames.computeIfAbsent(name, ::resolveUniqueId) } - public UUID resolveUniqueId(String name) { - try { - PreparedStatement prepareStatement = connection.prepareStatement("SELECT uuid FROM timolia_user_names WHERE name=? ORDER BY last_played DESC LIMIT 1"); - prepareStatement.setString(1, name); - ResultSet resultSet = prepareStatement.executeQuery(); + private fun resolveUniqueId(name: String?): UUID { + return try { + val prepareStatement = connection.prepareStatement("SELECT uuid FROM timolia_user_names WHERE name=? ORDER BY last_played DESC LIMIT 1") + prepareStatement.setString(1, name) + val resultSet = prepareStatement.executeQuery() if (!resultSet.next()) { - throw new RuntimeException("Cannot find UUID of '" + name + "'"); + throw RuntimeException("Cannot find UUID of '$name'") } - return UUID.fromString(resultSet.getString("uuid")); - } catch (SQLException exception) { - throw new RuntimeException("Failed to fetch uuid for name=" + name + "'", exception); + UUID.fromString(resultSet.getString("uuid")) + } catch (exception: SQLException) { + throw RuntimeException("Failed to fetch uuid for name=$name'", exception) } } - public String getName(UUID uuid, String fallback) { - return uuids.computeIfAbsent(uuid, uniqueId -> resolveName(uniqueId, fallback)); + fun getName(uuid: UUID?, fallback: String?): String? { + return uuids.computeIfAbsent(uuid) { uniqueId: UUID? -> resolveName(uniqueId, fallback) } } - private String resolveName(UUID uuid, String fallback) { + private fun resolveName(uuid: UUID?, fallback: String?): String? { try { - PreparedStatement prepareStatement = connection.prepareStatement("SELECT * FROM timolia_user WHERE uuid=?"); - prepareStatement.setString(1, uuid.toString()); - ResultSet resultSet = prepareStatement.executeQuery(); + val prepareStatement = connection.prepareStatement("SELECT * FROM timolia_user WHERE uuid=?") + prepareStatement.setString(1, uuid.toString()) + val resultSet = prepareStatement.executeQuery() if (resultSet.next()) { - return resultSet.getString("name"); + return resultSet.getString("name") } if (fallback != null) { - System.out.println("No name for uuid " + uuid + " falling back to " + fallback); - return fallback; + println("No name for uuid $uuid falling back to $fallback") + return fallback } - throw new RuntimeException("Cannot find name of '" + uuid + "'"); - } catch (SQLException exception) { - throw new RuntimeException("Failed to fetch uuid for uuid=" + uuid + "'", exception); + throw RuntimeException("Cannot find name of '$uuid'") + } catch (exception: SQLException) { + throw RuntimeException("Failed to fetch uuid for uuid=$uuid'", exception) + } + } + + companion object { + @Throws(SQLException::class) + fun connect(): SqlUserConnection { + val environmentSuffix = if (isDevEnv()) "DEV" else "LIVE" + val user = System.getenv("MYSQL_USER_$environmentSuffix") + val password = System.getenv("MYSQL_PASS_$environmentSuffix") + val connectionString = System.getenv("MYSQL_CON_STR_$environmentSuffix") + val connection = DriverManager.getConnection(connectionString, user, password) + return SqlUserConnection(connection) + } + + fun isDevEnv(): Boolean { + return System.getenv("MYSQL_USER_LIVE") == null } } } diff --git a/howto-dapp/src/main/java/de/timolia/howto/generator/FileWriter.kt b/howto-dapp/src/main/java/de/timolia/howto/generator/FileWriter.kt index 136a5cf2..4e490038 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/generator/FileWriter.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/generator/FileWriter.kt @@ -1,36 +1,31 @@ -package de.timolia.howto.generator; +package de.timolia.howto.generator -import de.timolia.howto.translate.Language; -import de.timolia.howto.translate.Translate; -import de.timolia.howto.translate.TranslationContext; +import de.timolia.howto.translate.Language +import de.timolia.howto.translate.Translate +import java.io.IOException +import java.nio.charset.Charset +import java.nio.file.Files +import java.nio.file.Path +import java.nio.file.StandardOpenOption +import kotlin.Throws -import java.io.IOException; -import java.nio.charset.Charset; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.StandardOpenOption; - -public class FileWriter { - private final Translate translate; - private final Path path; - - public FileWriter(Path path, Translate translate) { - this.path = path; - this.translate = translate; - } - - public void writeFile(String name, String text) throws IOException { - for (Language language : Language.values()) { - TranslationContext translation = translate.forLanguage(language); - String fileName = name + "." + language.key() + ".md"; - String content = translation.replaceAll(text); - writeFile(path.resolve(fileName), content); +class FileWriter(private val path: Path, private val translate: Translate) { + @Throws(IOException::class) + fun writeFile(name: String, text: String) { + for (language in Language.values()) { + val translation = translate.forLanguage(language) + val fileName = name + "." + language.key() + ".md" + val content = translation.replaceAll(text) + writeFile(path.resolve(fileName), content) } } - private static void writeFile(Path path, String text) throws IOException { - path.toFile().getParentFile().mkdirs(); - Files.writeString(path, text, Charset.defaultCharset(), StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE); - System.out.println("Wrote file '" + path + "'"); + companion object { + @Throws(IOException::class) + private fun writeFile(path: Path, text: String) { + path.toFile().parentFile.mkdirs() + Files.writeString(path, text, Charset.defaultCharset(), StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE) + println("Wrote file '$path'") + } } } diff --git a/howto-dapp/src/main/java/de/timolia/howto/generator/PageRankChange.kt b/howto-dapp/src/main/java/de/timolia/howto/generator/PageRankChange.kt index 3b1c2036..04152545 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/generator/PageRankChange.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/generator/PageRankChange.kt @@ -1,75 +1,64 @@ -package de.timolia.howto.generator; +package de.timolia.howto.generator -import de.timolia.howto.conversion.models.TeamlerRankChange; -import de.timolia.howto.models.Teamler; +import de.timolia.howto.rank.TeamlerRankChange +import de.timolia.howto.teamler.Sex +import de.timolia.howto.teamler.Teamler +import java.util.* -import java.util.ArrayList; -import java.util.Calendar; -import java.util.List; -import java.util.Locale; - -public class PageRankChange { - public static String generate(List teamlers) { - ArrayList rankChanges = new ArrayList<>(); - for (Teamler teamler : teamlers) { - rankChanges.addAll(teamler.getRankChanges(false)); +object PageRankChange { + fun generate(teamlers: MutableList): String { + val rankChanges = ArrayList() + for (teamler in teamlers) { + rankChanges.addAll(teamler.getRankChanges(false)) } - - rankChanges.sort((t1, t2) -> { - if (!t1.getDate().equals(t2.getDate())) { - return t2.getDate().compareTo(t1.getDate()); + rankChanges.sortWith { t1, t2 -> + if (t1.date != t2.date) { + return@sortWith t2.date.compareTo(t1.date) } - if (!t1.getRankTo().equals(t2.getRankTo())) { - Teamler teamler1 = teamlers.stream().filter(t -> t.getUuid().equals(t1.getUuid())).findFirst().orElse(null); - Teamler teamler2 = teamlers.stream().filter(t -> t.getUuid().equals(t2.getUuid())).findFirst().orElse(null); - return t1.getRankTo().getString(teamler1.getSex()).compareToIgnoreCase(t2.getRankTo().getString(teamler2.getSex())); + if (t1.rankTo != t2.rankTo) { + val teamler1 = teamlers.firstOrNull { t -> t.uuid == t1.uuid } + val teamler2 = teamlers.firstOrNull { t -> t.uuid == t2.uuid } + return@sortWith t1.rankTo.getString(teamler1?.sex ?: Sex.undefined).compareTo(t2.rankTo.getString(teamler2?.sex ?: Sex.undefined), ignoreCase = true) } - return t1.getName().compareToIgnoreCase(t2.getName()); - }); - - StringBuilder sb = new StringBuilder(); + t1.name.compareTo(t2.name, ignoreCase = true) + } + val sb = StringBuilder() sb .append("%page.rank-change.first%") .append("\n") - .append("\n"); - - String lastYear = ""; - String lastMonth = ""; - for (TeamlerRankChange teamlerRankChange : rankChanges) { - Teamler teamler = teamlers.stream().filter(t -> t.getUuid().equals(teamlerRankChange.getUuid())).findFirst().orElse(null); - - Calendar cal = Calendar.getInstance(); - cal.setTime(teamlerRankChange.getDate()); - String month = cal.getDisplayName(Calendar.MONTH, Calendar.LONG, Locale.GERMAN) + " " + cal.get(Calendar.YEAR); - String year = String.valueOf(cal.get(Calendar.YEAR)); - - if (!year.equals(lastYear)) { - lastYear = year; - sb.append("\n").append("\n").append("# ").append(year).append("\n"); + .append("\n") + var lastYear: String? = "" + var lastMonth: String? = "" + for (teamlerRankChange in rankChanges) { + val teamler = teamlers.firstOrNull { t -> t.uuid == teamlerRankChange.uuid } + val cal = Calendar.getInstance() + cal.time = teamlerRankChange.date + val month = cal.getDisplayName(Calendar.MONTH, Calendar.LONG, Locale.GERMAN) + " " + cal[Calendar.YEAR] + val year = cal[Calendar.YEAR].toString() + if (year != lastYear) { + lastYear = year + sb.append("\n").append("\n").append("# ").append(year).append("\n") } - if (!month.equals(lastMonth)) { - lastMonth = month; - sb.append("\n"); - sb.append("### ").append(month).append("").append("\n"); - sb.append("| %player% | %page.rank-change.rank-previous% | %page.rank-change.rank-new% | %date% |").append("\n"); - sb.append("| ------ | ------ | ------ | ------ |").append("\n"); + if (month != lastMonth) { + lastMonth = month + sb.append("\n") + sb.append("### ").append(month).append("").append("\n") + sb.append("| %player% | %page.rank-change.rank-previous% | %page.rank-change.rank-new% | %date% |").append("\n") + sb.append("| ------ | ------ | ------ | ------ |").append("\n") } - sb .append("| ") .append(teamlerRankChange.getNameForMarkdown()) .append(" | ") - .append("").append(teamlerRankChange.getRankFrom().getString(teamler.getSex())).append("") + .append("").append(teamlerRankChange.rankFrom.getString(teamler?.sex ?: Sex.undefined)).append("") .append(" | ") - .append("").append(teamlerRankChange.getRankTo().getString(teamler.getSex())).append("") + .append("").append(teamlerRankChange.rankTo.getString(teamler?.sex ?: Sex.undefined)).append("") .append(" | ") .append(teamlerRankChange.getReadableDate()) .append(" |") - .append("\n"); + .append("\n") } - - sb.append("\n"); - - return sb.toString(); + sb.append("\n") + return sb.toString() } } diff --git a/howto-dapp/src/main/java/de/timolia/howto/generator/PageResponsibilities.kt b/howto-dapp/src/main/java/de/timolia/howto/generator/PageResponsibilities.kt index aa1dd43f..e6809843 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/generator/PageResponsibilities.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/generator/PageResponsibilities.kt @@ -1,152 +1,138 @@ -package de.timolia.howto.generator; +package de.timolia.howto.generator -import de.timolia.howto.Dapp; -import de.timolia.howto.responsibility.Responsibility; -import de.timolia.howto.responsibility.ResponsibilityType; -import de.timolia.howto.translate.Language; -import de.timolia.howto.models.Teamler; -import de.timolia.howto.translate.Translate; -import de.timolia.howto.translate.TranslationContext; +import de.timolia.howto.Dapp +import de.timolia.howto.teamler.Teamler +import de.timolia.howto.responsibility.Responsibility +import de.timolia.howto.responsibility.ResponsibilityType +import de.timolia.howto.translate.Language +import java.util.* +import java.util.stream.Collectors -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -public class PageResponsibilities { - public static String generate(List teamlers) { - LinkedHashMap> responsibilities = new LinkedHashMap<>() {{ - put("%page.responsibilities.project-team-orga%", new LinkedHashMap<>() {{ - put("%page.responsibilities.teamleader%", "%page.responsibilities.teamleader.desc%"); - put("%page.responsibilities.project-team-orga.apply.builder%", null); - put("%page.responsibilities.project-team-orga.apply.development%", null); - put("%page.responsibilities.project-team-orga.apply.support%", "%page.responsibilities.project-team-orga.apply.support.desc%"); - put("%page.responsibilities.project-team-orga.howto%", "%page.responsibilities.project-team-orga.howto.desc%"); - put("%page.responsibilities.project-team-orga.tournament%", "%page.responsibilities.project-team-orga.tournament.desc%"); - //put("%page.responsibilities.project-team-orga.uhc%", "%page.responsibilities.project-team-orga.uhc.desc%"); - put("%page.responsibilities.project-team-orga.youtuber%", "%page.responsibilities.project-team-orga.youtuber.desc%"); - }}); - put("%page.responsibilities.communication-platforms%", new LinkedHashMap<>() {{ - put("%page.responsibilities.communication-platforms.community-discord%", "%page.responsibilities.communication-platforms.community-discord.desc%"); - //put("%page.responsibilities.communication-platforms.bug-reports%", null); - put("%page.responsibilities.communication-platforms.appeal%", null); - put("%page.responsibilities.communication-platforms.falsely-banned%", null); - put("%page.responsibilities.communication-platforms.socialmedia%", "%page.responsibilities.communication-platforms.socialmedia.desc%"); - put("%page.responsibilities.communication-platforms.teamspeak%", "%page.responsibilities.communication-platforms.teamspeak.desc%"); - }}); - put("%page.responsibilities.other-responsibilities%", new LinkedHashMap<>() {{ - put("%page.responsibilities.other-responsibilities.graphicdesign%", null); - put("%page.responsibilities.other-responsibilities.map-submissions%", null); - put("%page.responsibilities.other-responsibilities.monthly-winner%", null); - //put("%page.responsibilities.other-responsibilities.translation%", null); - }}); - }}; - - StringBuilder sb = new StringBuilder(); - sb.append("%page.responsibilities.info%"); - - for (Map.Entry> categories : responsibilities.entrySet()) { - String categoryName = categories.getKey(); - LinkedHashMap subcategories = categories.getValue(); +object PageResponsibilities { + fun generate(teamlers: MutableList): String { + val responsibilities: LinkedHashMap> = object : LinkedHashMap>() { + init { + put("%page.responsibilities.project-team-orga%", object : LinkedHashMap() { + init { + put("%page.responsibilities.teamleader%", "%page.responsibilities.teamleader.desc%") + put("%page.responsibilities.project-team-orga.apply.builder%", null) + put("%page.responsibilities.project-team-orga.apply.development%", null) + put("%page.responsibilities.project-team-orga.apply.support%", "%page.responsibilities.project-team-orga.apply.support.desc%") + put("%page.responsibilities.project-team-orga.howto%", "%page.responsibilities.project-team-orga.howto.desc%") + put("%page.responsibilities.project-team-orga.tournament%", "%page.responsibilities.project-team-orga.tournament.desc%") + //put("%page.responsibilities.project-team-orga.uhc%", "%page.responsibilities.project-team-orga.uhc.desc%"); + put("%page.responsibilities.project-team-orga.youtuber%", "%page.responsibilities.project-team-orga.youtuber.desc%") + } + }) + put("%page.responsibilities.communication-platforms%", object : LinkedHashMap() { + init { + put("%page.responsibilities.communication-platforms.community-discord%", "%page.responsibilities.communication-platforms.community-discord.desc%") + //put("%page.responsibilities.communication-platforms.bug-reports%", null); + put("%page.responsibilities.communication-platforms.appeal%", null) + put("%page.responsibilities.communication-platforms.falsely-banned%", null) + put("%page.responsibilities.communication-platforms.socialmedia%", "%page.responsibilities.communication-platforms.socialmedia.desc%") + put("%page.responsibilities.communication-platforms.teamspeak%", "%page.responsibilities.communication-platforms.teamspeak.desc%") + } + }) + put("%page.responsibilities.other-responsibilities%", object : LinkedHashMap() { + init { + put("%page.responsibilities.other-responsibilities.graphicdesign%", null) + put("%page.responsibilities.other-responsibilities.map-submissions%", null) + put("%page.responsibilities.other-responsibilities.monthly-winner%", null) + //put("%page.responsibilities.other-responsibilities.translation%", null); + } + }) + } + } + val sb = StringBuilder() + sb.append("%page.responsibilities.info%") + for ((categoryName, subcategories) in responsibilities) { sb .append("\n") - .append("\n").append("# ").append(categoryName); - - TranslationContext nameConverter = Dapp.translate.forLanguage(Language.DE); - for (Map.Entry e : subcategories.entrySet()) { - String name = nameConverter.replaceAll(e.getKey()); - String description = e.getValue(); - sb - .append("\n") - .append("\n").append("### **").append(name).append("**"); + .append("\n").append("# ").append(categoryName) + val nameConverter = Dapp.translate.forLanguage(Language.DE) + for (e in subcategories.entries) { + val name = nameConverter.replaceAll(e.key) + val description = e.value + sb.append("\n").append("\n").append("### **").append(name).append("**") if (description != null) { - sb.append("\n").append(description).append("\n"); + sb.append("\n").append(description).append("\n") } - - List hv = teamlers.stream() - .filter(teamler -> teamler.hasResponsibilityMain(name)) - .sorted(Teamler::compare) - .collect(Collectors.toList()); - List nv = teamlers.stream() - .filter(teamler -> teamler.hasResponsibilitySecondary(name)) - .sorted(Teamler::compare) - .collect(Collectors.toList()); - - String titleCustom = null; - - LinkedList hvCustom = new LinkedList<>(); - LinkedList nvCustom = new LinkedList<>(); - - // custom stuff - switch (e.getKey()) { - case "%page.responsibilities.bug-reports%": - nvCustom.add(Responsibility.simple(ResponsibilityType.NV, "%page.responsibilities.custom.bug-reports.modsanddevs%")); - break; - case "%page.responsibilities.sm%": - titleCustom = "Projekte u. Verantwortungsgrad"; - for (Teamler teamler : teamlers.stream().filter(teamler -> teamler.hasResponsibilityMain("Twitter")).sorted(Teamler::compare).collect(Collectors.toList())) { - nvCustom.add(Responsibility.concreteTeamster(teamler, "%page.responsibilities.custom.sm.twitter.hv%")); + val hv = teamlers + .filter { teamler -> teamler.hasResponsibilityMain(name) } + .sortedWith { obj, o -> obj.compare(o) } + val nv = teamlers + .filter { teamler -> teamler.hasResponsibilitySecondary(name) } + .sortedWith { obj, o -> obj.compare(o) } + var titleCustom: String? = null + val hvCustom = LinkedList() + val nvCustom = LinkedList() + when (e.key) { + "%page.responsibilities.bug-reports%" -> nvCustom.add(Responsibility.simple(ResponsibilityType.NV, "%page.responsibilities.custom.bug-reports.modsanddevs%")) + "%page.responsibilities.sm%" -> { + titleCustom = "Projekte u. Verantwortungsgrad" + for (teamler in teamlers.filter { teamler -> teamler.hasResponsibilityMain("Twitter") }.sortedWith { obj, o -> obj.compare(o) }) { + nvCustom.add(Responsibility.concreteTeamster(teamler, "%page.responsibilities.custom.sm.twitter.hv%")) } - for (Teamler teamler : teamlers.stream().filter(teamler -> teamler.hasResponsibilitySecondary("Twitter")).sorted(Teamler::compare).collect(Collectors.toList())) { - nvCustom.add(Responsibility.concreteTeamster(teamler, "%page.responsibilities.custom.sm.twitter.nv%")); + for (teamler in teamlers.filter { teamler -> teamler.hasResponsibilitySecondary("Twitter") }.sortedWith { obj, o -> obj.compare(o) }) { + nvCustom.add(Responsibility.concreteTeamster(teamler, "%page.responsibilities.custom.sm.twitter.nv%")) } - for (Teamler teamler : teamlers.stream().filter(teamler -> teamler.hasResponsibilityMain("Bauteam-Twitter")).sorted(Teamler::compare).collect(Collectors.toList())) { - nvCustom.add(Responsibility.concreteTeamster(teamler, "%page.responsibilities.custom.sm.twitter-builder.hv%")); + for (teamler in teamlers.filter { teamler -> teamler.hasResponsibilityMain("Bauteam-Twitter") }.sortedWith { obj, o -> obj.compare(o) }) { + nvCustom.add(Responsibility.concreteTeamster(teamler, "%page.responsibilities.custom.sm.twitter-builder.hv%")) } - for (Teamler teamler : teamlers.stream().filter(teamler -> teamler.hasResponsibilitySecondary("Bauteam-Twitter")).sorted(Teamler::compare).collect(Collectors.toList())) { - nvCustom.add(Responsibility.concreteTeamster(teamler, "%page.responsibilities.custom.sm.twitter-builder.nv%")); + for (teamler in teamlers.filter { teamler -> teamler.hasResponsibilitySecondary("Bauteam-Twitter") }.sortedWith { obj, o -> obj.compare(o) }) { + nvCustom.add(Responsibility.concreteTeamster(teamler, "%page.responsibilities.custom.sm.twitter-builder.nv%")) } - break; - case "%page.responsibilities.teamleader%": - titleCustom = "%page.responsibilities.custom.teamleader.title%"; - for (Teamler teamler : teamlers.stream().filter(teamler -> teamler.hasResponsibilityMain("Management des Timolia-Teams")).sorted(Teamler::compare).collect(Collectors.toList())) { - hvCustom.add(Responsibility.concreteTeamster(teamler, "%page.responsibilities.custom.teamleader.whole-team%")); + } + + "%page.responsibilities.teamleader%" -> { + titleCustom = "%page.responsibilities.custom.teamleader.title%" + for (teamler in teamlers.filter { teamler -> teamler.hasResponsibilityMain("Management des Timolia-Teams") }.sortedWith { obj, o -> obj.compare(o) }) { + hvCustom.add(Responsibility.concreteTeamster(teamler, "%page.responsibilities.custom.teamleader.whole-team%")) } - for (Teamler teamler : teamlers.stream().filter(teamler -> teamler.hasResponsibilityMain("Management des Bau-Teams")).sorted(Teamler::compare).collect(Collectors.toList())) { - hvCustom.add(Responsibility.concreteTeamster(teamler, "%page.responsibilities.custom.teamleader.builder%")); + for (teamler in teamlers.filter { teamler -> teamler.hasResponsibilityMain("Management des Bau-Teams") }.sortedWith { obj, o -> obj.compare(o) }) { + hvCustom.add(Responsibility.concreteTeamster(teamler, "%page.responsibilities.custom.teamleader.builder%")) } - for (Teamler teamler : teamlers.stream().filter(teamler -> teamler.hasResponsibilityMain("Management des Content-Teams")).sorted(Teamler::compare).collect(Collectors.toList())) { - hvCustom.add(Responsibility.concreteTeamster(teamler, "%page.responsibilities.custom.teamleader.content%")); + for (teamler in teamlers.filter { teamler -> teamler.hasResponsibilityMain("Management des Content-Teams") }.sortedWith { obj, o -> obj.compare(o) }) { + hvCustom.add(Responsibility.concreteTeamster(teamler, "%page.responsibilities.custom.teamleader.content%")) } - for (Teamler teamler : teamlers.stream().filter(teamler -> teamler.hasResponsibilityMain("Management des Development-Teams")).sorted(Teamler::compare).collect(Collectors.toList())) { - hvCustom.add(Responsibility.concreteTeamster(teamler, "%page.responsibilities.custom.teamleader.development%")); + for (teamler in teamlers.filter { teamler -> teamler.hasResponsibilityMain("Management des Development-Teams") }.sortedWith { obj, o -> obj.compare(o) }) { + hvCustom.add(Responsibility.concreteTeamster(teamler, "%page.responsibilities.custom.teamleader.development%")) } - break; - case "%page.responsibilities.yter%": - titleCustom = "%page.responsibilities.custom.yter.title%"; - break; + } + + "%page.responsibilities.yter%" -> titleCustom = "%page.responsibilities.custom.yter.title%" } if (titleCustom == null) { - sb.append("\n").append("| %page.responsibilities.teamler% | %page.responsibilities.responsib% |"); + sb.append("\n").append("| %page.responsibilities.teamler% | %page.responsibilities.responsib% |") } else { - sb.append("\n").append("| %page.responsibilities.teamler% | ").append(titleCustom).append(" |"); + sb.append("\n").append("| %page.responsibilities.teamler% | ").append(titleCustom).append(" |") } - sb.append("\n").append("| ------ | ------ |"); + sb.append("\n").append("| ------ | ------ |") if (hvCustom.isEmpty()) { - for (Teamler teamler : hv) { - hvCustom.add(Responsibility.concreteTeamster(ResponsibilityType.HV, teamler)); + for (teamler in hv) { + hvCustom.add(Responsibility.concreteTeamster(ResponsibilityType.HV, teamler)) } } - for (Responsibility hvEntry : hvCustom) { - sb.append("\n"); - hvEntry.renderTo(sb); + for (hvEntry in hvCustom) { + sb.append("\n") + hvEntry.renderTo(sb) } - if (!nv.isEmpty() || !nvCustom.isEmpty()) { - sb.append("\n").append("| | |"); + if (nv.isNotEmpty() || !nvCustom.isEmpty()) { + sb.append("\n").append("| | |") if (nvCustom.isEmpty()) { - for (Teamler teamler : nv) { - hvCustom.add(Responsibility.concreteTeamster(ResponsibilityType.NV, teamler)); + for (teamler in nv) { + hvCustom.add(Responsibility.concreteTeamster(ResponsibilityType.NV, teamler)) } } - for (Responsibility nvEntry : nvCustom) { - sb.append("\n"); - nvEntry.renderTo(sb); + for (nvEntry in nvCustom) { + sb.append("\n") + nvEntry.renderTo(sb) } } } } - sb.append("\n"); - return sb.toString(); + sb.append("\n") + return sb.toString() } } diff --git a/howto-dapp/src/main/java/de/timolia/howto/generator/PageTeamMembers.kt b/howto-dapp/src/main/java/de/timolia/howto/generator/PageTeamMembers.kt index cddc0530..d28b27a7 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/generator/PageTeamMembers.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/generator/PageTeamMembers.kt @@ -1,28 +1,27 @@ -package de.timolia.howto.generator; +package de.timolia.howto.generator -import de.timolia.howto.models.Rank; -import de.timolia.howto.models.Teamler; -import org.apache.commons.lang3.Validate; +import de.timolia.howto.rank.Rank +import de.timolia.howto.teamler.Teamler +import java.util.* +import java.util.stream.Collectors -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -public class PageTeamMembers { - public static String generate(List teamlers) { - teamlers = teamlers.stream().filter(teamler -> teamler.getRankCurrent().isInTeam()).collect(Collectors.toList()); - teamlers.sort(Teamler::compare); - List ranks = Arrays.stream(Rank.values()).filter(rank -> rank.getDescription() != null).sorted(Rank::compare).collect(Collectors.toList()); - StringBuilder sb = new StringBuilder(); - sb.append("%page.members.first-1%").append(teamlers.size()).append("%page.members.first-2%\n"); - List rankStrings = ranks.stream().map(rank -> "" + rank.getMale() + "").collect(Collectors.toList()); - for (int i = 0; i < rankStrings.size(); i++) { - sb.append(rankStrings.get(i)); - if (i < rankStrings.size() - 2) { - sb.append(", "); - } else if (i == rankStrings.size() - 2) { - sb.append(" %and% "); +object PageTeamMembers { + fun generate(teamlers: MutableList): String { + var teamlers = teamlers + teamlers = teamlers + .filter { teamler -> teamler.getRankCurrent().inTeam } + .sortedWith { obj, o -> obj.compare(o) } + .toMutableList() + val ranks = Arrays.stream(Rank.values()).filter { rank -> rank.description != null }.sorted { obj, o -> obj.compare(o) }.collect(Collectors.toList()) + val sb = StringBuilder() + sb.append("%page.members.first-1%").append(teamlers.size).append("%page.members.first-2%\n") + val rankStrings = ranks.map { rank -> "" + rank.male + "" } + for (i in rankStrings.indices) { + sb.append(rankStrings[i]) + if (i < rankStrings.size - 2) { + sb.append(", ") + } else if (i == rankStrings.size - 2) { + sb.append(" %and% ") } } sb @@ -30,49 +29,40 @@ public class PageTeamMembers { .append("\n") .append("\n").append("%page.members.first-4%") .append("\n") - .append("\n").append("![%page.members.first-5%](img/content-ranks.png)"); - - for (Rank rank : ranks) { + .append("\n").append("![%page.members.first-5%](img/content-ranks.png)") + for (rank in ranks) { sb .append("\n") .append("\n") .append("\n") - .append("\n").append("## ").append(rank.getMale()) + .append("\n").append("## ").append(rank.male) .append("\n") - .append("\n").append(rank.getDescription()) - .append("\n"); - - for (Teamler teamler : teamlers.stream().filter(teamler -> teamler.getRankCurrent().equals(rank)).collect(Collectors.toList())) { - - Validate.isTrue(teamler.getResponsibilitiesMain() == null || !teamler.getResponsibilitiesMain().contains(null), "Der Spieler '" + teamler.getName() + "' hat eine leere responsibilities_main, Komma zu viel?"); - Validate.isTrue(teamler.getResponsibilitiesMainHidden() == null || !teamler.getResponsibilitiesMainHidden().contains(null), "Der Spieler '" + teamler.getName() + "' hat eine leere responsibilities_main_hidden, Komma zu viel?"); - Validate.isTrue(teamler.getResponsibilitiesSecondary() == null || !teamler.getResponsibilitiesSecondary().contains(null), "Der Spieler '" + teamler.getName() + "' hat eine leere responsibilities_secondary, Komma zu viel?"); - Validate.isTrue(teamler.getResponsibilitiesSecondaryHidden() == null || !teamler.getResponsibilitiesSecondaryHidden().contains(null), "Der Spieler '" + teamler.getName() + "' hat eine leere responsibilities_secondary_hidden, Komma zu viel?"); - Validate.isTrue(teamler.getFields() == null || !teamler.getFields().contains(null), "Der Spieler '" + teamler.getName() + "' hat eine leere fields, Komma zu viel?"); - + .append("\n").append(rank.description) + .append("\n") + for (teamler in teamlers.filter { teamler -> teamler.getRankCurrent() == rank }) { sb .append("\n") .append("\n") - .append("### ").append(teamler.getNameForMarkdown()).append("") - .append("\n").append("- %page.members.rank-ingame%: ").append(rank.getString(teamler.getSex())); - if (teamler.getResponsibilitiesMain() != null) { + .append("### ").append(teamler.getNameForMarkdown()).append("") + .append("\n").append("- %page.members.rank-ingame%: ").append(rank.getString(teamler.sex)) + if (teamler.responsibilitiesMain != null) { sb .append("\n") - .append("- %page.members.hv%: ").append(teamler.getResponsibilitiesMain().stream().sorted(String::compareToIgnoreCase).collect(Collectors.joining(", "))); + .append("- %page.members.hv%: ").append(teamler.responsibilitiesMain!!.stream().sorted { obj, str -> obj.compareTo(str, ignoreCase = true) }.collect(Collectors.joining(", "))) } - if (teamler.getResponsibilitiesSecondary() != null) { + if (teamler.responsibilitiesSecondary != null) { sb .append("\n") - .append("- %page.members.nv%: ").append(teamler.getResponsibilitiesSecondary().stream().sorted(String::compareToIgnoreCase).collect(Collectors.joining(", "))); + .append("- %page.members.nv%: ").append(teamler.responsibilitiesSecondary!!.stream().sorted { obj, str -> obj.compareTo(str, ignoreCase = true) }.collect(Collectors.joining(", "))) } - if (teamler.getFields() != null){ + if (teamler.fields != null) { sb .append("\n") - .append("- %page.members.fields%: ").append(teamler.getFields().stream().sorted(String::compareToIgnoreCase).collect(Collectors.joining(", "))); + .append("- %page.members.fields%: ").append(teamler.fields.stream().sorted { obj, str -> obj.compareTo(str, ignoreCase = true) }.collect(Collectors.joining(", "))) } } } - sb.append("\n"); - return sb.toString(); + sb.append("\n") + return sb.toString() } } diff --git a/howto-dapp/src/main/java/de/timolia/howto/rank/Rank.kt b/howto-dapp/src/main/java/de/timolia/howto/rank/Rank.kt index 78f2584c..b600cdec 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/rank/Rank.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/rank/Rank.kt @@ -1,96 +1,76 @@ -package de.timolia.howto.models; +package de.timolia.howto.rank -public enum Rank { - administrator( 161, true, "administrator", "Administrator", "Administratorin", "%rank.administrator.description%"), - administrator_city( 160, true, "administrator", "Administrator City", null), - builder( 80, true, "builder", "Builder", "Builderin", "%rank.builder.description%"), - builder_plus( 85, true, "builder-plus", "Builder+", null, "%rank.builder_plus.description%"), - creator( 70, true, "creator", "Creator", null), - content( 71, true, "content", "Content", null, "%rank.content.description%"), - developer( 135, true, "developer", "Developer", null, "%rank.developer.description%"), - developer_city( 131, true, "developer", "Developer City", null), - developer_games( 130, true, "developer", "Developer Games", null), - developer_plus( 140, true, "developer-plus", "Developer+", null, "%rank.developer_plus.description%"), - expert( 50, false, "expert", "Expert", null), - head_builder( 90 , true, "headbuilder", "HeadBuilder", null, "%rank.head_builder.description%"), - mvp( 30, false, "mvp", "MVP", null), - mvp_plus( 40, false, "mvp", "MVP+", null), - management( 180, true, "management", "Management", null), - moderator( 125, true, "moderator", "Moderator", "Moderatorin", "%rank.moderator.description%"), - moderator_city( 121, true, "moderator", "Moderator City", null), - moderator_games( 120, true, "moderator", "Moderator Games", "Moderatorin Games"), - native_expert( 55, false, "expert", "Native Expert", null), - native_mvp( 35, false, "mvp", "Native MVP", null), - native_mvp_plus( 45, false, "mvp", "Native MVP+", null), - native_youtuber( 60, false, "youtuber", "Native YouTuber", null), - pro( 10, false, "pro", "Pro", null), - pro_plus( 20, false, "pro", "Pro+", null), - spieler( 0, false, "user", "Spieler", "Spielerin"), - supporter( 105, true, "supporter", "Supporter", "Supporterin", "%rank.supporter.description%"), - supporter_city( 102, true, "supporter", "Supporter City", "Supporterin City"), - supporter_games( 101, true, "supporter", "Supporter Games", "Supporterin Games"), - supporter_plus( 110, true, "supporter-plus", "Supporter+", "Supporterin+", "%rank.supporter_plus.description%"), - supporter_city_games(100, true, "supporter", "Supporter City & Games", "Supporterin City & Games"), - sysadmin( 150, true, "sysadmin", "SysAdmin", null); +import de.timolia.howto.teamler.Sex - private final int value; - private final boolean inTeam; - private final String male; - private final String female; - private final String cssClass; - private final String description; +enum class Rank { + administrator(161, true, "administrator", "Administrator", "Administratorin", "%rank.administrator.description%"), + administrator_city(160, true, "administrator", "Administrator City", null), + builder(80, true, "builder", "Builder", "Builderin", "%rank.builder.description%"), + builder_plus(85, true, "builder-plus", "Builder+", null, "%rank.builder_plus.description%"), + creator(70, true, "creator", "Creator", null), + content(71, true, "content", "Content", null, "%rank.content.description%"), + developer(135, true, "developer", "Developer", null, "%rank.developer.description%"), + developer_city(131, true, "developer", "Developer City", null), + developer_games(130, true, "developer", "Developer Games", null), + developer_plus(140, true, "developer-plus", "Developer+", null, "%rank.developer_plus.description%"), + expert(50, false, "expert", "Expert", null), + head_builder(90, true, "headbuilder", "HeadBuilder", null, "%rank.head_builder.description%"), + mvp(30, false, "mvp", "MVP", null), + mvp_plus(40, false, "mvp", "MVP+", null), + management(180, true, "management", "Management", null), + moderator(125, true, "moderator", "Moderator", "Moderatorin", "%rank.moderator.description%"), + moderator_city(121, true, "moderator", "Moderator City", null), + moderator_games(120, true, "moderator", "Moderator Games", "Moderatorin Games"), + native_expert(55, false, "expert", "Native Expert", null), + native_mvp(35, false, "mvp", "Native MVP", null), + native_mvp_plus(45, false, "mvp", "Native MVP+", null), + native_youtuber(60, false, "youtuber", "Native YouTuber", null), + pro(10, false, "pro", "Pro", null), + pro_plus(20, false, "pro", "Pro+", null), + spieler(0, false, "user", "Spieler", "Spielerin"), + supporter(105, true, "supporter", "Supporter", "Supporterin", "%rank.supporter.description%"), + supporter_city(102, true, "supporter", "Supporter City", "Supporterin City"), + supporter_games(101, true, "supporter", "Supporter Games", "Supporterin Games"), + supporter_plus(110, true, "supporter-plus", "Supporter+", "Supporterin+", "%rank.supporter_plus.description%"), + supporter_city_games(100, true, "supporter", "Supporter City & Games", "Supporterin City & Games"), + sysadmin(150, true, "sysadmin", "SysAdmin", null); - Rank(int value, boolean inTeam, String cssClass, String male, String female) { - this.value = value; - this.inTeam = inTeam; - this.male = male; - this.female = female; - this.cssClass = cssClass; - this.description = null; - } - - Rank(int value, boolean inTeam, String cssClass, String male, String female, String description) { - this.value = value; - this.inTeam = inTeam; - this.male = male; - this.female = female; - this.cssClass = cssClass; - this.description = description; - } - - public String getString(Sex sex) { - if (sex == Sex.female && this.female != null) { - return this.female; - } - return this.male; - } + private val value: Int + val inTeam: Boolean + val male: String + private val female: String? + val cssClass: String + val description: String? - public int getValue() { - return value; + constructor(value: Int, inTeam: Boolean, cssClass: String, male: String, female: String?) { + this.value = value + this.inTeam = inTeam + this.male = male + this.female = female + this.cssClass = cssClass + description = null } - public boolean isInTeam() { - return inTeam; + constructor(value: Int, inTeam: Boolean, cssClass: String, male: String, female: String?, description: String?) { + this.value = value + this.inTeam = inTeam + this.male = male + this.female = female + this.cssClass = cssClass + this.description = description } - public String getMale() { - return male; + fun getString(sex: Sex): String { + return if (sex == Sex.female && female != null) { + female + } else male } - public String getFemale() { - return female == null ? "undefined" : female; + fun getFemale(): String { + return female ?: "undefined" } - public String getCssClass() { - return cssClass; + fun compare(o: Rank): Int { + return Integer.compare(o.value, value) } - - public String getDescription() { - return description; - } - - public int compare(Rank o) { - return Integer.compare(o.value, this.value); - } - } diff --git a/howto-dapp/src/main/java/de/timolia/howto/rank/RankConversion.kt b/howto-dapp/src/main/java/de/timolia/howto/rank/RankConversion.kt index f886c4cd..70cfb5fc 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/rank/RankConversion.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/rank/RankConversion.kt @@ -1,73 +1,60 @@ -package de.timolia.howto.conversion; +package de.timolia.howto.rank -import de.timolia.howto.models.Rank; +import java.util.* +import java.util.function.Function +import java.util.stream.Collectors -import java.util.Arrays; -import java.util.Comparator; -import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; - -public class RankConversion { - - public static Rank getRank(String text) { - return Arrays.stream(Rank.values()) - .collect(Collectors.toMap(Function.identity(), rank -> Math.max(getSimilarity(text, rank.getFemale()), getSimilarity(text, rank.getMale())))) - .entrySet() +object RankConversion { + fun getRank(text: String): Rank? { + return Arrays.stream(Rank.values()) + .collect(Collectors.toMap(Function.identity()) { rank -> Math.max(getSimilarity(text, rank.getFemale()), getSimilarity(text, rank.male)) }) + .entries .stream() - .max(Comparator.comparingDouble(Map.Entry::getValue)) - .filter(e -> e.getValue() > 0.1) - .map(Map.Entry::getKey) - .orElse(null); + .max(Comparator.comparingDouble { (_, value) -> value }) + .filter { e -> e.value > 0.1 } + .map { (key, _) -> key } + .orElse(null) } /** * Calculates the similarity (a number within 0 and 1) between two strings. */ - public static double getSimilarity(String s1, String s2) { - String longer = s1, shorter = s2; - if (s1.length() < s2.length()) { // longer should always have greater length - longer = s2; - shorter = s1; - } - int longerLength = longer.length(); - if (longerLength == 0) { - return 1.0; /* both strings are zero length */ + fun getSimilarity(s1: String, s2: String): Double { + var longer = s1 + var shorter = s2 + if (s1.length < s2.length) { // longer should always have greater length + longer = s2 + shorter = s1 } - /* // If you have Apache Commons Text, you can use it to calculate the edit distance: - LevenshteinDistance levenshteinDistance = new LevenshteinDistance(); - return (longerLength - levenshteinDistance.apply(longer, shorter)) / (double) longerLength; */ - return (longerLength - editDistance(longer, shorter)) / (double) longerLength; - + val longerLength = longer.length + return if (longerLength == 0) { + 1.0 /* both strings are zero length */ + } else (longerLength - editDistance(longer, shorter)) / longerLength.toDouble() } // Example implementation of the Levenshtein Edit Distance // See http://rosettacode.org/wiki/Levenshtein_distance#Java - private static int editDistance(String s1, String s2) { - s1 = s1.toLowerCase(); - s2 = s2.toLowerCase(); - - int[] costs = new int[s2.length() + 1]; - for (int i = 0; i <= s1.length(); i++) { - int lastValue = i; - for (int j = 0; j <= s2.length(); j++) { - if (i == 0) - costs[j] = j; - else { + private fun editDistance(s1: String, s2: String): Int { + var s1 = s1 + var s2 = s2 + s1 = s1.lowercase(Locale.getDefault()) + s2 = s2.lowercase(Locale.getDefault()) + val costs = IntArray(s2.length + 1) + for (i in 0..s1.length) { + var lastValue = i + for (j in 0..s2.length) { + if (i == 0) costs[j] = j else { if (j > 0) { - int newValue = costs[j - 1]; - if (s1.charAt(i - 1) != s2.charAt(j - 1)) - newValue = Math.min(Math.min(newValue, lastValue), - costs[j]) + 1; - costs[j - 1] = lastValue; - lastValue = newValue; + var newValue = costs[j - 1] + if (s1[i - 1] != s2[j - 1]) newValue = Math.min(Math.min(newValue, lastValue), + costs[j]) + 1 + costs[j - 1] = lastValue + lastValue = newValue } } } - if (i > 0) - costs[s2.length()] = lastValue; + if (i > 0) costs[s2.length] = lastValue } - return costs[s2.length()]; + return costs[s2.length] } - } diff --git a/howto-dapp/src/main/java/de/timolia/howto/rank/TeamlerRankChange.kt b/howto-dapp/src/main/java/de/timolia/howto/rank/TeamlerRankChange.kt index 97a89022..ad87c758 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/rank/TeamlerRankChange.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/rank/TeamlerRankChange.kt @@ -1,110 +1,72 @@ -package de.timolia.howto.conversion.models; - -import de.timolia.howto.conversion.RankConversion; -import de.timolia.howto.conversion.SQLApi; -import de.timolia.howto.models.Rank; -import org.apache.commons.lang3.Validate; - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.UUID; - -public class TeamlerRankChange { - private static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd.MM.yyyy"); - - private final String name; - private final UUID uuid; - private final Rank rankFrom; - private final Rank rankTo; - private final Date date; - private final transient boolean hidden; - - public TeamlerRankChange(String name, String rankFrom, String rankTo, String date) throws ParseException { - this.name = name; - this.uuid = SQLApi.getUuid(name); - this.rankFrom = RankConversion.getRank(rankFrom); - this.rankTo = RankConversion.getRank(rankTo); - this.date = simpleDateFormat.parse(date); - this.hidden = false; - - Validate.notNull(this.rankFrom, "Der Rang von '" + name + "' ('" + rankFrom + "') existiert nicht"); - Validate.notNull(this.rankTo, "Der Rang von '" + name + "' ('" + rankTo + "') existiert nicht"); - } - - public TeamlerRankChange(String name, UUID uuid, Rank rankFrom, Rank rankTo, String date, boolean hidden) { - this.name = SQLApi.getName(uuid, name); - this.uuid = uuid; - this.rankFrom = rankFrom; - this.rankTo = rankTo; - this.date = toDate(date); - this.hidden = hidden; - - Validate.notNull(this.rankFrom, "Der Rang von '" + name + "' existiert nicht"); - Validate.notNull(this.rankTo, "Der Rang von '" + name + "' existiert nicht"); - } - - - public String getName() { - return name; - } - - public String getNameForMarkdown() { - return name.replaceAll("_", "\\\\_"); - } - - public UUID getUuid() { - return uuid; - } - - public Rank getRankFrom() { - return rankFrom; - } - - public Rank getRankTo() { - return rankTo; +package de.timolia.howto.rank + +import de.timolia.howto.database.SQLApi +import java.text.ParseException +import java.text.SimpleDateFormat +import java.util.* + +class TeamlerRankChange { + val name: String + val uuid: UUID + val rankFrom: Rank + val rankTo: Rank + val date: Date + + @Transient + private val hidden: Boolean + + constructor(name: String, rankFrom: String, rankTo: String, date: String) { + this.name = name + uuid = SQLApi.getUuid(name)!! + this.rankFrom = RankConversion.getRank(rankFrom) ?: throw IllegalArgumentException("Der Rang von '$name' ('$rankFrom') existiert nicht") + this.rankTo = RankConversion.getRank(rankTo) ?: throw IllegalArgumentException("Der Rang von '$name' ('$rankTo') existiert nicht") + this.date = simpleDateFormat.parse(date) + hidden = false } - public Date getDate() { - return date; + constructor(name: String?, uuid: UUID, rankFrom: Rank, rankTo: Rank, date: String, hidden: Boolean) { + this.name = SQLApi.getName(uuid, name)!! + this.uuid = uuid + this.rankFrom = rankFrom + this.rankTo = rankTo + this.date = toDate(date) + this.hidden = hidden } - public boolean isHidden() { - return hidden; + fun getNameForMarkdown(): String { + return name.replace("_".toRegex(), "\\\\_") } - public String getReadableDate() { - return simpleDateFormat.format(date); + fun getReadableDate(): String { + return simpleDateFormat.format(date) } - public static String toString(Date date) { - if (date.equals(new Date(0))) { - return "initial"; - } - return simpleDateFormat.format(date); - } - - public static Date toDate(String date) { - if (date.equals("initial")) { - return new Date(0); - } - - try { - return simpleDateFormat.parse(date); - } catch (ParseException e) { - throw new RuntimeException(e); - } - } - - - @Override - public String toString() { + override fun toString(): String { return "TeamlerRankChange{" + "name='" + name + '\'' + ", uuid=" + uuid + ", rankFrom='" + rankFrom + '\'' + ", rankTo='" + rankTo + '\'' + ", date=" + simpleDateFormat.format(date) + - '}'; + '}' + } + + companion object { + private val simpleDateFormat: SimpleDateFormat = SimpleDateFormat("dd.MM.yyyy") + fun toString(date: Date?): String { + return if (date == Date(0)) { + "initial" + } else simpleDateFormat.format(date) + } + + fun toDate(date: String): Date { + return if (date == "initial") { + Date(0) + } else try { + simpleDateFormat.parse(date) + } catch (e: ParseException) { + throw RuntimeException(e) + } + } } } diff --git a/howto-dapp/src/main/java/de/timolia/howto/responsibility/Responsibility.kt b/howto-dapp/src/main/java/de/timolia/howto/responsibility/Responsibility.kt index ed7cddc8..11760160 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/responsibility/Responsibility.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/responsibility/Responsibility.kt @@ -1,32 +1,38 @@ -package de.timolia.howto.responsibility; +package de.timolia.howto.responsibility -import de.timolia.howto.models.Teamler; +import de.timolia.howto.teamler.Teamler -public interface Responsibility { - void renderTo(StringBuilder builder); +fun interface Responsibility { + fun renderTo(builder: StringBuilder) - static Responsibility simple(ResponsibilityType type, String teamler) { - return builder -> builder - .append("|") - .append(teamler) - .append(" | ") - .append(type.defaultKey()) - .append(" |"); - } + companion object { + fun simple(type: ResponsibilityType, teamler: String): Responsibility { + return Responsibility { builder -> + builder + .append("|") + .append(teamler) + .append(" | ") + .append(type.defaultKey()) + .append(" |") + } + } - static Responsibility concreteTeamster(ResponsibilityType type, Teamler teamler) { - return concreteTeamster(teamler, type.defaultKey()); - } + fun concreteTeamster(type: ResponsibilityType, teamler: Teamler): Responsibility { + return concreteTeamster(teamler, type.defaultKey()) + } - static Responsibility concreteTeamster(Teamler teamler, String translationKey) { - return builder -> builder - .append("|") - .append(teamler.getNameForMarkdown()) - .append("") - .append(" | ") - .append(translationKey) - .append(" |"); + fun concreteTeamster(teamler: Teamler, translationKey: String): Responsibility { + return Responsibility { builder -> + builder + .append("|") + .append(teamler.getNameForMarkdown()) + .append("") + .append(" | ") + .append(translationKey) + .append(" |") + } + } } } diff --git a/howto-dapp/src/main/java/de/timolia/howto/responsibility/ResponsibilityType.kt b/howto-dapp/src/main/java/de/timolia/howto/responsibility/ResponsibilityType.kt index a708833a..7860cd79 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/responsibility/ResponsibilityType.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/responsibility/ResponsibilityType.kt @@ -1,12 +1,10 @@ -package de.timolia.howto.responsibility; +package de.timolia.howto.responsibility -import java.util.Locale; - -public enum ResponsibilityType { +enum class ResponsibilityType { HV, NV; - public String defaultKey() { - return "%page.responsibilities." + name().toLowerCase(Locale.ROOT) + "%"; + fun defaultKey(): String { + return "%page.responsibilities.${name.lowercase()}%" } } diff --git a/howto-dapp/src/main/java/de/timolia/howto/teamler/Sex.kt b/howto-dapp/src/main/java/de/timolia/howto/teamler/Sex.kt index 56662377..4ef06d8a 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/teamler/Sex.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/teamler/Sex.kt @@ -1,6 +1,6 @@ -package de.timolia.howto.models; +package de.timolia.howto.teamler -public enum Sex { +enum class Sex { female, male, undefined diff --git a/howto-dapp/src/main/java/de/timolia/howto/teamler/Teamler.kt b/howto-dapp/src/main/java/de/timolia/howto/teamler/Teamler.kt index e32bd879..d99f0292 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/teamler/Teamler.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/teamler/Teamler.kt @@ -1,170 +1,120 @@ -package de.timolia.howto.models; - -import de.timolia.howto.conversion.SQLApi; -import de.timolia.howto.conversion.models.TeamlerRankChange; -import org.apache.commons.lang3.Validate; - -import java.text.ParseException; -import java.text.RuleBasedCollator; -import java.util.*; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -public class Teamler { - - private String name; - private final UUID uuid; - private final Sex sex; - private List responsibilitiesMain; - private final List responsibilitiesMainHidden; - private List responsibilitiesSecondary; - private final List responsibilitiesSecondaryHidden; - private final List fields; - private final LinkedHashMap rankHistory; - private transient Rank rankCurrent = null; - - public Teamler(UUID uuid, Sex sex, List responsibilitiesMain, List responsibilitiesSecondary, List fields, LinkedHashMap rankHistory) { - this.name = SQLApi.getName(uuid); - this.uuid = uuid; - this.sex = sex; - this.responsibilitiesMain = responsibilitiesMain; - this.responsibilitiesMainHidden = null; - this.responsibilitiesSecondary = responsibilitiesSecondary; - this.responsibilitiesSecondaryHidden = null; - this.fields = fields; - this.rankHistory = rankHistory; - } - - public String getName() { - return name; - } - - public String getNameForMarkdown() { - return name.replaceAll("_", "\\\\_"); - } - - public UUID getUuid() { - return uuid; - } - - public Sex getSex() { - return sex; - } - - public List getResponsibilitiesMain() { - return responsibilitiesMain; - } - - public void setResponsibilitiesMain(List responsibilitiesMain) { - this.responsibilitiesMain = responsibilitiesMain; - } - - public List getResponsibilitiesMainHidden() { - return responsibilitiesMainHidden; - } - - public List getResponsibilitiesSecondary() { - return responsibilitiesSecondary; - } - - public void setResponsibilitiesSecondary(List responsibilitiesSecondary) { - this.responsibilitiesSecondary = responsibilitiesSecondary; - } - - public List getResponsibilitiesSecondaryHidden() { - return responsibilitiesSecondaryHidden; - } - - public List getFields() { - return fields; - } - - public HashMap getRankHistory() { - return rankHistory; - } - - public List getRankChanges(boolean includeHidden) { - List rankChanges = new ArrayList<>(); - if (rankHistory == null || rankHistory.isEmpty()) { - return rankChanges; +package de.timolia.howto.teamler + +import de.timolia.howto.database.SQLApi +import de.timolia.howto.rank.Rank +import de.timolia.howto.rank.TeamlerRankChange +import org.apache.commons.lang3.Validate +import java.text.ParseException +import java.text.RuleBasedCollator +import java.util.* +import java.util.stream.Collectors +import java.util.stream.Stream + +class Teamler( + val uuid: UUID, + val sex: Sex, + var responsibilitiesMain: MutableList?, + var responsibilitiesSecondary: MutableList?, + val fields: MutableList?, + private val rankHistory: LinkedHashMap? +) { + private var name: String + private val responsibilitiesMainHidden: MutableList? = null + private val responsibilitiesSecondaryHidden: MutableList? = null + + @Transient + private var rankCurrent: Rank? = null + + init { + name = SQLApi.getName(uuid)!! + } + + fun getNameForMarkdown(): String { + return name.replace("_", "\\\\_") + } + + fun getRankChanges(includeHidden: Boolean): MutableList { + val rankChanges: MutableList = ArrayList() + if (rankHistory.isNullOrEmpty()) { + return rankChanges } - - for (int i = 0; i < rankHistory.size(); i++) { - Rank rank = (Rank) rankHistory.values().toArray()[i]; - Validate.notNull(rank, "Der " + (i + 1) + ". Rang von '" + name + "' existiert nicht"); + for (i in 0 until rankHistory.size) { + val rank = rankHistory.values.toTypedArray()[i] + Validate.notNull(rank, "Der " + (i + 1) + ". Rang von '" + name + "' existiert nicht") } - - List dates = rankHistory.keySet().stream().map(s -> s.replace("hidden-", "")).map(TeamlerRankChange::toDate).sorted().collect(Collectors.toList()); - for (int i = Math.min(1, dates.size() - 1); i < dates.size(); i++) { - boolean hidden = false; - String rankOldKey = TeamlerRankChange.toString(dates.get(Math.max(i - 1, 0))); - if (!rankHistory.containsKey(rankOldKey) && rankHistory.containsKey("hidden-" + rankOldKey)) { - rankOldKey = "hidden-" + rankOldKey; + val dates = rankHistory.keys + .map { s -> s.replace("hidden-", "") } + .map { date -> TeamlerRankChange.toDate(date) } + .sorted() + for (i in Math.min(1, dates.size - 1) until dates.size) { + var hidden = false + var rankOldKey: String = TeamlerRankChange.toString(dates[Math.max(i - 1, 0)]) + if (!rankHistory.containsKey(rankOldKey) && rankHistory.containsKey("hidden-$rankOldKey")) { + rankOldKey = "hidden-$rankOldKey" } - Rank rank_old = rankHistory.get(rankOldKey); - - String rankNewKey = TeamlerRankChange.toString(dates.get(i)); - if (!rankHistory.containsKey(rankNewKey) && rankHistory.containsKey("hidden-" + rankNewKey)) { - rankNewKey = "hidden-" + rankNewKey; - hidden = true; + val rankOld = rankHistory[rankOldKey] + var rankNewKey: String = TeamlerRankChange.toString(dates[i]) + if (!rankHistory.containsKey(rankNewKey) && rankHistory.containsKey("hidden-$rankNewKey")) { + rankNewKey = "hidden-$rankNewKey" + hidden = true } - Rank rank_new = rankHistory.get(rankNewKey); - if (includeHidden || !hidden && !rankNewKey.equals("initial")) { - TeamlerRankChange teamlerRankChange = new TeamlerRankChange(name, uuid, rank_old, rank_new, TeamlerRankChange.toString(dates.get(i)), hidden); - rankChanges.add(teamlerRankChange); + val rankNew = rankHistory[rankNewKey] + if (includeHidden || !hidden && rankNewKey != "initial") { + val teamlerRankChange = TeamlerRankChange(name, uuid, rankOld!!, rankNew!!, TeamlerRankChange.toString(dates[i]), hidden) + rankChanges.add(teamlerRankChange) } } - return rankChanges; + return rankChanges } - public Rank getRankCurrent() { + fun getRankCurrent(): Rank { if (rankCurrent == null) { - List teamlerRankChanges = getRankChanges(true); - TeamlerRankChange lastRankChange = teamlerRankChanges.get(teamlerRankChanges.size() - 1); - rankCurrent = lastRankChange.getRankTo(); + val teamlerRankChanges = getRankChanges(true) + val lastRankChange = teamlerRankChanges[teamlerRankChanges.size - 1] + rankCurrent = lastRankChange.rankTo } - return rankCurrent; + return rankCurrent!! } - public int compare(Teamler o) { - if (!this.getRankCurrent().equals(o.getRankCurrent())) { + fun compare(o: Teamler): Int { + if (getRankCurrent() != o.getRankCurrent()) { // compare by rank - return this.getRankCurrent().compare(o.getRankCurrent()); + return getRankCurrent().compare(o.getRankCurrent()) } // compare by name - String rules = "< '_'"; - try { - RuleBasedCollator ruleBasedCollator = new RuleBasedCollator(rules); - return ruleBasedCollator.compare(this.getName().toLowerCase(), o.getName().toLowerCase()); - } catch (ParseException e) { - e.printStackTrace(); - throw new RuntimeException(); + val rules = "< '_'" + return try { + val ruleBasedCollator = RuleBasedCollator(rules) + ruleBasedCollator.compare(name.lowercase(Locale.getDefault()), o.name.lowercase(Locale.getDefault())) + } catch (e: ParseException) { + e.printStackTrace() + throw RuntimeException() } } - public boolean hasResponsibilityMain(String responsibility) { - return hasResponsibility(responsibility, Stream.concat(responsibilitiesMain == null ? Stream.empty() : responsibilitiesMain.stream(), responsibilitiesMainHidden == null ? Stream.empty() : responsibilitiesMainHidden.stream()).collect(Collectors.toList())); + fun hasResponsibilityMain(responsibility: String?): Boolean { + return hasResponsibility(responsibility, Stream.concat(if (responsibilitiesMain == null) Stream.empty() else responsibilitiesMain!!.stream(), responsibilitiesMainHidden?.stream() + ?: Stream.empty()).collect(Collectors.toList())) } - public boolean hasResponsibilitySecondary(String responsibility) { - return hasResponsibility(responsibility, Stream.concat(responsibilitiesSecondary == null ? Stream.empty() : responsibilitiesSecondary.stream(), responsibilitiesSecondaryHidden == null ? Stream.empty() : responsibilitiesSecondaryHidden.stream()).collect(Collectors.toList())); + fun hasResponsibilitySecondary(responsibility: String?): Boolean { + return hasResponsibility(responsibility, Stream.concat(if (responsibilitiesSecondary == null) Stream.empty() else responsibilitiesSecondary!!.stream(), responsibilitiesSecondaryHidden?.stream() + ?: Stream.empty()).collect(Collectors.toList())) } - private boolean hasResponsibility(String responsibility, List responsibilityList) { - if (!getRankCurrent().isInTeam() && !responsibilityList.isEmpty()) { - throw new RuntimeException("'" + name + "' has responsibilities but is not in team anymore"); + private fun hasResponsibility(responsibility: String?, responsibilityList: MutableList?): Boolean { + if (!getRankCurrent().inTeam && responsibilityList!!.isNotEmpty()) { + throw RuntimeException("'$name' has responsibilities but is not in team anymore") } - - return responsibilityList != null && (responsibilityList.contains(responsibility) || responsibilityList.contains(responsibility + " Forum")); + return responsibilityList != null && (responsibilityList.contains(responsibility) || responsibilityList.contains("$responsibility Forum")) } - public void updateName() { - this.name = SQLApi.getName(uuid, name); + fun updateName() { + name = SQLApi.getName(uuid, name)!! } - @Override - public String toString() { + override fun toString(): String { return "Teamler{" + "name='" + name + '\'' + ", uuid=" + uuid + @@ -172,6 +122,6 @@ public class Teamler { ", responsibilitiesMain=" + responsibilitiesMain + ", responsibilitiesSecondary=" + responsibilitiesSecondary + ", rankHistory=" + rankHistory + - '}'; + '}' } } diff --git a/howto-dapp/src/main/java/de/timolia/howto/translate/Language.kt b/howto-dapp/src/main/java/de/timolia/howto/translate/Language.kt index 6fc10247..dc9e28f0 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/translate/Language.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/translate/Language.kt @@ -1,12 +1,10 @@ -package de.timolia.howto.translate; +package de.timolia.howto.translate -import java.util.Locale; - -public enum Language { +enum class Language { DE, EN; - public String key() { - return name().toLowerCase(Locale.ROOT); + fun key(): String { + return name.lowercase() } } diff --git a/howto-dapp/src/main/java/de/timolia/howto/translate/Translate.kt b/howto-dapp/src/main/java/de/timolia/howto/translate/Translate.kt index f27eeb82..6920e14b 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/translate/Translate.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/translate/Translate.kt @@ -1,53 +1,53 @@ -package de.timolia.howto.translate; +package de.timolia.howto.translate -import java.io.IOException; -import java.io.UncheckedIOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.*; -import java.util.stream.Collectors; +import java.io.IOException +import java.io.UncheckedIOException +import java.nio.charset.StandardCharsets +import java.nio.file.Files +import java.nio.file.Path +import java.util.* +import java.util.stream.Collectors +import kotlin.Throws +import kotlin.io.path.extension +import kotlin.io.path.nameWithoutExtension -public class Translate { - private final Map> translations = new HashMap<>(); - - public void loadDirectory(Path path) throws IOException { - Files.list(path).forEach(file -> { - try { - mayLoadFile(file); - } catch (IOException e) { - throw new UncheckedIOException("Failed to load translation from " + file, e); - } - }); +class Translate { + private val translations = EnumMap>(Language::class.java) + @Throws(IOException::class) + fun loadDirectory(path: Path) { + Files.list(path).forEach { file: Path -> + try { + mayLoadFile(file) + } catch (e: IOException) { + throw UncheckedIOException("Failed to load translation from $file", e) + } + } } - private void mayLoadFile(Path path) throws IOException { - String name = path.getFileName().toString(); - System.out.println(name); - if (!name.endsWith(".properties")) { - return; - } - String languageName = name.substring(0, name.length() - ".properties".length()); - Language language = Language.valueOf(languageName.toUpperCase(Locale.ROOT)); - System.out.println(languageName); - Properties properties = new Properties(); - properties.load(Files.newBufferedReader(path, StandardCharsets.UTF_8)); - translations.put(language, properties.entrySet() - .stream() - .map(property -> new Translation(language, property.getKey().toString(), property.getValue().toString())) - .collect(Collectors.toList())); - } - - public TranslationContext forLanguage(Language language) { - List translations = this.translations.get(language); - if (translations == null) { - throw new IllegalArgumentException("No translations for language " + language); + @Throws(IOException::class) + private fun mayLoadFile(path: Path) { + if (path.extension != "properties") { + return } - return content -> { - for (Translation translation : translations) { - content = translation.replace(content); + val languageName = path.nameWithoutExtension + val language = Language.valueOf(languageName.uppercase()) + println(languageName) + val properties = Properties() + properties.load(Files.newBufferedReader(path, StandardCharsets.UTF_8)) + translations[language] = properties.entries + .map { property -> Translation(language, property.key.toString(), property.value.toString()) } + .toMutableList() + } + + fun forLanguage(language: Language): TranslationContext { + val translations = translations[language] + ?: throw IllegalArgumentException("No translations for language $language") + return TranslationContext { content -> + var content = content + for (translation in translations) { + content = translation.replace(content) } - return content; - }; + content + } } } diff --git a/howto-dapp/src/main/java/de/timolia/howto/translate/Translation.kt b/howto-dapp/src/main/java/de/timolia/howto/translate/Translation.kt index 721eec06..a400eb59 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/translate/Translation.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/translate/Translation.kt @@ -1,42 +1,19 @@ -package de.timolia.howto.translate; +package de.timolia.howto.translate -public class Translation { - private final Language language; - private final String key; - private final String value; - - public Translation(Language language, String key, String value) { - this.language = language; - this.key = key; - this.value = value; - } - - public String replace(String text) { - return text.replace(replacementKey(), getValue()); - } - - private String replacementKey() { - return "%" + getKey() + "%"; - } - - public Language getLanguage() { - return language; - } - - public String getKey() { - return key; +class Translation(private val language: Language, private val key: String, private val value: String) { + fun replace(text: String): String { + return text.replace(replacementKey(), value) } - public String getValue() { - return value; + private fun replacementKey(): String { + return "%$key%" } - @Override - public String toString() { + override fun toString(): String { return "LanguageString{" + "language=" + language + ", key='" + key + '\'' + ", value='" + value + '\'' + - '}'; + '}' } } diff --git a/howto-dapp/src/main/java/de/timolia/howto/translate/TranslationContext.kt b/howto-dapp/src/main/java/de/timolia/howto/translate/TranslationContext.kt index 56b0b909..00ca51c2 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/translate/TranslationContext.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/translate/TranslationContext.kt @@ -1,5 +1,5 @@ -package de.timolia.howto.translate; +package de.timolia.howto.translate -public interface TranslationContext { - String replaceAll(String content); +fun interface TranslationContext { + fun replaceAll(content: String): String } From 531a6809742c14f4901f06c8ca8692a6866bf289 Mon Sep 17 00:00:00 2001 From: David Scandurra Date: Fri, 19 May 2023 17:54:23 +0200 Subject: [PATCH 4/8] Let kotlin gradle plugin decide stdlib version --- howto-dapp/build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/howto-dapp/build.gradle b/howto-dapp/build.gradle index aedcece8..b733ec94 100644 --- a/howto-dapp/build.gradle +++ b/howto-dapp/build.gradle @@ -19,7 +19,6 @@ dependencies { // https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.11' - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" } jar { From 943f1d58396aba629710a820f2503d0ce0e88fa1 Mon Sep 17 00:00:00 2001 From: David Scandurra Date: Thu, 25 May 2023 22:56:55 +0200 Subject: [PATCH 5/8] use more kotlin features --- .../src/main/java/de/timolia/howto/Dapp.kt | 21 +++++----- .../howto/conversion/InitialConversion.kt | 34 ++++++++-------- .../timolia/howto/conversion/JsonBuilder.kt | 9 ++--- .../java/de/timolia/howto/database/SQLApi.kt | 1 + .../howto/database/SqlUserConnection.kt | 1 + .../timolia/howto/generator/PageRankChange.kt | 4 +- .../howto/generator/PageResponsibilities.kt | 3 +- .../howto/generator/PageTeamMembers.kt | 40 +++++++++---------- .../main/java/de/timolia/howto/rank/Rank.kt | 36 +++++------------ .../de/timolia/howto/rank/RankConversion.kt | 7 ++-- .../java/de/timolia/howto/teamler/Teamler.kt | 38 +++++++++--------- .../de/timolia/howto/translate/Language.kt | 4 +- .../de/timolia/howto/translate/Translate.kt | 4 +- .../de/timolia/howto/translate/Translation.kt | 8 +--- 14 files changed, 94 insertions(+), 116 deletions(-) diff --git a/howto-dapp/src/main/java/de/timolia/howto/Dapp.kt b/howto-dapp/src/main/java/de/timolia/howto/Dapp.kt index 408213a7..d134a035 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/Dapp.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/Dapp.kt @@ -1,6 +1,7 @@ package de.timolia.howto import com.google.gson.FieldNamingPolicy +import com.google.gson.Gson import com.google.gson.GsonBuilder import de.timolia.howto.conversion.InitialConversion import de.timolia.howto.generator.FileWriter @@ -9,7 +10,6 @@ import de.timolia.howto.generator.PageResponsibilities import de.timolia.howto.generator.PageTeamMembers import de.timolia.howto.teamler.Teamler import de.timolia.howto.translate.Translate -import java.nio.charset.StandardCharsets import java.nio.file.Files import java.nio.file.Path import java.util.* @@ -18,7 +18,7 @@ import kotlin.jvm.JvmStatic object Dapp { val translate: Translate = Translate() - val gson = GsonBuilder() + val gson: Gson = GsonBuilder() .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) .create() @@ -27,15 +27,16 @@ object Dapp { fun main(args: Array) { val path = Path.of("docs", "team") translate.loadDirectory(path.resolve("translate")) - val json = Files.readString(path.resolve("teamler.json"), StandardCharsets.UTF_8) + val json = Files.readString(path.resolve("teamler.json")) val teamlers = gson.fromJson(json, Array::class.java) - val teamlerList = Arrays.asList(*teamlers) - teamlerList.forEach { obj: Teamler -> obj.updateName() } - val fileWriter = FileWriter(path, translate) - fileWriter.writeFile("changes", PageRankChange.generate(teamlerList)) - fileWriter.writeFile("members", PageTeamMembers.generate(teamlerList)) - fileWriter.writeFile("responsibilities", PageResponsibilities.generate(teamlerList)) - if (args.size == 1 && args[0].equals("init", ignoreCase = true)) { + val teamlerList = listOf(*teamlers) + teamlerList.forEach(Teamler::updateName) + with(FileWriter(path, translate)) { + writeFile("changes", PageRankChange.generate(teamlerList)) + writeFile("members", PageTeamMembers(teamlerList).generate()) + writeFile("responsibilities", PageResponsibilities.generate(teamlerList)) + } + if(args.any { it.equals("init", ignoreCase = true) }) { InitialConversion.convert() } } diff --git a/howto-dapp/src/main/java/de/timolia/howto/conversion/InitialConversion.kt b/howto-dapp/src/main/java/de/timolia/howto/conversion/InitialConversion.kt index b50dae04..8037cf0a 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/conversion/InitialConversion.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/conversion/InitialConversion.kt @@ -2,6 +2,7 @@ package de.timolia.howto.conversion import de.timolia.howto.Dapp import de.timolia.howto.rank.Rank +import de.timolia.howto.rank.TeamlerRankChange import de.timolia.howto.teamler.Sex import de.timolia.howto.teamler.Teamler import java.io.IOException @@ -10,9 +11,8 @@ import java.text.ParseException object InitialConversion { @Throws(IOException::class, ParseException::class) fun convert() { - val teamlers: MutableList = ArrayList() val teamlerRankChanges = JsonBuilder.getTeamlerRankChanges() - teamlerRankChanges.map { obj -> obj.uuid }.sorted().distinct().forEach { uuid -> + val teamlers= teamlerRankChanges.map(TeamlerRankChange::uuid).sorted().distinct().map { uuid -> val rankHistory = LinkedHashMap() teamlerRankChanges .filter { teamlerRankChange -> teamlerRankChange.uuid == uuid } @@ -22,22 +22,24 @@ object InitialConversion { } rankHistory[it.getReadableDate()] = it.rankTo } - val teamler = Teamler(uuid, Sex.undefined, null, null, null, rankHistory) - teamlers.add(teamler) - } - val teamlerResponsibilitiesList = JsonBuilder.getTeamlerResponsibilities() - teamlerResponsibilitiesList.forEach { teamlerResponsibilities -> - val teamler = teamlers.stream() - .filter { teamler1 -> teamler1.uuid == teamlerResponsibilities.uuid } - .findFirst() - .orElseGet { Teamler(teamlerResponsibilities.uuid, Sex.undefined, null, null, null, null) } + Teamler(uuid, Sex.undefined, null, null, null, rankHistory) + }.toList() + JsonBuilder.getTeamlerResponsibilities().forEach { responsibilities -> + val teamler = teamlers.find { teamler1 -> teamler1.uuid == responsibilities.uuid } ?: Teamler ( + uuid = responsibilities.uuid, + sex = Sex.undefined, + responsibilitiesMain = null, + responsibilitiesSecondary = null, + fields = null, + rankHistory = null + ) println("teamler: $teamler") - if (teamlerResponsibilities.hv != null) { - println("teamlerResponsibilities.getHv(): " + teamlerResponsibilities.hv) - teamler.responsibilitiesMain = mutableListOf(*teamlerResponsibilities.hv.split(", ").toTypedArray()) + if (responsibilities.hv != null) { + println("responsibilities.getHv(): " + responsibilities.hv) + teamler.responsibilitiesMain = responsibilities.hv.split(", ") } - if (teamlerResponsibilities.nv != null) { - teamler.responsibilitiesSecondary = mutableListOf(*teamlerResponsibilities.nv.split(", ").toTypedArray()) + if (responsibilities.nv != null) { + teamler.responsibilitiesSecondary = responsibilities.nv.split(", ") } } println(Dapp.gson.toJson(teamlers)) diff --git a/howto-dapp/src/main/java/de/timolia/howto/conversion/JsonBuilder.kt b/howto-dapp/src/main/java/de/timolia/howto/conversion/JsonBuilder.kt index 78d36dfc..c1ab095c 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/conversion/JsonBuilder.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/conversion/JsonBuilder.kt @@ -2,7 +2,6 @@ package de.timolia.howto.conversion import de.timolia.howto.rank.TeamlerRankChange import java.io.IOException -import java.nio.charset.StandardCharsets import java.nio.file.Files import java.nio.file.Path import java.text.ParseException @@ -13,13 +12,13 @@ import kotlin.Throws object JsonBuilder { @Throws(IOException::class, ParseException::class) fun getTeamlerRankChanges(): MutableList { - var content = Files.readString(Path.of("src/main/resources", "changes.md"), StandardCharsets.UTF_8) + var content = Files.readString(Path.of("src/main/resources", "changes.md")) content = Pattern.compile("^([^|]|\\| ------|\\| Spieler).*$", Pattern.MULTILINE).matcher(content).replaceAll("") content = Pattern.compile("(\r\n)+", Pattern.MULTILINE).matcher(content).replaceAll("\n") content = Pattern.compile("[ \t]*\\|[ \t]*", Pattern.MULTILINE).matcher(content).replaceAll("|") content = Pattern.compile("", Pattern.MULTILINE).matcher(content).replaceAll("") content = Pattern.compile("", Pattern.MULTILINE).matcher(content).replaceAll("") - val teamlerRankChanges: MutableList = ArrayList() + val teamlerRankChanges = mutableListOf() val lines: Array = content.split("\n".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() for (i in lines.indices.reversed()) { val line = lines[i]!! @@ -40,11 +39,11 @@ object JsonBuilder { @Throws(IOException::class) fun getTeamlerResponsibilities(): MutableList { - var content = Files.readString(Path.of("src/main/resources", "members.md"), StandardCharsets.UTF_8) + var content = Files.readString(Path.of("src/main/resources", "members.md")) content = Pattern.compile("^(?!-|###).*$", Pattern.MULTILINE).matcher(content).replaceAll("") content = Pattern.compile("^- Rang \\(ingame\\):.*$", Pattern.MULTILINE).matcher(content).replaceAll("") content = Pattern.compile("(\r\n)+", Pattern.MULTILINE).matcher(content).replaceAll("\n") - val teamlerResponsibilitiesList = ArrayList() + val teamlerResponsibilitiesList = mutableListOf() for (s in content.split("###")) { var s = s if (s.isEmpty() || !s.contains("Hauptverantwortlich") && !s.contains("Nebenverantwortlich")) continue diff --git a/howto-dapp/src/main/java/de/timolia/howto/database/SQLApi.kt b/howto-dapp/src/main/java/de/timolia/howto/database/SQLApi.kt index d8aaee6f..daf56cc2 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/database/SQLApi.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/database/SQLApi.kt @@ -10,6 +10,7 @@ object SQLApi { @Volatile private var triedConnect = false + private fun establishConnection(): SqlUserConnection { if (!triedConnect) { synchronized(SQLApi::class.java) { diff --git a/howto-dapp/src/main/java/de/timolia/howto/database/SqlUserConnection.kt b/howto-dapp/src/main/java/de/timolia/howto/database/SqlUserConnection.kt index 3f71c1b4..324aba9b 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/database/SqlUserConnection.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/database/SqlUserConnection.kt @@ -6,6 +6,7 @@ import java.util.* class SqlUserConnection private constructor(private val connection: Connection) { private val usernames: MutableMap = HashMap() private val uuids: MutableMap = HashMap() + fun getUuid(name: String?): UUID? { return usernames.computeIfAbsent(name, ::resolveUniqueId) } diff --git a/howto-dapp/src/main/java/de/timolia/howto/generator/PageRankChange.kt b/howto-dapp/src/main/java/de/timolia/howto/generator/PageRankChange.kt index 04152545..7af16500 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/generator/PageRankChange.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/generator/PageRankChange.kt @@ -6,8 +6,8 @@ import de.timolia.howto.teamler.Teamler import java.util.* object PageRankChange { - fun generate(teamlers: MutableList): String { - val rankChanges = ArrayList() + fun generate(teamlers: List): String { + val rankChanges = arrayListOf() for (teamler in teamlers) { rankChanges.addAll(teamler.getRankChanges(false)) } diff --git a/howto-dapp/src/main/java/de/timolia/howto/generator/PageResponsibilities.kt b/howto-dapp/src/main/java/de/timolia/howto/generator/PageResponsibilities.kt index e6809843..4e5d44fe 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/generator/PageResponsibilities.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/generator/PageResponsibilities.kt @@ -6,10 +6,9 @@ import de.timolia.howto.responsibility.Responsibility import de.timolia.howto.responsibility.ResponsibilityType import de.timolia.howto.translate.Language import java.util.* -import java.util.stream.Collectors object PageResponsibilities { - fun generate(teamlers: MutableList): String { + fun generate(teamlers: List): String { val responsibilities: LinkedHashMap> = object : LinkedHashMap>() { init { put("%page.responsibilities.project-team-orga%", object : LinkedHashMap() { diff --git a/howto-dapp/src/main/java/de/timolia/howto/generator/PageTeamMembers.kt b/howto-dapp/src/main/java/de/timolia/howto/generator/PageTeamMembers.kt index d28b27a7..ad0d36fd 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/generator/PageTeamMembers.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/generator/PageTeamMembers.kt @@ -5,17 +5,18 @@ import de.timolia.howto.teamler.Teamler import java.util.* import java.util.stream.Collectors -object PageTeamMembers { - fun generate(teamlers: MutableList): String { - var teamlers = teamlers - teamlers = teamlers +class PageTeamMembers( + private val teamlers: List, + val sb: StringBuilder = StringBuilder() +) { + fun generate(): String { + val teamlers = teamlers .filter { teamler -> teamler.getRankCurrent().inTeam } - .sortedWith { obj, o -> obj.compare(o) } + .sortedWith(Teamler::compare) .toMutableList() - val ranks = Arrays.stream(Rank.values()).filter { rank -> rank.description != null }.sorted { obj, o -> obj.compare(o) }.collect(Collectors.toList()) - val sb = StringBuilder() + val ranks = Rank.values().filter { rank -> rank.description != null }.sortedWith(Rank::compare).toList() sb.append("%page.members.first-1%").append(teamlers.size).append("%page.members.first-2%\n") - val rankStrings = ranks.map { rank -> "" + rank.male + "" } + val rankStrings = ranks.map { rank -> "${rank.male}" } for (i in rankStrings.indices) { sb.append(rankStrings[i]) if (i < rankStrings.size - 2) { @@ -45,24 +46,23 @@ object PageTeamMembers { .append("\n") .append("### ").append(teamler.getNameForMarkdown()).append("") .append("\n").append("- %page.members.rank-ingame%: ").append(rank.getString(teamler.sex)) - if (teamler.responsibilitiesMain != null) { - sb - .append("\n") - .append("- %page.members.hv%: ").append(teamler.responsibilitiesMain!!.stream().sorted { obj, str -> obj.compareTo(str, ignoreCase = true) }.collect(Collectors.joining(", "))) + teamler.responsibilitiesMain?.let { + appendStringList("page.members.hv", it) } - if (teamler.responsibilitiesSecondary != null) { - sb - .append("\n") - .append("- %page.members.nv%: ").append(teamler.responsibilitiesSecondary!!.stream().sorted { obj, str -> obj.compareTo(str, ignoreCase = true) }.collect(Collectors.joining(", "))) + teamler.responsibilitiesSecondary?.let { + appendStringList("page.members.nv", it) } - if (teamler.fields != null) { - sb - .append("\n") - .append("- %page.members.fields%: ").append(teamler.fields.stream().sorted { obj, str -> obj.compareTo(str, ignoreCase = true) }.collect(Collectors.joining(", "))) + teamler.fields?.let { + appendStringList("page.members.fields", it) } } } sb.append("\n") return sb.toString() } + + private fun appendStringList(name: String, strings: List) { + sb.append("\n").append("- %${name}%: ") + strings.sortedWith { obj, str -> obj.compareTo(str, ignoreCase = true) }.joinTo(sb) + } } diff --git a/howto-dapp/src/main/java/de/timolia/howto/rank/Rank.kt b/howto-dapp/src/main/java/de/timolia/howto/rank/Rank.kt index b600cdec..57772be1 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/rank/Rank.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/rank/Rank.kt @@ -2,7 +2,14 @@ package de.timolia.howto.rank import de.timolia.howto.teamler.Sex -enum class Rank { +enum class Rank( + private val value: Int, + val inTeam: Boolean, + val cssClass: String, + val male: String, + private val female: String?, + val description: String? = null +) { administrator(161, true, "administrator", "Administrator", "Administratorin", "%rank.administrator.description%"), administrator_city(160, true, "administrator", "Administrator City", null), builder(80, true, "builder", "Builder", "Builderin", "%rank.builder.description%"), @@ -35,31 +42,6 @@ enum class Rank { supporter_city_games(100, true, "supporter", "Supporter City & Games", "Supporterin City & Games"), sysadmin(150, true, "sysadmin", "SysAdmin", null); - private val value: Int - val inTeam: Boolean - val male: String - private val female: String? - val cssClass: String - val description: String? - - constructor(value: Int, inTeam: Boolean, cssClass: String, male: String, female: String?) { - this.value = value - this.inTeam = inTeam - this.male = male - this.female = female - this.cssClass = cssClass - description = null - } - - constructor(value: Int, inTeam: Boolean, cssClass: String, male: String, female: String?, description: String?) { - this.value = value - this.inTeam = inTeam - this.male = male - this.female = female - this.cssClass = cssClass - this.description = description - } - fun getString(sex: Sex): String { return if (sex == Sex.female && female != null) { female @@ -71,6 +53,6 @@ enum class Rank { } fun compare(o: Rank): Int { - return Integer.compare(o.value, value) + return o.value.compareTo(value) } } diff --git a/howto-dapp/src/main/java/de/timolia/howto/rank/RankConversion.kt b/howto-dapp/src/main/java/de/timolia/howto/rank/RankConversion.kt index 70cfb5fc..19f3d3a3 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/rank/RankConversion.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/rank/RankConversion.kt @@ -7,7 +7,7 @@ import java.util.stream.Collectors object RankConversion { fun getRank(text: String): Rank? { return Arrays.stream(Rank.values()) - .collect(Collectors.toMap(Function.identity()) { rank -> Math.max(getSimilarity(text, rank.getFemale()), getSimilarity(text, rank.male)) }) + .collect(Collectors.toMap(Function.identity()) { rank -> getSimilarity(text, rank.getFemale()).coerceAtLeast(getSimilarity(text, rank.male)) }) .entries .stream() .max(Comparator.comparingDouble { (_, value) -> value }) @@ -19,7 +19,7 @@ object RankConversion { /** * Calculates the similarity (a number within 0 and 1) between two strings. */ - fun getSimilarity(s1: String, s2: String): Double { + private fun getSimilarity(s1: String, s2: String): Double { var longer = s1 var shorter = s2 if (s1.length < s2.length) { // longer should always have greater length @@ -46,8 +46,7 @@ object RankConversion { if (i == 0) costs[j] = j else { if (j > 0) { var newValue = costs[j - 1] - if (s1[i - 1] != s2[j - 1]) newValue = Math.min(Math.min(newValue, lastValue), - costs[j]) + 1 + if (s1[i - 1] != s2[j - 1]) newValue = newValue.coerceAtMost(lastValue).coerceAtMost(costs[j]) + 1 costs[j - 1] = lastValue lastValue = newValue } diff --git a/howto-dapp/src/main/java/de/timolia/howto/teamler/Teamler.kt b/howto-dapp/src/main/java/de/timolia/howto/teamler/Teamler.kt index d99f0292..236ce63b 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/teamler/Teamler.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/teamler/Teamler.kt @@ -7,20 +7,18 @@ import org.apache.commons.lang3.Validate import java.text.ParseException import java.text.RuleBasedCollator import java.util.* -import java.util.stream.Collectors -import java.util.stream.Stream class Teamler( val uuid: UUID, val sex: Sex, - var responsibilitiesMain: MutableList?, - var responsibilitiesSecondary: MutableList?, - val fields: MutableList?, + var responsibilitiesMain: List?, + var responsibilitiesSecondary: List?, + val fields: List?, private val rankHistory: LinkedHashMap? ) { private var name: String - private val responsibilitiesMainHidden: MutableList? = null - private val responsibilitiesSecondaryHidden: MutableList? = null + private val responsibilitiesMainHidden: List? = null + private val responsibilitiesSecondaryHidden: List? = null @Transient private var rankCurrent: Rank? = null @@ -34,7 +32,7 @@ class Teamler( } fun getRankChanges(includeHidden: Boolean): MutableList { - val rankChanges: MutableList = ArrayList() + val rankChanges = mutableListOf() if (rankHistory.isNullOrEmpty()) { return rankChanges } @@ -46,9 +44,9 @@ class Teamler( .map { s -> s.replace("hidden-", "") } .map { date -> TeamlerRankChange.toDate(date) } .sorted() - for (i in Math.min(1, dates.size - 1) until dates.size) { + for (i in 1.coerceAtMost(dates.size - 1) until dates.size) { var hidden = false - var rankOldKey: String = TeamlerRankChange.toString(dates[Math.max(i - 1, 0)]) + var rankOldKey: String = TeamlerRankChange.toString(dates[(i - 1).coerceAtLeast(0)]) if (!rankHistory.containsKey(rankOldKey) && rankHistory.containsKey("hidden-$rankOldKey")) { rankOldKey = "hidden-$rankOldKey" } @@ -89,25 +87,29 @@ class Teamler( ruleBasedCollator.compare(name.lowercase(Locale.getDefault()), o.name.lowercase(Locale.getDefault())) } catch (e: ParseException) { e.printStackTrace() - throw RuntimeException() + throw RuntimeException(e) } } fun hasResponsibilityMain(responsibility: String?): Boolean { - return hasResponsibility(responsibility, Stream.concat(if (responsibilitiesMain == null) Stream.empty() else responsibilitiesMain!!.stream(), responsibilitiesMainHidden?.stream() - ?: Stream.empty()).collect(Collectors.toList())) + return hasResponsibility( + responsibility, + (responsibilitiesMain ?: emptyList()) + (responsibilitiesMainHidden ?: emptyList()) + ) } fun hasResponsibilitySecondary(responsibility: String?): Boolean { - return hasResponsibility(responsibility, Stream.concat(if (responsibilitiesSecondary == null) Stream.empty() else responsibilitiesSecondary!!.stream(), responsibilitiesSecondaryHidden?.stream() - ?: Stream.empty()).collect(Collectors.toList())) + return hasResponsibility( + responsibility, + (responsibilitiesSecondary ?: emptyList()) + (responsibilitiesSecondaryHidden ?: emptyList()) + ) } - private fun hasResponsibility(responsibility: String?, responsibilityList: MutableList?): Boolean { - if (!getRankCurrent().inTeam && responsibilityList!!.isNotEmpty()) { + private fun hasResponsibility(responsibility: String?, responsibilityList: List): Boolean { + if (!getRankCurrent().inTeam && responsibilityList.isNotEmpty()) { throw RuntimeException("'$name' has responsibilities but is not in team anymore") } - return responsibilityList != null && (responsibilityList.contains(responsibility) || responsibilityList.contains("$responsibility Forum")) + return responsibilityList.contains(responsibility) || responsibilityList.contains("$responsibility Forum") } fun updateName() { diff --git a/howto-dapp/src/main/java/de/timolia/howto/translate/Language.kt b/howto-dapp/src/main/java/de/timolia/howto/translate/Language.kt index dc9e28f0..e8b21b34 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/translate/Language.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/translate/Language.kt @@ -4,7 +4,5 @@ enum class Language { DE, EN; - fun key(): String { - return name.lowercase() - } + fun key() = name.lowercase() } diff --git a/howto-dapp/src/main/java/de/timolia/howto/translate/Translate.kt b/howto-dapp/src/main/java/de/timolia/howto/translate/Translate.kt index 6920e14b..1aa2a4e7 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/translate/Translate.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/translate/Translate.kt @@ -2,11 +2,9 @@ package de.timolia.howto.translate import java.io.IOException import java.io.UncheckedIOException -import java.nio.charset.StandardCharsets import java.nio.file.Files import java.nio.file.Path import java.util.* -import java.util.stream.Collectors import kotlin.Throws import kotlin.io.path.extension import kotlin.io.path.nameWithoutExtension @@ -33,7 +31,7 @@ class Translate { val language = Language.valueOf(languageName.uppercase()) println(languageName) val properties = Properties() - properties.load(Files.newBufferedReader(path, StandardCharsets.UTF_8)) + properties.load(Files.newBufferedReader(path)) translations[language] = properties.entries .map { property -> Translation(language, property.key.toString(), property.value.toString()) } .toMutableList() diff --git a/howto-dapp/src/main/java/de/timolia/howto/translate/Translation.kt b/howto-dapp/src/main/java/de/timolia/howto/translate/Translation.kt index a400eb59..75c4d2bd 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/translate/Translation.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/translate/Translation.kt @@ -1,13 +1,9 @@ package de.timolia.howto.translate class Translation(private val language: Language, private val key: String, private val value: String) { - fun replace(text: String): String { - return text.replace(replacementKey(), value) - } + fun replace(text: String) = text.replace(replacementKey(), value) - private fun replacementKey(): String { - return "%$key%" - } + private fun replacementKey() = "%$key%" override fun toString(): String { return "LanguageString{" + From 372263fdb6e21af6255614ed8f6b2d1e4ff36f6a Mon Sep 17 00:00:00 2001 From: David Scandurra Date: Thu, 25 May 2023 23:18:10 +0200 Subject: [PATCH 6/8] use more kotlin features --- .../howto/conversion/InitialConversion.kt | 2 +- .../timolia/howto/conversion/JsonBuilder.kt | 68 ++++++++----------- .../howto/generator/PageResponsibilities.kt | 2 +- .../java/de/timolia/howto/teamler/Teamler.kt | 4 +- 4 files changed, 31 insertions(+), 45 deletions(-) diff --git a/howto-dapp/src/main/java/de/timolia/howto/conversion/InitialConversion.kt b/howto-dapp/src/main/java/de/timolia/howto/conversion/InitialConversion.kt index 8037cf0a..d962d7f1 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/conversion/InitialConversion.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/conversion/InitialConversion.kt @@ -12,7 +12,7 @@ object InitialConversion { @Throws(IOException::class, ParseException::class) fun convert() { val teamlerRankChanges = JsonBuilder.getTeamlerRankChanges() - val teamlers= teamlerRankChanges.map(TeamlerRankChange::uuid).sorted().distinct().map { uuid -> + val teamlers = teamlerRankChanges.asSequence().map(TeamlerRankChange::uuid).sorted().distinct().map { uuid -> val rankHistory = LinkedHashMap() teamlerRankChanges .filter { teamlerRankChange -> teamlerRankChange.uuid == uuid } diff --git a/howto-dapp/src/main/java/de/timolia/howto/conversion/JsonBuilder.kt b/howto-dapp/src/main/java/de/timolia/howto/conversion/JsonBuilder.kt index c1ab095c..3810083f 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/conversion/JsonBuilder.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/conversion/JsonBuilder.kt @@ -11,61 +11,49 @@ import kotlin.Throws object JsonBuilder { @Throws(IOException::class, ParseException::class) - fun getTeamlerRankChanges(): MutableList { + fun getTeamlerRankChanges(): List { var content = Files.readString(Path.of("src/main/resources", "changes.md")) content = Pattern.compile("^([^|]|\\| ------|\\| Spieler).*$", Pattern.MULTILINE).matcher(content).replaceAll("") content = Pattern.compile("(\r\n)+", Pattern.MULTILINE).matcher(content).replaceAll("\n") content = Pattern.compile("[ \t]*\\|[ \t]*", Pattern.MULTILINE).matcher(content).replaceAll("|") content = Pattern.compile("", Pattern.MULTILINE).matcher(content).replaceAll("") content = Pattern.compile("", Pattern.MULTILINE).matcher(content).replaceAll("") - val teamlerRankChanges = mutableListOf() - val lines: Array = content.split("\n".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() - for (i in lines.indices.reversed()) { - val line = lines[i]!! - if (line.isEmpty()) { - continue - } - val split: List = line.split("|") - val name: String = split[1].replace("\\", "") - val rankFrom = split[2] - val rankTo = split[3] - val date = split[4] + return content.split("\n").reversed().filter(String::isNotEmpty).map { + var (_, name, rankFrom, rankTo, date) = it.split("|") + name = name.replace("\\", "") val teamlerRankChange = TeamlerRankChange(name, rankFrom, rankTo, date) - teamlerRankChanges.add(teamlerRankChange) println(teamlerRankChange) + teamlerRankChange } - return teamlerRankChanges } @Throws(IOException::class) - fun getTeamlerResponsibilities(): MutableList { + fun getTeamlerResponsibilities(): Iterable { var content = Files.readString(Path.of("src/main/resources", "members.md")) content = Pattern.compile("^(?!-|###).*$", Pattern.MULTILINE).matcher(content).replaceAll("") content = Pattern.compile("^- Rang \\(ingame\\):.*$", Pattern.MULTILINE).matcher(content).replaceAll("") content = Pattern.compile("(\r\n)+", Pattern.MULTILINE).matcher(content).replaceAll("\n") - val teamlerResponsibilitiesList = mutableListOf() - for (s in content.split("###")) { - var s = s - if (s.isEmpty() || !s.contains("Hauptverantwortlich") && !s.contains("Nebenverantwortlich")) continue - s = s.substring(s.indexOf("'") + 1) - s = s.substring(s.indexOf("'") + 2) - val name: String = s.substring(0, s.indexOf("<")).replace("\\\\_".toRegex(), "_") - var hv: String? = null - var nv: String? = null - s = s.substring(s.indexOf("-")) - if (s.contains("Hauptverantwortlich")) { - hv = s.substring(s.indexOf("Hauptverantwortlich") + "Hauptverantwortlich".length + 6, s.indexOf("\n")) - s = s.substring(s.indexOf("Hauptverantwortlich") + "Hauptverantwortlich\n".length + 6 + hv.length) - } - if (s.contains("Nebenverantwortlich")) { - nv = s.substring(s.indexOf("Nebenverantwortlich") + "Nebenverantwortlich".length + 6, s.indexOf("\n")) - } - println("name: $name") - println("hv: $hv") - println("nv: $nv") - val teamlerResponsibilities = TeamlerResponsibilities(name, hv, nv) - teamlerResponsibilitiesList.add(teamlerResponsibilities) - } - return teamlerResponsibilitiesList + return content.split("###") + .filter { it.contains("Hauptverantwortlich") || it.contains("Nebenverantwortlich") } + .map {s -> + var s = s + s = s.substring(s.indexOf("'") + 1) + s = s.substring(s.indexOf("'") + 2) + val name: String = s.substring(0, s.indexOf("<")).replace("\\\\_".toRegex(), "_") + var hv: String? = null + var nv: String? = null + s = s.substring(s.indexOf("-")) + if (s.contains("Hauptverantwortlich")) { + hv = s.substring(s.indexOf("Hauptverantwortlich") + "Hauptverantwortlich".length + 6, s.indexOf("\n")) + s = s.substring(s.indexOf("Hauptverantwortlich") + "Hauptverantwortlich\n".length + 6 + hv.length) + } + if (s.contains("Nebenverantwortlich")) { + nv = s.substring(s.indexOf("Nebenverantwortlich") + "Nebenverantwortlich".length + 6, s.indexOf("\n")) + } + println("name: $name") + println("hv: $hv") + println("nv: $nv") + TeamlerResponsibilities(name, hv, nv) + } } } diff --git a/howto-dapp/src/main/java/de/timolia/howto/generator/PageResponsibilities.kt b/howto-dapp/src/main/java/de/timolia/howto/generator/PageResponsibilities.kt index 4e5d44fe..fa0769f4 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/generator/PageResponsibilities.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/generator/PageResponsibilities.kt @@ -118,7 +118,7 @@ object PageResponsibilities { hvEntry.renderTo(sb) } if (nv.isNotEmpty() || !nvCustom.isEmpty()) { - sb.append("\n").append("| | |") + sb.append("\n") if (nvCustom.isEmpty()) { for (teamler in nv) { hvCustom.add(Responsibility.concreteTeamster(ResponsibilityType.NV, teamler)) diff --git a/howto-dapp/src/main/java/de/timolia/howto/teamler/Teamler.kt b/howto-dapp/src/main/java/de/timolia/howto/teamler/Teamler.kt index 236ce63b..c62f0a50 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/teamler/Teamler.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/teamler/Teamler.kt @@ -27,9 +27,7 @@ class Teamler( name = SQLApi.getName(uuid)!! } - fun getNameForMarkdown(): String { - return name.replace("_", "\\\\_") - } + fun getNameForMarkdown() = name.replace("_", "\\_") fun getRankChanges(includeHidden: Boolean): MutableList { val rankChanges = mutableListOf() From e32ded139ca05c999e60cac060fc1f2a8aab0a62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lennart=20L=C3=B6sche?= Date: Thu, 6 Jul 2023 08:54:42 +0200 Subject: [PATCH 7/8] add youtuber rank again to kt file --- howto-dapp/src/main/java/de/timolia/howto/rank/Rank.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/howto-dapp/src/main/java/de/timolia/howto/rank/Rank.kt b/howto-dapp/src/main/java/de/timolia/howto/rank/Rank.kt index 57772be1..1b42f83f 100644 --- a/howto-dapp/src/main/java/de/timolia/howto/rank/Rank.kt +++ b/howto-dapp/src/main/java/de/timolia/howto/rank/Rank.kt @@ -32,6 +32,7 @@ enum class Rank( native_mvp(35, false, "mvp", "Native MVP", null), native_mvp_plus(45, false, "mvp", "Native MVP+", null), native_youtuber(60, false, "youtuber", "Native YouTuber", null), + youtuber(59, false, "youtuber", "YouTuber", null), pro(10, false, "pro", "Pro", null), pro_plus(20, false, "pro", "Pro+", null), spieler(0, false, "user", "Spieler", "Spielerin"), From 0f39efda6ee3b774e225090e247bca0598f4e8b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lennart=20L=C3=B6sche?= Date: Thu, 6 Jul 2023 08:55:31 +0200 Subject: [PATCH 8/8] java17 + update gradle to 8.1.1 --- howto-dapp/build.gradle | 2 +- howto-dapp/gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/howto-dapp/build.gradle b/howto-dapp/build.gradle index b733ec94..6ad834da 100644 --- a/howto-dapp/build.gradle +++ b/howto-dapp/build.gradle @@ -27,5 +27,5 @@ jar { } } kotlin { - jvmToolchain(11) + jvmToolchain(17) } \ No newline at end of file diff --git a/howto-dapp/gradle/wrapper/gradle-wrapper.properties b/howto-dapp/gradle/wrapper/gradle-wrapper.properties index afef0da9..8f5ef1a1 100644 --- a/howto-dapp/gradle/wrapper/gradle-wrapper.properties +++ b/howto-dapp/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists \ No newline at end of file