From fb8395b6e3e30d2f133b4743c28ccd16bc5affd5 Mon Sep 17 00:00:00 2001 From: dmitry-weirdo Date: Thu, 21 Nov 2024 01:29:24 +0100 Subject: [PATCH 01/30] feat: #81 Start including the latest kotling in the pom.xml or kgstatsSrv. --- kgstatsSrv/pom.xml | 99 +++++++++++++++++++++++++++++++++++++++++++++- pom.xml | 21 +++++++++- 2 files changed, 117 insertions(+), 3 deletions(-) diff --git a/kgstatsSrv/pom.xml b/kgstatsSrv/pom.xml index 66906ff8d..bd229282f 100644 --- a/kgstatsSrv/pom.xml +++ b/kgstatsSrv/pom.xml @@ -149,11 +149,74 @@ - + + + org.jetbrains.kotlin + kotlin-maven-plugin + ${kotlin.version} + true + + + compile + + compile + + + + ${project.basedir}/src/main/kotlin + ${project.basedir}/src/main/java + + + + + test-compile + + test-compile + + + + ${project.basedir}/src/test/kotlin + ${project.basedir}/src/test/java + + + + + org.apache.maven.plugins maven-compiler-plugin ${maven-compiler-plugin.version} + + + + default-compile + none + + + + default-testCompile + none + + + java-compile + compile + + compile + + + + java-test-compile + test-compile + + testCompile + + + + + ${java.version} ${java.version} @@ -178,7 +241,41 @@ + + + + + diff --git a/pom.xml b/pom.xml index b851a0737..fec4a7d9b 100644 --- a/pom.xml +++ b/pom.xml @@ -17,6 +17,7 @@ 17 + 2.0.21 1.4.1.Final 1.18.34 0.2.0 @@ -41,7 +42,7 @@ 3.5.2 2.2.1 3.4.0 - 2.9.1 + 3.11.1 3.2.4 5.0.0 3.6.0 @@ -158,9 +159,25 @@ - + + + + + + org.jetbrains.kotlin + kotlin-stdlib + ${kotlin.version} + + + + org.jetbrains.kotlin + kotlin-reflect + ${kotlin.version} + + + From 4922d7dee1faa845bed1541fbdc22a2e4087236f Mon Sep 17 00:00:00 2001 From: dmitry-weirdo Date: Thu, 21 Nov 2024 02:16:28 +0100 Subject: [PATCH 02/30] feat: #81 Convert StatisticsGeneratorConfig to a simple Kotlin data class. Statistics generation is working locally. --- .../export/StatisticsGenerator.java | 42 ++++----- .../export/StatisticsGeneratorConfig.java | 47 ---------- .../export/StatisticsGeneratorConfig.kt | 37 ++++++++ .../resources/application.actions.properties | 5 +- run-statistics-copy-static-files.sh | 86 +++++++++++++++++++ run-statistics-process-my-windows-set-env.sh | 3 +- 6 files changed, 149 insertions(+), 71 deletions(-) delete mode 100644 kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/StatisticsGeneratorConfig.java create mode 100644 kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/export/StatisticsGeneratorConfig.kt create mode 100644 run-statistics-copy-static-files.sh diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/StatisticsGenerator.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/StatisticsGenerator.java index f52aaaadb..bea369c52 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/StatisticsGenerator.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/StatisticsGenerator.java @@ -120,31 +120,31 @@ public void generateStatistics(final Config config, final StatisticsGeneratorCon logger.debug("{}: {}", StatisticsGeneratorConfig.class.getSimpleName(), generatorConfig); // global tops exporters - export(context, generatorConfig.isExportIndexPage(), indexPageExporter); - export(context, generatorConfig.isExportTopBySpeed(), topBySpeedExporter); - export(context, generatorConfig.isExportTop500Pages(), top500PagesExporter); - export(context, generatorConfig.isExportPlayersByRank(), playersByRankExporter); + export(context, generatorConfig.getExportIndexPage(), indexPageExporter); + export(context, generatorConfig.getExportTopBySpeed(), topBySpeedExporter); + export(context, generatorConfig.getExportTop500Pages(), top500PagesExporter); + export(context, generatorConfig.getExportPlayersByRank(), playersByRankExporter); // standard vocabularies exporters - export(context, generatorConfig.isExportNormalTop(), normalTopExporter); - export(context, generatorConfig.isExportAbraTop(), abraTopExporter); - export(context, generatorConfig.isExportReferatsTop(), referatsTopExporter); - export(context, generatorConfig.isExportNoErrorTop(), noErrorTopExporter); - export(context, generatorConfig.isExportMarathonTop(), marathonTopExporter); - export(context, generatorConfig.isExportCharsTop(), charsTopExporter); - export(context, generatorConfig.isExportDigitsTop(), digitsTopExporter); - export(context, generatorConfig.isExportSprintTop(), sprintTopExporter); + export(context, generatorConfig.getExportNormalTop(), normalTopExporter); + export(context, generatorConfig.getExportAbraTop(), abraTopExporter); + export(context, generatorConfig.getExportReferatsTop(), referatsTopExporter); + export(context, generatorConfig.getExportNoErrorTop(), noErrorTopExporter); + export(context, generatorConfig.getExportMarathonTop(), marathonTopExporter); + export(context, generatorConfig.getExportCharsTop(), charsTopExporter); + export(context, generatorConfig.getExportDigitsTop(), digitsTopExporter); + export(context, generatorConfig.getExportSprintTop(), sprintTopExporter); // non-standard vocabularies exporters - export(context, generatorConfig.isExportNormalInEnglishTop(), normalInEnglishTopExporter); - export(context, generatorConfig.isExportMiniMarathonTop(), miniMarathonTopExporter); - export(context, generatorConfig.isExportShortTextsTop(), shortTextsTopExporter); - export(context, generatorConfig.isExportFrequencyVocabularyTop(), frequencyVocabularyTopExporter); - export(context, generatorConfig.isExportOneHundredRussianTop(), oneHundredRussianTopExporter); - export(context, generatorConfig.isExportDigitsOneHundredTop(), digitsOneHundredTopExporter); - export(context, generatorConfig.isExportTrainingIndexFingersTop(), trainingIndexFingersTopExporter); - export(context, generatorConfig.isExportRingFingersTop(), ringFingersTopExporter); - export(context, generatorConfig.isExportPinkiesPlusTop(), pinkiesPlusTopExporter); + export(context, generatorConfig.getExportNormalInEnglishTop(), normalInEnglishTopExporter); + export(context, generatorConfig.getExportMiniMarathonTop(), miniMarathonTopExporter); + export(context, generatorConfig.getExportShortTextsTop(), shortTextsTopExporter); + export(context, generatorConfig.getExportFrequencyVocabularyTop(), frequencyVocabularyTopExporter); + export(context, generatorConfig.getExportOneHundredRussianTop(), oneHundredRussianTopExporter); + export(context, generatorConfig.getExportDigitsOneHundredTop(), digitsOneHundredTopExporter); + export(context, generatorConfig.getExportTrainingIndexFingersTop(), trainingIndexFingersTopExporter); + export(context, generatorConfig.getExportRingFingersTop(), ringFingersTopExporter); + export(context, generatorConfig.getExportPinkiesPlusTop(), pinkiesPlusTopExporter); } // todo: think about moving StatisticsGeneratorConfig field determination to Exporter interface diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/StatisticsGeneratorConfig.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/StatisticsGeneratorConfig.java deleted file mode 100644 index 665a0446b..000000000 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/StatisticsGeneratorConfig.java +++ /dev/null @@ -1,47 +0,0 @@ -package ru.klavogonki.statistics.export; - -import lombok.Data; - -/** - *

- * Конфиг, настраивающий генерацию словарей. - *

- * - *

- * todo: по факту, в конфиг можно перенести настройки, которые сейчас реализуют классы, - * реализующие VocabularyTopExporter. - *

- */ -@Data -public class StatisticsGeneratorConfig { - - // aggregate tops - private boolean exportIndexPage; - - private boolean exportTopBySpeed; // old exporter, not by normal vocabulary - - private boolean exportTop500Pages; - - private boolean exportPlayersByRank; - - // standard vocabularies - private boolean exportNormalTop; - private boolean exportAbraTop; - private boolean exportReferatsTop; - private boolean exportNoErrorTop; - private boolean exportMarathonTop; - private boolean exportCharsTop; - private boolean exportDigitsTop; - private boolean exportSprintTop; - - // non-standard vocabularies - private boolean exportNormalInEnglishTop; - private boolean exportMiniMarathonTop; - private boolean exportShortTextsTop; - private boolean exportFrequencyVocabularyTop; - private boolean exportOneHundredRussianTop; - private boolean exportDigitsOneHundredTop; - private boolean exportTrainingIndexFingersTop; - private boolean exportRingFingersTop; - private boolean exportPinkiesPlusTop; -} diff --git a/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/export/StatisticsGeneratorConfig.kt b/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/export/StatisticsGeneratorConfig.kt new file mode 100644 index 000000000..1e56fc900 --- /dev/null +++ b/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/export/StatisticsGeneratorConfig.kt @@ -0,0 +1,37 @@ +package ru.klavogonki.statistics.export + +/** + * Конфиг, настраивающий генерацию словарей. + * + * todo: по факту, в конфиг можно перенести настройки, которые сейчас реализуют классы, + * реализующие [ru.klavogonki.statistics.export.vocabulary.VocabularyTopExporter]. + */ +data class StatisticsGeneratorConfig( + // aggregate tops + val exportIndexPage: Boolean = false, + + val exportTopBySpeed: Boolean = false, // old exporter, not by normal vocabulary + val exportTop500Pages: Boolean = false, + val exportPlayersByRank: Boolean = false, + + // standard vocabularies + val exportNormalTop: Boolean = false, + val exportAbraTop: Boolean = false, + val exportReferatsTop: Boolean = false, + val exportNoErrorTop: Boolean = false, + val exportMarathonTop: Boolean = false, + val exportCharsTop: Boolean = false, + val exportDigitsTop: Boolean = false, + val exportSprintTop: Boolean = false, + + // non-standard vocabularies + val exportNormalInEnglishTop: Boolean = false, + val exportMiniMarathonTop: Boolean = false, + val exportShortTextsTop: Boolean = false, + val exportFrequencyVocabularyTop: Boolean = false, + val exportOneHundredRussianTop: Boolean = false, + val exportDigitsOneHundredTop: Boolean = false, + val exportTrainingIndexFingersTop: Boolean = false, + val exportRingFingersTop: Boolean = false, + val exportPinkiesPlusTop: Boolean = false +) \ No newline at end of file diff --git a/kgstatsSrv/src/main/resources/application.actions.properties b/kgstatsSrv/src/main/resources/application.actions.properties index d1224968f..9f2151b6f 100644 --- a/kgstatsSrv/src/main/resources/application.actions.properties +++ b/kgstatsSrv/src/main/resources/application.actions.properties @@ -1,7 +1,9 @@ spring.datasource.continue-on-error=true spring.jpa.hibernate.ddl-auto=update -spring.datasource.url=jdbc:mysql://localhost:3306/actions?serverTimezone=UTC&rewriteBatchedStatements=true&profileSQL=false&useUnicode=yes&characterEncoding=UTF-8 +#spring.datasource.url=jdbc:mysql://localhost:3306/actions?serverTimezone=UTC&rewriteBatchedStatements=true&profileSQL=false&useUnicode=yes&characterEncoding=UTF-8 +spring.datasource.url=jdbc:mysql://localhost:3306/kgparser-2024.11.11?serverTimezone=UTC&rewriteBatchedStatements=true&profileSQL=false&useUnicode=yes&characterEncoding=UTF-8 + spring.datasource.username=root spring.datasource.password=root @@ -15,4 +17,3 @@ spring.jpa.properties.hibernate.generate_statistics=false # log sql statements by Hibernate spring.jpa.show-sql=false spring.jpa.properties.hibernate.format_sql=true - diff --git a/run-statistics-copy-static-files.sh b/run-statistics-copy-static-files.sh new file mode 100644 index 000000000..28b41f5f1 --- /dev/null +++ b/run-statistics-copy-static-files.sh @@ -0,0 +1,86 @@ +echo "Arguments: " +echo "" + +echo "Environment variables values: " +echo "ROOT_WORKING_DIR: $ROOT_WORKING_DIR" +echo "LOG4J_XML_FILE_PATH: $LOG4J_XML_FILE_PATH" +echo "KGSTATS_SRV_JAR_FILE_PATH: $KGSTATS_SRV_JAR_FILE_PATH" +echo "KGSTATS_SRV_SQL_DIR: $KGSTATS_SRV_SQL_DIR" +echo "KGSTATS_WEB_ROOT_DIR: $KGSTATS_WEB_ROOT_DIR" +echo "SPRING_CONFIG_LOCATION: $SPRING_CONFIG_LOCATION" +echo "GENERATE_STATISTICS_CONFIG_LOCATION: $GENERATE_STATISTICS_CONFIG_LOCATION" +echo "DATABASE_USER: $DATABASE_USER" +echo "DATABASE_PASSWORD: $DATABASE_PASSWORD" +echo "DATABASE_NAME: $DATABASE_NAME" +echo "" + +# declare required variables +# todo: set defaults, see https://stackoverflow.com/a/2013589/8534088 +# todo: we should be able to override them from the command line +#ROOT_WORKING_DIR=/d/kg/ + +#LOG4J_XML_FILE_PATH=log4j2.xml + +#KGSTATS_SRV_JAR_FILE_PATH=kgstatsSrv/target/kgstats-srv-1.0.jar +# todo: maybe take kgstatsSrv statics from target? +#KGSTATS_SRV_SQL_DIR=kgstatsSrv/src/main/resources/sql +# todo: maybe take kgstatsWeb statics from target? +#KGSTATS_WEB_ROOT_DIR=kgstatsWeb/src/main/webapp +#SPRING_CONFIG_LOCATION=kgstatsSrv/src/main/resources/application.actions.properties + +#DATABASE_USER=root +#DATABASE_PASSWORD=root +#DATABASE_NAME=actions + +DATABASE_DUMP_FILE_NAME=database.sql +DATABASE_DUMP_FILE_PATH=$ROOT_WORKING_DIR/$DATABASE_DUMP_FILE_NAME + +JSON_FILES_DIRECTORY_NAME=/json +JSON_FILES_DIRECTORY_PATH=$ROOT_WORKING_DIR/$JSON_FILES_DIRECTORY_NAME + +INPUT_CONFIG_FILE_NAME=config.json +INPUT_CONFIG_FILE_PATH=$ROOT_WORKING_DIR/$INPUT_CONFIG_FILE_NAME + +OUTPUT_CONFIG_FILE_NAME=config-output.json +OUTPUT_CONFIG_FILE_PATH=$ROOT_WORKING_DIR/$OUTPUT_CONFIG_FILE_NAME + +GENERATE_STATISTICS_DIRECTORY_NAME=/stats +GENERATE_STATISTICS_DIRECTORY_PATH=$ROOT_WORKING_DIR/$GENERATE_STATISTICS_DIRECTORY_NAME +STATIC_DIR=$GENERATE_STATISTICS_DIRECTORY_PATH + +# zip files +JSON_DATA_ZIP_FILE_NAME=json.zip +STATISTICS_ZIP_FILE_NAME=statistics.zip +DATABASE_DUMP_ZIP_FILE_NAME=database.zip + +# s3 buckets +S3_BUCKET_TEST=klavostat-test +S3_BUCKET_DATA=klavostat-data + +# create config json file from input arguments +# todo: add input arguments validation, although it will already work in SpringBoot app +MIN_PLAYER_ID=$1 +MAX_PLAYER_ID=$2 +THREADS_COUNT=$3 + +# copy static files from sources of kgstatsWeb to generated statistics +cp -R $KGSTATS_WEB_ROOT_DIR/css $STATIC_DIR +cp -R $KGSTATS_WEB_ROOT_DIR/img $STATIC_DIR + +# make sure /js is a directory +mkdir -p "$STATIC_DIR/js" + +# make sure /xlsx is a directory +mkdir -p "$STATIC_DIR/xlsx" + +# todo: after we exclude the generated files from sources, copy js recursively + +# cp -R $KGSTATS_WEB_ROOT_DIR/js $STATIC_DIR +cp "$KGSTATS_WEB_ROOT_DIR/js/players-by-rank-chart.js" "$STATIC_DIR/js" +cp "$KGSTATS_WEB_ROOT_DIR/js/stats-data.js" "$STATIC_DIR/js" +cp "$KGSTATS_WEB_ROOT_DIR/js/stats-top-table.js" "$STATIC_DIR/js" + +# todo: old tops must be copied from archive S3 buckets, not from sources +cp -R $KGSTATS_WEB_ROOT_DIR/2020-12-09 $STATIC_DIR + +echo "Copied static files from $KGSTATS_WEB_ROOT_DIR to $STATIC_DIR." diff --git a/run-statistics-process-my-windows-set-env.sh b/run-statistics-process-my-windows-set-env.sh index 026a9a5ad..603ab9d79 100755 --- a/run-statistics-process-my-windows-set-env.sh +++ b/run-statistics-process-my-windows-set-env.sh @@ -1,4 +1,5 @@ -export ROOT_WORKING_DIR=/d/kg/ +#export ROOT_WORKING_DIR=/d/kg/ +export ROOT_WORKING_DIR=/c/kg/2024.11.11 export LOG4J_XML_FILE_PATH=./log4j2.xml From fbd0e592033705a2a68226edba7f1af594924b25 Mon Sep 17 00:00:00 2001 From: dmitry-weirdo Date: Thu, 21 Nov 2024 02:32:52 +0100 Subject: [PATCH 03/30] feat: #81 Migrate StatisticsGenerator to Kotlin. --- .../export/StatisticsGenerator.java | 174 ----------------- .../statistics/export/StatisticsGenerator.kt | 176 ++++++++++++++++++ pom.xml | 10 + 3 files changed, 186 insertions(+), 174 deletions(-) delete mode 100644 kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/StatisticsGenerator.java create mode 100644 kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/export/StatisticsGenerator.kt diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/StatisticsGenerator.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/StatisticsGenerator.java deleted file mode 100644 index bea369c52..000000000 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/StatisticsGenerator.java +++ /dev/null @@ -1,174 +0,0 @@ -package ru.klavogonki.statistics.export; - -import lombok.extern.log4j.Log4j2; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Profile; -import org.springframework.stereotype.Component; -import ru.klavogonki.statistics.Config; -import ru.klavogonki.statistics.export.vocabulary.non_standard.DigitsOneHundredTopExporter; -import ru.klavogonki.statistics.export.vocabulary.non_standard.FrequencyVocabularyTopExporter; -import ru.klavogonki.statistics.export.vocabulary.non_standard.MiniMarathonTopExporter; -import ru.klavogonki.statistics.export.vocabulary.non_standard.NormalInEnglishTopExporter; -import ru.klavogonki.statistics.export.vocabulary.non_standard.OneHundredRussianTopExporter; -import ru.klavogonki.statistics.export.vocabulary.non_standard.PinkiesPlusTopExporter; -import ru.klavogonki.statistics.export.vocabulary.non_standard.RingFingersTopExporter; -import ru.klavogonki.statistics.export.vocabulary.non_standard.ShortTextsTopExporter; -import ru.klavogonki.statistics.export.vocabulary.non_standard.TrainingIndexFingersTopExporter; -import ru.klavogonki.statistics.export.vocabulary.standard.AbraTopExporter; -import ru.klavogonki.statistics.export.vocabulary.standard.CharsTopExporter; -import ru.klavogonki.statistics.export.vocabulary.standard.DigitsTopExporter; -import ru.klavogonki.statistics.export.vocabulary.standard.MarathonTopExporter; -import ru.klavogonki.statistics.export.vocabulary.standard.NoErrorTopExporter; -import ru.klavogonki.statistics.export.vocabulary.standard.NormalTopExporter; -import ru.klavogonki.statistics.export.vocabulary.standard.ReferatsTopExporter; -import ru.klavogonki.statistics.export.vocabulary.standard.SprintTopExporter; -import ru.klavogonki.statistics.springboot.Profiles; - -@Component -@Profile(Profiles.DATABASE) -@Log4j2 -public class StatisticsGenerator { - - // aggregate tops - @Autowired - private IndexPageExporter indexPageExporter; - - @Autowired - private TopBySpeedExporter topBySpeedExporter; - - @Autowired - private Top500PagesExporter top500PagesExporter; - - @Autowired - private PlayersByRankExporter playersByRankExporter; - - // standard vocabularies - @Autowired - private NormalTopExporter normalTopExporter; - - @Autowired - private AbraTopExporter abraTopExporter; - - @Autowired - private ReferatsTopExporter referatsTopExporter; - - @Autowired - private NoErrorTopExporter noErrorTopExporter; - - @Autowired - private MarathonTopExporter marathonTopExporter; - - @Autowired - private CharsTopExporter charsTopExporter; - - @Autowired - private DigitsTopExporter digitsTopExporter; - - @Autowired - private SprintTopExporter sprintTopExporter; - - // non-standard vocabularies - @Autowired - private NormalInEnglishTopExporter normalInEnglishTopExporter; - - @Autowired - private MiniMarathonTopExporter miniMarathonTopExporter; - - @Autowired - private ShortTextsTopExporter shortTextsTopExporter; - - @Autowired - private FrequencyVocabularyTopExporter frequencyVocabularyTopExporter; - - @Autowired - private OneHundredRussianTopExporter oneHundredRussianTopExporter; - - @Autowired - private DigitsOneHundredTopExporter digitsOneHundredTopExporter; - - @Autowired - private TrainingIndexFingersTopExporter trainingIndexFingersTopExporter; - - @Autowired - private RingFingersTopExporter ringFingersTopExporter; - - @Autowired - private PinkiesPlusTopExporter pinkiesPlusTopExporter; - - public void generateStatistics(final Config config, final StatisticsGeneratorConfig generatorConfig) { - ExportContext context = new ExportContext(config); -/* - context.webRootDir = "C:/java/kgparser/kgstats/src/main/webapp/"; - - // data load from 2020-12-28 - context.minPlayerId = 1; - context.maxPlayerId = 628000; - context.dataDownloadStartDate = DateUtils.parseLocalDateTimeWithUiDateFormat("2020-12-28 00:28:13"); - context.dataDownloadEndDate = DateUtils.parseLocalDateTimeWithUiDateFormat("2020-12-28 01:44:43"); -*/ - -/* - // data load from 2020-12-09 - context.minPlayerId = 1; - context.maxPlayerId = 625000; - context.dataDownloadStartDate = DateUtils.parseLocalDateTimeWithUiDateFormat("2020-12-08 02:39:07"); - context.dataDownloadEndDate = DateUtils.parseLocalDateTimeWithUiDateFormat("2020-12-09 16:28:01"); -*/ - - // todo: add an option to skip Excel import - - logger.debug("{}: {}", StatisticsGeneratorConfig.class.getSimpleName(), generatorConfig); - - // global tops exporters - export(context, generatorConfig.getExportIndexPage(), indexPageExporter); - export(context, generatorConfig.getExportTopBySpeed(), topBySpeedExporter); - export(context, generatorConfig.getExportTop500Pages(), top500PagesExporter); - export(context, generatorConfig.getExportPlayersByRank(), playersByRankExporter); - - // standard vocabularies exporters - export(context, generatorConfig.getExportNormalTop(), normalTopExporter); - export(context, generatorConfig.getExportAbraTop(), abraTopExporter); - export(context, generatorConfig.getExportReferatsTop(), referatsTopExporter); - export(context, generatorConfig.getExportNoErrorTop(), noErrorTopExporter); - export(context, generatorConfig.getExportMarathonTop(), marathonTopExporter); - export(context, generatorConfig.getExportCharsTop(), charsTopExporter); - export(context, generatorConfig.getExportDigitsTop(), digitsTopExporter); - export(context, generatorConfig.getExportSprintTop(), sprintTopExporter); - - // non-standard vocabularies exporters - export(context, generatorConfig.getExportNormalInEnglishTop(), normalInEnglishTopExporter); - export(context, generatorConfig.getExportMiniMarathonTop(), miniMarathonTopExporter); - export(context, generatorConfig.getExportShortTextsTop(), shortTextsTopExporter); - export(context, generatorConfig.getExportFrequencyVocabularyTop(), frequencyVocabularyTopExporter); - export(context, generatorConfig.getExportOneHundredRussianTop(), oneHundredRussianTopExporter); - export(context, generatorConfig.getExportDigitsOneHundredTop(), digitsOneHundredTopExporter); - export(context, generatorConfig.getExportTrainingIndexFingersTop(), trainingIndexFingersTopExporter); - export(context, generatorConfig.getExportRingFingersTop(), ringFingersTopExporter); - export(context, generatorConfig.getExportPinkiesPlusTop(), pinkiesPlusTopExporter); - } - - // todo: think about moving StatisticsGeneratorConfig field determination to Exporter interface - private void export(ExportContext context, boolean export, DataExporter exporter) { - logger.info("==============================================="); - - if (!export) { - logger.info( - "{} flag for {} is {}. Do not execute the export.", - StatisticsGeneratorConfig.class.getSimpleName(), - exporter.getClass().getSimpleName(), - false - ); - - return; - } - - logger.info( - "{} flag for {} is {}. Execute the export.", - StatisticsGeneratorConfig.class.getSimpleName(), - exporter.getClass().getSimpleName(), - true - ); - - exporter.export(context); - } -} diff --git a/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/export/StatisticsGenerator.kt b/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/export/StatisticsGenerator.kt new file mode 100644 index 000000000..5a2b78108 --- /dev/null +++ b/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/export/StatisticsGenerator.kt @@ -0,0 +1,176 @@ +package ru.klavogonki.statistics.export + +import lombok.extern.log4j.Log4j2 +import org.apache.logging.log4j.kotlin.Logging +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.context.annotation.Profile +import org.springframework.stereotype.Component +import ru.klavogonki.statistics.Config +import ru.klavogonki.statistics.export.vocabulary.non_standard.DigitsOneHundredTopExporter +import ru.klavogonki.statistics.export.vocabulary.non_standard.FrequencyVocabularyTopExporter +import ru.klavogonki.statistics.export.vocabulary.non_standard.MiniMarathonTopExporter +import ru.klavogonki.statistics.export.vocabulary.non_standard.NormalInEnglishTopExporter +import ru.klavogonki.statistics.export.vocabulary.non_standard.OneHundredRussianTopExporter +import ru.klavogonki.statistics.export.vocabulary.non_standard.PinkiesPlusTopExporter +import ru.klavogonki.statistics.export.vocabulary.non_standard.RingFingersTopExporter +import ru.klavogonki.statistics.export.vocabulary.non_standard.ShortTextsTopExporter +import ru.klavogonki.statistics.export.vocabulary.non_standard.TrainingIndexFingersTopExporter +import ru.klavogonki.statistics.export.vocabulary.standard.AbraTopExporter +import ru.klavogonki.statistics.export.vocabulary.standard.CharsTopExporter +import ru.klavogonki.statistics.export.vocabulary.standard.DigitsTopExporter +import ru.klavogonki.statistics.export.vocabulary.standard.MarathonTopExporter +import ru.klavogonki.statistics.export.vocabulary.standard.NoErrorTopExporter +import ru.klavogonki.statistics.export.vocabulary.standard.NormalTopExporter +import ru.klavogonki.statistics.export.vocabulary.standard.ReferatsTopExporter +import ru.klavogonki.statistics.export.vocabulary.standard.SprintTopExporter +import ru.klavogonki.statistics.springboot.Profiles + +@Component +@Profile(Profiles.DATABASE) +@Log4j2 +class StatisticsGenerator : Logging { + // aggregate tops + @Autowired + private val indexPageExporter: IndexPageExporter? = null + + @Autowired + private val topBySpeedExporter: TopBySpeedExporter? = null + + @Autowired + private val top500PagesExporter: Top500PagesExporter? = null + + @Autowired + private val playersByRankExporter: PlayersByRankExporter? = null + + // standard vocabularies + @Autowired + private val normalTopExporter: NormalTopExporter? = null + + @Autowired + private val abraTopExporter: AbraTopExporter? = null + + @Autowired + private val referatsTopExporter: ReferatsTopExporter? = null + + @Autowired + private val noErrorTopExporter: NoErrorTopExporter? = null + + @Autowired + private val marathonTopExporter: MarathonTopExporter? = null + + @Autowired + private val charsTopExporter: CharsTopExporter? = null + + @Autowired + private val digitsTopExporter: DigitsTopExporter? = null + + @Autowired + private val sprintTopExporter: SprintTopExporter? = null + + // non-standard vocabularies + @Autowired + private val normalInEnglishTopExporter: NormalInEnglishTopExporter? = null + + @Autowired + private val miniMarathonTopExporter: MiniMarathonTopExporter? = null + + @Autowired + private val shortTextsTopExporter: ShortTextsTopExporter? = null + + @Autowired + private val frequencyVocabularyTopExporter: FrequencyVocabularyTopExporter? = null + + @Autowired + private val oneHundredRussianTopExporter: OneHundredRussianTopExporter? = null + + @Autowired + private val digitsOneHundredTopExporter: DigitsOneHundredTopExporter? = null + + @Autowired + private val trainingIndexFingersTopExporter: TrainingIndexFingersTopExporter? = null + + @Autowired + private val ringFingersTopExporter: RingFingersTopExporter? = null + + @Autowired + private val pinkiesPlusTopExporter: PinkiesPlusTopExporter? = null + + fun generateStatistics(config: Config, generatorConfig: StatisticsGeneratorConfig) { + val context = ExportContext(config) + + /* + context.webRootDir = "C:/java/kgparser/kgstats/src/main/webapp/"; + + // data load from 2020-12-28 + context.minPlayerId = 1; + context.maxPlayerId = 628000; + context.dataDownloadStartDate = DateUtils.parseLocalDateTimeWithUiDateFormat("2020-12-28 00:28:13"); + context.dataDownloadEndDate = DateUtils.parseLocalDateTimeWithUiDateFormat("2020-12-28 01:44:43"); +*/ + + /* + // data load from 2020-12-09 + context.minPlayerId = 1; + context.maxPlayerId = 625000; + context.dataDownloadStartDate = DateUtils.parseLocalDateTimeWithUiDateFormat("2020-12-08 02:39:07"); + context.dataDownloadEndDate = DateUtils.parseLocalDateTimeWithUiDateFormat("2020-12-09 16:28:01"); +*/ + + // todo: add an option to skip Excel import + logger.debug("${StatisticsGeneratorConfig::class.java.simpleName}: $generatorConfig") + + // global tops exporters + export(context, generatorConfig.exportIndexPage, indexPageExporter) + export(context, generatorConfig.exportTopBySpeed, topBySpeedExporter) + export(context, generatorConfig.exportTop500Pages, top500PagesExporter) + export(context, generatorConfig.exportPlayersByRank, playersByRankExporter) + + // standard vocabularies exporters + export(context, generatorConfig.exportNormalTop, normalTopExporter) + export(context, generatorConfig.exportAbraTop, abraTopExporter) + export(context, generatorConfig.exportReferatsTop, referatsTopExporter) + export(context, generatorConfig.exportNoErrorTop, noErrorTopExporter) + export(context, generatorConfig.exportMarathonTop, marathonTopExporter) + export(context, generatorConfig.exportCharsTop, charsTopExporter) + export(context, generatorConfig.exportDigitsTop, digitsTopExporter) + export(context, generatorConfig.exportSprintTop, sprintTopExporter) + + // non-standard vocabularies exporters + export(context, generatorConfig.exportNormalInEnglishTop, normalInEnglishTopExporter) + export(context, generatorConfig.exportMiniMarathonTop, miniMarathonTopExporter) + export(context, generatorConfig.exportShortTextsTop, shortTextsTopExporter) + export(context, generatorConfig.exportFrequencyVocabularyTop, frequencyVocabularyTopExporter) + export(context, generatorConfig.exportOneHundredRussianTop, oneHundredRussianTopExporter) + export(context, generatorConfig.exportDigitsOneHundredTop, digitsOneHundredTopExporter) + export(context, generatorConfig.exportTrainingIndexFingersTop, trainingIndexFingersTopExporter) + export(context, generatorConfig.exportRingFingersTop, ringFingersTopExporter) + export(context, generatorConfig.exportPinkiesPlusTop, pinkiesPlusTopExporter) + } + + // todo: think about moving StatisticsGeneratorConfig field determination to Exporter interface + private fun export( + context: ExportContext, + export: Boolean, + exporter: DataExporter? + ) { + checkNotNull(exporter) + + logger.info("===============================================") + + if (!export) { + logger.info( + "${StatisticsGeneratorConfig::class.java.simpleName} flag" + + " for ${exporter.javaClass.simpleName} is ${false}. Do not execute the export.", + ) + + return + } + + logger.info( + "${StatisticsGeneratorConfig::class.java.simpleName} flag" + + " for ${exporter.javaClass.simpleName} is ${true}. Execute the export.", + ) + + exporter.export(context) + } +} diff --git a/pom.xml b/pom.xml index fec4a7d9b..6c9ef72c6 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,10 @@ 17 + 2.0.21 + 1.5.0 + 1.4.1.Final 1.18.34 0.2.0 @@ -192,6 +195,13 @@ ${log4j2.version}
+ + + org.apache.logging.log4j + log4j-api-kotlin + ${log4j2.api.kotlin.version} + + org.projectlombok From 70b2799f560f5794001cf88c299b3174e396431a Mon Sep 17 00:00:00 2001 From: dmitry-weirdo Date: Thu, 21 Nov 2024 03:44:48 +0100 Subject: [PATCH 04/30] feat: #81 Migrate ExportContext to Kotlin. Use dokka plugin instead of maven-javadoc-plugin to support Kotlin classes and not fail. --- kgstatsSrv/pom.xml | 38 ++++++++++++++--- .../java/ru/klavogonki/statistics/Config.java | 21 ++++++++++ .../statistics/export/ExportContext.java | 27 ------------ .../statistics/export/ExportContext.kt | 32 +++++++++++++++ pom.xml | 41 ++++++++++++++++++- 5 files changed, 125 insertions(+), 34 deletions(-) delete mode 100644 kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/ExportContext.java create mode 100644 kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/export/ExportContext.kt diff --git a/kgstatsSrv/pom.xml b/kgstatsSrv/pom.xml index bd229282f..a64780c63 100644 --- a/kgstatsSrv/pom.xml +++ b/kgstatsSrv/pom.xml @@ -150,18 +150,27 @@
+ org.jetbrains.kotlin kotlin-maven-plugin ${kotlin.version} - true + true + + + + lombok + + + + + + compile - compile + compile @@ -173,8 +182,7 @@ test-compile - test-compile + test-compile @@ -184,6 +192,24 @@ + + + + + + org.jetbrains.kotlin + kotlin-maven-lombok + ${kotlin.version} + + + org.apache.maven.plugins diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/Config.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/Config.java index 09065090b..edc842791 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/Config.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/Config.java @@ -29,6 +29,27 @@ public class Config { // @see ExportContext private String statisticsPagesRootDir; + // Explicit non-Lombok getters added to make the usage from the Kotlin clas work (see ExportContext). + public int getMinPlayerId() { + return minPlayerId; + } + + public int getMaxPlayerId() { + return maxPlayerId; + } + + public OffsetDateTime getDataDownloadStartDate() { + return dataDownloadStartDate; + } + + public OffsetDateTime getDataDownloadEndDate() { + return dataDownloadEndDate; + } + + public String getStatisticsPagesRootDir() { + return statisticsPagesRootDir; + } + @JsonProperty(access = JsonProperty.Access.READ_ONLY) // do not de-serialize, there is no setter and no field public int getTotalPlayers() { return maxPlayerId - minPlayerId + 1; diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/ExportContext.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/ExportContext.java deleted file mode 100644 index 1774250e3..000000000 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/ExportContext.java +++ /dev/null @@ -1,27 +0,0 @@ -package ru.klavogonki.statistics.export; - -import lombok.Data; -import ru.klavogonki.statistics.Config; -import ru.klavogonki.statistics.util.DateUtils; - -import java.time.LocalDateTime; - -@Data -public class ExportContext { - - public ExportContext(Config config) { - // todo: probably we don't require this class, all fields are already present in Config - this.webRootDir = config.getStatisticsPagesRootDir(); - this.minPlayerId = config.getMinPlayerId(); - this.maxPlayerId = config.getMaxPlayerId(); - this.dataDownloadStartDate = DateUtils.convertToUtcLocalDateTime(config.getDataDownloadStartDate()); // todo: think about UTC timeZone - this.dataDownloadEndDate = DateUtils.convertToUtcLocalDateTime(config.getDataDownloadEndDate()); // todo: think about UTC timeZone - } - - public String webRootDir; // where to export web files - - public int minPlayerId; - public int maxPlayerId; - public LocalDateTime dataDownloadStartDate; // todo: also change to OffsetDateTime - public LocalDateTime dataDownloadEndDate; // todo: also change to OffsetDateTime -} diff --git a/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/export/ExportContext.kt b/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/export/ExportContext.kt new file mode 100644 index 000000000..f5b285961 --- /dev/null +++ b/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/export/ExportContext.kt @@ -0,0 +1,32 @@ +package ru.klavogonki.statistics.export + +import ru.klavogonki.statistics.Config +import ru.klavogonki.statistics.util.DateUtils +import java.time.LocalDateTime + +// todo: probably we don't require this class, all fields are already present in Config +// todo: remove @JvmField annotations after moving all the using classes to Kotlin +data class ExportContext( + @JvmField val webRootDir: String, + @JvmField val minPlayerId: Int, + @JvmField val maxPlayerId: Int, + @JvmField val dataDownloadStartDate: LocalDateTime, + @JvmField val dataDownloadEndDate: LocalDateTime +) { + constructor(config: Config): this( + // we can use property-access from a Java class when there is an explicit geter + // but the lombok-generated getters do NOT work + + webRootDir = config.statisticsPagesRootDir, + minPlayerId = config.minPlayerId, + maxPlayerId = config.maxPlayerId, + + // todo: think about UTC timeZone + // todo: also change to OffsetDateTime + dataDownloadStartDate = DateUtils.convertToUtcLocalDateTime(config.dataDownloadStartDate), + + // todo: think about UTC timeZone + // todo: also change to OffsetDateTime + dataDownloadEndDate = DateUtils.convertToUtcLocalDateTime(config.dataDownloadEndDate) + ) +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 6c9ef72c6..3d59fac87 100644 --- a/pom.xml +++ b/pom.xml @@ -45,7 +45,10 @@ 3.5.2 2.2.1 3.4.0 + 3.11.1 + 1.9.20 + 3.2.4 5.0.0 3.6.0 @@ -138,13 +141,19 @@ ${maven-war-plugin.version} + + + + <!– see https://stackoverflow.com/a/61884267/8534088 –> false @@ -157,6 +166,36 @@ +--> + + + + + org.jetbrains.dokka + dokka-maven-plugin + ${maven-dokka-plugin.version} + + + + package + + dokka + javadoc + + + + + + + ${project.basedir}/src/main/kotlin + ${project.basedir}/src/main/java + + + From 6c83724abfd3fc5395c038e9d57528e811e7745c Mon Sep 17 00:00:00 2001 From: dmitry-weirdo Date: Thu, 21 Nov 2024 03:54:26 +0100 Subject: [PATCH 05/30] feat: #81 Some re-build magic - actually the Lombok-generated getters ARE working in Kotlin classes (even in IntelliJ IDEA). --- kgstatsSrv/pom.xml | 14 +++++++++++++ .../java/ru/klavogonki/statistics/Config.java | 21 ------------------- 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/kgstatsSrv/pom.xml b/kgstatsSrv/pom.xml index a64780c63..232f2b43c 100644 --- a/kgstatsSrv/pom.xml +++ b/kgstatsSrv/pom.xml @@ -265,6 +265,20 @@ lombok-mapstruct-binding ${lombok-mapstruct-binding.version} + + + + + diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/Config.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/Config.java index edc842791..09065090b 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/Config.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/Config.java @@ -29,27 +29,6 @@ public class Config { // @see ExportContext private String statisticsPagesRootDir; - // Explicit non-Lombok getters added to make the usage from the Kotlin clas work (see ExportContext). - public int getMinPlayerId() { - return minPlayerId; - } - - public int getMaxPlayerId() { - return maxPlayerId; - } - - public OffsetDateTime getDataDownloadStartDate() { - return dataDownloadStartDate; - } - - public OffsetDateTime getDataDownloadEndDate() { - return dataDownloadEndDate; - } - - public String getStatisticsPagesRootDir() { - return statisticsPagesRootDir; - } - @JsonProperty(access = JsonProperty.Access.READ_ONLY) // do not de-serialize, there is no setter and no field public int getTotalPlayers() { return maxPlayerId - minPlayerId + 1; From 31f308eb62127c9948dfc7ca8d66e1732c8792bd Mon Sep 17 00:00:00 2001 From: dmitry-weirdo Date: Fri, 22 Nov 2024 01:35:39 +0100 Subject: [PATCH 06/30] refactor: #81 In PageUrls, extract the common path pattern to a common method. --- .../statistics/freemarker/PageUrls.java | 61 ++++++++++--------- 1 file changed, 33 insertions(+), 28 deletions(-) diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/freemarker/PageUrls.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/freemarker/PageUrls.java index 57177734e..4b3d0cf3d 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/freemarker/PageUrls.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/freemarker/PageUrls.java @@ -96,97 +96,102 @@ public static String removeLeadingSlash(final String path) { } public static String getIndexPageFilePath(final String rootDir) { - return rootDir + "/" + INDEX; + return fullPath(rootDir, INDEX); } public static String getTopBySpeedPageFilePath(final String rootDir, final int pageNumber) { - return rootDir + "/" + "stat-top-by-best-speed-page-" + pageNumber + ".html"; + String pageFileName = "stat-top-by-best-speed-page-" + pageNumber + ".html"; + return fullPath(rootDir, pageFileName); } public static String getTopBySpeedAllPagesExcelFilePath(final String rootDir) { - return rootDir + "/" + TOP_BY_BEST_SPEED_ALL_PAGES_XLSX; + return fullPath(rootDir, TOP_BY_BEST_SPEED_ALL_PAGES_XLSX); } public static String getTopBySpeedAllPagesExcelZipFilePath(final String rootDir) { - return rootDir + "/" + TOP_BY_BEST_SPEED_ALL_PAGES_ZIP; + return fullPath(rootDir, TOP_BY_BEST_SPEED_ALL_PAGES_ZIP); } public static String getTopBySpeedLoginToPageFilePath(final String rootDir) { - return rootDir + "/" + TOP_BY_BEST_SPEED_LOGIN_TO_PAGE_JS; + return fullPath(rootDir, TOP_BY_BEST_SPEED_LOGIN_TO_PAGE_JS); } public static String getTopByTotalRacesCountFilePath(final String rootDir) { - return rootDir + "/" + TOP_BY_TOTAL_RACES; + return fullPath(rootDir, TOP_BY_TOTAL_RACES); } public static String getTopByTotalRacesCountExcelFilePath(final String rootDir) { - return rootDir + "/" + TOP_BY_TOTAL_RACES_XLSX; + return fullPath(rootDir, TOP_BY_TOTAL_RACES_XLSX); } public static String getTopByTotalRacesCountExcelZipFilePath(final String rootDir) { - return rootDir + "/" + TOP_BY_TOTAL_RACES_ZIP; + return fullPath(rootDir, TOP_BY_TOTAL_RACES_ZIP); } public static String getTopByBestSpeedFilePath(final String rootDir) { - return rootDir + "/" + TOP_BY_BEST_SPEED; + return fullPath(rootDir, TOP_BY_BEST_SPEED); } public static String getTopByBestSpeedExcelFilePath(final String rootDir) { - return rootDir + "/" + TOP_BY_BEST_SPEED_XLSX; + return fullPath(rootDir, TOP_BY_BEST_SPEED_XLSX); } public static String getTopByBestSpeedExcelZipFilePath(final String rootDir) { - return rootDir + "/" + TOP_BY_BEST_SPEED_ZIP; + return fullPath(rootDir, TOP_BY_BEST_SPEED_ZIP); } public static String getTopByRatingLevelFilePath(final String rootDir) { - return rootDir + "/" + TOP_BY_RATING_LEVEL; + return fullPath(rootDir, TOP_BY_RATING_LEVEL); } public static String getTopByRatingLevelExcelFilePath(final String rootDir) { - return rootDir + "/" + TOP_BY_RATING_LEVEL_XLSX; + return fullPath(rootDir, TOP_BY_RATING_LEVEL_XLSX); } public static String getTopByRatingLevelExcelZipFilePath(final String rootDir) { - return rootDir + "/" + TOP_BY_RATING_LEVEL_ZIP; + return fullPath(rootDir, TOP_BY_RATING_LEVEL_ZIP); } public static String getTopByFriendsCountFilePath(final String rootDir) { - return rootDir + "/" + TOP_BY_FRIENDS_COUNT; + return fullPath(rootDir, TOP_BY_FRIENDS_COUNT); } public static String getTopByFriendsCountExcelFilePath(final String rootDir) { - return rootDir + "/" + TOP_BY_FRIENDS_COUNT_XLSX; + return fullPath(rootDir, TOP_BY_FRIENDS_COUNT_XLSX); } public static String getTopByFriendsCountExcelZipFilePath(final String rootDir) { - return rootDir + "/" + TOP_BY_FRIENDS_COUNT_ZIP; + return fullPath(rootDir, TOP_BY_FRIENDS_COUNT_ZIP); } public static String getTopByAchievementsCountFilePath(final String rootDir) { - return rootDir + "/" + TOP_BY_ACHIEVEMENTS_COUNT; + return fullPath(rootDir, TOP_BY_ACHIEVEMENTS_COUNT); } public static String getTopByAchievementsCountExcelFilePath(final String rootDir) { - return rootDir + "/" + TOP_BY_ACHIEVEMENTS_COUNT_XLSX; + return fullPath(rootDir, TOP_BY_ACHIEVEMENTS_COUNT_XLSX); } public static String getTopByAchievementsCountExcelZipFilePath(final String rootDir) { - return rootDir + "/" + TOP_BY_ACHIEVEMENTS_COUNT_ZIP; + return fullPath(rootDir, TOP_BY_ACHIEVEMENTS_COUNT_ZIP); } public static String getTopByVocabulariesCountFilePath(final String rootDir) { - return rootDir + "/" + TOP_BY_VOCABULARIES_COUNT; + return fullPath(rootDir, TOP_BY_VOCABULARIES_COUNT); } public static String getTopByVocabulariesCountExcelFilePath(final String rootDir) { - return rootDir + "/" + TOP_BY_VOCABULARIES_COUNT_XLSX; + return fullPath(rootDir, TOP_BY_VOCABULARIES_COUNT_XLSX); } public static String getTopByVocabulariesCountExcelZipFilePath(final String rootDir) { - return rootDir + "/" + TOP_BY_VOCABULARIES_COUNT_ZIP; + return fullPath(rootDir, TOP_BY_VOCABULARIES_COUNT_ZIP); } public static String getTopByCarsCountFilePath(final String rootDir) { - return rootDir + "/" + TOP_BY_CARS_COUNT; + return fullPath(rootDir, TOP_BY_CARS_COUNT); } public static String getTopByCarsCountExcelFilePath(final String rootDir) { - return rootDir + "/" + TOP_BY_CARS_COUNT_XLSX; + return fullPath(rootDir, TOP_BY_CARS_COUNT_XLSX); } public static String getTopByCarsCountExcelZipFilePath(final String rootDir) { - return rootDir + "/" + TOP_BY_CARS_COUNT_ZIP; + return fullPath(rootDir, TOP_BY_CARS_COUNT_ZIP); } public static String getPlayerByRankFilePath(final String rootDir) { - return rootDir + "/" + PLAYER_BY_RANK; + return fullPath(rootDir, PLAYER_BY_RANK); } public static String getPlayerByRankDataFilePath(final String rootDir) { - return rootDir + "/" + PLAYERS_BY_RANK_DATA_JS; + return fullPath(rootDir, PLAYERS_BY_RANK_DATA_JS); + } + + private static String fullPath(String rootDir, String relativePath) { + return rootDir + "/" + relativePath; } } From e2e0af87aa58c4bb8f9fc05a20789d0a22df7a2f Mon Sep 17 00:00:00 2001 From: dmitry-weirdo Date: Fri, 22 Nov 2024 02:05:56 +0100 Subject: [PATCH 07/30] feat: #81 Migrate VocabularyTopUtils and ExporterUtils to Kotlin. --- .../statistics/export/ExporterUtils.java | 25 --- .../export/vocabulary/VocabularyTopUtils.java | 118 -------------- .../statistics/freemarker/PageUrls.java | 3 +- .../statistics/export/ExporterUtils.kt | 27 ++++ .../export/vocabulary/VocabularyTopUtils.kt | 153 ++++++++++++++++++ 5 files changed, 182 insertions(+), 144 deletions(-) delete mode 100644 kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/ExporterUtils.java delete mode 100644 kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/VocabularyTopUtils.java create mode 100644 kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/export/ExporterUtils.kt create mode 100644 kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/export/vocabulary/VocabularyTopUtils.kt diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/ExporterUtils.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/ExporterUtils.java deleted file mode 100644 index e651d99a1..000000000 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/ExporterUtils.java +++ /dev/null @@ -1,25 +0,0 @@ -package ru.klavogonki.statistics.export; - -import java.util.List; - -public final class ExporterUtils { - - public static final int FIRST_PAGE_NUMBER = 1; - - private ExporterUtils() { - } - - public static int getPagesCount(int totalRecords, int pageSize) { - if ((totalRecords % pageSize) == 0) - return totalRecords / pageSize; - - return (totalRecords / pageSize) + 1; - } - - public static List subList(List list, int pageSize, int pageNumberStartingWith1) { - int fromIndex = (pageNumberStartingWith1 - 1) * pageSize; - int toIndex = Math.min(fromIndex + pageSize, list.size()); - - return list.subList(fromIndex, toIndex); - } -} diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/VocabularyTopUtils.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/VocabularyTopUtils.java deleted file mode 100644 index 9ab18273a..000000000 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/VocabularyTopUtils.java +++ /dev/null @@ -1,118 +0,0 @@ -package ru.klavogonki.statistics.export.vocabulary; - -import lombok.extern.log4j.Log4j2; -import ru.klavogonki.kgparser.NonStandardDictionary; -import ru.klavogonki.kgparser.StandardDictionary; -import ru.klavogonki.statistics.excel.ExcelExporter; - -@Log4j2 -public final class VocabularyTopUtils { - // todo: cast StandardDictionary and NonStandardDictionary to common interface and use methods for interface instead of 2 methods for each operation - - private VocabularyTopUtils() { - } - - public static String takenPlayersWithMinimalRacesCount(StandardDictionary vocabulary, int racesCount) { - return takenPlayersWithMinimalRacesCount(StandardDictionary.getDisplayNameInPrepositionalCase(vocabulary), racesCount); - } - public static String takenPlayersWithMinimalRacesCount(NonStandardDictionary vocabulary, int racesCount) { - return takenPlayersWithMinimalRacesCount(vocabulary.namePrepositional, racesCount); - } - public static String takenPlayersWithMinimalRacesCount(String vocabularyNamePrepositional, int racesCount) { - return String.format("Учтены игроки с минимальным пробегом %d в «%s»", racesCount, vocabularyNamePrepositional); - } - - public static String topByBestSpeedIn(StandardDictionary vocabulary) { - return topByBestSpeedIn(StandardDictionary.getDisplayNameInPrepositionalCase(vocabulary)); - } - public static String topByBestSpeedIn(NonStandardDictionary vocabulary) { - return topByBestSpeedIn(vocabulary.namePrepositional); - } - public static String topByBestSpeedIn(String vocabularyNamePrepositional) { - return String.format("Топ по лучшей скорости в «%s»", vocabularyNamePrepositional); - } - - public static String topByRecordIn(StandardDictionary vocabulary) { - return topByRecordIn(StandardDictionary.getDisplayNameInPrepositionalCase(vocabulary)); - } - public static String topByRecordIn(NonStandardDictionary vocabulary) { - return topByRecordIn(vocabulary.namePrepositional); - } - public static String topByRecordIn(String vocabularyNamePrepositional) { - return String.format("Топ по рекорду в «%s»", vocabularyNamePrepositional); - } - - public static String topByBestSpeedExcelSheetName(StandardDictionary vocabulary) { - String longName = topByBestSpeedIn(vocabulary); - if (ExcelExporter.isValidSheetName(longName)) { - logger.debug("\"{}\" (long name) is a valid topByBestSpeedExcelSheetName for dictionary {}. Use it.", longName, vocabulary); - return longName; - } - else { - logger.debug("\"{}\" (long name) is not a valid topByBestSpeedExcelSheetName for dictionary {}. Trying a short name...", longName, vocabulary); - } - - String shortName = topByRecordIn(vocabulary); - if (ExcelExporter.isValidSheetName(shortName)) { - logger.debug("\"{}\" (short name) is a valid topByBestSpeedExcelSheetName for dictionary {}. Use it.", shortName, vocabulary); - return shortName; - } - else { - logger.warn("\"{}\" (short name) is not a valid topByBestSpeedExcelSheetName for dictionary {}. This is an epic fail.", shortName, vocabulary); - } - - throw new IllegalStateException(String.format( - "Cannot get topByBestSpeedExcelSheetName for vocabulary %s. Both long name \"%s\" and short name \"%s\" are non-valid.", - vocabulary, - longName, - shortName - )); - } - public static String topByBestSpeedExcelSheetName(NonStandardDictionary vocabulary) { - String longName = topByBestSpeedIn(vocabulary); - if (ExcelExporter.isValidSheetName(longName)) { - logger.debug("\"{}\" (long name) is a valid topByBestSpeedExcelSheetName for dictionary {}. Use it.", longName, vocabulary); - return longName; - } - else { - logger.debug("\"{}\" (long name) is not a valid topByBestSpeedExcelSheetName for dictionary {}. Trying a short name...", longName, vocabulary); - } - - String shortName = topByRecordIn(vocabulary); - if (ExcelExporter.isValidSheetName(shortName)) { - logger.debug("\"{}\" (short name) is a valid topByBestSpeedExcelSheetName for dictionary {}. Use it.", shortName, vocabulary); - return shortName; - } - else { - logger.warn("\"{}\" (short name) is not a valid topByBestSpeedExcelSheetName for dictionary {}. This is an epic fail.", shortName, vocabulary); - } - - throw new IllegalStateException(String.format( - "Cannot get topByBestSpeedExcelSheetName for vocabulary %s. Both long name \"%s\" and short name \"%s\" are non-valid.", - vocabulary, - longName, - shortName - )); - } - - - public static String topByRacesCountIn(StandardDictionary vocabulary) { - return topByRacesCountIn(StandardDictionary.getDisplayNameInPrepositionalCase(vocabulary)); - } - public static String topByRacesCountIn(NonStandardDictionary vocabulary) { - return topByRacesCountIn(vocabulary.namePrepositional); - } - public static String topByRacesCountIn(String vocabularyNamePrepositional) { - return String.format("Топ по пробегу в «%s»", vocabularyNamePrepositional); - } - - public static String topByHaulIn(StandardDictionary vocabulary) { - return topByHaulIn(StandardDictionary.getDisplayNameInPrepositionalCase(vocabulary)); - } - public static String topByHaulIn(NonStandardDictionary vocabulary) { - return topByHaulIn(vocabulary.namePrepositional); - } - public static String topByHaulIn(String vocabularyNamePrepositional) { - return String.format("Топ по времени в «%s»", vocabularyNamePrepositional); - } -} diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/freemarker/PageUrls.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/freemarker/PageUrls.java index 4b3d0cf3d..7b17dfed0 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/freemarker/PageUrls.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/freemarker/PageUrls.java @@ -1,6 +1,7 @@ package ru.klavogonki.statistics.freemarker; import ru.klavogonki.statistics.export.ExportContext; +import ru.klavogonki.statistics.export.ExporterUtils; /** * Aggregates names/paths of all pages, so that we can pass them to FreeMarker templates @@ -11,7 +12,7 @@ public final class PageUrls { // html files public static final String INDEX = "index.html"; - public static final String TOP_BY_BEST_SPEED_PAGE_1 = removeLeadingSlash(getTopBySpeedPageFilePath("", 1)); + public static final String TOP_BY_BEST_SPEED_PAGE_1 = removeLeadingSlash(getTopBySpeedPageFilePath("", ExporterUtils.FIRST_PAGE_NUMBER)); public static final String TOP_BY_BEST_SPEED = "stat-top-by-best-speed.html"; public static final String TOP_BY_TOTAL_RACES = "stat-top-by-total-races.html"; diff --git a/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/export/ExporterUtils.kt b/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/export/ExporterUtils.kt new file mode 100644 index 000000000..96a5be06c --- /dev/null +++ b/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/export/ExporterUtils.kt @@ -0,0 +1,27 @@ +package ru.klavogonki.statistics.export + +import kotlin.math.min + +object ExporterUtils { + const val FIRST_PAGE_NUMBER: Int = 1 + + @JvmStatic + fun getPagesCount(totalRecords: Int, pageSize: Int): Int { + if ((totalRecords % pageSize) == 0) { + return totalRecords / pageSize + } + + return (totalRecords / pageSize) + 1 + } + + @JvmStatic + fun subList( + list: List, pageSize: Int, + pageNumberStartingWith1: Int + ): List { + val fromIndex = (pageNumberStartingWith1 - 1) * pageSize + val toIndex = min(fromIndex + pageSize, list.size) + + return list.subList(fromIndex, toIndex) + } +} diff --git a/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/export/vocabulary/VocabularyTopUtils.kt b/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/export/vocabulary/VocabularyTopUtils.kt new file mode 100644 index 000000000..01937f6fb --- /dev/null +++ b/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/export/vocabulary/VocabularyTopUtils.kt @@ -0,0 +1,153 @@ +package ru.klavogonki.statistics.export.vocabulary + +import org.apache.logging.log4j.kotlin.Logging +import ru.klavogonki.kgparser.NonStandardDictionary +import ru.klavogonki.kgparser.StandardDictionary +import ru.klavogonki.statistics.excel.ExcelExporter + +@Suppress("TooManyFunctions") +object VocabularyTopUtils : Logging { + @JvmStatic + fun takenPlayersWithMinimalRacesCount(vocabulary: StandardDictionary, racesCount: Int) = + takenPlayersWithMinimalRacesCount( + StandardDictionary.getDisplayNameInPrepositionalCase(vocabulary), + racesCount + ) + + @JvmStatic + fun takenPlayersWithMinimalRacesCount(vocabulary: NonStandardDictionary, racesCount: Int) = + takenPlayersWithMinimalRacesCount(vocabulary.namePrepositional, racesCount) + + @JvmStatic + fun takenPlayersWithMinimalRacesCount(vocabularyNamePrepositional: String, racesCount: Int) = + "Учтены игроки с минимальным пробегом $racesCount в «$vocabularyNamePrepositional»" + + @JvmStatic + fun topByBestSpeedIn(vocabulary: StandardDictionary) = + topByBestSpeedIn(StandardDictionary.getDisplayNameInPrepositionalCase(vocabulary)) + + @JvmStatic + fun topByBestSpeedIn(vocabulary: NonStandardDictionary) = + topByBestSpeedIn(vocabulary.namePrepositional) + + @JvmStatic + fun topByBestSpeedIn(vocabularyNamePrepositional: String) = + "Топ по лучшей скорости в «$vocabularyNamePrepositional»" + + @JvmStatic + fun topByRecordIn(vocabulary: StandardDictionary) = + topByRecordIn(StandardDictionary.getDisplayNameInPrepositionalCase(vocabulary)) + + @JvmStatic + fun topByRecordIn(vocabulary: NonStandardDictionary) = + topByRecordIn(vocabulary.namePrepositional) + + @JvmStatic + fun topByRecordIn(vocabularyNamePrepositional: String) = + "Топ по рекорду в «${vocabularyNamePrepositional}»" + + @JvmStatic + fun topByBestSpeedExcelSheetName(vocabulary: StandardDictionary): String { + val longName = topByBestSpeedIn(vocabulary) + if (ExcelExporter.isValidSheetName(longName)) { + logger.debug( + "\"$longName\" (long name)" + + " is a valid topByBestSpeedExcelSheetName for dictionary \"$vocabulary\"." + + " Use it." + ) + + return longName + } else { + logger.debug( + "\"$longName\" (long name)" + + " is not a valid topByBestSpeedExcelSheetName for dictionary \"$vocabulary\"." + + " Trying a short name..." + ) + } + + val shortName = topByRecordIn(vocabulary) + if (ExcelExporter.isValidSheetName(shortName)) { + logger.debug( + "\"$shortName\" (short name) is a valid topByBestSpeedExcelSheetName for dictionary \"$vocabulary\"." + + " Use it." + ) + + return shortName + } else { + logger.warn( + "\"$shortName\" (short name)" + + " is not a valid topByBestSpeedExcelSheetName for dictionary \"$vocabulary\"." + + " This is an epic fail." + ) + } + + error( + "Cannot get topByBestSpeedExcelSheetName for vocabulary \"$vocabulary\"." + + " Both long name \"$longName\" and short name \"$shortName\" are non-valid." + ) + } + + @JvmStatic + fun topByBestSpeedExcelSheetName(vocabulary: NonStandardDictionary): String { + val longName = topByBestSpeedIn(vocabulary) + if (ExcelExporter.isValidSheetName(longName)) { + logger.debug( + "\"$longName\" (long name) is a valid topByBestSpeedExcelSheetName for dictionary \"$vocabulary\"." + + " Use it." + ) + + return longName + } else { + logger.debug( + "\"$longName\" (long name)" + + " is not a valid topByBestSpeedExcelSheetName for dictionary \"$vocabulary\"." + + " Trying a short name..." + ) + } + + val shortName = topByRecordIn(vocabulary) + if (ExcelExporter.isValidSheetName(shortName)) { + logger.debug( + "\"$shortName\" (short name) is a valid topByBestSpeedExcelSheetName for dictionary \"$vocabulary\"." + + " Use it." + ) + + return shortName + } else { + logger.warn( + "\"$shortName\" (short name)" + + " is not a valid topByBestSpeedExcelSheetName for dictionary \"$vocabulary\"." + + " This is an epic fail." + ) + } + + error( + "Cannot get topByBestSpeedExcelSheetName for vocabulary \"$vocabulary\"." + + " Both long name \"$longName\" and short name \"$shortName\" are non-valid." + ) + } + + @JvmStatic + fun topByRacesCountIn(vocabulary: StandardDictionary) = + topByRacesCountIn(StandardDictionary.getDisplayNameInPrepositionalCase(vocabulary)) + + @JvmStatic + fun topByRacesCountIn(vocabulary: NonStandardDictionary) = + topByRacesCountIn(vocabulary.namePrepositional) + + @JvmStatic + fun topByRacesCountIn(vocabularyNamePrepositional: String) = + "Топ по пробегу в «$vocabularyNamePrepositional»" + + @JvmStatic + fun topByHaulIn(vocabulary: StandardDictionary) = + topByHaulIn(StandardDictionary.getDisplayNameInPrepositionalCase(vocabulary)) + + @JvmStatic + fun topByHaulIn(vocabulary: NonStandardDictionary) = + topByHaulIn(vocabulary.namePrepositional) + + @JvmStatic + fun topByHaulIn(vocabularyNamePrepositional: String) = + "Топ по времени в «$vocabularyNamePrepositional»" +} From 2e7677042ee51690595d849616269329b2c99740 Mon Sep 17 00:00:00 2001 From: dmitry-weirdo Date: Fri, 22 Nov 2024 02:19:29 +0100 Subject: [PATCH 08/30] feat: #81 Migrate ZipUtils to Kotlin. Close the ZipFile resource correctly. --- .../klavogonki/statistics/zip/ZipUtils.java | 24 ------------------- .../ru/klavogonki/statistics/zip/ZipUtils.kt | 23 ++++++++++++++++++ 2 files changed, 23 insertions(+), 24 deletions(-) delete mode 100644 kgstatsSrv/src/main/java/ru/klavogonki/statistics/zip/ZipUtils.java create mode 100644 kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/zip/ZipUtils.kt diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/zip/ZipUtils.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/zip/ZipUtils.java deleted file mode 100644 index 4e00d10e2..000000000 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/zip/ZipUtils.java +++ /dev/null @@ -1,24 +0,0 @@ -package ru.klavogonki.statistics.zip; - -import lombok.extern.log4j.Log4j2; -import net.lingala.zip4j.ZipFile; -import net.lingala.zip4j.exception.ZipException; - -@Log4j2 -public final class ZipUtils { - - private ZipUtils() { - } - - public static void zipFile(String filePath, String zipFilePath) { - try { - new ZipFile(zipFilePath).addFile(filePath); - logger.debug("Successfully zipped file {} to zip file {}", filePath, zipFilePath); - } - catch (ZipException e) { - logger.error(String.format("Error on zipping file %s to zip file %s", filePath, zipFilePath), e ); - - throw new RuntimeException(e); - } - } -} diff --git a/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/zip/ZipUtils.kt b/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/zip/ZipUtils.kt new file mode 100644 index 000000000..89e6508e7 --- /dev/null +++ b/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/zip/ZipUtils.kt @@ -0,0 +1,23 @@ +package ru.klavogonki.statistics.zip + +import net.lingala.zip4j.ZipFile +import net.lingala.zip4j.exception.ZipException +import org.apache.logging.log4j.kotlin.Logging + +object ZipUtils : Logging { + + @JvmStatic + fun zipFile(filePath: String, zipFilePath: String) { + ZipFile(zipFilePath).use { + try { + it.addFile(filePath) + + logger.debug("Successfully zipped file \"$filePath\" to zip file \"$zipFilePath\".") + } catch (e: ZipException) { + logger.error("Error on zipping file \"$filePath\" to zip file \"$zipFilePath\"", e) + + throw e + } + } + } +} \ No newline at end of file From 7aa1fdd5af12e8e3ae1773744fcb4f925c40b1d7 Mon Sep 17 00:00:00 2001 From: dmitry-weirdo Date: Fri, 22 Nov 2024 02:25:47 +0100 Subject: [PATCH 09/30] chore: #81 Make fields `final` when they can be `final` (found by the corresponding inspection). --- .../statistics/excel/VocabularyTopByBestSpeedExcelTemplate.java | 2 +- .../statistics/excel/VocabularyTopByHaulExcelTemplate.java | 2 +- .../excel/VocabularyTopByRacesCountExcelTemplate.java | 2 +- .../ru/klavogonki/statistics/import_db/DatabaseImporter.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/VocabularyTopByBestSpeedExcelTemplate.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/VocabularyTopByBestSpeedExcelTemplate.java index f221e4289..aa28fef24 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/VocabularyTopByBestSpeedExcelTemplate.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/VocabularyTopByBestSpeedExcelTemplate.java @@ -17,7 +17,7 @@ public class VocabularyTopByBestSpeedExcelTemplate extends ExcelTemplate { - private String sheetName; + private final String sheetName; public VocabularyTopByBestSpeedExcelTemplate(final String sheetName) { this.sheetName = sheetName; diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/VocabularyTopByHaulExcelTemplate.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/VocabularyTopByHaulExcelTemplate.java index 0a5c5b04c..def6a5a7a 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/VocabularyTopByHaulExcelTemplate.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/VocabularyTopByHaulExcelTemplate.java @@ -17,7 +17,7 @@ public class VocabularyTopByHaulExcelTemplate extends ExcelTemplate { - private String sheetName; + private final String sheetName; public VocabularyTopByHaulExcelTemplate(final String sheetName) { this.sheetName = sheetName; diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/VocabularyTopByRacesCountExcelTemplate.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/VocabularyTopByRacesCountExcelTemplate.java index 1cd9afe0a..b4248bb01 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/VocabularyTopByRacesCountExcelTemplate.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/VocabularyTopByRacesCountExcelTemplate.java @@ -17,7 +17,7 @@ public class VocabularyTopByRacesCountExcelTemplate extends ExcelTemplate { - private String sheetName; + private final String sheetName; public VocabularyTopByRacesCountExcelTemplate(final String sheetName) { this.sheetName = sheetName; diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/import_db/DatabaseImporter.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/import_db/DatabaseImporter.java index e9194ebbb..e99e8ee00 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/import_db/DatabaseImporter.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/import_db/DatabaseImporter.java @@ -42,7 +42,7 @@ public class DatabaseImporter { // todo: autowire it, @see https://mapstruct.org/documentation/stable/reference/html/#using-dependency-injection private final PlayerVocabularyStatsMapper statsMapper = Mappers.getMapper(PlayerVocabularyStatsMapper.class); - private List playersBatch = new ArrayList<>(); // todo: find a nicer solution + private final List playersBatch = new ArrayList<>(); // todo: find a nicer solution public void importJsonToDatabase(final Config config) { // todo: move all related logic to a separate Spring component From a835e04904ace1ecce11a8b7b6fcacc6c07f71a8 Mon Sep 17 00:00:00 2001 From: dmitry-weirdo Date: Fri, 22 Nov 2024 02:50:19 +0100 Subject: [PATCH 10/30] feat: #81 Converted PageUrls to Kotlin. Looks less cumbersome now. --- .../statistics/freemarker/PageUrls.java | 198 ---------------- .../statistics/freemarker/PageUrls.kt | 217 ++++++++++++++++++ 2 files changed, 217 insertions(+), 198 deletions(-) delete mode 100644 kgstatsSrv/src/main/java/ru/klavogonki/statistics/freemarker/PageUrls.java create mode 100644 kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/freemarker/PageUrls.kt diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/freemarker/PageUrls.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/freemarker/PageUrls.java deleted file mode 100644 index 7b17dfed0..000000000 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/freemarker/PageUrls.java +++ /dev/null @@ -1,198 +0,0 @@ -package ru.klavogonki.statistics.freemarker; - -import ru.klavogonki.statistics.export.ExportContext; -import ru.klavogonki.statistics.export.ExporterUtils; - -/** - * Aggregates names/paths of all pages, so that we can pass them to FreeMarker templates - * and change links in one place. - */ -public final class PageUrls { - - // html files - public static final String INDEX = "index.html"; - - public static final String TOP_BY_BEST_SPEED_PAGE_1 = removeLeadingSlash(getTopBySpeedPageFilePath("", ExporterUtils.FIRST_PAGE_NUMBER)); - public static final String TOP_BY_BEST_SPEED = "stat-top-by-best-speed.html"; - - public static final String TOP_BY_TOTAL_RACES = "stat-top-by-total-races.html"; - public static final String TOP_BY_RATING_LEVEL = "stat-top-by-rating-level.html"; - public static final String TOP_BY_FRIENDS_COUNT = "stat-top-by-friends-count.html"; - public static final String TOP_BY_ACHIEVEMENTS_COUNT = "stat-top-by-achievements-count.html"; - public static final String TOP_BY_VOCABULARIES_COUNT = "stat-top-by-vocabularies-count.html"; - public static final String TOP_BY_CARS_COUNT = "stat-top-by-cars-count.html"; - - public static final String PLAYER_BY_RANK = "stat-players-by-rank.html"; - - // xls files and their zip form - // big top by speed, all pages - public static final String TOP_BY_BEST_SPEED_ALL_PAGES_XLSX = "xlsx/stat-top-by-best-speed-all-pages.xlsx"; - public static final String TOP_BY_BEST_SPEED_ALL_PAGES_ZIP = "xlsx/stat-top-by-best-speed-all-pages.zip"; - - public static final String TOP_BY_BEST_SPEED_XLSX = "xlsx/stat-top-by-best-speed.xlsx"; - public static final String TOP_BY_BEST_SPEED_ZIP = "xlsx/stat-top-by-best-speed.zip"; - - public static final String TOP_BY_TOTAL_RACES_XLSX = "xlsx/stat-top-by-total-races.xlsx"; - public static final String TOP_BY_TOTAL_RACES_ZIP = "xlsx/stat-top-by-total-races.zip"; - - public static final String TOP_BY_RATING_LEVEL_XLSX = "xlsx/stat-top-by-rating-level.xlsx"; - public static final String TOP_BY_RATING_LEVEL_ZIP = "xlsx/stat-top-by-rating-level.zip"; - - public static final String TOP_BY_FRIENDS_COUNT_XLSX = "xlsx/stat-top-by-friends-count.xlsx"; - public static final String TOP_BY_FRIENDS_COUNT_ZIP = "xlsx/stat-top-by-friends-count.zip"; - - public static final String TOP_BY_ACHIEVEMENTS_COUNT_XLSX = "xlsx/stat-top-by-achievements-count.xlsx"; - public static final String TOP_BY_ACHIEVEMENTS_COUNT_ZIP = "xlsx/stat-top-by-achievements-count.zip"; - - public static final String TOP_BY_VOCABULARIES_COUNT_XLSX = "xlsx/stat-top-by-vocabularies-count.xlsx"; - public static final String TOP_BY_VOCABULARIES_COUNT_ZIP = "xlsx/stat-top-by-vocabularies-count.zip"; - - public static final String TOP_BY_CARS_COUNT_XLSX = "xlsx/stat-top-by-cars-count.xlsx"; - public static final String TOP_BY_CARS_COUNT_ZIP = "xlsx/stat-top-by-cars-count.zip"; - - // css files and images - public static final String STATS_CSS = "./css/stats.css"; - public static final String FAVICON_ICO = "./img/favicon/favicon.ico"; - public static final String EXCEL_PNG = "./img/excel.png"; - public static final String INFO_PNG = "./img/info.png"; - - // js files - // Chart.js - // see https://www.chartjs.org/docs/latest/getting-started/installation.html - public static final String CHART_JS = "https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.bundle.min.js"; - public static final String CHART_JS_INTEGRITY = "sha512-SuxO9djzjML6b9w9/I07IWnLnQhgyYVSpHZx0JV97kGBfTIsUYlWflyuW4ypnvhBrslz1yJ3R+S14fdCWmSmSA=="; - - public static final String PLAYERS_BY_RANK_CHART_JS = "./js/players-by-rank-chart.js"; - public static final String PLAYERS_BY_RANK_DATA_JS = "./js/players-by-rank-data.js"; - public static final String TOP_TABLE_JS = "./js/stats-top-table.js"; - public static final String TOP_BY_BEST_SPEED_LOGIN_TO_PAGE_JS = "./js/stat-top-by-best-speed-login-to-page.js"; - - private PageUrls() { - } - - public static String getPath(final ExportContext context, final String relativePath) { - return getPath(context.webRootDir, relativePath); - } - - public static String getPath(final String rootDir, final String relativePath) { - StringBuilder sb = new StringBuilder(); - sb.append(rootDir); - - if (!relativePath.startsWith("/")) { - sb.append("/"); - } - - // todo: maybe remove "." from relativePath if every required - sb.append(relativePath); - - return sb.toString(); - } - - public static String removeLeadingSlash(final String path) { - if (!path.startsWith("/")) { - return path; - } - - return path.substring("/".length()); - } - - public static String getIndexPageFilePath(final String rootDir) { - return fullPath(rootDir, INDEX); - } - - public static String getTopBySpeedPageFilePath(final String rootDir, final int pageNumber) { - String pageFileName = "stat-top-by-best-speed-page-" + pageNumber + ".html"; - return fullPath(rootDir, pageFileName); - } - public static String getTopBySpeedAllPagesExcelFilePath(final String rootDir) { - return fullPath(rootDir, TOP_BY_BEST_SPEED_ALL_PAGES_XLSX); - } - public static String getTopBySpeedAllPagesExcelZipFilePath(final String rootDir) { - return fullPath(rootDir, TOP_BY_BEST_SPEED_ALL_PAGES_ZIP); - } - - public static String getTopBySpeedLoginToPageFilePath(final String rootDir) { - return fullPath(rootDir, TOP_BY_BEST_SPEED_LOGIN_TO_PAGE_JS); - } - - public static String getTopByTotalRacesCountFilePath(final String rootDir) { - return fullPath(rootDir, TOP_BY_TOTAL_RACES); - } - public static String getTopByTotalRacesCountExcelFilePath(final String rootDir) { - return fullPath(rootDir, TOP_BY_TOTAL_RACES_XLSX); - } - public static String getTopByTotalRacesCountExcelZipFilePath(final String rootDir) { - return fullPath(rootDir, TOP_BY_TOTAL_RACES_ZIP); - } - - public static String getTopByBestSpeedFilePath(final String rootDir) { - return fullPath(rootDir, TOP_BY_BEST_SPEED); - } - public static String getTopByBestSpeedExcelFilePath(final String rootDir) { - return fullPath(rootDir, TOP_BY_BEST_SPEED_XLSX); - } - public static String getTopByBestSpeedExcelZipFilePath(final String rootDir) { - return fullPath(rootDir, TOP_BY_BEST_SPEED_ZIP); - } - - public static String getTopByRatingLevelFilePath(final String rootDir) { - return fullPath(rootDir, TOP_BY_RATING_LEVEL); - } - public static String getTopByRatingLevelExcelFilePath(final String rootDir) { - return fullPath(rootDir, TOP_BY_RATING_LEVEL_XLSX); - } - public static String getTopByRatingLevelExcelZipFilePath(final String rootDir) { - return fullPath(rootDir, TOP_BY_RATING_LEVEL_ZIP); - } - - public static String getTopByFriendsCountFilePath(final String rootDir) { - return fullPath(rootDir, TOP_BY_FRIENDS_COUNT); - } - public static String getTopByFriendsCountExcelFilePath(final String rootDir) { - return fullPath(rootDir, TOP_BY_FRIENDS_COUNT_XLSX); - } - public static String getTopByFriendsCountExcelZipFilePath(final String rootDir) { - return fullPath(rootDir, TOP_BY_FRIENDS_COUNT_ZIP); - } - - public static String getTopByAchievementsCountFilePath(final String rootDir) { - return fullPath(rootDir, TOP_BY_ACHIEVEMENTS_COUNT); - } - public static String getTopByAchievementsCountExcelFilePath(final String rootDir) { - return fullPath(rootDir, TOP_BY_ACHIEVEMENTS_COUNT_XLSX); - } - public static String getTopByAchievementsCountExcelZipFilePath(final String rootDir) { - return fullPath(rootDir, TOP_BY_ACHIEVEMENTS_COUNT_ZIP); - } - - public static String getTopByVocabulariesCountFilePath(final String rootDir) { - return fullPath(rootDir, TOP_BY_VOCABULARIES_COUNT); - } - public static String getTopByVocabulariesCountExcelFilePath(final String rootDir) { - return fullPath(rootDir, TOP_BY_VOCABULARIES_COUNT_XLSX); - } - public static String getTopByVocabulariesCountExcelZipFilePath(final String rootDir) { - return fullPath(rootDir, TOP_BY_VOCABULARIES_COUNT_ZIP); - } - - public static String getTopByCarsCountFilePath(final String rootDir) { - return fullPath(rootDir, TOP_BY_CARS_COUNT); - } - public static String getTopByCarsCountExcelFilePath(final String rootDir) { - return fullPath(rootDir, TOP_BY_CARS_COUNT_XLSX); - } - public static String getTopByCarsCountExcelZipFilePath(final String rootDir) { - return fullPath(rootDir, TOP_BY_CARS_COUNT_ZIP); - } - - public static String getPlayerByRankFilePath(final String rootDir) { - return fullPath(rootDir, PLAYER_BY_RANK); - } - public static String getPlayerByRankDataFilePath(final String rootDir) { - return fullPath(rootDir, PLAYERS_BY_RANK_DATA_JS); - } - - private static String fullPath(String rootDir, String relativePath) { - return rootDir + "/" + relativePath; - } -} diff --git a/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/freemarker/PageUrls.kt b/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/freemarker/PageUrls.kt new file mode 100644 index 000000000..d4e348932 --- /dev/null +++ b/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/freemarker/PageUrls.kt @@ -0,0 +1,217 @@ +package ru.klavogonki.statistics.freemarker + +import ru.klavogonki.statistics.export.ExportContext +import ru.klavogonki.statistics.export.ExporterUtils + +/** + * Aggregates names/paths of all pages, so that we can pass them to FreeMarker templates + * and change links in one place. + */ +@SuppressWarnings("TooManyFunctions") +object PageUrls { + // html files + const val INDEX: String = "index.html" + + @JvmField // calculated field cannot be const + val TOP_BY_BEST_SPEED_PAGE_1 = removeLeadingSlash( + getTopBySpeedPageFilePath("", ExporterUtils.FIRST_PAGE_NUMBER) + ) + + const val TOP_BY_BEST_SPEED = "stat-top-by-best-speed.html" + + const val TOP_BY_TOTAL_RACES = "stat-top-by-total-races.html" + const val TOP_BY_RATING_LEVEL = "stat-top-by-rating-level.html" + const val TOP_BY_FRIENDS_COUNT = "stat-top-by-friends-count.html" + const val TOP_BY_ACHIEVEMENTS_COUNT = "stat-top-by-achievements-count.html" + const val TOP_BY_VOCABULARIES_COUNT = "stat-top-by-vocabularies-count.html" + const val TOP_BY_CARS_COUNT = "stat-top-by-cars-count.html" + + const val PLAYER_BY_RANK = "stat-players-by-rank.html" + + // xls files and their zip form + // big top by speed, all pages + const val TOP_BY_BEST_SPEED_ALL_PAGES_XLSX = "xlsx/stat-top-by-best-speed-all-pages.xlsx" + const val TOP_BY_BEST_SPEED_ALL_PAGES_ZIP = "xlsx/stat-top-by-best-speed-all-pages.zip" + + const val TOP_BY_BEST_SPEED_XLSX = "xlsx/stat-top-by-best-speed.xlsx" + const val TOP_BY_BEST_SPEED_ZIP = "xlsx/stat-top-by-best-speed.zip" + + const val TOP_BY_TOTAL_RACES_XLSX = "xlsx/stat-top-by-total-races.xlsx" + const val TOP_BY_TOTAL_RACES_ZIP = "xlsx/stat-top-by-total-races.zip" + + const val TOP_BY_RATING_LEVEL_XLSX = "xlsx/stat-top-by-rating-level.xlsx" + const val TOP_BY_RATING_LEVEL_ZIP = "xlsx/stat-top-by-rating-level.zip" + + const val TOP_BY_FRIENDS_COUNT_XLSX = "xlsx/stat-top-by-friends-count.xlsx" + const val TOP_BY_FRIENDS_COUNT_ZIP = "xlsx/stat-top-by-friends-count.zip" + + const val TOP_BY_ACHIEVEMENTS_COUNT_XLSX = "xlsx/stat-top-by-achievements-count.xlsx" + const val TOP_BY_ACHIEVEMENTS_COUNT_ZIP = "xlsx/stat-top-by-achievements-count.zip" + + const val TOP_BY_VOCABULARIES_COUNT_XLSX = "xlsx/stat-top-by-vocabularies-count.xlsx" + const val TOP_BY_VOCABULARIES_COUNT_ZIP = "xlsx/stat-top-by-vocabularies-count.zip" + + const val TOP_BY_CARS_COUNT_XLSX = "xlsx/stat-top-by-cars-count.xlsx" + const val TOP_BY_CARS_COUNT_ZIP = "xlsx/stat-top-by-cars-count.zip" + + // css files and images + const val STATS_CSS = "./css/stats.css" + const val FAVICON_ICO = "./img/favicon/favicon.ico" + const val EXCEL_PNG = "./img/excel.png" + const val INFO_PNG = "./img/info.png" + + // js files + // Chart.js + // see https://www.chartjs.org/docs/latest/getting-started/installation.html + const val CHART_JS = "https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.bundle.min.js" + const val CHART_JS_INTEGRITY = + "sha512-SuxO9djzjML6b9w9/I07IWnLnQhgyYVSpHZx0JV97kGBfTIsUYlWflyuW4ypnvhBrslz1yJ3R+S14fdCWmSmSA==" + + const val PLAYERS_BY_RANK_CHART_JS = "./js/players-by-rank-chart.js" + const val PLAYERS_BY_RANK_DATA_JS = "./js/players-by-rank-data.js" + const val TOP_TABLE_JS = "./js/stats-top-table.js" + const val TOP_BY_BEST_SPEED_LOGIN_TO_PAGE_JS = "./js/stat-top-by-best-speed-login-to-page.js" + + @JvmStatic + fun getPath(context: ExportContext, relativePath: String) = + getPath(context.webRootDir, relativePath) + + private fun getPath(rootDir: String, relativePath: String): String { + val sb = StringBuilder() + sb.append(rootDir) + + if (!relativePath.startsWith("/")) { + sb.append("/") + } + + // todo: maybe remove "." from relativePath if every required + sb.append(relativePath) + + return sb.toString() + } + + private fun removeLeadingSlash(path: String): String { + if (!path.startsWith("/")) { + return path + } + + return path.substring("/".length) + } + + @JvmStatic + fun getIndexPageFilePath(rootDir: String) = + fullPath(rootDir, INDEX) + + @JvmStatic + fun getTopBySpeedPageFilePath(rootDir: String, pageNumber: Int): String { + val pageFileName = "stat-top-by-best-speed-page-$pageNumber.html" + return fullPath(rootDir, pageFileName) + } + + @JvmStatic + fun getTopBySpeedAllPagesExcelFilePath(rootDir: String) = + fullPath(rootDir, TOP_BY_BEST_SPEED_ALL_PAGES_XLSX) + + @JvmStatic + fun getTopBySpeedAllPagesExcelZipFilePath(rootDir: String) = + fullPath(rootDir, TOP_BY_BEST_SPEED_ALL_PAGES_ZIP) + + @JvmStatic + fun getTopBySpeedLoginToPageFilePath(rootDir: String) = + fullPath(rootDir, TOP_BY_BEST_SPEED_LOGIN_TO_PAGE_JS) + + @JvmStatic + fun getTopByTotalRacesCountFilePath(rootDir: String) = + fullPath(rootDir, TOP_BY_TOTAL_RACES) + + @JvmStatic + fun getTopByTotalRacesCountExcelFilePath(rootDir: String) = + fullPath(rootDir, TOP_BY_TOTAL_RACES_XLSX) + + @JvmStatic + fun getTopByTotalRacesCountExcelZipFilePath(rootDir: String) = + fullPath(rootDir, TOP_BY_TOTAL_RACES_ZIP) + + @JvmStatic + fun getTopByBestSpeedFilePath(rootDir: String) = + fullPath(rootDir, TOP_BY_BEST_SPEED) + + @JvmStatic + fun getTopByBestSpeedExcelFilePath(rootDir: String) = + fullPath(rootDir, TOP_BY_BEST_SPEED_XLSX) + + @JvmStatic + fun getTopByBestSpeedExcelZipFilePath(rootDir: String) = + fullPath(rootDir, TOP_BY_BEST_SPEED_ZIP) + + @JvmStatic + fun getTopByRatingLevelFilePath(rootDir: String) = + fullPath(rootDir, TOP_BY_RATING_LEVEL) + + @JvmStatic + fun getTopByRatingLevelExcelFilePath(rootDir: String) = + fullPath(rootDir, TOP_BY_RATING_LEVEL_XLSX) + + @JvmStatic + fun getTopByRatingLevelExcelZipFilePath(rootDir: String) = + fullPath(rootDir, TOP_BY_RATING_LEVEL_ZIP) + + @JvmStatic + fun getTopByFriendsCountFilePath(rootDir: String) = + fullPath(rootDir, TOP_BY_FRIENDS_COUNT) + + @JvmStatic + fun getTopByFriendsCountExcelFilePath(rootDir: String) = + fullPath(rootDir, TOP_BY_FRIENDS_COUNT_XLSX) + + @JvmStatic + fun getTopByFriendsCountExcelZipFilePath(rootDir: String) = + fullPath(rootDir, TOP_BY_FRIENDS_COUNT_ZIP) + + @JvmStatic + fun getTopByAchievementsCountFilePath(rootDir: String) = + fullPath(rootDir, TOP_BY_ACHIEVEMENTS_COUNT) + + @JvmStatic + fun getTopByAchievementsCountExcelFilePath(rootDir: String) = + fullPath(rootDir, TOP_BY_ACHIEVEMENTS_COUNT_XLSX) + + @JvmStatic + fun getTopByAchievementsCountExcelZipFilePath(rootDir: String) = + fullPath(rootDir, TOP_BY_ACHIEVEMENTS_COUNT_ZIP) + + @JvmStatic + fun getTopByVocabulariesCountFilePath(rootDir: String) = + fullPath(rootDir, TOP_BY_VOCABULARIES_COUNT) + + @JvmStatic + fun getTopByVocabulariesCountExcelFilePath(rootDir: String) = + fullPath(rootDir, TOP_BY_VOCABULARIES_COUNT_XLSX) + + @JvmStatic + fun getTopByVocabulariesCountExcelZipFilePath(rootDir: String) = + fullPath(rootDir, TOP_BY_VOCABULARIES_COUNT_ZIP) + + @JvmStatic + fun getTopByCarsCountFilePath(rootDir: String) = + fullPath(rootDir, TOP_BY_CARS_COUNT) + + @JvmStatic + fun getTopByCarsCountExcelFilePath(rootDir: String) = + fullPath(rootDir, TOP_BY_CARS_COUNT_XLSX) + + @JvmStatic + fun getTopByCarsCountExcelZipFilePath(rootDir: String) = + fullPath(rootDir, TOP_BY_CARS_COUNT_ZIP) + + @JvmStatic + fun getPlayerByRankFilePath(rootDir: String) = + fullPath(rootDir, PLAYER_BY_RANK) + + @JvmStatic + fun getPlayerByRankDataFilePath(rootDir: String) = + fullPath(rootDir, PLAYERS_BY_RANK_DATA_JS) + + private fun fullPath(rootDir: String, relativePath: String) = + "$rootDir/$relativePath" +} \ No newline at end of file From 38e9f67aa15f97d69cb1e02c74a2dfb266ac938d Mon Sep 17 00:00:00 2001 From: dmitry-weirdo Date: Fri, 22 Nov 2024 03:03:06 +0100 Subject: [PATCH 11/30] feat: #81 Convert HaulUtils and HaulUtilsTest to Kotlin. --- .../statistics/freemarker/HaulUtils.java | 31 ------------------ .../statistics/freemarker/HaulUtils.kt | 30 +++++++++++++++++ .../statistics/freemarker/HaulUtilsTest.java | 32 ------------------- .../statistics/freemarker/HaulUtilsTest.kt | 31 ++++++++++++++++++ 4 files changed, 61 insertions(+), 63 deletions(-) delete mode 100644 kgstatsSrv/src/main/java/ru/klavogonki/statistics/freemarker/HaulUtils.java create mode 100644 kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/freemarker/HaulUtils.kt delete mode 100644 kgstatsSrv/src/test/java/ru/klavogonki/statistics/freemarker/HaulUtilsTest.java create mode 100644 kgstatsSrv/src/test/kotlin/ru/klavogonki/statistics/freemarker/HaulUtilsTest.kt diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/freemarker/HaulUtils.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/freemarker/HaulUtils.java deleted file mode 100644 index 4624a7691..000000000 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/freemarker/HaulUtils.java +++ /dev/null @@ -1,31 +0,0 @@ -package ru.klavogonki.statistics.freemarker; - -import lombok.extern.log4j.Log4j2; - -@Log4j2 -public final class HaulUtils { - - // todo: use some library with these constants - // see https://stackoverflow.com/questions/2442486/time-consts-in-java - public static final int SECONDS_IN_MINUTE = 60; - public static final int MINUTES_IN_HOUR = 60; - public static final int SECONDS_IN_HOUR = SECONDS_IN_MINUTE * MINUTES_IN_HOUR; - - private HaulUtils() { - } - - public static String format(Integer haul) { - if (haul == null || haul < 0) { - return "—"; - } - - int hours = haul / SECONDS_IN_HOUR; - int minutes = (haul % SECONDS_IN_HOUR) / SECONDS_IN_MINUTE; - int seconds = haul % SECONDS_IN_MINUTE; - - // todo: библиотека со склонением слов - String result = String.format("%d ч. %d мин. %d сек.", hours, minutes, seconds); - logger.debug("Haul {} converted to formatted string: {}", haul, result); - return result; - } -} diff --git a/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/freemarker/HaulUtils.kt b/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/freemarker/HaulUtils.kt new file mode 100644 index 000000000..73dd0b45b --- /dev/null +++ b/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/freemarker/HaulUtils.kt @@ -0,0 +1,30 @@ +package ru.klavogonki.statistics.freemarker + +import org.apache.logging.log4j.kotlin.Logging + +object HaulUtils : Logging { + // todo: use some library with these constants + // see https://stackoverflow.com/questions/2442486/time-consts-in-java + private const val SECONDS_IN_MINUTE = 60 + private const val MINUTES_IN_HOUR = 60 + private const val SECONDS_IN_HOUR = SECONDS_IN_MINUTE * MINUTES_IN_HOUR + + const val NO_HAUL_STRING = "—" + + @JvmStatic + fun format(haul: Int?): String { + if (haul == null || haul < 0) { + return NO_HAUL_STRING + } + + val hours = haul / SECONDS_IN_HOUR + val minutes = (haul % SECONDS_IN_HOUR) / SECONDS_IN_MINUTE + val seconds = haul % SECONDS_IN_MINUTE + + // todo: библиотека со склонением слов + val result = "$hours ч. $minutes мин. $seconds сек." + logger.debug("Haul $haul converted to formatted string \"$result\".") + + return result + } +} diff --git a/kgstatsSrv/src/test/java/ru/klavogonki/statistics/freemarker/HaulUtilsTest.java b/kgstatsSrv/src/test/java/ru/klavogonki/statistics/freemarker/HaulUtilsTest.java deleted file mode 100644 index fa121c529..000000000 --- a/kgstatsSrv/src/test/java/ru/klavogonki/statistics/freemarker/HaulUtilsTest.java +++ /dev/null @@ -1,32 +0,0 @@ -package ru.klavogonki.statistics.freemarker; - -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -class HaulUtilsTest { - - @Test - void testNull() { - String haul = HaulUtils.format(null); - assertThat(haul).isEqualTo("—"); - } - - @Test - void testSecondsLessThanMinute() { - String haul = HaulUtils.format(59); - assertThat(haul).isEqualTo("0 ч. 0 мин. 59 сек."); - } - - @Test - void testMoreThan1Hour() { - String haul = HaulUtils.format(3735); - assertThat(haul).isEqualTo("1 ч. 2 мин. 15 сек."); - } - - @Test - void testRealHaul() { - String haul = HaulUtils.format(1029641); - assertThat(haul).isEqualTo("286 ч. 0 мин. 41 сек."); - } -} diff --git a/kgstatsSrv/src/test/kotlin/ru/klavogonki/statistics/freemarker/HaulUtilsTest.kt b/kgstatsSrv/src/test/kotlin/ru/klavogonki/statistics/freemarker/HaulUtilsTest.kt new file mode 100644 index 000000000..a9953b2cd --- /dev/null +++ b/kgstatsSrv/src/test/kotlin/ru/klavogonki/statistics/freemarker/HaulUtilsTest.kt @@ -0,0 +1,31 @@ +package ru.klavogonki.statistics.freemarker + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class HaulUtilsTest { + + @Test + fun testNull() { + val haul = HaulUtils.format(null) + assertThat(haul).isEqualTo(HaulUtils.NO_HAUL_STRING) + } + + @Test + fun testSecondsLessThanMinute() { + val haul = HaulUtils.format(59) + assertThat(haul).isEqualTo("0 ч. 0 мин. 59 сек.") + } + + @Test + fun testMoreThan1Hour() { + val haul = HaulUtils.format(3735) + assertThat(haul).isEqualTo("1 ч. 2 мин. 15 сек.") + } + + @Test + fun testRealHaul() { + val haul = HaulUtils.format(1029641) + assertThat(haul).isEqualTo("286 ч. 0 мин. 41 сек.") + } +} From 7cfedbf48c7c61a240b348380ad8c87eed13a0b8 Mon Sep 17 00:00:00 2001 From: dmitry-weirdo Date: Fri, 22 Nov 2024 03:55:05 +0100 Subject: [PATCH 12/30] refactor: #81 In StandardDictionary enum, use enum fields instead of ugly static methods (same as it was done for the Rank enum). --- .../ru/klavogonki/kgparser/Competition.java | 2 +- .../ru/klavogonki/kgparser/Dictionary.java | 20 +- .../kgparser/StandardDictionary.java | 189 ++++++++---------- .../java/ru/klavogonki/kgparser/Wiki.java | 12 ++ .../kgparser/processing/FakeDataFactory.java | 2 +- .../klavogonki/kgparser/test/TestHelper.java | 2 +- .../export/vocabulary/VocabularyTopUtils.kt | 10 +- .../statistics/util/JacksonUtilsTest.java | 12 +- 8 files changed, 121 insertions(+), 128 deletions(-) create mode 100644 kgparserSrv/src/main/java/ru/klavogonki/kgparser/Wiki.java diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Competition.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Competition.java index c49032f11..0e261c9d3 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Competition.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Competition.java @@ -250,7 +250,7 @@ public void fillDictionariesNames() { if (dictionary.isStandard()) { StandardDictionary standardDictionary = StandardDictionary.valueOf(dictionaryCode); - codesToNames.put(dictionaryCode, StandardDictionary.getDisplayName(standardDictionary)); + codesToNames.put(dictionaryCode, standardDictionary.displayName); } else { diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Dictionary.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Dictionary.java index a044c48fc..cf55a4aa3 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Dictionary.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Dictionary.java @@ -113,11 +113,13 @@ public static boolean isStandard(String code) { */ @Json(exclude = true) public static int getDictionaryId(String code) { - if ( isStandard(code) ) { - throw new IllegalArgumentException("Dictionary with code = \"" + code + "\" is standard. Cannot get dictionary id from it."); // todo: use concat + if (isStandard(code)) { + throw new IllegalArgumentException( + String.format("Dictionary with code = \"%s\" is standard. Cannot get dictionary id from it.", code) + ); } - String codeStr = code.substring( NON_STANDARD_DICTIONARY_ID_PREFIX.length() ); + String codeStr = code.substring(NON_STANDARD_DICTIONARY_ID_PREFIX.length()); return Integer.parseInt(codeStr); } @@ -137,7 +139,7 @@ public static int getTextType(String code) { } StandardDictionary standardDictionary = StandardDictionary.valueOf(code); - return StandardDictionary.getTextType(standardDictionary); + return standardDictionary.textType; } /** @@ -146,9 +148,8 @@ public static int getTextType(String code) { */ @Json(exclude = true) public static String getDictionaryColor(String dictionaryCode) { - if ( isStandard(dictionaryCode) ) - { - return StandardDictionary.getColor( StandardDictionary.valueOf(dictionaryCode) ); + if (isStandard(dictionaryCode)) { + return StandardDictionary.valueOf(dictionaryCode).color; } return NON_STANDARD_DICTIONARY_COLOR; @@ -161,8 +162,9 @@ public static String getDictionaryColor(String dictionaryCode) { * ссылка на страницу словаря — для нестандартных словарей */ public static String getDictionaryPageUrl(String dictionaryCode) { - if ( isStandard(dictionaryCode) ) - return StandardDictionary.getDictionaryPageUrl( StandardDictionary.valueOf(dictionaryCode) ); + if (isStandard(dictionaryCode)) { + return StandardDictionary.valueOf(dictionaryCode).wikiPageUrl; + } return UrlConstructor.dictionaryPage( getDictionaryId(dictionaryCode) ); } diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/StandardDictionary.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/StandardDictionary.java index 4771a5949..839984a5f 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/StandardDictionary.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/StandardDictionary.java @@ -8,159 +8,138 @@ * $Date:: $ *
*
- * Энум с названиями стандартных словарей (режимов), как они используются в ajax-api. + * Энум с названиями стандартных словарей (режимов), как они используются в AJAX-API. */ public enum StandardDictionary { /** * Обычный. */ - normal, + normal( + "Обычный", + "Обычном", + "#333333", + Wiki.getUrl("%D0%9E%D0%B1%D1%8B%D1%87%D0%BD%D1%8B%D0%B9"), + 0 + ), /** * Безошибочный. */ - noerror, + noerror( + "Безошибочный", + "Безошибочном", + "#4692AA", + Wiki.getUrl("%D0%91%D0%B5%D0%B7%D0%BE%D1%88%D0%B8%D0%B1%D0%BE%D1%87%D0%BD%D1%8B%D0%B9"), + 0 + ), /** * Буквы. */ - chars, + chars( + "Буквы", + "Буквах", + "#B55900", + Wiki.getUrl("%D0%91%D1%83%D0%BA%D0%B2%D1%8B"), + -4 + ), /** * Марафон. */ - marathon, + marathon( + "Марафон", + "Марафоне", + "#D43E68", + Wiki.getUrl("%D0%9C%D0%B0%D1%80%D0%B0%D1%84%D0%BE%D0%BD"), + 0 + ), /** * Абракадабра. */ - abra, + abra( + "Абракадабра", + "Абракадабре", + "#3D4856", + Wiki.getUrl("%D0%90%D0%B1%D1%80%D0%B0%D0%BA%D0%B0%D0%B4%D0%B0%D0%B1%D1%80%D0%B0"), + -1 + ), /** * Яндекс.Рефераты. */ - referats, + referats( + "Яндекс.Рефераты", + "Яндекс.Рефератах", + "#698725", + Wiki.getUrl("%D0%AF%D0%BD%D0%B4%D0%B5%D0%BA%D1%81.%D0%A0%D0%B5%D1%84%D0%B5%D1%80%D0%B0%D1%82%D1%8B"), + -3 + ), /** * Цифры. */ - digits, + digits( + "Цифры", + "Цифрах", + "#777777", + Wiki.getUrl("%D0%A6%D0%B8%D1%84%D1%80%D1%8B"), + -2 + ), /** * Спринт. */ - sprint, + sprint( + "Спринт", + "Спринте", + "#833F3A", + Wiki.getUrl("%D0%A1%D0%BF%D1%80%D0%B8%D0%BD%D1%82"), + 0 + ), ; - /** - * @param dictionary стандартный словарь - * @return цвет стандартного словаря в формате «#123456» - */ - public static String getColor(StandardDictionary dictionary) { - switch (dictionary) - { - case normal: return "#333333"; - case noerror: return "#4692AA"; - case chars: return "#B55900"; - case marathon: return "#D43E68"; - case abra: return "#3D4856"; - case referats: return "#698725"; - case digits: return "#777777"; - case sprint: return "#833F3A"; - - default: - throw new IllegalArgumentException("Unknown standard dictionary: " + dictionary); // todo: use concat - } + StandardDictionary( + String displayName, + String displayNamePrepositional, + String color, + String wikiPageUrl, + int textType + ) { + this.displayName = displayName; + this.displayNamePrepositional = displayNamePrepositional; + this.color = color; + this.wikiPageUrl = wikiPageUrl; + this.textType = textType; } /** - * @param dictionary стандартный словарь - * @return русское название словаря для отображения + * Русское название словаря для отображения. */ - public static String getDisplayName(StandardDictionary dictionary) { - switch (dictionary) - { - case normal: return "Обычный"; - case noerror: return "Безошибочный"; - case chars: return "Буквы"; - case marathon: return "Марафон"; - case abra: return "Абракадабра"; - case referats: return "Яндекс.Рефераты"; - case digits: return "Цифры"; - case sprint: return "Спринт"; - - default: - throw new IllegalArgumentException("Unknown standard dictionary: " + dictionary); // todo: use concat - } - } + public final String displayName; /** - * @param dictionary стандартный словарь - * @return русское название словаря для отображения, в предложном падеже + * Русское название словаря для отображения, в предложном падеже. */ - public static String getDisplayNameInPrepositionalCase(StandardDictionary dictionary) { - switch (dictionary) - { - case normal: return "Обычном"; - case noerror: return "Безошибочном"; - case chars: return "Буквах"; - case marathon: return "Марафоне"; - case abra: return "Абракадабре"; - case referats: return "Яндекс.Рефератах"; - case digits: return "Цифрах"; - case sprint: return "Спринте"; - - default: - throw new IllegalArgumentException("Unknown standard dictionary: " + dictionary); // todo: use concat - } - } + public final String displayNamePrepositional; /** - * @param dictionary стандартный словарь - * @return страница стандартного словаря в википедии клавогонок. + * Цвет стандартного словаря в формате «#123456» */ - public static String getDictionaryPageUrl(StandardDictionary dictionary) { - switch (dictionary) - { - case normal: return "http://klavogonki.ru/wiki/%D0%9E%D0%B1%D1%8B%D1%87%D0%BD%D1%8B%D0%B9"; - case noerror: return "http://klavogonki.ru/wiki/%D0%91%D0%B5%D0%B7%D0%BE%D1%88%D0%B8%D0%B1%D0%BE%D1%87%D0%BD%D1%8B%D0%B9"; - case chars: return "http://klavogonki.ru/wiki/%D0%91%D1%83%D0%BA%D0%B2%D1%8B"; - case marathon: return "http://klavogonki.ru/wiki/%D0%9C%D0%B0%D1%80%D0%B0%D1%84%D0%BE%D0%BD"; - case abra: return "http://klavogonki.ru/wiki/%D0%90%D0%B1%D1%80%D0%B0%D0%BA%D0%B0%D0%B4%D0%B0%D0%B1%D1%80%D0%B0"; - case referats: return "http://klavogonki.ru/wiki/%D0%AF%D0%BD%D0%B4%D0%B5%D0%BA%D1%81.%D0%A0%D0%B5%D1%84%D0%B5%D1%80%D0%B0%D1%82%D1%8B"; - case digits: return "http://klavogonki.ru/wiki/%D0%A6%D0%B8%D1%84%D1%80%D1%8B"; - case sprint: return "http://klavogonki.ru/wiki/%D0%A1%D0%BF%D1%80%D0%B8%D0%BD%D1%82"; + public final String color; - default: - throw new IllegalArgumentException("Unknown standard dictionary: " + dictionary); // todo: use concat - } - } - - public static int getTextType(StandardDictionary dictionary) { // for non-standards it, will be dictionaryId - switch (dictionary) { - case normal: - case noerror: - case sprint: - case marathon: - return 0; - - case abra: - return -1; - - case digits: - return -2; - - case referats: - return -3; - - case chars: - return -4; + /** + * Страница стандартного словаря в википедии клавогонок. + */ + public final String wikiPageUrl; - default: - throw new IllegalArgumentException("Unknown standard dictionary: " + dictionary); // todo: use concat - } - } + /** + * Тип текста словаря. + * Для нестандартных словарей будет равен идентификатору словаря. + */ + public final int textType; public static boolean isValidStandardDictionaryCode(String code) { try { diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Wiki.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Wiki.java new file mode 100644 index 000000000..4677b8a0c --- /dev/null +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Wiki.java @@ -0,0 +1,12 @@ +package ru.klavogonki.kgparser; + +public class Wiki { + public static final String WIKI_BASE_URL = "https://klavogonki.ru/wiki/"; + + private Wiki() { + } + + public static String getUrl(String pageName) { + return WIKI_BASE_URL + pageName.trim(); + } +} diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/processing/FakeDataFactory.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/processing/FakeDataFactory.java index bca1367a6..cacd6b4a7 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/processing/FakeDataFactory.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/processing/FakeDataFactory.java @@ -69,7 +69,7 @@ public static Round createRound(Dictionary dictionary) { // todo: move to constructors public static Dictionary getDictionary(StandardDictionary dictionary) { - return getDictionary( dictionary.toString(), StandardDictionary.getDisplayName(dictionary) ); + return getDictionary( dictionary.toString(), dictionary.displayName ); } public static Dictionary getDictionary(int dictionaryId, String name) { return getDictionary( Dictionary.getDictionaryCode(dictionaryId), name ); diff --git a/kgparserSrv/src/test/java/ru/klavogonki/kgparser/test/TestHelper.java b/kgparserSrv/src/test/java/ru/klavogonki/kgparser/test/TestHelper.java index 3b55ebc1d..19342f624 100644 --- a/kgparserSrv/src/test/java/ru/klavogonki/kgparser/test/TestHelper.java +++ b/kgparserSrv/src/test/java/ru/klavogonki/kgparser/test/TestHelper.java @@ -25,7 +25,7 @@ public static Round createRound(Dictionary dictionary) { // todo: move to constructors public static Dictionary getDictionary(StandardDictionary dictionary) { - return getDictionary( dictionary.toString(), StandardDictionary.getDisplayName(dictionary) ); + return getDictionary( dictionary.toString(), dictionary.displayName ); } public static Dictionary getDictionary(int dictionaryId, String name) { return getDictionary( Dictionary.getDictionaryCode(dictionaryId), name ); diff --git a/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/export/vocabulary/VocabularyTopUtils.kt b/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/export/vocabulary/VocabularyTopUtils.kt index 01937f6fb..1467202dd 100644 --- a/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/export/vocabulary/VocabularyTopUtils.kt +++ b/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/export/vocabulary/VocabularyTopUtils.kt @@ -10,7 +10,7 @@ object VocabularyTopUtils : Logging { @JvmStatic fun takenPlayersWithMinimalRacesCount(vocabulary: StandardDictionary, racesCount: Int) = takenPlayersWithMinimalRacesCount( - StandardDictionary.getDisplayNameInPrepositionalCase(vocabulary), + vocabulary.displayNamePrepositional, racesCount ) @@ -24,7 +24,7 @@ object VocabularyTopUtils : Logging { @JvmStatic fun topByBestSpeedIn(vocabulary: StandardDictionary) = - topByBestSpeedIn(StandardDictionary.getDisplayNameInPrepositionalCase(vocabulary)) + topByBestSpeedIn(vocabulary.displayNamePrepositional) @JvmStatic fun topByBestSpeedIn(vocabulary: NonStandardDictionary) = @@ -36,7 +36,7 @@ object VocabularyTopUtils : Logging { @JvmStatic fun topByRecordIn(vocabulary: StandardDictionary) = - topByRecordIn(StandardDictionary.getDisplayNameInPrepositionalCase(vocabulary)) + topByRecordIn(vocabulary.displayNamePrepositional) @JvmStatic fun topByRecordIn(vocabulary: NonStandardDictionary) = @@ -129,7 +129,7 @@ object VocabularyTopUtils : Logging { @JvmStatic fun topByRacesCountIn(vocabulary: StandardDictionary) = - topByRacesCountIn(StandardDictionary.getDisplayNameInPrepositionalCase(vocabulary)) + topByRacesCountIn(vocabulary.displayNamePrepositional) @JvmStatic fun topByRacesCountIn(vocabulary: NonStandardDictionary) = @@ -141,7 +141,7 @@ object VocabularyTopUtils : Logging { @JvmStatic fun topByHaulIn(vocabulary: StandardDictionary) = - topByHaulIn(StandardDictionary.getDisplayNameInPrepositionalCase(vocabulary)) + topByHaulIn(vocabulary.displayNamePrepositional) @JvmStatic fun topByHaulIn(vocabulary: NonStandardDictionary) = diff --git a/kgstatsSrv/src/test/java/ru/klavogonki/statistics/util/JacksonUtilsTest.java b/kgstatsSrv/src/test/java/ru/klavogonki/statistics/util/JacksonUtilsTest.java index b3891c4b6..64c00d762 100644 --- a/kgstatsSrv/src/test/java/ru/klavogonki/statistics/util/JacksonUtilsTest.java +++ b/kgstatsSrv/src/test/java/ru/klavogonki/statistics/util/JacksonUtilsTest.java @@ -495,12 +495,12 @@ void existingPlayer() { // todo: validate size // validate player stats in "normal" - GetStatsOverviewGameType normalStats = gameTypes.get(StandardDictionary.normal.name());// no getValue, but toString works + GetStatsOverviewGameType normalStats = gameTypes.get(StandardDictionary.normal.name()); // no getValue, but toString works GetStatsOverviewGameTypeAssert .assertThat(normalStats) .isNotNull() .hasId(null) - .hasName(StandardDictionary.getDisplayName(StandardDictionary.normal)) + .hasName(StandardDictionary.normal.displayName) .hasNumRaces(29445) .hasType(null) // type set for non-standard dictionaries only .hasRows(null) // rows set for non-standard dictionaries only @@ -514,7 +514,7 @@ void existingPlayer() { .hasId(1826608) .hasUserId(242585) .hasMode(VocabularyMode.NORMAL) - .hasTexttype(StandardDictionary.getTextType(StandardDictionary.normal)) + .hasTexttype(StandardDictionary.normal.textType) .hasNumRaces(29445) .hasAvgSpeed(453.123) .hasBestSpeed(626) @@ -568,12 +568,12 @@ void brandNewPlayer() { .hasSize(1); // for new player, only empty result for "normal" is present // validate player stats in "normal" - GetStatsOverviewGameType normalStats = gameTypes.get(StandardDictionary.normal.name());// no getValue, but toString works + GetStatsOverviewGameType normalStats = gameTypes.get(StandardDictionary.normal.name()); // no getValue, but toString works GetStatsOverviewGameTypeAssert .assertThat(normalStats) .isNotNull() .hasId(null) - .hasName(StandardDictionary.getDisplayName(StandardDictionary.normal)) + .hasName(StandardDictionary.normal.displayName) .hasNumRaces(0) .hasType(null) // type set for non-standard dictionaries only .hasRows(null) // rows set for non-standard dictionaries only @@ -588,7 +588,7 @@ void brandNewPlayer() { .hasId(30914229) .hasUserId(624511) .hasMode(VocabularyMode.NORMAL) - .hasTexttype(StandardDictionary.getTextType(StandardDictionary.normal)) + .hasTexttype(StandardDictionary.normal.textType) .hasNumRaces(0) .hasAvgSpeed(0d) .hasBestSpeed(null) From b22af043ab661c12977fe4d8aba28acdb7d8e7b8 Mon Sep 17 00:00:00 2001 From: dmitry-weirdo Date: Fri, 22 Nov 2024 04:10:57 +0100 Subject: [PATCH 13/30] feat: #101 Reduce kefir's StringUtils.concat usage - use String.format instead. --- .../ru/klavogonki/kgparser/Competition.java | 44 ++++++++++++++----- .../java/ru/klavogonki/kgparser/Rank.java | 4 +- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Competition.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Competition.java index 0e261c9d3..fbdba0fdf 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Competition.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Competition.java @@ -18,8 +18,6 @@ import java.util.SortedSet; import java.util.TreeSet; -import static su.opencode.kefir.util.StringUtils.concat; - /** * Соревнование. Содержит в себе набор заездов в рамках соревнования. * По заездам соревнования формируются результаты. @@ -153,8 +151,11 @@ public void fillPlayersRanks() { continue; Rank normalRank = profileIdsToRanks.get( player.getProfileId() ); - if (normalRank == null) - throw new IllegalStateException( concat("Cannot get normal rank for player with profileId = \"", player.getProfileId(), "\"") ); + if (normalRank == null) { + throw new IllegalStateException( + String.format("Cannot get normal rank for player with profileId = %d.", player.getProfileId()) + ); + } player.setRank(normalRank); } @@ -204,7 +205,11 @@ public void fillPlayersNormalModeData() { Integer profileId = player.getProfileId(); Rank normalRank = profileIdsToRanks.get(profileId); if (normalRank == null) - throw new IllegalStateException( concat("Cannot get normal rank for player with profileId = \"", profileId, "\"") ); + { + throw new IllegalStateException( + String.format("Cannot get normal rank for player with profileId = %d.", profileId) + ); + } Integer normalRecord = profileIdsToNormalRecords.get(profileId); // do not check on null because normal record may be null @@ -227,7 +232,11 @@ public Set getDictionaries() { { Dictionary dictionary = round.getDictionary(); if (dictionary == null) - throw new IllegalStateException( StringUtils.concat("Round ", round.getNumber(), " has no set dictionary") ); + { + throw new IllegalStateException( + String.format("Round %d has no set dictionary", round.getNumber()) + ); + } dictionaries.add(dictionary); } @@ -315,18 +324,25 @@ public boolean containsDictionary(Dictionary dictionary) { @Json(exclude = true) public int getRoundsCount(String dictionaryCode) { if ( StringUtils.empty(dictionaryCode) ) + { throw new IllegalArgumentException("dictionaryCode must not be null or empty"); + } int count = 0; for (Round round : rounds) { Dictionary dictionary = round.getDictionary(); - if (dictionary == null) - throw new IllegalStateException( StringUtils.concat("Round ", round.getNumber(), " has no set dictionary") ); + if (dictionary == null) { + throw new IllegalStateException( + String.format("Round %d has no set dictionary.", round.getNumber()) + ); + } if ( dictionary.hasCode(dictionaryCode) ) + { count++; + } } return count; @@ -337,8 +353,9 @@ public int getRoundsCount(String dictionaryCode) { */ @Json(exclude = true) public int getRoundsCount(Dictionary dictionary) { - if (dictionary == null) + if (dictionary == null) { throw new IllegalArgumentException("dictionary cannot be null"); + } return getRoundsCount( dictionary.getCode() ); } @@ -349,8 +366,9 @@ public int getRoundsCount(Dictionary dictionary) { */ @Json(exclude = true) public int getRoundsCount(Player player) { - if (player == null) + if (player == null) { throw new IllegalArgumentException("player cannot be null"); + } int count = 0; @@ -398,7 +416,11 @@ public Map> getRoundsByDictionariesMap() { { Dictionary dictionary = round.getDictionary(); if (dictionary == null) - throw new IllegalStateException( StringUtils.concat("Round ", round.getNumber(), " has no set dictionary") ); + { + throw new IllegalStateException( + String.format("Round %d has no set dictionary.", round.getNumber()) + ); + } String dictionaryCode = dictionary.getCode(); diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Rank.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Rank.java index f50a40873..3bdf7403f 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Rank.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Rank.java @@ -2,8 +2,6 @@ import java.util.Arrays; -import static su.opencode.kefir.util.StringUtils.concat; - /** * Ранг игрока. Различается в зависимости от рекорда в обычном режиме. */ @@ -121,7 +119,7 @@ public static Rank getRank(int level) { .filter( rank -> rank.level == level ) .findFirst() .orElseThrow(() -> - new IllegalArgumentException( concat("Incorrect rank level: " + level) ) + new IllegalArgumentException( String.format("Incorrect rank level: %d.", level) ) ); } From 7f4a4dfe05a91a596be19b5cc9dc5ef23f2c5682 Mon Sep 17 00:00:00 2001 From: dmitry-weirdo Date: Fri, 22 Nov 2024 04:18:57 +0100 Subject: [PATCH 14/30] chore: #101 Remove kefir's StringUtils.concat usage from kgparser-srv module. --- .../java/ru/klavogonki/kgparser/Dictionary.java | 2 +- .../klavogonki/kgparser/PlayerRoundResult.java | 16 +++++++--------- .../PlayerRoundResultPlacesComparator.java | 6 ++---- .../kgparser/http/ConfigurationLoader.java | 4 +--- .../players_table/PlayersResultsTable.java | 5 +---- 5 files changed, 12 insertions(+), 21 deletions(-) diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Dictionary.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Dictionary.java index cf55a4aa3..e386002d7 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Dictionary.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Dictionary.java @@ -129,7 +129,7 @@ public static int getDictionaryId(String code) { */ @Json(exclude = true) public static String getDictionaryCode(int dictionaryId) { - return StringUtils.concat( NON_STANDARD_DICTIONARY_ID_PREFIX, Integer.toString(dictionaryId) ); + return NON_STANDARD_DICTIONARY_ID_PREFIX + dictionaryId; } @Json(exclude = true) diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/PlayerRoundResult.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/PlayerRoundResult.java index 642fe5b6e..b9530e257 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/PlayerRoundResult.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/PlayerRoundResult.java @@ -5,8 +5,6 @@ import java.util.Date; -import static su.opencode.kefir.util.StringUtils.concat; - /** * Результат игрока в конкретном заезде. */ @@ -39,13 +37,13 @@ public Integer getPlace() { return null; if (place < FIRST_PLACE) - throw new IllegalArgumentException( concat("Incorrect place: ", place) ); + throw new IllegalArgumentException( String.format("Incorrect place: %d.", place) ); return place; } public void setPlace(Integer place) { if (place < FIRST_PLACE) - throw new IllegalArgumentException( concat("Incorrect place: ", place) ); + throw new IllegalArgumentException( String.format("Incorrect place: %d.", place) ); this.place = place; } @@ -69,7 +67,7 @@ public Integer getSpeed() { } public void setSpeed(Integer speed) { if (speed <= 0) - throw new IllegalArgumentException( concat("Incorrect speed: ", speed) ); + throw new IllegalArgumentException( String.format("Incorrect speed: %d.", speed) ); this.speed = speed; } @@ -79,7 +77,7 @@ public Integer getCharsTotal() { } public void setCharsTotal(Integer charsTotal) { if (charsTotal <= 0) - throw new IllegalArgumentException( concat("Incorrect charsTotal: ", charsTotal) ); + throw new IllegalArgumentException( String.format("Incorrect charsTotal: %d.", charsTotal) ); this.charsTotal = charsTotal; } @@ -89,7 +87,7 @@ public Integer getErrorsCount() { } public void setErrorsCount(Integer errorsCount) { if (errorsCount < 0) - throw new IllegalArgumentException( concat("Incorrect errorsCount: ", errorsCount) ); + throw new IllegalArgumentException( String.format("Incorrect errorsCount: %d.", errorsCount) ); this.errorsCount = errorsCount; } @@ -99,7 +97,7 @@ public Double getErrorPercentage() { } public void setErrorPercentage(Double errorPercentage) { if (errorPercentage < 0) - throw new IllegalArgumentException( concat("Incorrect errorPercentage: ", errorPercentage) ); + throw new IllegalArgumentException( String.format("Incorrect errorPercentage: %s.", errorPercentage) ); this.errorPercentage = errorPercentage; } @@ -116,7 +114,7 @@ public Float getTime() { } public void setTime(Float time) { if (time < 0) - throw new IllegalArgumentException( concat("Incorrect time: ", time) ); + throw new IllegalArgumentException( String.format("Incorrect time: %s.", time) ); this.time = time; } diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/PlayerRoundResultPlacesComparator.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/PlayerRoundResultPlacesComparator.java index 14e648c78..0dd7eff86 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/PlayerRoundResultPlacesComparator.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/PlayerRoundResultPlacesComparator.java @@ -2,8 +2,6 @@ import java.util.Comparator; -import static su.opencode.kefir.util.StringUtils.concat; - /** * Copyright 2014 Dmitriy Popov. * $HeadURL$ @@ -24,11 +22,11 @@ public int compare(PlayerRoundResult o1, PlayerRoundResult o2) { // check place1 validity if ( (place1 != null) && (!PlayerRoundResult.isCorrectPlace(place1)) ) - throw new IllegalArgumentException( concat("Incorrect player1 place: ", place1) ); + throw new IllegalArgumentException( String.format("Incorrect player1 place: %d.", place1) ); // check place2 validity if ( (place2 != null) && (!PlayerRoundResult.isCorrectPlace(place2)) ) - throw new IllegalArgumentException( concat("Incorrect player2 place: ", place2) ); + throw new IllegalArgumentException( String.format("Incorrect player2 place: %d.", place2) ); if ( (place1 == null) && (place2 == null) ) return 0; // undefined order diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/http/ConfigurationLoader.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/http/ConfigurationLoader.java index e29c0498a..2c93c93b6 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/http/ConfigurationLoader.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/http/ConfigurationLoader.java @@ -4,8 +4,6 @@ import java.nio.charset.StandardCharsets; -import static su.opencode.kefir.util.StringUtils.concat; - /** * Copyright 2014 Dmitriy Popov. * $HeadURL$ @@ -16,7 +14,7 @@ public class ConfigurationLoader { public String readConfigurationFile(String filePath) { - String path = concat( System.getProperty("jboss.server.home.dir"), "/conf/", filePath); + String path = System.getProperty("jboss.server.home.dir") + "/conf/" + filePath; byte[] bytes = FileUtils.readFile(path); return new String(bytes, StandardCharsets.UTF_8); } diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/processing/players_table/PlayersResultsTable.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/processing/players_table/PlayersResultsTable.java index 822126657..159072b21 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/processing/players_table/PlayersResultsTable.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/processing/players_table/PlayersResultsTable.java @@ -5,7 +5,6 @@ import ru.klavogonki.kgparser.Competition; import ru.klavogonki.kgparser.Player; import ru.klavogonki.kgparser.PlayerRoundResult; -import ru.klavogonki.kgparser.Rank; import ru.klavogonki.kgparser.Round; import su.opencode.kefir.srv.json.JsonObject; import su.opencode.kefir.util.StringUtils; @@ -14,8 +13,6 @@ import java.util.List; import java.util.Set; -import static su.opencode.kefir.util.StringUtils.concat; - /** * Результирующая таблица игроков. * Присутствуют все {@linkplain ru.klavogonki.kgparser.Player игроки}, @@ -41,7 +38,7 @@ private void fillHeaderRows(Competition competition) { // rounds data for (Round round : competition.getRounds()) { - firstRow.addCell( concat(sb, "Заезд № ", round.getNumber()), 3 ); + firstRow.addCell( String.format("Заезд № %d", round.getNumber()), 3 ); } // total From 10baa8b94d1d190b23ec08d588fe0830a895edcd Mon Sep 17 00:00:00 2001 From: dmitry-weirdo Date: Mon, 25 Nov 2024 17:53:45 +0100 Subject: [PATCH 15/30] feat: #101 Remove kefir's StringUtils.concat usage from kgparser-web module. --- .../entity/CompetitionUploadServlet.java | 17 ++-- .../CompetitionZipFileDownloadServlet.java | 8 +- .../servlet/entity/ZipFileParser.java | 15 ++-- .../CompetitionBasicInfoGetServlet.java | 48 ++++++------ .../ErrorsCountChartValuesGetServlet.java | 47 +++++------ .../highchart/SpeedChartValuesGetServlet.java | 47 +++++------ .../model/round/RoundInfoGetServlet.java | 77 ++++++++++--------- .../PlayerResultsTableXlsGetServlet.java | 65 ++++++++-------- .../PlayersResultsTableDataGetServlet.java | 61 ++++++++------- 9 files changed, 195 insertions(+), 190 deletions(-) diff --git a/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/entity/CompetitionUploadServlet.java b/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/entity/CompetitionUploadServlet.java index 7bc4f0232..3f73161a9 100644 --- a/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/entity/CompetitionUploadServlet.java +++ b/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/entity/CompetitionUploadServlet.java @@ -18,8 +18,6 @@ import java.nio.charset.StandardCharsets; import java.util.List; -import static su.opencode.kefir.util.StringUtils.concat; - /** * Copyright 2014 Dmitriy Popov. * $HeadURL$ @@ -66,8 +64,10 @@ public void doAction() throws Exception { } catch (Exception e) { - logger.error( concat("Error while parsing zip file \"", entity.getZipFileName(), "\" into Competition model:"), e ); - throw new RuntimeException( concat("Error while parsing zip file \"", entity.getZipFileName(), "\" into Competition model:"), e); + String errorMessage = String.format("Error while parsing zip file \"%s\" into Competition model:", entity.getZipFileName()); + + logger.error(errorMessage, e ); + throw new RuntimeException(errorMessage, e); } try @@ -77,14 +77,17 @@ public void doAction() throws Exception { } catch (Exception e) { - logger.error(concat("Error while transforming Competition model to JSON:"), e); - throw new RuntimeException( concat("Error while transforming Competition model to JSON:"), e); + String errorMessage = "Error while transforming Competition model to JSON:"; + + logger.error(errorMessage, e); + throw new RuntimeException(errorMessage, e); } CompetitionEntityService service = getService(CompetitionEntityService.class); Long competitionId = service.createCompetitionEntity(entity); - response.sendRedirect( concat(sb, "./competitionUploadSuccess.jsp?competitionId=", competitionId) ); + String redirectLocation = String.format("./competitionUploadSuccess.jsp?competitionId=%d", competitionId); + response.sendRedirect(redirectLocation); } private CompetitionEntity processMultipartContent() throws FileUploadException, UnsupportedEncodingException { diff --git a/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/entity/CompetitionZipFileDownloadServlet.java b/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/entity/CompetitionZipFileDownloadServlet.java index f9cb89b9e..363577fe9 100644 --- a/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/entity/CompetitionZipFileDownloadServlet.java +++ b/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/entity/CompetitionZipFileDownloadServlet.java @@ -13,8 +13,6 @@ import java.io.InputStream; import java.nio.charset.StandardCharsets; -import static su.opencode.kefir.util.StringUtils.concat; - /** * Copyright 2014 LLC "Open Code" * http://www.o-code.ru @@ -33,14 +31,16 @@ protected Action getAction() { public void doAction() throws Exception { Long competitionEntityId = getLongParam(COMPETITION_ENTITY_ID_PARAM_NAME); if (competitionEntityId == null) { - throw new ClientException(concat(sb, "\"", COMPETITION_ENTITY_ID_PARAM_NAME, "\" parameter is not set")); + String errorMessage = String.format("\"%s\" parameter is not set", COMPETITION_ENTITY_ID_PARAM_NAME); + throw new ClientException(errorMessage); } CompetitionEntityService service = getService(CompetitionEntityService.class); CompetitionEntity entity = service.getCompetitionEntity(competitionEntityId); if (entity == null) { - throw new ClientException(concat(sb, "CompetitionEntity not found for id = ", competitionEntityId)); + String errorMessage = String.format("CompetitionEntity not found for id = %d", competitionEntityId); + throw new ClientException(errorMessage); } String contentType = entity.getZipFileContentType(); diff --git a/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/entity/ZipFileParser.java b/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/entity/ZipFileParser.java index dc30344fb..c0b52179f 100644 --- a/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/entity/ZipFileParser.java +++ b/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/entity/ZipFileParser.java @@ -10,8 +10,6 @@ import java.util.UUID; -import static su.opencode.kefir.util.StringUtils.concat; - /** * Copyright 2014 Dmitriy Popov. * $HeadURL$ @@ -28,26 +26,27 @@ private ZipFileParser() { } public static Competition parseZipFile(CompetitionEntity entity, String exportScriptVersion) { - StringBuilder sb = new StringBuilder(); - String dirPath = getDirPath(sb); + String dirPath = getDirPath(); logger.info("Directory path to extract zip file: \"{}\"", dirPath); FileUtils.createDirs(dirPath); logger.info("Directory \"{}\" created successfully.", dirPath); - String filePath = concat(sb, dirPath, FileUtils.FILE_SEPARATOR, entity.getZipFileName()); + String filePath = dirPath + FileUtils.FILE_SEPARATOR + entity.getZipFileName(); logger.info("Zip file path: {}", filePath); FileUtils.writeToFile(filePath, entity.getZipFileData()); logger.info("Zip file successfully written to path \"{}\".", filePath); - String extractDirPath = concat(sb, dirPath, FileUtils.FILE_SEPARATOR, "extracted"); + String extractDirPath = dirPath + FileUtils.FILE_SEPARATOR + "extracted"; ZipUtils.unzip(filePath, extractDirPath); logger.info("Zip file \"{}\" successfully extracted to path \"{}\".", filePath, extractDirPath); return VoidmainJsonParser.parseCompetition(entity.getName(), extractDirPath, exportScriptVersion); } - private static String getDirPath(StringBuilder sb) { - return concat(sb, System.getProperty("jboss.server.home.dir"), FileUtils.FILE_SEPARATOR, ZIP_FILES_EXTRACT_DIR, FileUtils.FILE_SEPARATOR, "zip-", UUID.randomUUID()); + private static String getDirPath() { + return System.getProperty("jboss.server.home.dir") + + FileUtils.FILE_SEPARATOR + ZIP_FILES_EXTRACT_DIR + + FileUtils.FILE_SEPARATOR + "zip-" + UUID.randomUUID(); } } diff --git a/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/model/basic_info/CompetitionBasicInfoGetServlet.java b/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/model/basic_info/CompetitionBasicInfoGetServlet.java index 69afbad12..952723e74 100644 --- a/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/model/basic_info/CompetitionBasicInfoGetServlet.java +++ b/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/model/basic_info/CompetitionBasicInfoGetServlet.java @@ -7,8 +7,6 @@ import su.opencode.kefir.web.InitiableAction; import su.opencode.kefir.web.JsonServlet; -import static su.opencode.kefir.util.StringUtils.concat; - /** * Copyright 2014 Dmitriy Popov. * $HeadURL$ @@ -16,31 +14,31 @@ * $Revision$ * $Date:: $ */ -public class CompetitionBasicInfoGetServlet extends JsonServlet -{ - @Override - protected Action getAction() { - return new InitiableAction() - { - @Override - public void doAction() throws Exception { - Long competitionEntityId = getLongParam(COMPETITION_ENTITY_ID_PARAM_NAME); - if (competitionEntityId == null) { - throw new ClientException( concat(sb, "\"", COMPETITION_ENTITY_ID_PARAM_NAME, "\" parameter is not set") ); - } +public class CompetitionBasicInfoGetServlet extends JsonServlet { + @Override + protected Action getAction() { + return new InitiableAction() { + @Override + public void doAction() throws Exception { + Long competitionEntityId = getLongParam(COMPETITION_ENTITY_ID_PARAM_NAME); + if (competitionEntityId == null) { + String errorMessage = String.format("\"%s\" parameter is not set", COMPETITION_ENTITY_ID_PARAM_NAME); + throw new ClientException(errorMessage); + } - CompetitionEntityService service = getService(CompetitionEntityService.class); - Competition competition = service.getCompetition(competitionEntityId); + CompetitionEntityService service = getService(CompetitionEntityService.class); + Competition competition = service.getCompetition(competitionEntityId); - if (competition == null) { - throw new ClientException( concat(sb, "Competition not found for competitionEntityId = ", competitionEntityId) ); - } + if (competition == null) { + String errorMessage = String.format("Competition not found for competitionEntityId = %d", competitionEntityId); + throw new ClientException(errorMessage); + } - CompetitionBasicInfo basicInfo = new CompetitionBasicInfo(competition); - writeSuccess(basicInfo); - } - }; - } + CompetitionBasicInfo basicInfo = new CompetitionBasicInfo(competition); + writeSuccess(basicInfo); + } + }; + } - public static final String COMPETITION_ENTITY_ID_PARAM_NAME = "competitionId"; + public static final String COMPETITION_ENTITY_ID_PARAM_NAME = "competitionId"; } diff --git a/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/model/highchart/ErrorsCountChartValuesGetServlet.java b/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/model/highchart/ErrorsCountChartValuesGetServlet.java index e416655af..acdbb262b 100644 --- a/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/model/highchart/ErrorsCountChartValuesGetServlet.java +++ b/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/model/highchart/ErrorsCountChartValuesGetServlet.java @@ -9,8 +9,6 @@ import su.opencode.kefir.web.InitiableAction; import su.opencode.kefir.web.JsonServlet; -import static su.opencode.kefir.util.StringUtils.concat; - /** * Copyright 2014 Dmitriy Popov. * $HeadURL$ @@ -18,29 +16,32 @@ * $Revision$ * $Date:: $ */ -public class ErrorsCountChartValuesGetServlet extends JsonServlet -{ - @Override - protected Action getAction() { - return new InitiableAction() - { - @Override - public void doAction() throws Exception { - Long competitionEntityId = getLongParam(COMPETITION_ENTITY_ID_PARAM_NAME); - if (competitionEntityId == null) - throw new ClientException( concat(sb, "\"", COMPETITION_ENTITY_ID_PARAM_NAME, "\" parameter is not set") ); +public class ErrorsCountChartValuesGetServlet extends JsonServlet { + + @Override + protected Action getAction() { + return new InitiableAction() { + @Override + public void doAction() throws Exception { + Long competitionEntityId = getLongParam(COMPETITION_ENTITY_ID_PARAM_NAME); + if (competitionEntityId == null) { + String errorMessage = String.format("\"%s\" parameter is not set", COMPETITION_ENTITY_ID_PARAM_NAME); + throw new ClientException(errorMessage); + } - CompetitionEntityService service = getService(CompetitionEntityService.class); - Competition competition = service.getCompetition(competitionEntityId); + CompetitionEntityService service = getService(CompetitionEntityService.class); + Competition competition = service.getCompetition(competitionEntityId); - if (competition == null) - throw new ClientException( concat(sb, "Competition not found for competitionEntityId = ", competitionEntityId) ); + if (competition == null) { + String errorMessage = String.format("Competition not found for competitionEntityId = %d", competitionEntityId); + throw new ClientException(errorMessage); + } - HighChartValue highChartValue = ErrorsCountChartFiller.fillData(competition); - writeSuccess(highChartValue); - } - }; - } + HighChartValue highChartValue = ErrorsCountChartFiller.fillData(competition); + writeSuccess(highChartValue); + } + }; + } - public static final String COMPETITION_ENTITY_ID_PARAM_NAME = "competitionId"; + public static final String COMPETITION_ENTITY_ID_PARAM_NAME = "competitionId"; } \ No newline at end of file diff --git a/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/model/highchart/SpeedChartValuesGetServlet.java b/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/model/highchart/SpeedChartValuesGetServlet.java index 1514c9693..8fa0607e8 100644 --- a/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/model/highchart/SpeedChartValuesGetServlet.java +++ b/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/model/highchart/SpeedChartValuesGetServlet.java @@ -9,8 +9,6 @@ import su.opencode.kefir.web.InitiableAction; import su.opencode.kefir.web.JsonServlet; -import static su.opencode.kefir.util.StringUtils.concat; - /** * Copyright 2014 Dmitriy Popov. * $HeadURL$ @@ -18,29 +16,32 @@ * $Revision$ * $Date:: $ */ -public class SpeedChartValuesGetServlet extends JsonServlet -{ - @Override - protected Action getAction() { - return new InitiableAction() - { - @Override - public void doAction() throws Exception { - Long competitionEntityId = getLongParam(COMPETITION_ENTITY_ID_PARAM_NAME); - if (competitionEntityId == null) - throw new ClientException( concat(sb, "\"", COMPETITION_ENTITY_ID_PARAM_NAME, "\" parameter is not set") ); +public class SpeedChartValuesGetServlet extends JsonServlet { + + @Override + protected Action getAction() { + return new InitiableAction() { + @Override + public void doAction() throws Exception { + Long competitionEntityId = getLongParam(COMPETITION_ENTITY_ID_PARAM_NAME); + if (competitionEntityId == null) { + String errorMessage = String.format("\"%s\" parameter is not set", COMPETITION_ENTITY_ID_PARAM_NAME); + throw new ClientException(errorMessage); + } - CompetitionEntityService service = getService(CompetitionEntityService.class); - Competition competition = service.getCompetition(competitionEntityId); + CompetitionEntityService service = getService(CompetitionEntityService.class); + Competition competition = service.getCompetition(competitionEntityId); - if (competition == null) - throw new ClientException( concat(sb, "Competition not found for competitionEntityId = ", competitionEntityId) ); + if (competition == null) { + String errorMessage = String.format("Competition not found for competitionEntityId = %d", competitionEntityId); + throw new ClientException(errorMessage); + } - HighChartValue highChartValue = SpeedChartFiller.fillData(competition); - writeSuccess(highChartValue); - } - }; - } + HighChartValue highChartValue = SpeedChartFiller.fillData(competition); + writeSuccess(highChartValue); + } + }; + } - public static final String COMPETITION_ENTITY_ID_PARAM_NAME = "competitionId"; + public static final String COMPETITION_ENTITY_ID_PARAM_NAME = "competitionId"; } \ No newline at end of file diff --git a/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/model/round/RoundInfoGetServlet.java b/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/model/round/RoundInfoGetServlet.java index 38d4782d7..e189d897d 100644 --- a/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/model/round/RoundInfoGetServlet.java +++ b/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/model/round/RoundInfoGetServlet.java @@ -8,8 +8,6 @@ import su.opencode.kefir.web.InitiableAction; import su.opencode.kefir.web.JsonServlet; -import static su.opencode.kefir.util.StringUtils.concat; - /** * Copyright 2014 Dmitriy Popov. * $HeadURL$ @@ -17,38 +15,45 @@ * $Revision$ * $Date:: $ */ -public class RoundInfoGetServlet extends JsonServlet -{ - @Override - protected Action getAction() { - return new InitiableAction() - { - @Override - public void doAction() throws Exception { - Long competitionEntityId = getLongParam(COMPETITION_ENTITY_ID_PARAM_NAME); - if (competitionEntityId == null) - throw new ClientException( concat(sb, "\"", COMPETITION_ENTITY_ID_PARAM_NAME, "\" parameter is not set") ); - - Integer roundNumber = getIntegerParam(ROUND_NUMBER_PARAM_NAME); - if (roundNumber == null) - throw new ClientException( concat(sb, "\"", ROUND_NUMBER_PARAM_NAME, "\" parameter is not set") ); - - CompetitionEntityService service = getService(CompetitionEntityService.class); - Competition competition = service.getCompetition(competitionEntityId); - - if (competition == null) - throw new ClientException( concat(sb, "Competition not found for competitionEntityId = ", competitionEntityId) ); - - Round round = competition.getRound(roundNumber); - if (round == null) - throw new ClientException( concat(sb, "Round with number ", roundNumber, " is not found for competitionEntityId = ", competitionEntityId) ); - - RoundInfo roundInfo = new RoundInfo(competition, round); - writeSuccess(roundInfo); - } - }; - } - - public static final String COMPETITION_ENTITY_ID_PARAM_NAME = "competitionId"; - public static final String ROUND_NUMBER_PARAM_NAME = "roundNumber"; +public class RoundInfoGetServlet extends JsonServlet { + + @Override + protected Action getAction() { + return new InitiableAction() { + @Override + public void doAction() throws Exception { + Long competitionEntityId = getLongParam(COMPETITION_ENTITY_ID_PARAM_NAME); + if (competitionEntityId == null) { + String errorMessage = String.format("\"%s\" parameter is not set", COMPETITION_ENTITY_ID_PARAM_NAME); + throw new ClientException(errorMessage); + } + + Integer roundNumber = getIntegerParam(ROUND_NUMBER_PARAM_NAME); + if (roundNumber == null) { + String errorMessage = String.format("\"%s\" parameter is not set", ROUND_NUMBER_PARAM_NAME); + throw new ClientException(errorMessage); + } + + CompetitionEntityService service = getService(CompetitionEntityService.class); + Competition competition = service.getCompetition(competitionEntityId); + + if (competition == null) { + String errorMessage = String.format("Competition not found for competitionEntityId = %d", competitionEntityId); + throw new ClientException(errorMessage); + } + + Round round = competition.getRound(roundNumber); + if (round == null) { + String errorMessage = String.format("Round with number %d is not found for competitionEntityId = %d", roundNumber, competitionEntityId); + throw new ClientException(errorMessage); + } + + RoundInfo roundInfo = new RoundInfo(competition, round); + writeSuccess(roundInfo); + } + }; + } + + public static final String COMPETITION_ENTITY_ID_PARAM_NAME = "competitionId"; + public static final String ROUND_NUMBER_PARAM_NAME = "roundNumber"; } \ No newline at end of file diff --git a/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/processing/players_table/PlayerResultsTableXlsGetServlet.java b/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/processing/players_table/PlayerResultsTableXlsGetServlet.java index 84155a755..dabc3c0b5 100644 --- a/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/processing/players_table/PlayerResultsTableXlsGetServlet.java +++ b/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/processing/players_table/PlayerResultsTableXlsGetServlet.java @@ -9,8 +9,6 @@ import su.opencode.kefir.web.InitiableAction; import su.opencode.kefir.web.JsonServlet; -import static su.opencode.kefir.util.StringUtils.concat; - /** * Copyright 2014 Dmitriy Popov. * $HeadURL$ @@ -18,35 +16,36 @@ * $Revision$ * $Date:: $ */ -public class PlayerResultsTableXlsGetServlet extends JsonServlet -{ - @Override - protected Action getAction() { - return new InitiableAction() - { - @Override - public void doAction() throws Exception { - Long competitionEntityId = getLongParam(COMPETITION_ENTITY_ID_PARAM_NAME); - if (competitionEntityId == null) { - throw new ClientException( concat(sb, "\"", COMPETITION_ENTITY_ID_PARAM_NAME, "\" parameter is not set") ); - } - - CompetitionEntityService service = getService(CompetitionEntityService.class); - Competition competition = service.getCompetition(competitionEntityId); - - if (competition == null) { - throw new ClientException( concat(sb, "Competition not found for competitionEntityId = ", competitionEntityId) ); - } - - PlayersResultsTable table = new PlayersResultsTable(); - table.fillTable(competition); - - String fileName = concat(sb, "competition-", competitionEntityId, "-playerResultsTable.xlsx"); - XSSFWorkbook workbook = PlayerResultsTableToXlsConverter.toXssfWorkbook(table); - writeToExcel(fileName, workbook); - } - }; - } - - public static final String COMPETITION_ENTITY_ID_PARAM_NAME = "competitionId"; +public class PlayerResultsTableXlsGetServlet extends JsonServlet { + + @Override + protected Action getAction() { + return new InitiableAction() { + @Override + public void doAction() throws Exception { + Long competitionEntityId = getLongParam(COMPETITION_ENTITY_ID_PARAM_NAME); + if (competitionEntityId == null) { + String errorMessage = String.format("\"%s\" parameter is not set", COMPETITION_ENTITY_ID_PARAM_NAME); + throw new ClientException(errorMessage); + } + + CompetitionEntityService service = getService(CompetitionEntityService.class); + Competition competition = service.getCompetition(competitionEntityId); + + if (competition == null) { + String errorMessage = String.format("Competition not found for competitionEntityId = %d", competitionEntityId); + throw new ClientException(errorMessage); + } + + PlayersResultsTable table = new PlayersResultsTable(); + table.fillTable(competition); + + String fileName = String.format("competition-%s-playerResultsTable.xlsx", competitionEntityId); + XSSFWorkbook workbook = PlayerResultsTableToXlsConverter.toXssfWorkbook(table); + writeToExcel(fileName, workbook); + } + }; + } + + public static final String COMPETITION_ENTITY_ID_PARAM_NAME = "competitionId"; } diff --git a/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/processing/players_table/PlayersResultsTableDataGetServlet.java b/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/processing/players_table/PlayersResultsTableDataGetServlet.java index 25245d91d..e3f278684 100644 --- a/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/processing/players_table/PlayersResultsTableDataGetServlet.java +++ b/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/processing/players_table/PlayersResultsTableDataGetServlet.java @@ -8,8 +8,6 @@ import su.opencode.kefir.web.InitiableAction; import su.opencode.kefir.web.JsonServlet; -import static su.opencode.kefir.util.StringUtils.concat; - /** * Copyright 2014 LLC "Open Code" * http://www.o-code.ru @@ -18,33 +16,34 @@ * $Revision$ * $Date:: $ */ -public class PlayersResultsTableDataGetServlet extends JsonServlet -{ - @Override - protected Action getAction() { - return new InitiableAction() - { - @Override - public void doAction() throws Exception { - Long competitionEntityId = getLongParam(COMPETITION_ENTITY_ID_PARAM_NAME); - if (competitionEntityId == null) { - throw new ClientException( concat(sb, "\"", COMPETITION_ENTITY_ID_PARAM_NAME, "\" parameter is not set") ); - } - - CompetitionEntityService service = getService(CompetitionEntityService.class); - Competition competition = service.getCompetition(competitionEntityId); - - if (competition == null) { - throw new ClientException( concat(sb, "Competition not found for competitionEntityId = ", competitionEntityId) ); - } - - PlayersResultsTable table = new PlayersResultsTable(); - table.fillTable(competition); - - writeSuccess(table); - } - }; - } - - public static final String COMPETITION_ENTITY_ID_PARAM_NAME = "competitionId"; +public class PlayersResultsTableDataGetServlet extends JsonServlet { + + @Override + protected Action getAction() { + return new InitiableAction() { + @Override + public void doAction() throws Exception { + Long competitionEntityId = getLongParam(COMPETITION_ENTITY_ID_PARAM_NAME); + if (competitionEntityId == null) { + String errorMessage = String.format("\"%s\" parameter is not set", COMPETITION_ENTITY_ID_PARAM_NAME); + throw new ClientException(errorMessage); + } + + CompetitionEntityService service = getService(CompetitionEntityService.class); + Competition competition = service.getCompetition(competitionEntityId); + + if (competition == null) { + String errorMessage = String.format("Competition not found for competitionEntityId = %d", competitionEntityId); + throw new ClientException(errorMessage); + } + + PlayersResultsTable table = new PlayersResultsTable(); + table.fillTable(competition); + + writeSuccess(table); + } + }; + } + + public static final String COMPETITION_ENTITY_ID_PARAM_NAME = "competitionId"; } From faf58ce9f4ab8b378a601b1a1ca5495ec5fac1a4 Mon Sep 17 00:00:00 2001 From: dmitry-weirdo Date: Mon, 25 Nov 2024 18:53:06 +0100 Subject: [PATCH 16/30] feat: #102 Add the basic `kg-common` module. Move one class `Car` to it. --- kgCommon/pom.xml | 349 ++++++++++++++++++ .../main/java/ru/klavogonki/common}/Car.java | 2 +- kgparserSrv/pom.xml | 7 + .../kgparser/http/HttpClientTest.java | 4 +- .../kgparser/http/UrlConstructor.java | 2 +- kgstatsSrv/pom.xml | 11 + .../statistics/download/PlayerJsonParser.java | 2 +- .../statistics/util/JacksonUtilsTest.java | 2 +- pom.xml | 10 + 9 files changed, 383 insertions(+), 6 deletions(-) create mode 100644 kgCommon/pom.xml rename {kgparserSrv/src/main/java/ru/klavogonki/kgparser => kgCommon/src/main/java/ru/klavogonki/common}/Car.java (99%) diff --git a/kgCommon/pom.xml b/kgCommon/pom.xml new file mode 100644 index 000000000..1678b3c9a --- /dev/null +++ b/kgCommon/pom.xml @@ -0,0 +1,349 @@ + + + 4.0.0 + + + ru.klavogonki.kgparser + kgparser + 1.0 + + + kg-common + kg-common + Common module with basic Klavogonki classes, uses by both legacy kgparser and kgstats + + + jar + + + + + org.assertj + assertj-core + + + + com.fasterxml.jackson.core + jackson-core + + + + com.fasterxml.jackson.core + jackson-databind + + + com.fasterxml.jackson.core + jackson-annotations + + + + org.junit.jupiter + junit-jupiter-api + + + + org.junit.jupiter + junit-jupiter-engine + + + + + + + + mysql + mysql-connector-java + + + + + + + + + + + + org.mapstruct + mapstruct + + + + + org.openapitools + jackson-databind-nullable + ${jackson-databind-nullable-version} + + + + io.swagger + swagger-annotations + ${swagger-annotations-version} + + + + + + + + + + + + org.jetbrains.kotlin + kotlin-maven-plugin + ${kotlin.version} + true + + + + lombok + + + + + + + + + compile + + compile + + + + ${project.basedir}/src/main/kotlin + ${project.basedir}/src/main/java + + + + + test-compile + + test-compile + + + + ${project.basedir}/src/test/kotlin + ${project.basedir}/src/test/java + + + + + + + + + + org.jetbrains.kotlin + kotlin-maven-lombok + ${kotlin.version} + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + + + default-compile + none + + + + default-testCompile + none + + + java-compile + compile + + compile + + + + java-test-compile + test-compile + + testCompile + + + + + + + ${java.version} + ${java.version} + + + org.mapstruct + mapstruct-processor + ${org.mapstruct.version} + + + org.projectlombok + lombok + ${lombok.version} + + + + + + org.projectlombok + lombok-mapstruct-binding + ${lombok-mapstruct-binding.version} + + + + + + + + + + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + ${build-helper-maven-plugin.version} + + + add-source + generate-sources + + add-source + + + + ${project.build.directory}/generated-sources/openapi/src + + + + + + + + org.assertj + assertj-assertions-generator-maven-plugin + ${assertj-assertions-generator-maven-plugin.version} + + + ru.klavogonki.statistics.entity + ru.klavogonki.statistics.dto + ru.klavogonki.openapi.model + + + ru.klavogonki.statistics + true + + + + + generate-assertions + + generate-test-resources + + + + + + + + diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Car.java b/kgCommon/src/main/java/ru/klavogonki/common/Car.java similarity index 99% rename from kgparserSrv/src/main/java/ru/klavogonki/kgparser/Car.java rename to kgCommon/src/main/java/ru/klavogonki/common/Car.java index de3da11a8..47ad19614 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Car.java +++ b/kgCommon/src/main/java/ru/klavogonki/common/Car.java @@ -1,4 +1,4 @@ -package ru.klavogonki.kgparser; +package ru.klavogonki.common; import java.util.Arrays; import java.util.List; diff --git a/kgparserSrv/pom.xml b/kgparserSrv/pom.xml index 9305c608c..62f0a15ea 100644 --- a/kgparserSrv/pom.xml +++ b/kgparserSrv/pom.xml @@ -14,6 +14,13 @@ jar + + + + ru.klavogonki.kgparser + kg-common + + com.fasterxml.jackson.core jackson-core diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/http/HttpClientTest.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/http/HttpClientTest.java index 7048feb2d..46db323fc 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/http/HttpClientTest.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/http/HttpClientTest.java @@ -41,8 +41,8 @@ public static void main(String[] args) throws IOException { // int playerId = 233067; // E_l_e_n_a (racer) // int playerId = 139052; // alanen (maniac) // int playerId = NOSFERATUM_PROFILE_ID; // nosferatum (superman) -// int playerId = 79473; // _Jack_ (cyberracer> -// int playerId = 1210; // ToNick (extracyber> +// int playerId = 79473; // _Jack_ (cyberracer) +// int playerId = 1210; // ToNick (extracyber) // int playerId = 231371; // Phemmer diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/http/UrlConstructor.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/http/UrlConstructor.java index 0fbab5f0a..4a41a39c8 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/http/UrlConstructor.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/http/UrlConstructor.java @@ -1,6 +1,6 @@ package ru.klavogonki.kgparser.http; -import ru.klavogonki.kgparser.Car; +import ru.klavogonki.common.Car; import ru.klavogonki.kgparser.Dictionary; import ru.klavogonki.kgparser.Player; diff --git a/kgstatsSrv/pom.xml b/kgstatsSrv/pom.xml index 232f2b43c..9bb32b0b0 100644 --- a/kgstatsSrv/pom.xml +++ b/kgstatsSrv/pom.xml @@ -13,6 +13,10 @@ kgstats-srv Spring Boot module of Klavogonki statistics + + + jar + org.assertj @@ -76,7 +80,14 @@ spring-boot-starter-log4j2 + + + ru.klavogonki.kgparser + kg-common + + + ru.klavogonki.kgparser kgparser-srv diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/download/PlayerJsonParser.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/download/PlayerJsonParser.java index a091afe2d..e29ef1372 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/download/PlayerJsonParser.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/download/PlayerJsonParser.java @@ -3,7 +3,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import ru.klavogonki.kgparser.Car; +import ru.klavogonki.common.Car; import ru.klavogonki.kgparser.Dictionary; import ru.klavogonki.kgparser.DictionaryMode; import ru.klavogonki.kgparser.Rank; diff --git a/kgstatsSrv/src/test/java/ru/klavogonki/statistics/util/JacksonUtilsTest.java b/kgstatsSrv/src/test/java/ru/klavogonki/statistics/util/JacksonUtilsTest.java index 64c00d762..beae0600a 100644 --- a/kgstatsSrv/src/test/java/ru/klavogonki/statistics/util/JacksonUtilsTest.java +++ b/kgstatsSrv/src/test/java/ru/klavogonki/statistics/util/JacksonUtilsTest.java @@ -5,7 +5,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -import ru.klavogonki.kgparser.Car; +import ru.klavogonki.common.Car; import ru.klavogonki.kgparser.Rank; import ru.klavogonki.kgparser.StandardDictionary; import ru.klavogonki.openapi.model.Bio; diff --git a/pom.xml b/pom.xml index 3d59fac87..e4aea877d 100644 --- a/pom.xml +++ b/pom.xml @@ -9,6 +9,7 @@ pom + kgCommon kgparserSrv kgparserWeb kgstatsSrv @@ -351,6 +352,15 @@ ${maven.multiModuleProjectDirectory}/jboss-libs/kefir-srv-1.0.jar + + + ru.klavogonki.kgparser + kg-common + 1.0 + compile + true + + ru.klavogonki.kgparser From 61a3fec4c16a5fa3c172085dbe41a88c391a950e Mon Sep 17 00:00:00 2001 From: dmitry-weirdo Date: Mon, 25 Nov 2024 19:32:30 +0100 Subject: [PATCH 17/30] feat: #81 #102 Convert Car to Kotlin. Move CarTest to `kg-common`. --- kgCommon/pom.xml | 2 + .../ru/klavogonki/common/Car.kt} | 127 ++++++++++-------- .../kotlin/ru/klavogonki/common/CarTest.kt | 94 +++++++++++++ .../kgparser/http/UrlConstructor.java | 2 +- .../java/ru/klavogonki/kgparser/CarTest.java | 108 --------------- 5 files changed, 165 insertions(+), 168 deletions(-) rename kgCommon/src/main/{java/ru/klavogonki/common/Car.java => kotlin/ru/klavogonki/common/Car.kt} (66%) create mode 100644 kgCommon/src/test/kotlin/ru/klavogonki/common/CarTest.kt delete mode 100644 kgparserSrv/src/test/java/ru/klavogonki/kgparser/CarTest.java diff --git a/kgCommon/pom.xml b/kgCommon/pom.xml index 1678b3c9a..7d825b809 100644 --- a/kgCommon/pom.xml +++ b/kgCommon/pom.xml @@ -137,6 +137,7 @@ ${kotlin.version} true + diff --git a/kgCommon/src/main/java/ru/klavogonki/common/Car.java b/kgCommon/src/main/kotlin/ru/klavogonki/common/Car.kt similarity index 66% rename from kgCommon/src/main/java/ru/klavogonki/common/Car.java rename to kgCommon/src/main/kotlin/ru/klavogonki/common/Car.kt index 47ad19614..c8f0281b4 100644 --- a/kgCommon/src/main/java/ru/klavogonki/common/Car.java +++ b/kgCommon/src/main/kotlin/ru/klavogonki/common/Car.kt @@ -1,12 +1,10 @@ -package ru.klavogonki.common; - -import java.util.Arrays; -import java.util.List; +package ru.klavogonki.common /** * List of cars with ids and Russian names. */ -public enum Car { +@SuppressWarnings("MagicNumber") +enum class Car { // common/public autos ZAZ_965(1, "ЗАЗ 965"), VAZ_2104(2, "ВАЗ 2104"), @@ -23,11 +21,13 @@ public enum Car { BMW_X6(12, "BMW X6"), AUDI_TT(13, "Audi TT"), BUGATTI_VEYRON(14, "Bugatti Veyron"), + /** * Notably, car 21 is also the F1 car. * Looks like car 21 is now a tuning option for car 15. - * @see Image for car 15 - * @see Image for car 21 + * @see [Image for car 15](http://klavogonki.ru/img/cars/15.png) + * + * @see [Image for car 21](http://klavogonki.ru/img/cars/21.png) */ F1(15, "Болид F1"), // Notably, car 21 is also the F1 car, LAMBORGHINI_MURCIELAGO(16, "Lamborghini Murcielago"), @@ -36,6 +36,7 @@ public enum Car { DUESENBERG_SPEEDSTER(19, "Duesenberg Speedster"), UFO(20, "НЛО"), + // car 21 became a tuning for car 15 FERRARI_FX_CONCEPT(22, "Ferrari FX Concept"), SMART_FORTWO(23, "Smart Fortwo"), @@ -72,25 +73,31 @@ public enum Car { HENNESSEY_VENOM_GT1(1001, "Hennessey Venom GT1", 30297), // http://klavogonki.ru/u/#/30297/car/ DE_LOREAN_TIME_MACHINE(1002, "DeLorean Time Machine", 151752), // http://klavogonki.ru/u/#/151752/car/ SUBMARINE(1003, "Submarine", 100600), // http://klavogonki.ru/u/#/100600/car/ + // car 1004 made public // car 1005 made public MOTORCITY_EUROPE_MC1(1006, "Motorcity Europe MC1", 1596), // http://klavogonki.ru/u/#/1596/car/ + // car 1007 made public MERCEDES_BENZ_SL_600(1008, "Mercedes-Benz SL 600", 157594), // http://klavogonki.ru/u/#/157594/car/ + // car 1009 made public PAGANI_ZONDA_R(1010, "Pagani Zonda R", 235269), // http://klavogonki.ru/u/#/235269/car/ BATPOD(1011, "Бэтпод", 195256), // http://klavogonki.ru/u/#/195256/car/ ZIS_155(1012, "ЗИС-155", 306936), // http://klavogonki.ru/u/#/306936/car/ + /** * 2 exclusive owners: Fenex & Аромат - * @see Fenex' cars - * @see Аромат's cars + * @see [Fenex' cars](http://klavogonki.ru/u/./82885/car/) + * + * @see [Аромат's cars](http://klavogonki.ru/u/./101646/car/) */ VOLKSWAGEN_CORRADO(1013, "Volkswagen Corrado", 101646), // http://klavogonki.ru/u/#/101646/car/ RED_EAGLE(1015, "Red Eagle", 24119), // http://klavogonki.ru/u/#/24119/car/ // ! From Carmageddon! IHOUE(1016, "ΙΧΘΥΣ", 73879), // http://klavogonki.ru/u/#/73879/car/ PARASAILING(1017, "Parasailing", 291992), // http://klavogonki.ru/u/#/291992/car/ DRAGON(1018, "Дракон", 211962), // http://klavogonki.ru/u/#/211962/car/ + // car 1019 made public N_BAR(1020, "N-Bar", 20106), // http://klavogonki.ru/u/#/20106/car/ DU_49(1021, "ДУ-49", 173903), // http://klavogonki.ru/u/#/173903/car/ @@ -99,70 +106,72 @@ public enum Car { FERRARI_F2(1024, "Ferrari F12", 320247), // http://klavogonki.ru/u/#/320247/car/ ; - Car(final int id, final String name) { - this.id = id; - this.name = name; - this.ownerId = null; - this.personalId = null; - } - - Car(final int id, final String name, final int ownerId) { // for personal cars that have not been made public - this.id = id; - this.name = name; - this.ownerId = ownerId; - this.personalId = null; + constructor(id: Int, displayName: String) { + this.id = id + this.displayName = displayName + this.ownerId = null + this.personalId = null } - Car(final int id, final String name, final Integer ownerId, final Integer personalId) { // for personal cars that have not been made public - this.id = id; - this.name = name; - this.ownerId = ownerId; - this.personalId = personalId; + constructor(id: Int, displayName: String, ownerId: Int) { // for personal cars that have not been made public + this.id = id + this.displayName = displayName + this.ownerId = ownerId + this.personalId = null } - public boolean isPersonalOnly() { - return (ownerId != null) && (personalId == null); + constructor( + id: Int, + displayName: String, + ownerId: Int, + personalId: Int + ) { // for personal cars that have not been made public + this.id = id + this.displayName = displayName + this.ownerId = ownerId + this.personalId = personalId } - public boolean wasPersonalButMadePublic() { - return (personalId != null); - } + @Suppress("Unused") + fun isPersonalOnly() = (ownerId != null) && (personalId == null) - public boolean isPublic() { - return (id < FIRST_PERSONAL_CAR_ID); - } + @Suppress("Unused") + fun wasPersonalButMadePublic() = (personalId != null) - public static boolean isPersonalId(int carId) { - return carId >= FIRST_PERSONAL_CAR_ID; - } + @Suppress("Unused") + fun isPublic() = (id < FIRST_PERSONAL_CAR_ID) - public static Car getById(int carId) { - List carsWithId = Arrays - .stream(Car.values()) - .filter(car -> car.id == carId) - .toList(); + val id: Int + val displayName: String + val ownerId: Int? // for personal autos + val personalId: Int? // for personal autos that have been made public - if (carsWithId.size() == 1) { - return carsWithId.get(0); + companion object { + fun isPersonalId(carId: Int): Boolean { + return carId >= FIRST_PERSONAL_CAR_ID } - // original owners might have cars with personalId ids! - List carsWithPersonalId = Arrays - .stream(Car.values()) - .filter(car -> (car.personalId != null) && (car.personalId == carId)) - .toList(); + fun getById(carId: Int): Car { + val carsWithId = entries + .filter { it.id == carId } - if (carsWithPersonalId.size() == 1) { - return carsWithPersonalId.get(0); - } + if (carsWithId.size == 1) { + return carsWithId[0] + } - throw new IllegalArgumentException(String.format("Found %d cars with id or personalId = %d.", carsWithId.size(), carId)); - } + // original owners might have cars with personalId ids! + val carsWithPersonalId = entries + .filter { (it.personalId != null) && (it.personalId == carId) } + + if (carsWithPersonalId.size == 1) { + return carsWithPersonalId[0] + } - public static final int FIRST_PERSONAL_CAR_ID = 1000; + // todo: understand what does it mean - no cars? More than 1 cars? + // more than one car by + error("Found ${carsWithId.size} cars with id or personalId = $carId.") + } - public final int id; - public final String name; - public final Integer ownerId; // for personal autos - public final Integer personalId; // for personal autos that have been made public + const val FIRST_PERSONAL_CAR_ID: Int = 1000 + } } diff --git a/kgCommon/src/test/kotlin/ru/klavogonki/common/CarTest.kt b/kgCommon/src/test/kotlin/ru/klavogonki/common/CarTest.kt new file mode 100644 index 000000000..0e96bd8a5 --- /dev/null +++ b/kgCommon/src/test/kotlin/ru/klavogonki/common/CarTest.kt @@ -0,0 +1,94 @@ +package ru.klavogonki.common + +import org.apache.logging.log4j.kotlin.Logging +import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.api.Assertions.assertThatThrownBy +import org.junit.jupiter.api.Test + +internal class CarTest : Logging { + + @Test + fun testCarIdsAreUnique() { + val cars = Car.entries + + val uniqueCarIds = cars + .map { car: Car -> car.id } + .distinct() + .sorted() + + logger.info("Unique car ids: \n$uniqueCarIds") + + assertThat(uniqueCarIds).hasSameSizeAs(cars) + } + + @Test + fun testCarNamesAreUnique() { + val cars = Car.entries + + val uniqueCarNames = cars + .map { it.name } + .distinct() + .sorted() + + logger.info("Unique car names: \n$uniqueCarNames") + + assertThat(uniqueCarNames).hasSameSizeAs(cars) + } + + @Test + fun testAllPersonalCarIdsArePersonalIds() { + val cars = Car.entries + + val carPersonalIds = cars + .filter { it.personalId != null } + .map { it.personalId!! } + .distinct() + .sorted() + + logger.info("Personal car ids for cars that have been made public: \n$carPersonalIds") + + carPersonalIds.forEach { + assertThat(Car.isPersonalId(it)).isTrue() + } + } + + @Test + fun testAllPersonalCarsThatWereMadePublicHaveOriginalOwnerFilled() { + val cars = Car.entries + + val personalCarsThatWereMadePublic = cars + .filter { it.wasPersonalButMadePublic() } + .distinct() + .sorted() + + logger.info("Cars that were personal but have been made public: \n$personalCarsThatWereMadePublic") + + personalCarsThatWereMadePublic.forEach { + assertThat(it.ownerId).isNotNull() + assertThat(it.personalId).isNotNull() + } + } + + @Test + fun testCarById() { + val publicCarById = Car.getById(Car.NISSAN_ROUND_BOX.id) + assertThat(publicCarById).isEqualTo(Car.NISSAN_ROUND_BOX) + + val personalCarById = Car.getById(Car.DUCATI_848_2010.id) + assertThat(personalCarById).isEqualTo(Car.DUCATI_848_2010) + + val publishedPersonalCarById = Car.getById(Car.TRAM.id) + assertThat(publishedPersonalCarById).isEqualTo(Car.TRAM) + + assertThat(Car.TRAM.personalId).isNotNull() + val publishedPersonalCarByPersonalId = Car.getById(Car.TRAM.personalId!!) + assertThat(publishedPersonalCarByPersonalId).isEqualTo(Car.TRAM) + + assertThatThrownBy { + Car.getById(0) // non-existing car id + } + .isInstanceOf(IllegalStateException::class.java) + .hasMessageContaining("0 cars") + .hasMessageContaining(" = 0") + } +} diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/http/UrlConstructor.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/http/UrlConstructor.java index 4a41a39c8..1b51f6bd0 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/http/UrlConstructor.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/http/UrlConstructor.java @@ -138,7 +138,7 @@ public static String dictionaryPage(int dictionaryId) { // car images public static String basicCarImage(Car car) { - return getLink("/img/cars/%d.png", car.id); + return getLink("/img/cars/%d.png", car.getId()); } // todo: maybe extract API to a separate class diff --git a/kgparserSrv/src/test/java/ru/klavogonki/kgparser/CarTest.java b/kgparserSrv/src/test/java/ru/klavogonki/kgparser/CarTest.java deleted file mode 100644 index 7b9d7cd80..000000000 --- a/kgparserSrv/src/test/java/ru/klavogonki/kgparser/CarTest.java +++ /dev/null @@ -1,108 +0,0 @@ -package ru.klavogonki.kgparser; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.junit.jupiter.api.Test; - -import java.util.Arrays; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -class CarTest { - private static final Logger logger = LogManager.getLogger(CarTest.class); - - @Test - void testCarIdsAreUnique() { - Car[] cars = Car.values(); - - List uniqueCarIds = Arrays - .stream(cars) - .map(car -> car.id) - .distinct() - .sorted() - .toList(); - - logger.info("unique car ids: \n{}", uniqueCarIds); - - assertThat(uniqueCarIds).hasSameSizeAs(cars); - } - - @Test - void testCarNamesAreUnique() { - Car[] cars = Car.values(); - - List uniqueCarNames = Arrays - .stream(cars) - .map(car -> car.name) - .distinct() - .sorted() - .toList(); - - logger.info("unique car names: \n{}", uniqueCarNames); - - assertThat(uniqueCarNames).hasSameSizeAs(cars); - } - - @Test - void testAllPersonalCarIdsArePersonalIds() { - Car[] cars = Car.values(); - - List carPersonalIds = Arrays - .stream(cars) - .filter(car -> (car.personalId != null)) - .map(car -> car.personalId) - .distinct() - .sorted() - .toList(); - - logger.info("personal car ids for cars that have been made public: \n{}", carPersonalIds); - - carPersonalIds.forEach(personalId -> - assertThat(Car.isPersonalId(personalId)).isTrue() - ); - } - - @Test - void testAllPersonalCarsThatWereMadePublicHaveOriginalOwnerFilled() { - Car[] cars = Car.values(); - - List personalCarsThatWereMadePublic = Arrays - .stream(cars) - .filter(Car::wasPersonalButMadePublic) - .distinct() - .sorted() - .toList(); - - logger.info("cars that were personal but have been made public: \n{}", personalCarsThatWereMadePublic); - - personalCarsThatWereMadePublic.forEach(car -> { - assertThat(car.ownerId).isNotNull(); - assertThat(car.personalId).isNotNull(); - }); - } - - @Test - void testCarById() { - Car publicCarById = Car.getById(Car.NISSAN_ROUND_BOX.id); - assertThat(publicCarById).isEqualTo(Car.NISSAN_ROUND_BOX); - - Car personalCarById = Car.getById(Car.DUCATI_848_2010.id); - assertThat(personalCarById).isEqualTo(Car.DUCATI_848_2010); - - Car publishedPersonalCarById = Car.getById(Car.TRAM.id); - assertThat(publishedPersonalCarById).isEqualTo(Car.TRAM); - - assertThat(Car.TRAM.personalId).isNotNull(); - Car publishedPersonalCarByPersonalId = Car.getById(Car.TRAM.personalId); - assertThat(publishedPersonalCarByPersonalId).isEqualTo(Car.TRAM); - - assertThatThrownBy(() -> { - Car.getById(0); // non-existing car id - }) - .isInstanceOf(IllegalArgumentException.class) - .hasMessageContaining("0 cars") - .hasMessageContaining(" = 0"); - } -} From b2fa6ef404e207382fc76db89de7352b221f81cd Mon Sep 17 00:00:00 2001 From: dmitry-weirdo Date: Mon, 25 Nov 2024 19:42:43 +0100 Subject: [PATCH 18/30] fix: #81 Make `Car#getById` method accessible from the Java classes. --- kgCommon/src/main/kotlin/ru/klavogonki/common/Car.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/kgCommon/src/main/kotlin/ru/klavogonki/common/Car.kt b/kgCommon/src/main/kotlin/ru/klavogonki/common/Car.kt index c8f0281b4..3ed8744f2 100644 --- a/kgCommon/src/main/kotlin/ru/klavogonki/common/Car.kt +++ b/kgCommon/src/main/kotlin/ru/klavogonki/common/Car.kt @@ -151,6 +151,7 @@ enum class Car { return carId >= FIRST_PERSONAL_CAR_ID } + @JvmStatic fun getById(carId: Int): Car { val carsWithId = entries .filter { it.id == carId } From 5d89decacd014526766bfe2d520a36a6564a4c8a Mon Sep 17 00:00:00 2001 From: dmitry-weirdo Date: Mon, 25 Nov 2024 19:49:50 +0100 Subject: [PATCH 19/30] test: #81 Fix `JacksonUtilsTest`: access kotlin `Car` enum fields via getters. --- .../ru/klavogonki/statistics/util/JacksonUtilsTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kgstatsSrv/src/test/java/ru/klavogonki/statistics/util/JacksonUtilsTest.java b/kgstatsSrv/src/test/java/ru/klavogonki/statistics/util/JacksonUtilsTest.java index beae0600a..856d96b9d 100644 --- a/kgstatsSrv/src/test/java/ru/klavogonki/statistics/util/JacksonUtilsTest.java +++ b/kgstatsSrv/src/test/java/ru/klavogonki/statistics/util/JacksonUtilsTest.java @@ -87,7 +87,7 @@ void existingPlayer() { CarAssert .assertThat(car) .isNotNull() - .hasCar(Car.F1.id) + .hasCar(Car.F1.getId()) .hasColor("#BF1300"); Map tuning = getNonEmptyTuning(car); @@ -132,7 +132,7 @@ void playerWithPersonalCarId() { CarAssert .assertThat(car) .isNotNull() - .hasCar(Car.CARAVEL.personalId) + .hasCar(Car.CARAVEL.getPersonalId()) .hasColor("#000000"); assertEmptyTunning(car); @@ -172,7 +172,7 @@ void brandNewPlayer() { CarAssert .assertThat(car) .isNotNull() - .hasCar(Car.ZAZ_965.id) + .hasCar(Car.ZAZ_965.getId()) .hasColor("#777777"); assertEmptyTunning(car); @@ -213,7 +213,7 @@ void klavoMechanicWithHiddenProfile() { CarAssert .assertThat(car) .isNotNull() - .hasCar(Car.AUDI_TT.id) + .hasCar(Car.AUDI_TT.getId()) .hasColor("#893425"); Map tuning = getNonEmptyTuning(car); From 7f249c4f3dd0007eab4017524d7932e9025e2c43 Mon Sep 17 00:00:00 2001 From: dmitry-weirdo Date: Mon, 25 Nov 2024 20:23:06 +0100 Subject: [PATCH 20/30] feat: #81 #102 Move `Wiki` and `StandardDictionary` to `kg-common` and convert them to Kotlin. --- .../klavogonki/common/StandardDictionary.kt | 165 ++++++++++++++++++ .../main/kotlin/ru/klavogonki/common/Wiki.kt | 8 + .../ru/klavogonki/kgparser/Competition.java | 3 +- .../ru/klavogonki/kgparser/Dictionary.java | 7 +- .../klavogonki/kgparser/DictionaryMode.java | 4 +- .../java/ru/klavogonki/kgparser/Rank.java | 2 + .../java/ru/klavogonki/kgparser/Round.java | 1 + .../kgparser/StandardDictionary.java | 153 ---------------- .../java/ru/klavogonki/kgparser/Wiki.java | 12 -- .../kgparser/http/HttpClientTest.java | 2 +- .../kgparser/processing/FakeDataFactory.java | 2 +- .../kgparser/test/CompetitionTest.java | 2 +- .../klavogonki/kgparser/test/RoundTest.java | 2 +- .../klavogonki/kgparser/test/TestHelper.java | 2 +- .../statistics/download/PlayerJsonParser.java | 2 +- .../statistics/excel/ExcelExporter.java | 2 +- .../vocabulary/standard/AbraTopExporter.java | 2 +- .../vocabulary/standard/CharsTopExporter.java | 2 +- .../standard/DigitsTopExporter.java | 2 +- .../standard/MarathonTopExporter.java | 2 +- .../standard/NoErrorTopExporter.java | 2 +- .../standard/NormalTopExporter.java | 2 +- .../standard/ReferatsTopExporter.java | 2 +- .../standard/SprintTopExporter.java | 2 +- .../StandardVocabularyTopExporter.java | 2 +- .../export/vocabulary/VocabularyTopUtils.kt | 2 +- .../download/PlayerJsonParserTest.java | 4 +- .../statistics/util/JacksonUtilsTest.java | 2 +- kgstatsWeb/src/main/webapp/css/stats.css | 2 +- 29 files changed, 206 insertions(+), 191 deletions(-) create mode 100644 kgCommon/src/main/kotlin/ru/klavogonki/common/StandardDictionary.kt create mode 100644 kgCommon/src/main/kotlin/ru/klavogonki/common/Wiki.kt delete mode 100644 kgparserSrv/src/main/java/ru/klavogonki/kgparser/StandardDictionary.java delete mode 100644 kgparserSrv/src/main/java/ru/klavogonki/kgparser/Wiki.java diff --git a/kgCommon/src/main/kotlin/ru/klavogonki/common/StandardDictionary.kt b/kgCommon/src/main/kotlin/ru/klavogonki/common/StandardDictionary.kt new file mode 100644 index 000000000..dc8e00f6a --- /dev/null +++ b/kgCommon/src/main/kotlin/ru/klavogonki/common/StandardDictionary.kt @@ -0,0 +1,165 @@ +package ru.klavogonki.common + +/** + * Copyright 2014 [Dmitriy Popov](mailto:dmitry.weirdo@gmail.com). + * $HeadURL$ + * $Author$ + * $Revision$ + * $Date:: $ + *

+ *

+ * Энум с названиями стандартных словарей (режимов), как они используются в AJAX-API. + */ +@SuppressWarnings("MagicNumber") +enum class StandardDictionary( + + /** + * Имя в API клавогонок. Все буквы в нижнем регистре. + */ + @JvmField val klavogonkiName: String, + + /** + * Русское название словаря для отображения. + */ + @JvmField val displayName: String, + + /** + * Русское название словаря для отображения, в предложном падеже. + */ + @JvmField val displayNamePrepositional: String, + + /** + * Цвет стандартного словаря в формате #123456 + */ + @JvmField val color: String, + + /** + * Страница стандартного словаря в [википедии клавогонок](http://klavogonki.ru/wiki/). + */ + @JvmField val wikiPageUrl: String, + + /** + * Тип текста словаря. + * Для нестандартных словарей будет равен идентификатору словаря. + */ + @JvmField val textType: Int +) { + /** + * Обычный. + */ + normal( + klavogonkiName = "normal", + displayName = "Обычный", + displayNamePrepositional = "Обычном", + color = "#333333", + wikiPageUrl = Wiki.getUrl("%D0%9E%D0%B1%D1%8B%D1%87%D0%BD%D1%8B%D0%B9"), + textType = 0 + ), + + /** + * Безошибочный. + */ + noerror( + klavogonkiName = "noerror", + displayName = "Безошибочный", + displayNamePrepositional = "Безошибочном", + color = "#4692AA", + wikiPageUrl = Wiki.getUrl("%D0%91%D0%B5%D0%B7%D0%BE%D1%88%D0%B8%D0%B1%D0%BE%D1%87%D0%BD%D1%8B%D0%B9"), + textType = 0 + ), + + /** + * Буквы. + */ + chars( + klavogonkiName = "chars", + displayName = "Буквы", + displayNamePrepositional = "Буквах", + color = "#B55900", + wikiPageUrl = Wiki.getUrl("%D0%91%D1%83%D0%BA%D0%B2%D1%8B"), + textType = -4 + ), + + /** + * Марафон. + */ + marathon( + klavogonkiName = "marathon", + displayName = "Марафон", + displayNamePrepositional = "Марафоне", + color = "#D43E68", + wikiPageUrl = Wiki.getUrl("%D0%9C%D0%B0%D1%80%D0%B0%D1%84%D0%BE%D0%BD"), + textType = 0 + ), + + /** + * Абракадабра. + */ + abra( + klavogonkiName = "abra", + displayName = "Абракадабра", + displayNamePrepositional = "Абракадабре", + color = "#3D4856", + wikiPageUrl = Wiki.getUrl("%D0%90%D0%B1%D1%80%D0%B0%D0%BA%D0%B0%D0%B4%D0%B0%D0%B1%D1%80%D0%B0"), + textType = -1 + ), + + /** + * Яндекс.Рефераты. + */ + referats( + klavogonkiName = "referats", + displayName = "Яндекс.Рефераты", + displayNamePrepositional = "Яндекс.Рефератах", + color = "#698725", + wikiPageUrl = Wiki.getUrl("%D0%AF%D0%BD%D0%B4%D0%B5%D0%BA%D1%81.%D0%A0%D0%B5%D1%84%D0%B5%D1%80%D0%B0%D1%82%D1%8B"), + textType = -3 + ), + + /** + * Цифры. + */ + digits( + klavogonkiName = "digits", + displayName = "Цифры", + displayNamePrepositional = "Цифрах", + color = "#777777", + wikiPageUrl = Wiki.getUrl("%D0%A6%D0%B8%D1%84%D1%80%D1%8B"), + textType = -2 + ), + + /** + * Спринт. + */ + sprint( + klavogonkiName = "sprint", + displayName = "Спринт", + displayNamePrepositional = "Спринте", + color = "#833F3A", + wikiPageUrl = Wiki.getUrl("%D0%A1%D0%BF%D1%80%D0%B8%D0%BD%D1%82"), + textType = 0 + ), + ; + + companion object { + + @JvmStatic + fun isValidStandardDictionaryCode(code: String) = + entries.any { it.klavogonkiName == code } + + @JvmStatic + fun getByKlavogonkiName(code: String): StandardDictionary { + val values = entries.filter { it.klavogonkiName == code } + + check(values.isNotEmpty()) { + "No standard dictionary for code = \"$code\"." + } + + check(values.size == 1) { + "More than one standard dictionary for code = \"$code\"." + } + + return values[0] + } + } +} diff --git a/kgCommon/src/main/kotlin/ru/klavogonki/common/Wiki.kt b/kgCommon/src/main/kotlin/ru/klavogonki/common/Wiki.kt new file mode 100644 index 000000000..2582fbd92 --- /dev/null +++ b/kgCommon/src/main/kotlin/ru/klavogonki/common/Wiki.kt @@ -0,0 +1,8 @@ +package ru.klavogonki.common + +object Wiki { + private const val WIKI_BASE_URL = "https://klavogonki.ru/wiki/" + + fun getUrl(pageName: String) = + WIKI_BASE_URL + pageName.trim() +} diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Competition.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Competition.java index fbdba0fdf..15f881466 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Competition.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Competition.java @@ -2,6 +2,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import ru.klavogonki.common.StandardDictionary; import ru.klavogonki.kgparser.http.HttpClientTest; import su.opencode.kefir.srv.json.Json; import su.opencode.kefir.srv.json.JsonObject; @@ -258,7 +259,7 @@ public void fillDictionariesNames() { if (dictionary.isStandard()) { - StandardDictionary standardDictionary = StandardDictionary.valueOf(dictionaryCode); + StandardDictionary standardDictionary = StandardDictionary.getByKlavogonkiName(dictionaryCode); codesToNames.put(dictionaryCode, standardDictionary.displayName); } else diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Dictionary.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Dictionary.java index e386002d7..9508bd85f 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Dictionary.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Dictionary.java @@ -1,5 +1,6 @@ package ru.klavogonki.kgparser; +import ru.klavogonki.common.StandardDictionary; import ru.klavogonki.kgparser.http.UrlConstructor; import su.opencode.kefir.srv.json.Json; import su.opencode.kefir.util.StringUtils; @@ -138,7 +139,7 @@ public static int getTextType(String code) { return getDictionaryId(code); } - StandardDictionary standardDictionary = StandardDictionary.valueOf(code); + StandardDictionary standardDictionary = StandardDictionary.getByKlavogonkiName(code); return standardDictionary.textType; } @@ -149,7 +150,7 @@ public static int getTextType(String code) { @Json(exclude = true) public static String getDictionaryColor(String dictionaryCode) { if (isStandard(dictionaryCode)) { - return StandardDictionary.valueOf(dictionaryCode).color; + return StandardDictionary.getByKlavogonkiName(dictionaryCode).color; } return NON_STANDARD_DICTIONARY_COLOR; @@ -163,7 +164,7 @@ public static String getDictionaryColor(String dictionaryCode) { */ public static String getDictionaryPageUrl(String dictionaryCode) { if (isStandard(dictionaryCode)) { - return StandardDictionary.valueOf(dictionaryCode).wikiPageUrl; + return StandardDictionary.getByKlavogonkiName(dictionaryCode).wikiPageUrl; } return UrlConstructor.dictionaryPage( getDictionaryId(dictionaryCode) ); diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/DictionaryMode.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/DictionaryMode.java index 522bc7f14..3ad2f4bc9 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/DictionaryMode.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/DictionaryMode.java @@ -1,5 +1,7 @@ package ru.klavogonki.kgparser; +import ru.klavogonki.common.StandardDictionary; + public enum DictionaryMode { normal, @@ -17,7 +19,7 @@ public static DictionaryMode getDictionaryMode(String dictionaryCode) { return normal; } - StandardDictionary standardDictionary = StandardDictionary.valueOf(dictionaryCode); + StandardDictionary standardDictionary = StandardDictionary.getByKlavogonkiName(dictionaryCode); switch (standardDictionary) { case normal: diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Rank.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Rank.java index 3bdf7403f..e771f8268 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Rank.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Rank.java @@ -1,5 +1,7 @@ package ru.klavogonki.kgparser; +import ru.klavogonki.common.StandardDictionary; + import java.util.Arrays; /** diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Round.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Round.java index 929dc9e6c..b3d98f1fc 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Round.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Round.java @@ -2,6 +2,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import ru.klavogonki.common.StandardDictionary; import su.opencode.kefir.srv.json.Json; import su.opencode.kefir.srv.json.JsonObject; import su.opencode.kefir.util.ObjectUtils; diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/StandardDictionary.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/StandardDictionary.java deleted file mode 100644 index 839984a5f..000000000 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/StandardDictionary.java +++ /dev/null @@ -1,153 +0,0 @@ -package ru.klavogonki.kgparser; - -/** - * Copyright 2014 Dmitriy Popov. - * $HeadURL$ - * $Author$ - * $Revision$ - * $Date:: $ - *
- *
- * Энум с названиями стандартных словарей (режимов), как они используются в AJAX-API. - */ -public enum StandardDictionary -{ - /** - * Обычный. - */ - normal( - "Обычный", - "Обычном", - "#333333", - Wiki.getUrl("%D0%9E%D0%B1%D1%8B%D1%87%D0%BD%D1%8B%D0%B9"), - 0 - ), - - /** - * Безошибочный. - */ - noerror( - "Безошибочный", - "Безошибочном", - "#4692AA", - Wiki.getUrl("%D0%91%D0%B5%D0%B7%D0%BE%D1%88%D0%B8%D0%B1%D0%BE%D1%87%D0%BD%D1%8B%D0%B9"), - 0 - ), - - /** - * Буквы. - */ - chars( - "Буквы", - "Буквах", - "#B55900", - Wiki.getUrl("%D0%91%D1%83%D0%BA%D0%B2%D1%8B"), - -4 - ), - - /** - * Марафон. - */ - marathon( - "Марафон", - "Марафоне", - "#D43E68", - Wiki.getUrl("%D0%9C%D0%B0%D1%80%D0%B0%D1%84%D0%BE%D0%BD"), - 0 - ), - - /** - * Абракадабра. - */ - abra( - "Абракадабра", - "Абракадабре", - "#3D4856", - Wiki.getUrl("%D0%90%D0%B1%D1%80%D0%B0%D0%BA%D0%B0%D0%B4%D0%B0%D0%B1%D1%80%D0%B0"), - -1 - ), - - /** - * Яндекс.Рефераты. - */ - referats( - "Яндекс.Рефераты", - "Яндекс.Рефератах", - "#698725", - Wiki.getUrl("%D0%AF%D0%BD%D0%B4%D0%B5%D0%BA%D1%81.%D0%A0%D0%B5%D1%84%D0%B5%D1%80%D0%B0%D1%82%D1%8B"), - -3 - ), - - /** - * Цифры. - */ - digits( - "Цифры", - "Цифрах", - "#777777", - Wiki.getUrl("%D0%A6%D0%B8%D1%84%D1%80%D1%8B"), - -2 - ), - - /** - * Спринт. - */ - sprint( - "Спринт", - "Спринте", - "#833F3A", - Wiki.getUrl("%D0%A1%D0%BF%D1%80%D0%B8%D0%BD%D1%82"), - 0 - ), - ; - - StandardDictionary( - String displayName, - String displayNamePrepositional, - String color, - String wikiPageUrl, - int textType - ) { - this.displayName = displayName; - this.displayNamePrepositional = displayNamePrepositional; - this.color = color; - this.wikiPageUrl = wikiPageUrl; - this.textType = textType; - } - - /** - * Русское название словаря для отображения. - */ - public final String displayName; - - /** - * Русское название словаря для отображения, в предложном падеже. - */ - public final String displayNamePrepositional; - - /** - * Цвет стандартного словаря в формате «#123456» - */ - public final String color; - - /** - * Страница стандартного словаря в википедии клавогонок. - */ - public final String wikiPageUrl; - - /** - * Тип текста словаря. - * Для нестандартных словарей будет равен идентификатору словаря. - */ - public final int textType; - - public static boolean isValidStandardDictionaryCode(String code) { - try { - StandardDictionary.valueOf(code); - return true; - } - catch (IllegalArgumentException e) { - return false; - } - } -} diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Wiki.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Wiki.java deleted file mode 100644 index 4677b8a0c..000000000 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Wiki.java +++ /dev/null @@ -1,12 +0,0 @@ -package ru.klavogonki.kgparser; - -public class Wiki { - public static final String WIKI_BASE_URL = "https://klavogonki.ru/wiki/"; - - private Wiki() { - } - - public static String getUrl(String pageName) { - return WIKI_BASE_URL + pageName.trim(); - } -} diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/http/HttpClientTest.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/http/HttpClientTest.java index 46db323fc..8197a3eb1 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/http/HttpClientTest.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/http/HttpClientTest.java @@ -12,8 +12,8 @@ import org.apache.logging.log4j.core.config.Configurator; import org.apache.logging.log4j.core.config.DefaultConfiguration; import org.json.JSONObject; +import ru.klavogonki.common.StandardDictionary; import ru.klavogonki.kgparser.Rank; -import ru.klavogonki.kgparser.StandardDictionary; import su.opencode.kefir.util.JsonUtils; import su.opencode.kefir.util.ObjectUtils; import su.opencode.kefir.util.StringUtils; diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/processing/FakeDataFactory.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/processing/FakeDataFactory.java index cacd6b4a7..24ba12417 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/processing/FakeDataFactory.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/processing/FakeDataFactory.java @@ -1,11 +1,11 @@ package ru.klavogonki.kgparser.processing; +import ru.klavogonki.common.StandardDictionary; import ru.klavogonki.kgparser.Competition; import ru.klavogonki.kgparser.Dictionary; import ru.klavogonki.kgparser.Player; import ru.klavogonki.kgparser.PlayerRoundResult; import ru.klavogonki.kgparser.Round; -import ru.klavogonki.kgparser.StandardDictionary; /** * Copyright 2014 LLC "Open Code" diff --git a/kgparserSrv/src/test/java/ru/klavogonki/kgparser/test/CompetitionTest.java b/kgparserSrv/src/test/java/ru/klavogonki/kgparser/test/CompetitionTest.java index c2cee267d..9bafdc055 100644 --- a/kgparserSrv/src/test/java/ru/klavogonki/kgparser/test/CompetitionTest.java +++ b/kgparserSrv/src/test/java/ru/klavogonki/kgparser/test/CompetitionTest.java @@ -1,12 +1,12 @@ package ru.klavogonki.kgparser.test; import org.junit.jupiter.api.Test; +import ru.klavogonki.common.StandardDictionary; import ru.klavogonki.kgparser.Competition; import ru.klavogonki.kgparser.Dictionary; import ru.klavogonki.kgparser.Player; import ru.klavogonki.kgparser.PlayerRoundResult; import ru.klavogonki.kgparser.Round; -import ru.klavogonki.kgparser.StandardDictionary; import java.util.List; import java.util.Map; diff --git a/kgparserSrv/src/test/java/ru/klavogonki/kgparser/test/RoundTest.java b/kgparserSrv/src/test/java/ru/klavogonki/kgparser/test/RoundTest.java index 2b676fdb7..3b7bfda4a 100644 --- a/kgparserSrv/src/test/java/ru/klavogonki/kgparser/test/RoundTest.java +++ b/kgparserSrv/src/test/java/ru/klavogonki/kgparser/test/RoundTest.java @@ -1,11 +1,11 @@ package ru.klavogonki.kgparser.test; import org.junit.jupiter.api.Test; +import ru.klavogonki.common.StandardDictionary; import ru.klavogonki.kgparser.Dictionary; import ru.klavogonki.kgparser.Player; import ru.klavogonki.kgparser.PlayerRoundResult; import ru.klavogonki.kgparser.Round; -import ru.klavogonki.kgparser.StandardDictionary; import static org.assertj.core.api.Assertions.assertThat; import static ru.klavogonki.kgparser.test.TestHelper.createPlayer; diff --git a/kgparserSrv/src/test/java/ru/klavogonki/kgparser/test/TestHelper.java b/kgparserSrv/src/test/java/ru/klavogonki/kgparser/test/TestHelper.java index 19342f624..56019fd57 100644 --- a/kgparserSrv/src/test/java/ru/klavogonki/kgparser/test/TestHelper.java +++ b/kgparserSrv/src/test/java/ru/klavogonki/kgparser/test/TestHelper.java @@ -1,9 +1,9 @@ package ru.klavogonki.kgparser.test; +import ru.klavogonki.common.StandardDictionary; import ru.klavogonki.kgparser.Dictionary; import ru.klavogonki.kgparser.Player; import ru.klavogonki.kgparser.Round; -import ru.klavogonki.kgparser.StandardDictionary; /** * Copyright 2014 LLC "Open Code" diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/download/PlayerJsonParser.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/download/PlayerJsonParser.java index e29ef1372..c7034ae27 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/download/PlayerJsonParser.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/download/PlayerJsonParser.java @@ -4,10 +4,10 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import ru.klavogonki.common.Car; +import ru.klavogonki.common.StandardDictionary; import ru.klavogonki.kgparser.Dictionary; import ru.klavogonki.kgparser.DictionaryMode; import ru.klavogonki.kgparser.Rank; -import ru.klavogonki.kgparser.StandardDictionary; import ru.klavogonki.openapi.model.GetIndexDataResponse; import ru.klavogonki.openapi.model.GetIndexDataStats; import ru.klavogonki.openapi.model.GetStatsOverviewGameType; diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/ExcelExporter.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/ExcelExporter.java index 5bccb69f8..0e0297c97 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/ExcelExporter.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/ExcelExporter.java @@ -6,8 +6,8 @@ import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import ru.klavogonki.common.StandardDictionary; import ru.klavogonki.kgparser.Rank; -import ru.klavogonki.kgparser.StandardDictionary; import ru.klavogonki.kgparser.http.UrlConstructor; import ru.klavogonki.statistics.dto.PlayerDto; import ru.klavogonki.statistics.dto.PlayerVocabularyDto; diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/standard/AbraTopExporter.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/standard/AbraTopExporter.java index c09be09cd..b73e6920a 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/standard/AbraTopExporter.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/standard/AbraTopExporter.java @@ -4,7 +4,7 @@ import org.apache.logging.log4j.Logger; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; -import ru.klavogonki.kgparser.StandardDictionary; +import ru.klavogonki.common.StandardDictionary; import ru.klavogonki.statistics.springboot.Profiles; @Log4j2 diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/standard/CharsTopExporter.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/standard/CharsTopExporter.java index c94720da3..177bdf573 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/standard/CharsTopExporter.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/standard/CharsTopExporter.java @@ -4,7 +4,7 @@ import org.apache.logging.log4j.Logger; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; -import ru.klavogonki.kgparser.StandardDictionary; +import ru.klavogonki.common.StandardDictionary; import ru.klavogonki.statistics.springboot.Profiles; @Log4j2 diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/standard/DigitsTopExporter.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/standard/DigitsTopExporter.java index 0de9f5759..a63792244 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/standard/DigitsTopExporter.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/standard/DigitsTopExporter.java @@ -4,7 +4,7 @@ import org.apache.logging.log4j.Logger; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; -import ru.klavogonki.kgparser.StandardDictionary; +import ru.klavogonki.common.StandardDictionary; import ru.klavogonki.statistics.springboot.Profiles; @Log4j2 diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/standard/MarathonTopExporter.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/standard/MarathonTopExporter.java index 7bb5a4fba..046f40435 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/standard/MarathonTopExporter.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/standard/MarathonTopExporter.java @@ -4,7 +4,7 @@ import org.apache.logging.log4j.Logger; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; -import ru.klavogonki.kgparser.StandardDictionary; +import ru.klavogonki.common.StandardDictionary; import ru.klavogonki.statistics.springboot.Profiles; @Log4j2 diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/standard/NoErrorTopExporter.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/standard/NoErrorTopExporter.java index 8b03a97da..2a5f35441 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/standard/NoErrorTopExporter.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/standard/NoErrorTopExporter.java @@ -4,7 +4,7 @@ import org.apache.logging.log4j.Logger; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; -import ru.klavogonki.kgparser.StandardDictionary; +import ru.klavogonki.common.StandardDictionary; import ru.klavogonki.statistics.springboot.Profiles; @Log4j2 diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/standard/NormalTopExporter.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/standard/NormalTopExporter.java index 93d52846b..f33e70b4b 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/standard/NormalTopExporter.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/standard/NormalTopExporter.java @@ -4,7 +4,7 @@ import org.apache.logging.log4j.Logger; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; -import ru.klavogonki.kgparser.StandardDictionary; +import ru.klavogonki.common.StandardDictionary; import ru.klavogonki.statistics.springboot.Profiles; @Log4j2 diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/standard/ReferatsTopExporter.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/standard/ReferatsTopExporter.java index 2f4fd5792..8a46b7985 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/standard/ReferatsTopExporter.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/standard/ReferatsTopExporter.java @@ -4,7 +4,7 @@ import org.apache.logging.log4j.Logger; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; -import ru.klavogonki.kgparser.StandardDictionary; +import ru.klavogonki.common.StandardDictionary; import ru.klavogonki.statistics.springboot.Profiles; @Log4j2 diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/standard/SprintTopExporter.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/standard/SprintTopExporter.java index 4449dc915..1a50c9c93 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/standard/SprintTopExporter.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/standard/SprintTopExporter.java @@ -4,7 +4,7 @@ import org.apache.logging.log4j.Logger; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; -import ru.klavogonki.kgparser.StandardDictionary; +import ru.klavogonki.common.StandardDictionary; import ru.klavogonki.statistics.springboot.Profiles; @Log4j2 diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/standard/StandardVocabularyTopExporter.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/standard/StandardVocabularyTopExporter.java index e96909f09..838b01758 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/standard/StandardVocabularyTopExporter.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/standard/StandardVocabularyTopExporter.java @@ -1,6 +1,6 @@ package ru.klavogonki.statistics.export.vocabulary.standard; -import ru.klavogonki.kgparser.StandardDictionary; +import ru.klavogonki.common.StandardDictionary; import ru.klavogonki.statistics.export.vocabulary.VocabularyTopExporter; import ru.klavogonki.statistics.export.vocabulary.VocabularyTopUtils; diff --git a/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/export/vocabulary/VocabularyTopUtils.kt b/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/export/vocabulary/VocabularyTopUtils.kt index 1467202dd..cab3c2db8 100644 --- a/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/export/vocabulary/VocabularyTopUtils.kt +++ b/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/export/vocabulary/VocabularyTopUtils.kt @@ -1,8 +1,8 @@ package ru.klavogonki.statistics.export.vocabulary import org.apache.logging.log4j.kotlin.Logging +import ru.klavogonki.common.StandardDictionary import ru.klavogonki.kgparser.NonStandardDictionary -import ru.klavogonki.kgparser.StandardDictionary import ru.klavogonki.statistics.excel.ExcelExporter @Suppress("TooManyFunctions") diff --git a/kgstatsSrv/src/test/java/ru/klavogonki/statistics/download/PlayerJsonParserTest.java b/kgstatsSrv/src/test/java/ru/klavogonki/statistics/download/PlayerJsonParserTest.java index 08b4de8f1..93cbe778c 100644 --- a/kgstatsSrv/src/test/java/ru/klavogonki/statistics/download/PlayerJsonParserTest.java +++ b/kgstatsSrv/src/test/java/ru/klavogonki/statistics/download/PlayerJsonParserTest.java @@ -2,8 +2,7 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import ru.klavogonki.kgparser.StandardDictionary; -import ru.klavogonki.statistics.util.TestUtils; +import ru.klavogonki.common.StandardDictionary; import ru.klavogonki.openapi.model.Bio; import ru.klavogonki.openapi.model.BioAssert; import ru.klavogonki.openapi.model.GetStatsOverviewGameType; @@ -14,6 +13,7 @@ import ru.klavogonki.openapi.model.MicrotimeAssert; import ru.klavogonki.openapi.model.NonStandardVocabularyType; import ru.klavogonki.openapi.model.VocabularyMode; +import ru.klavogonki.statistics.util.TestUtils; import java.io.File; import java.time.OffsetDateTime; diff --git a/kgstatsSrv/src/test/java/ru/klavogonki/statistics/util/JacksonUtilsTest.java b/kgstatsSrv/src/test/java/ru/klavogonki/statistics/util/JacksonUtilsTest.java index 856d96b9d..c854680d5 100644 --- a/kgstatsSrv/src/test/java/ru/klavogonki/statistics/util/JacksonUtilsTest.java +++ b/kgstatsSrv/src/test/java/ru/klavogonki/statistics/util/JacksonUtilsTest.java @@ -6,8 +6,8 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import ru.klavogonki.common.Car; +import ru.klavogonki.common.StandardDictionary; import ru.klavogonki.kgparser.Rank; -import ru.klavogonki.kgparser.StandardDictionary; import ru.klavogonki.openapi.model.Bio; import ru.klavogonki.openapi.model.BioAssert; import ru.klavogonki.openapi.model.CarAssert; diff --git a/kgstatsWeb/src/main/webapp/css/stats.css b/kgstatsWeb/src/main/webapp/css/stats.css index 896164d74..89a39fe6c 100644 --- a/kgstatsWeb/src/main/webapp/css/stats.css +++ b/kgstatsWeb/src/main/webapp/css/stats.css @@ -51,7 +51,7 @@ a:hover { .extracyber { color: #061956; } /* standard vocabularies colors, apply to any elements */ -/* see ru.klavogonki.kgparser.StandardDictionary.getColor */ +/* see ru.klavogonki.common.StandardDictionary.getColor */ .normal { color: #333333 !important; } .noerror { color: #4692AA !important; } .chars { color: #B55900 !important; } /* todo: maybe solve via a:link, a:visited styles for each link */ From 53c374df3949fde7a40c2d29a8f8c8c6d1fd19fb Mon Sep 17 00:00:00 2001 From: dmitry-weirdo Date: Mon, 25 Nov 2024 20:29:09 +0100 Subject: [PATCH 21/30] refactor: #81 In `NonStandardDictionary`, use `displayName` and `displayNamePrepositional` field names, same as in `StandardDictionary`. --- .../klavogonki/kgparser/NonStandardDictionary.java | 14 +++++++------- .../export/vocabulary/VocabularyTopUtils.kt | 10 +++++----- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/NonStandardDictionary.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/NonStandardDictionary.java index e9bdb1313..4098cfa67 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/NonStandardDictionary.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/NonStandardDictionary.java @@ -59,17 +59,17 @@ public enum NonStandardDictionary { ; - NonStandardDictionary(final int code, final String name, final String namePrepositional) { - this(Dictionary.NON_STANDARD_DICTIONARY_ID_PREFIX + code, name, namePrepositional); + NonStandardDictionary(final int code, final String displayName, final String displayNamePrepositional) { + this(Dictionary.NON_STANDARD_DICTIONARY_ID_PREFIX + code, displayName, displayNamePrepositional); } - NonStandardDictionary(final String code, final String name, final String namePrepositional) { + NonStandardDictionary(final String code, final String displayName, final String displayNamePrepositional) { this.code = code; - this.name = name; - this.namePrepositional = namePrepositional; + this.displayName = displayName; + this.displayNamePrepositional = displayNamePrepositional; } public final String code; - public final String name; - public final String namePrepositional; + public final String displayName; + public final String displayNamePrepositional; } diff --git a/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/export/vocabulary/VocabularyTopUtils.kt b/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/export/vocabulary/VocabularyTopUtils.kt index cab3c2db8..30b260199 100644 --- a/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/export/vocabulary/VocabularyTopUtils.kt +++ b/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/export/vocabulary/VocabularyTopUtils.kt @@ -16,7 +16,7 @@ object VocabularyTopUtils : Logging { @JvmStatic fun takenPlayersWithMinimalRacesCount(vocabulary: NonStandardDictionary, racesCount: Int) = - takenPlayersWithMinimalRacesCount(vocabulary.namePrepositional, racesCount) + takenPlayersWithMinimalRacesCount(vocabulary.displayNamePrepositional, racesCount) @JvmStatic fun takenPlayersWithMinimalRacesCount(vocabularyNamePrepositional: String, racesCount: Int) = @@ -28,7 +28,7 @@ object VocabularyTopUtils : Logging { @JvmStatic fun topByBestSpeedIn(vocabulary: NonStandardDictionary) = - topByBestSpeedIn(vocabulary.namePrepositional) + topByBestSpeedIn(vocabulary.displayNamePrepositional) @JvmStatic fun topByBestSpeedIn(vocabularyNamePrepositional: String) = @@ -40,7 +40,7 @@ object VocabularyTopUtils : Logging { @JvmStatic fun topByRecordIn(vocabulary: NonStandardDictionary) = - topByRecordIn(vocabulary.namePrepositional) + topByRecordIn(vocabulary.displayNamePrepositional) @JvmStatic fun topByRecordIn(vocabularyNamePrepositional: String) = @@ -133,7 +133,7 @@ object VocabularyTopUtils : Logging { @JvmStatic fun topByRacesCountIn(vocabulary: NonStandardDictionary) = - topByRacesCountIn(vocabulary.namePrepositional) + topByRacesCountIn(vocabulary.displayNamePrepositional) @JvmStatic fun topByRacesCountIn(vocabularyNamePrepositional: String) = @@ -145,7 +145,7 @@ object VocabularyTopUtils : Logging { @JvmStatic fun topByHaulIn(vocabulary: NonStandardDictionary) = - topByHaulIn(vocabulary.namePrepositional) + topByHaulIn(vocabulary.displayNamePrepositional) @JvmStatic fun topByHaulIn(vocabularyNamePrepositional: String) = From e732c7324ff3463d4516d25ac5b1ebf22d051878 Mon Sep 17 00:00:00 2001 From: dmitry-weirdo Date: Mon, 25 Nov 2024 22:05:53 +0100 Subject: [PATCH 22/30] feat: #81 Move `UrlConstructor` to `kg-common` and convert it to Kotlin. Extract static methods from Dictionary to a common Kotlin clas `DictionaryUtils`. --- .../ru/klavogonki/common/DictionaryUtils.kt | 129 ++++++++++++ .../klavogonki/common/StandardDictionary.kt | 7 - .../ru/klavogonki/common/UrlConstructor.kt | 156 ++++++++++++++ .../klavogonki/common/UrlConstructorTest.kt | 198 ++++++++++++++++++ .../ru/klavogonki/kgparser/Dictionary.java | 109 +--------- .../klavogonki/kgparser/DictionaryMode.java | 3 +- .../kgparser/NonStandardDictionary.java | 4 +- .../java/ru/klavogonki/kgparser/Player.java | 2 +- .../kgparser/http/HttpClientTest.java | 3 +- .../klavogonki/kgparser/http/ImagesUrls.java | 2 + .../kgparser/http/UrlConstructor.java | 172 --------------- .../processing/CompetitionResultsTest.java | 4 +- .../kgparser/processing/FakeDataFactory.java | 3 +- .../klavogonki/kgparser/test/TestHelper.java | 3 +- .../download/IndexDataDownloader.java | 2 +- .../statistics/download/PlayerJsonParser.java | 10 +- .../download/StatsOverviewDownloader.java | 2 +- .../download/SummaryDownloader.java | 2 +- .../statistics/entity/PlayerEntity.java | 2 +- .../entity/PlayerVocabularyStatsEntity.java | 3 +- .../statistics/excel/ExcelExporter.java | 8 +- .../excel/player/ProfileLinkColumn.java | 4 +- .../statistics/export/IndexPageExporter.java | 2 +- .../mapper/PlayerVocabularyDtoMapper.java | 2 +- 24 files changed, 524 insertions(+), 308 deletions(-) create mode 100644 kgCommon/src/main/kotlin/ru/klavogonki/common/DictionaryUtils.kt create mode 100644 kgCommon/src/main/kotlin/ru/klavogonki/common/UrlConstructor.kt create mode 100644 kgCommon/src/test/kotlin/ru/klavogonki/common/UrlConstructorTest.kt delete mode 100644 kgparserSrv/src/main/java/ru/klavogonki/kgparser/http/UrlConstructor.java diff --git a/kgCommon/src/main/kotlin/ru/klavogonki/common/DictionaryUtils.kt b/kgCommon/src/main/kotlin/ru/klavogonki/common/DictionaryUtils.kt new file mode 100644 index 000000000..2f4887a99 --- /dev/null +++ b/kgCommon/src/main/kotlin/ru/klavogonki/common/DictionaryUtils.kt @@ -0,0 +1,129 @@ +package ru.klavogonki.common + +import ru.klavogonki.common.StandardDictionary.Companion.getByKlavogonkiName +import ru.klavogonki.common.UrlConstructor.dictionaryPage + +object DictionaryUtils { + + /** + * Префикс, с которого начинается код нестандартного словаря. + */ + const val NON_STANDARD_DICTIONARY_ID_PREFIX = "voc-" + + /** + * Цвет для отображения нестандартного словаря. + */ + const val NON_STANDARD_DICTIONARY_COLOR = "#524CA7" + + /** + * @param code строковый код словаря (gametype в ajax-api) + * @return `true` — если словарь с указанным кодом является [стандартным][StandardDictionary]; + * + * `false` — если словарь с указанным кодом является пользовательским словарем. + */ + @JvmStatic + fun isStandard(code: String): Boolean { + if (code.startsWith(NON_STANDARD_DICTIONARY_ID_PREFIX)) { + return false + } + + if (StandardDictionary.isValidStandardDictionaryCode(code)) { + return true + } + + throw IllegalArgumentException("Incorrect dictionary code: \"$code\".") + } + + @JvmStatic + fun isValid(code: String) = + code.startsWith(NON_STANDARD_DICTIONARY_ID_PREFIX) || + StandardDictionary.isValidStandardDictionaryCode(code) + + @JvmStatic + fun getValidCode(code: String): String { + if (isValid(code)) { + return code + } + + val codeConstructedFromIntValue = getDictionaryCode(code.toInt()) + + require( isValid(codeConstructedFromIntValue) ) { + "Vocabulary code \"$codeConstructedFromIntValue\"" + + " constructed from given vocabulary code \"$code\"" + + " is still not valud." + } + + return codeConstructedFromIntValue + } + + /** + * @param code строковый код словаря (gametype в ajax-api) + * @return числовой идентификатор словаря + */ + @JvmStatic + fun getDictionaryId(code: String): Int { + require(!isStandard(code)) { + "Dictionary with code = \"$code\" is standard. Cannot get dictionary id from it." + } + + val codeStr = code.substring(NON_STANDARD_DICTIONARY_ID_PREFIX.length) + return codeStr.toInt() + } + + /** + * @param dictionaryId идентификатор словаря + * @return строковый код словаря + */ + @JvmStatic + fun getDictionaryCode(dictionaryId: Int): String { + return NON_STANDARD_DICTIONARY_ID_PREFIX + dictionaryId + } + + @JvmStatic + fun getTextType(code: String?): Int { + requireNotNull(code) { "dictionaryCode cannot be null" } + + if (!isStandard(code)) { + return getDictionaryId(code) + } + + val standardDictionary = StandardDictionary.getByKlavogonkiName(code) + return standardDictionary.textType + } + + /** + * @param dictionaryCode строковый код словаря + * @return цвет, соответствующий словарю. + */ + @JvmStatic + fun getDictionaryColor(dictionaryCode: String?): String { + requireNotNull(dictionaryCode) { "dictionaryCode cannot be null" } + + if (isStandard(dictionaryCode)) { + return getByKlavogonkiName(dictionaryCode).color + } + + return NON_STANDARD_DICTIONARY_COLOR + } + + /** + * @param dictionaryCode строковый код словаря + * @return страница вики клавогонок — для стандартных словарей + * + * ссылка на страницу словаря — для нестандартных словарей + */ + @JvmStatic + fun getDictionaryPageUrl(dictionaryCode: String?): String { + requireNotNull(dictionaryCode) { "dictionaryCode cannot be null" } + + if (isStandard(dictionaryCode)) { + return getByKlavogonkiName(dictionaryCode).wikiPageUrl + } + + return dictionaryPage( + getDictionaryId(dictionaryCode) + ) + } + + +} \ No newline at end of file diff --git a/kgCommon/src/main/kotlin/ru/klavogonki/common/StandardDictionary.kt b/kgCommon/src/main/kotlin/ru/klavogonki/common/StandardDictionary.kt index dc8e00f6a..9f91001a0 100644 --- a/kgCommon/src/main/kotlin/ru/klavogonki/common/StandardDictionary.kt +++ b/kgCommon/src/main/kotlin/ru/klavogonki/common/StandardDictionary.kt @@ -1,13 +1,6 @@ package ru.klavogonki.common /** - * Copyright 2014 [Dmitriy Popov](mailto:dmitry.weirdo@gmail.com). - * $HeadURL$ - * $Author$ - * $Revision$ - * $Date:: $ - *

- *

* Энум с названиями стандартных словарей (режимов), как они используются в AJAX-API. */ @SuppressWarnings("MagicNumber") diff --git a/kgCommon/src/main/kotlin/ru/klavogonki/common/UrlConstructor.kt b/kgCommon/src/main/kotlin/ru/klavogonki/common/UrlConstructor.kt new file mode 100644 index 000000000..86284332d --- /dev/null +++ b/kgCommon/src/main/kotlin/ru/klavogonki/common/UrlConstructor.kt @@ -0,0 +1,156 @@ +package ru.klavogonki.common + +/** + * Copyright 2014 [Dmitriy Popov](mailto:dmitry.weirdo@gmail.com). + */ +@Suppress("unused", "TooManyFunctions") +object UrlConstructor { + const val DOMAIN_NAME = "https://klavogonki.ru" // always use the https:// link + + private fun getLink(relativeUrl: String, vararg relativeUrlArguments: Any?): String { + return DOMAIN_NAME + String.format(relativeUrl, *relativeUrlArguments) + } + + // web page links + /** + * Сводка. + * + * @param playerId id игрока + * @return ссылка на сводку игрока (корневая страница пользователя, саммари) + */ + @JvmStatic + fun userProfileLink(playerId: Int) = + getLink("/u/#/%d/", playerId) + + /** + * @param playerId id игрока + * @return ссылка на профиль игрока без символа `#`. Ссылки с `#` не открываются из Excel. + */ + @JvmStatic + fun userProfileLinkWithoutHash(playerId: Int) = + getLink("/profile/%d/", playerId) + + /** + * Достижения. + * + * @param playerId id игрока + * @return ссылка на достижения игрока + */ + @JvmStatic + fun userAchievements(playerId: Int) = + getLink("/u/#/%d/achievements/", playerId) + + /** + * Гараж. + * + * @param playerId id игрока + * @return ссылка на гараж игрока + */ + @JvmStatic + fun userCars(playerId: Int) = + getLink("/u/#/%d/car/", playerId) + + /** + * Бортжурнал. + * + * @param playerId id игрока + * @return ссылка на бортжурнал игрока + */ + @JvmStatic + fun userJournalLink(playerId: Int) = + getLink("/u/#/%d/journal/", playerId) + + /** + * Друзья. + * + * @param playerId id игрока + * @return ссылка на список друзей игрока + */ + @JvmStatic + fun userFriendsList(playerId: Int) = + getLink("/u/#/%d/friends/list/", playerId) + + /** + * Статистика. + * + * @param playerId id игрока + * @return ссылка на статистику игрока + */ + @JvmStatic + fun userStatistics(playerId: Int) = + getLink("/u/#/%d/stats/", playerId) + + /** + * Статистика по словарю. + * + * @param playerId id игрока + * @param vocabularyCode код словаря + * @return ссылка на статистику игрока по словарю + */ + @JvmStatic + fun userStatsByVocabulary(playerId: Int, vocabularyCode: String): String { + val validCode = DictionaryUtils.getValidCode(vocabularyCode) + + return getLink("/u/#/%s/stats/%s/", playerId, validCode) + } + + /** + * Статистика по словарю. + * + * @param playerId id игрока + * @param vocabularyCode код словаря + * @return ссылка на статистику игрока по словарю без символа `#`. Ссылки с `#` не открываются из Excel. + */ + @JvmStatic + fun userStatsByVocabularyWithoutHash(playerId: Int, vocabularyCode: String): String { + val validCode = DictionaryUtils.getValidCode(vocabularyCode) + + return getLink("/profile/%s/stats/?gametype=%s", playerId, validCode) + } + + // dictionaries + /** + * @param dictionaryId идентификатор нестандартного словаря. + * @return урл страницы словаря на клавогонках + */ + @JvmStatic + fun dictionaryPage(dictionaryId: Int) = + getLink("/vocs/%d", dictionaryId) + + // car images + @JvmStatic + fun basicCarImage(car: Car) = + getLink("/img/cars/%d.png", car.id) + + // todo: maybe extract API to a separate class + // todo: write a OAS for the API + // API calls + // /api/profile + @JvmStatic + fun getSummary(playerId: Int) = + getLink("/api/profile/get-summary?id=%d", playerId) + + @JvmStatic + fun getIndexData(playerId: Int) = + getLink("/api/profile/get-index-data?userId=%d", playerId) + + @JvmStatic + fun getStatsOverview(playerId: Int) = + getLink("/api/profile/get-stats-overview?userId=%d", playerId) + + @JvmStatic + fun getStatsDetail(playerId: Int, vocabularyCode: String): String { + val validCode = DictionaryUtils.getValidCode(vocabularyCode) + + return getLink("/api/profile/get-stats-details?userId=%d&gametype=%s", playerId, validCode) + } + + /** + * @param playerLogin логин игрока + * @return json вида `{"id":242585}` для корректного логина + * либо `{"id":false}` для некорректного логина + */ + @JvmStatic + fun getUserIdByLogin(playerLogin: String) = + getLink(".fetchuser?login=%s", playerLogin) +} diff --git a/kgCommon/src/test/kotlin/ru/klavogonki/common/UrlConstructorTest.kt b/kgCommon/src/test/kotlin/ru/klavogonki/common/UrlConstructorTest.kt new file mode 100644 index 000000000..a02258c0c --- /dev/null +++ b/kgCommon/src/test/kotlin/ru/klavogonki/common/UrlConstructorTest.kt @@ -0,0 +1,198 @@ +package ru.klavogonki.common + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class UrlConstructorTest { + + @Test + fun testUserProfileLink() { + val link = UrlConstructor.userProfileLink(NOSFERATUM_PROFILE_ID) + + assertThat(link).isEqualTo("https://klavogonki.ru/u/#/242585/") + } + + @Test + fun testUserProfileLinkWithoutHash() { + val link = UrlConstructor.userProfileLinkWithoutHash(NOSFERATUM_PROFILE_ID) + + assertThat(link).isEqualTo("https://klavogonki.ru/profile/242585/") + } + + @Test + fun testUserAchievements() { + val link = UrlConstructor.userAchievements(NOSFERATUM_PROFILE_ID) + + assertThat(link).isEqualTo("https://klavogonki.ru/u/#/242585/achievements/") + } + + @Test + fun testUserCars() { + val link = UrlConstructor.userCars(NOSFERATUM_PROFILE_ID) + + assertThat(link).isEqualTo("https://klavogonki.ru/u/#/242585/car/") + } + + @Test + fun testUserJournalLink() { + val link = UrlConstructor.userJournalLink(NOSFERATUM_PROFILE_ID) + + assertThat(link).isEqualTo("https://klavogonki.ru/u/#/242585/journal/") + } + + @Test + fun testUserFriendsList() { + val link = UrlConstructor.userFriendsList(NOSFERATUM_PROFILE_ID) + + assertThat(link).isEqualTo("https://klavogonki.ru/u/#/242585/friends/list/") + } + + @Test + fun testUserStatistics() { + val link = UrlConstructor.userStatistics(NOSFERATUM_PROFILE_ID) + + assertThat(link).isEqualTo("https://klavogonki.ru/u/#/242585/stats/") + } + + @Test + fun testUserStatsByVocabulary() { + // standard vocabulary + val standardVocabularyLink = UrlConstructor.userStatsByVocabulary( + NOSFERATUM_PROFILE_ID, + STANDARD_DICTIONARY_CODE + ) + + assertThat(standardVocabularyLink).isEqualTo("https://klavogonki.ru/u/#/242585/stats/normal/") + + // non-standard vocabulary -> pass code without "voc-" prefix + val nonStandardVocabularyLinkById = UrlConstructor.userStatsByVocabulary( + NOSFERATUM_PROFILE_ID, + NON_STANDARD_DICTIONARY_ID_STRING + ) + + assertThat(nonStandardVocabularyLinkById).isEqualTo("https://klavogonki.ru/u/#/242585/stats/voc-5539/") + + // non-standard vocabulary -> pass code with "voc-" prefix + val nonStandardVocabularyLinkByCode = UrlConstructor.userStatsByVocabulary( + NOSFERATUM_PROFILE_ID, + NON_STANDARD_DICTIONARY_CODE + ) + + assertThat(nonStandardVocabularyLinkByCode).isEqualTo("https://klavogonki.ru/u/#/242585/stats/voc-5539/") + } + + @Test + fun testUserStatsByVocabularyWithoutHash() { + // standard vocabulary + val standardVocabularyLnk = UrlConstructor.userStatsByVocabularyWithoutHash( + NOSFERATUM_PROFILE_ID, + STANDARD_DICTIONARY_CODE + ) + + assertThat(standardVocabularyLnk).isEqualTo( + "https://klavogonki.ru/profile/242585/stats/?gametype=normal" + ) + + // non-standard vocabulary -> pass code without "voc-" prefix + val nonStandardVocabularyLinkById = UrlConstructor.userStatsByVocabularyWithoutHash( + NOSFERATUM_PROFILE_ID, + NON_STANDARD_DICTIONARY_ID_STRING + ) + + assertThat(nonStandardVocabularyLinkById).isEqualTo( + "https://klavogonki.ru/profile/242585/stats/?gametype=voc-5539" + ) + + // non-standard vocabulary -> pass code with "voc-" prefix + val nonStandardVocabularyLinkByCode = UrlConstructor.userStatsByVocabularyWithoutHash( + NOSFERATUM_PROFILE_ID, + NON_STANDARD_DICTIONARY_CODE + ) + + assertThat(nonStandardVocabularyLinkByCode).isEqualTo( + "https://klavogonki.ru/profile/242585/stats/?gametype=voc-5539" + ) + } + + @Test + fun testNonStandardDictionaryPage() { + val link = UrlConstructor.dictionaryPage(NON_STANDARD_DICTIONARY_ID) + + assertThat(link).isEqualTo("https://klavogonki.ru/vocs/5539") + } + + @Test + fun testBasicCarImage() { + val publicCarLink = UrlConstructor.basicCarImage(Car.TRAM) + + assertThat(publicCarLink).isEqualTo("https://klavogonki.ru/img/cars/31.png") + + val personalCarLink = UrlConstructor.basicCarImage(Car.DE_LOREAN_TIME_MACHINE) + + assertThat(personalCarLink).isEqualTo("https://klavogonki.ru/img/cars/1002.png") + } + + @Test + fun testGetSummary() { + val link = UrlConstructor.getSummary(NOSFERATUM_PROFILE_ID) + + assertThat(link).isEqualTo("https://klavogonki.ru/api/profile/get-summary?id=242585") + } + + @Test + fun testGetIndexData() { + val link = UrlConstructor.getIndexData(NOSFERATUM_PROFILE_ID) + + assertThat(link).isEqualTo("https://klavogonki.ru/api/profile/get-index-data?userId=242585") + } + + @Test + fun testGetStatsOverview() { + val link = UrlConstructor.getStatsOverview(NOSFERATUM_PROFILE_ID) + + assertThat(link).isEqualTo("https://klavogonki.ru/api/profile/get-stats-overview?userId=242585") + } + + @Test + fun testGetStatsDetail() { + // standard vocabulary + val standardVocabularyLnk = UrlConstructor.getStatsDetail( + NOSFERATUM_PROFILE_ID, + STANDARD_DICTIONARY_CODE + ) + + assertThat(standardVocabularyLnk).isEqualTo( + "https://klavogonki.ru/api/profile/get-stats-details?userId=242585&gametype=normal" + ) + + // non-standard vocabulary -> pass code without "voc-" prefix + val nonStandardVocabularyLinkById = UrlConstructor.getStatsDetail( + NOSFERATUM_PROFILE_ID, + NON_STANDARD_DICTIONARY_ID_STRING + ) + + assertThat(nonStandardVocabularyLinkById).isEqualTo( + "https://klavogonki.ru/api/profile/get-stats-details?userId=242585&gametype=voc-5539" + ) + + // non-standard vocabulary -> pass code with "voc-" prefix + val nonStandardVocabularyLinkByCode = UrlConstructor.getStatsDetail( + NOSFERATUM_PROFILE_ID, + NON_STANDARD_DICTIONARY_CODE + ) + + assertThat(nonStandardVocabularyLinkByCode).isEqualTo( + "https://klavogonki.ru/api/profile/get-stats-details?userId=242585&gametype=voc-5539" + ) + } + + companion object { + const val NOSFERATUM_PROFILE_ID = 242585 + + val STANDARD_DICTIONARY_CODE = StandardDictionary.normal.klavogonkiName // cannot use const here + + const val NON_STANDARD_DICTIONARY_ID = 5539 // todo: use constant from NonStandardDictionary + const val NON_STANDARD_DICTIONARY_ID_STRING = NON_STANDARD_DICTIONARY_ID.toString() + val NON_STANDARD_DICTIONARY_CODE = DictionaryUtils.getDictionaryCode(NON_STANDARD_DICTIONARY_ID) + } +} \ No newline at end of file diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Dictionary.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Dictionary.java index 9508bd85f..42d241d20 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Dictionary.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Dictionary.java @@ -1,7 +1,7 @@ package ru.klavogonki.kgparser; +import ru.klavogonki.common.DictionaryUtils; import ru.klavogonki.common.StandardDictionary; -import ru.klavogonki.kgparser.http.UrlConstructor; import su.opencode.kefir.srv.json.Json; import su.opencode.kefir.util.StringUtils; @@ -28,7 +28,7 @@ public Integer getId() { if ( this.isStandard() ) return null; - return getDictionaryId( this.getCode() ); + return DictionaryUtils.getDictionaryId( this.getCode() ); // return id; } // public void setId(int id) { @@ -44,6 +44,7 @@ public boolean hasCode(String dictionaryCode) { return this.code.equals(dictionaryCode); } + public boolean isSame(Dictionary dictionary) { if (dictionary == null) throw new IllegalArgumentException("dictionary cannot be null"); @@ -71,108 +72,22 @@ public int hashCode() { // necessary for HashMap */ @Json(exclude = true) public boolean isStandard() { - return isStandard(this.code); + return DictionaryUtils.isStandard(this.code); } @Json(exclude = true) public String getColor() { - return getDictionaryColor(this.code); + return DictionaryUtils.getDictionaryColor(this.code); } @Json(exclude = true) public String getDictionaryPageUrl() { - return getDictionaryPageUrl(this.code); - } - - @Json(exclude = true) - public static boolean isValid(String code) { - return code.startsWith(NON_STANDARD_DICTIONARY_ID_PREFIX) || StandardDictionary.isValidStandardDictionaryCode(code); - } - - /** - * @param code строковый код словаря (gametype в ajax-api) - * @return true — если словарь с указанным кодом является {@linkplain StandardDictionary стандартным}; - *
- * false — если словарь с указанным кодом является пользовательским словарем. - */ - @Json(exclude = true) - public static boolean isStandard(String code) { - if (code.startsWith(NON_STANDARD_DICTIONARY_ID_PREFIX)) { - return false; - } - - if (StandardDictionary.isValidStandardDictionaryCode(code)) { - return true; - } - - throw new IllegalArgumentException(String.format("Incorrect dictionary code: \"%s\".", code)); - } - - /** - * @param code строковый код словаря (gametype в ajax-api) - * @return числовой идентификатор словаря - */ - @Json(exclude = true) - public static int getDictionaryId(String code) { - if (isStandard(code)) { - throw new IllegalArgumentException( - String.format("Dictionary with code = \"%s\" is standard. Cannot get dictionary id from it.", code) - ); - } - - String codeStr = code.substring(NON_STANDARD_DICTIONARY_ID_PREFIX.length()); - return Integer.parseInt(codeStr); - } - - /** - * @param dictionaryId идентификатор словаря - * @return строковый код словаря - */ - @Json(exclude = true) - public static String getDictionaryCode(int dictionaryId) { - return NON_STANDARD_DICTIONARY_ID_PREFIX + dictionaryId; - } - - @Json(exclude = true) - public static int getTextType(String code) { - if (!isStandard(code)) { - return getDictionaryId(code); - } - - StandardDictionary standardDictionary = StandardDictionary.getByKlavogonkiName(code); - return standardDictionary.textType; - } - - /** - * @param dictionaryCode строковый код словаря - * @return цвет, соответствующий словарю. - */ - @Json(exclude = true) - public static String getDictionaryColor(String dictionaryCode) { - if (isStandard(dictionaryCode)) { - return StandardDictionary.getByKlavogonkiName(dictionaryCode).color; - } - - return NON_STANDARD_DICTIONARY_COLOR; - } - - /** - * @param dictionaryCode строковый код словаря - * @return null — для стандартных словарей - *
- * ссылка на страницу словаря — для нестандартных словарей - */ - public static String getDictionaryPageUrl(String dictionaryCode) { - if (isStandard(dictionaryCode)) { - return StandardDictionary.getByKlavogonkiName(dictionaryCode).wikiPageUrl; - } - - return UrlConstructor.dictionaryPage( getDictionaryId(dictionaryCode) ); + return DictionaryUtils.getDictionaryPageUrl(this.code); } /** * Строковый код словаря. - * Для нестандартных словарей начинается с {@linkplain #NON_STANDARD_DICTIONARY_ID_PREFIX соответствующего префикса}. + * Для нестандартных словарей начинается с {@linkplain ru.klavogonki.common.DictionaryUtils#NON_STANDARD_DICTIONARY_ID_PREFIX соответствующего префикса}. */ private String code; @@ -185,14 +100,4 @@ public static String getDictionaryPageUrl(String dictionaryCode) { * Название словаря. */ private String name; - - /** - * Префикс, с которого начинается код нестандартного словаря. - */ - public static final String NON_STANDARD_DICTIONARY_ID_PREFIX = "voc-"; - - /** - * Цвет для отображения нестандартного словаря. - */ - public static final String NON_STANDARD_DICTIONARY_COLOR = "#524CA7"; } diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/DictionaryMode.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/DictionaryMode.java index 3ad2f4bc9..3570729b1 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/DictionaryMode.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/DictionaryMode.java @@ -1,5 +1,6 @@ package ru.klavogonki.kgparser; +import ru.klavogonki.common.DictionaryUtils; import ru.klavogonki.common.StandardDictionary; public enum DictionaryMode { @@ -15,7 +16,7 @@ public enum DictionaryMode { ; public static DictionaryMode getDictionaryMode(String dictionaryCode) { - if (!Dictionary.isStandard(dictionaryCode)) { + if (!DictionaryUtils.isStandard(dictionaryCode)) { return normal; } diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/NonStandardDictionary.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/NonStandardDictionary.java index 4098cfa67..3a2405540 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/NonStandardDictionary.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/NonStandardDictionary.java @@ -1,5 +1,7 @@ package ru.klavogonki.kgparser; +import ru.klavogonki.common.DictionaryUtils; + /** * Популярные нестандартные словари. */ @@ -60,7 +62,7 @@ public enum NonStandardDictionary { NonStandardDictionary(final int code, final String displayName, final String displayNamePrepositional) { - this(Dictionary.NON_STANDARD_DICTIONARY_ID_PREFIX + code, displayName, displayNamePrepositional); + this(DictionaryUtils.NON_STANDARD_DICTIONARY_ID_PREFIX + code, displayName, displayNamePrepositional); } NonStandardDictionary(final String code, final String displayName, final String displayNamePrepositional) { diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Player.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Player.java index e1a4fbdb6..a641841df 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Player.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Player.java @@ -1,6 +1,6 @@ package ru.klavogonki.kgparser; -import ru.klavogonki.kgparser.http.UrlConstructor; +import ru.klavogonki.common.UrlConstructor; import su.opencode.kefir.srv.json.Json; import su.opencode.kefir.srv.json.JsonObject; diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/http/HttpClientTest.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/http/HttpClientTest.java index 8197a3eb1..12ddecb45 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/http/HttpClientTest.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/http/HttpClientTest.java @@ -13,6 +13,7 @@ import org.apache.logging.log4j.core.config.DefaultConfiguration; import org.json.JSONObject; import ru.klavogonki.common.StandardDictionary; +import ru.klavogonki.common.UrlConstructor; import ru.klavogonki.kgparser.Rank; import su.opencode.kefir.util.JsonUtils; import su.opencode.kefir.util.ObjectUtils; @@ -70,7 +71,7 @@ public static void main(String[] args) throws IOException { logger.info(""); // String dictionaryCode = StandardDictionary.normal.toString(); // обычный String dictionaryCode = StandardDictionary.chars.toString(); // буквы -// String dictionaryCode = Dictionary.getDictionaryCode(192); // частотный +// String dictionaryCode = DictionaryUtils.getDictionaryCode(192); // частотный url = UrlConstructor.getStatsDetail(playerId, dictionaryCode); logger.info("url: {}", url); body = getResponseBody(url); diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/http/ImagesUrls.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/http/ImagesUrls.java index 39ecbfbab..cb633c15f 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/http/ImagesUrls.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/http/ImagesUrls.java @@ -1,5 +1,7 @@ package ru.klavogonki.kgparser.http; +import ru.klavogonki.common.UrlConstructor; + /** * Copyright 2014 Dmitriy Popov. * $HeadURL$ diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/http/UrlConstructor.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/http/UrlConstructor.java deleted file mode 100644 index 1b51f6bd0..000000000 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/http/UrlConstructor.java +++ /dev/null @@ -1,172 +0,0 @@ -package ru.klavogonki.kgparser.http; - -import ru.klavogonki.common.Car; -import ru.klavogonki.kgparser.Dictionary; -import ru.klavogonki.kgparser.Player; - -/** - * Copyright 2014 Dmitriy Popov. - * $HeadURL$ - * $Author$ - * $Revision$ - * $Date:: $ - */ -@SuppressWarnings("unused") -public final class UrlConstructor { - public static final String DOMAIN_NAME = "http://klavogonki.ru"; - public static final String DOMAIN_NAME_HTTPS = "https://klavogonki.ru"; - - private UrlConstructor() { - } - - public static String getLink(String relativeUrl, Object... relativeUrlArguments) { - return DOMAIN_NAME_HTTPS + String.format(relativeUrl, relativeUrlArguments); - } - - public static String getLinkHttps(String relativeUrl, Object... relativeUrlArguments) { - return DOMAIN_NAME_HTTPS + String.format(relativeUrl, relativeUrlArguments); - } - - // web page links - /** - * @param player игрок - * @return урл профиля игрока - */ - public static String userProfileLink(Player player) { - return userProfileLink(player.getProfileId()); - } - - /** - * Сводка - * - * @param playerId id игрока - * @return ссылка на сводку игрока (корневая страница пользователя, саммари) - */ - public static String userProfileLink(final int playerId) { - return getLinkHttps("/u/#/%d/", playerId); - } - - /** - * @param playerId id игрока - * @return ссылка на профиль игрока без символа {@code #}. Ссылки с {@code #} не открываются из Excel. - */ - public static String userProfileLinkWithNoHash(final int playerId) { - return getLinkHttps("/profile/%d/", playerId); - } - - /** - * Достижения - * - * @param playerId id игрока - * @return ссылка на достижения игрока - */ - public static String userAchievements(final int playerId) { - return getLink("/u/#/%d/achievements/", playerId); - } - - /** - * Гараж - * - * @param playerId id игрока - * @return ссылка на гараж игрока - */ - public static String userCars(final int playerId) { - return getLink("/u/#/%d/car/", playerId); - } - - /** - * Бортжурнал - * - * @param playerId id игрока - * @return ссылка на бортжурнал игрока - */ - public static String userJournalLink(final int playerId) { - return getLink("/u/#/%d/journal/", playerId); - } - - /** - * Друзья - * - * @param playerId id игрока - * @return ссылка на список друзей игрока - */ - public static String userFriendsList(final int playerId) { - return getLink("/u/#/%d/friends/list/", playerId); - } - - /** - * Статистика - * - * @param playerId id игрока - * @return ссылка на статистику игрока - */ - public static String userStatistics(final int playerId) { - return getLink("/u/#/%d/stats/", playerId); - } - - /** - * Статистика по словарю - * - * @param playerId id игрока - * @param vocabularyCode {@link Dictionary#getCode код словаря} - * @return ссылка на статистику игрока по словарю - */ - public static String userStatsByVocabulary(final int playerId, final String vocabularyCode) { - return getLink("/u/#/%s/stats/%s/", playerId, vocabularyCode); - } - - /** - * Статистика по словарю - * - * @param playerId id игрока - * @param vocabularyCode {@link Dictionary#getCode код словаря} - * @return ссылка на статистику игрока по словарю без символа {@code #}. Ссылки с {@code #} не открываются из Excel. - */ - public static String userStatsByVocabularyWithoutHash(final int playerId, final String vocabularyCode) { - return getLink("/profile/%s/stats/?gametype=%s", playerId, vocabularyCode); - } - - // dictionaries - - /** - * @param dictionaryId идентификатор нестандартного словаря. - * @return урл страницы словаря на клавогонках - */ - public static String dictionaryPage(int dictionaryId) { - return getLink("/vocs/%d", dictionaryId); - } - - // car images - public static String basicCarImage(Car car) { - return getLink("/img/cars/%d.png", car.getId()); - } - - // todo: maybe extract API to a separate class - // todo: write a OAS for the API - // API calls - // /api/profile - public static String getSummary(final int playerId) { - return getLink("/api/profile/get-summary?id=%d", playerId); - } - - public static String getIndexData(final int playerId) { - return getLink("/api/profile/get-index-data?userId=%d", playerId); - } - - public static String getStatsOverview(int playerId) { - return getLink("/api/profile/get-stats-overview?userId=%d", playerId); - } - - public static String getStatsDetail(int playerId, String dictionaryCode) { - return getLink("/api/profile/get-stats-details?userId=%d&gametype=%s", playerId, dictionaryCode); - } - - /** - * @param playerLogin логин игрока - * @return json вида {@code {"id":242585}} для корректного логина - * либо {@code {"id":false}} для некорректного логина - */ - public static String getUserIdByLogin(String playerLogin) { - return getLink(".fetchuser?login=%s", playerLogin); - } -} diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/processing/CompetitionResultsTest.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/processing/CompetitionResultsTest.java index 96ac1db07..5f48eef33 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/processing/CompetitionResultsTest.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/processing/CompetitionResultsTest.java @@ -5,10 +5,10 @@ import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.core.config.Configurator; import org.apache.logging.log4j.core.config.DefaultConfiguration; +import ru.klavogonki.common.UrlConstructor; import ru.klavogonki.kgparser.Competition; import ru.klavogonki.kgparser.Dictionary; import ru.klavogonki.kgparser.Player; -import ru.klavogonki.kgparser.http.UrlConstructor; import java.util.Set; @@ -70,7 +70,7 @@ public static void getPlayerDictionariesResultsCount(Competition competition) { "Player {} (profileId = {}, profileLink = {})", player.getName(), player.getProfileId(), - UrlConstructor.userProfileLink(player) + UrlConstructor.userProfileLink(player.getProfileId()) ); int totalRoundsCount = competition.getRoundsCount(player); diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/processing/FakeDataFactory.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/processing/FakeDataFactory.java index 24ba12417..17fb0effa 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/processing/FakeDataFactory.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/processing/FakeDataFactory.java @@ -1,5 +1,6 @@ package ru.klavogonki.kgparser.processing; +import ru.klavogonki.common.DictionaryUtils; import ru.klavogonki.common.StandardDictionary; import ru.klavogonki.kgparser.Competition; import ru.klavogonki.kgparser.Dictionary; @@ -72,7 +73,7 @@ public static Dictionary getDictionary(StandardDictionary dictionary) { return getDictionary( dictionary.toString(), dictionary.displayName ); } public static Dictionary getDictionary(int dictionaryId, String name) { - return getDictionary( Dictionary.getDictionaryCode(dictionaryId), name ); + return getDictionary( DictionaryUtils.getDictionaryCode(dictionaryId), name ); } public static Dictionary getDictionary(String code, String name) { Dictionary dictionary = new Dictionary(); diff --git a/kgparserSrv/src/test/java/ru/klavogonki/kgparser/test/TestHelper.java b/kgparserSrv/src/test/java/ru/klavogonki/kgparser/test/TestHelper.java index 56019fd57..176a21f91 100644 --- a/kgparserSrv/src/test/java/ru/klavogonki/kgparser/test/TestHelper.java +++ b/kgparserSrv/src/test/java/ru/klavogonki/kgparser/test/TestHelper.java @@ -1,5 +1,6 @@ package ru.klavogonki.kgparser.test; +import ru.klavogonki.common.DictionaryUtils; import ru.klavogonki.common.StandardDictionary; import ru.klavogonki.kgparser.Dictionary; import ru.klavogonki.kgparser.Player; @@ -28,7 +29,7 @@ public static Dictionary getDictionary(StandardDictionary dictionary) { return getDictionary( dictionary.toString(), dictionary.displayName ); } public static Dictionary getDictionary(int dictionaryId, String name) { - return getDictionary( Dictionary.getDictionaryCode(dictionaryId), name ); + return getDictionary( DictionaryUtils.getDictionaryCode(dictionaryId), name ); } public static Dictionary getDictionary(String code, String name) { Dictionary dictionary = new Dictionary(); diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/download/IndexDataDownloader.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/download/IndexDataDownloader.java index 1c2931a58..93802bb8d 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/download/IndexDataDownloader.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/download/IndexDataDownloader.java @@ -2,7 +2,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import ru.klavogonki.kgparser.http.UrlConstructor; +import ru.klavogonki.common.UrlConstructor; import ru.klavogonki.statistics.Config; public class IndexDataDownloader implements DataDownloader { diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/download/PlayerJsonParser.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/download/PlayerJsonParser.java index c7034ae27..c1ae42c8c 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/download/PlayerJsonParser.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/download/PlayerJsonParser.java @@ -4,8 +4,8 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import ru.klavogonki.common.Car; +import ru.klavogonki.common.DictionaryUtils; import ru.klavogonki.common.StandardDictionary; -import ru.klavogonki.kgparser.Dictionary; import ru.klavogonki.kgparser.DictionaryMode; import ru.klavogonki.kgparser.Rank; import ru.klavogonki.openapi.model.GetIndexDataResponse; @@ -435,12 +435,12 @@ private static void validate(int playerId, GetStatsOverviewResponse response, St GetStatsOverviewGameType vocabularyStats = entry.getValue(); - if (!Dictionary.isValid(vocabularyCode)) { // we have dictionaries with "" code + if (!DictionaryUtils.isValid(vocabularyCode)) { // we have dictionaries with "" code logger.warn("Stats overview file {}: Invalid vocabulary code: {}. Cannot validate it as standard or non-standard.", statsOverviewFilePath, vocabularyCode); // todo: we may write some heuristic determination whether this dictionary is standard or non-standard // throw new ParserException("Stats overview file %s: Incorrect vocabulary code in gametypes: \"%s\"", statsOverviewFilePath, vocabularyCode); } - else if (Dictionary.isStandard(vocabularyCode)) { + else if (DictionaryUtils.isStandard(vocabularyCode)) { validateCommon(statsOverviewFilePath, vocabularyCode, vocabularyStats); validateStandardVocabulary(statsOverviewFilePath, vocabularyCode, vocabularyStats); validateInfo(playerId, statsOverviewFilePath, vocabularyCode, vocabularyStats); @@ -508,7 +508,7 @@ private static void validateNonStandardVocabulary(final String statsOverviewFile throw new ParserException("Stats overview file %s: Vocabulary %s is non-standard, but id is not present.", statsOverviewFilePath, vocabularyCode); } - int expectedId = Dictionary.getDictionaryId(vocabularyCode); + int expectedId = DictionaryUtils.getDictionaryId(vocabularyCode); if (id != expectedId) { throw new ParserException("Stats overview file %s: Vocabulary %s is non-standard, but id = %d is not equal to expectedId = %d.", statsOverviewFilePath, vocabularyCode, id, expectedId); } @@ -618,7 +618,7 @@ private static void validateInfo(final int playerId, final String statsOverviewF throw new ParserException("Stats overview file %s: Vocabulary %s: info.texttype is not present.", statsOverviewFilePath, vocabularyCode); } - int expectedTextType = Dictionary.getTextType(vocabularyCode); + int expectedTextType = DictionaryUtils.getTextType(vocabularyCode); if (!textType.equals(expectedTextType)) { throw new ParserException("Stats overview file %s: Vocabulary %s: info.texttype %s is not equal to expected textType = %d.", statsOverviewFilePath, vocabularyCode, textType, expectedTextType); } diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/download/StatsOverviewDownloader.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/download/StatsOverviewDownloader.java index 2c37bc92d..53b24294c 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/download/StatsOverviewDownloader.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/download/StatsOverviewDownloader.java @@ -2,7 +2,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import ru.klavogonki.kgparser.http.UrlConstructor; +import ru.klavogonki.common.UrlConstructor; import ru.klavogonki.statistics.Config; public class StatsOverviewDownloader implements DataDownloader { diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/download/SummaryDownloader.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/download/SummaryDownloader.java index 89f4e7ee9..2b749f044 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/download/SummaryDownloader.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/download/SummaryDownloader.java @@ -2,7 +2,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import ru.klavogonki.kgparser.http.UrlConstructor; +import ru.klavogonki.common.UrlConstructor; import ru.klavogonki.statistics.Config; public class SummaryDownloader implements DataDownloader { diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/entity/PlayerEntity.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/entity/PlayerEntity.java index 29e14b1cc..99056f5b9 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/entity/PlayerEntity.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/entity/PlayerEntity.java @@ -3,8 +3,8 @@ import lombok.Data; import lombok.ToString; import org.hibernate.annotations.NaturalId; +import ru.klavogonki.common.UrlConstructor; import ru.klavogonki.kgparser.Rank; -import ru.klavogonki.kgparser.http.UrlConstructor; import javax.persistence.AttributeOverride; import javax.persistence.AttributeOverrides; diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/entity/PlayerVocabularyStatsEntity.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/entity/PlayerVocabularyStatsEntity.java index 58f0750f4..f228c1a89 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/entity/PlayerVocabularyStatsEntity.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/entity/PlayerVocabularyStatsEntity.java @@ -1,7 +1,6 @@ package ru.klavogonki.statistics.entity; import lombok.Data; -import ru.klavogonki.kgparser.Dictionary; import ru.klavogonki.kgparser.DictionaryMode; import ru.klavogonki.kgparser.NonStandardDictionaryType; @@ -81,7 +80,7 @@ public class PlayerVocabularyStatsEntity implements Serializable { *
  • Для нестандартных словарей — числовой id словаря.
  • * * - * @see Dictionary#getTextType + * @see ru.klavogonki.common.DictionaryUtils#getTextType */ private Integer vocabularyTextType; diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/ExcelExporter.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/ExcelExporter.java index 0e0297c97..2ad25e688 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/ExcelExporter.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/ExcelExporter.java @@ -7,8 +7,8 @@ import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import ru.klavogonki.common.StandardDictionary; +import ru.klavogonki.common.UrlConstructor; import ru.klavogonki.kgparser.Rank; -import ru.klavogonki.kgparser.http.UrlConstructor; import ru.klavogonki.statistics.dto.PlayerDto; import ru.klavogonki.statistics.dto.PlayerVocabularyDto; import ru.klavogonki.statistics.excel.data.ExcelExportContextData; @@ -88,7 +88,7 @@ public static void testExportTotalRacesCountTop(String filePath) { player1.setOrderNumber("1"); player1.setLogin("ant1k"); player1.setPlayerId(146269); - player1.setProfileLink(UrlConstructor.userProfileLinkWithNoHash(player1.getPlayerId())); + player1.setProfileLink(UrlConstructor.userProfileLinkWithoutHash(player1.getPlayerId())); player1.setBestSpeed(1070); player1.setTotalRacesCount(30259); player1.setRegistered("2009-07-31 12:31:23"); @@ -104,7 +104,7 @@ public static void testExportTotalRacesCountTop(String filePath) { player2.setOrderNumber("2–3"); player2.setLogin("170000"); player2.setPlayerId(169106); - player2.setProfileLink(UrlConstructor.userProfileLinkWithNoHash(player2.getPlayerId())); + player2.setProfileLink(UrlConstructor.userProfileLinkWithoutHash(player2.getPlayerId())); player2.setBestSpeed(967); player2.setTotalRacesCount(57976); player2.setRegistered("2009-12-26 14:30:55"); @@ -120,7 +120,7 @@ public static void testExportTotalRacesCountTop(String filePath) { player3.setOrderNumber("2–3"); player3.setLogin("HRUST"); player3.setPlayerId(61254); - player3.setProfileLink(UrlConstructor.userProfileLinkWithNoHash(player3.getPlayerId())); + player3.setProfileLink(UrlConstructor.userProfileLinkWithoutHash(player3.getPlayerId())); player3.setBestSpeed(967); player3.setTotalRacesCount(154973); player3.setRegistered("2008-11-04 18:38:19"); diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/player/ProfileLinkColumn.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/player/ProfileLinkColumn.java index 935083522..b88b97efd 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/player/ProfileLinkColumn.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/player/ProfileLinkColumn.java @@ -1,9 +1,9 @@ package ru.klavogonki.statistics.excel.player; import lombok.extern.log4j.Log4j2; +import ru.klavogonki.common.UrlConstructor; import ru.klavogonki.statistics.excel.ExcelExportContext; import ru.klavogonki.statistics.excel.data.ExcelExportContextData; -import ru.klavogonki.kgparser.http.UrlConstructor; import java.util.function.Function; @@ -42,7 +42,7 @@ public void formatCell(final ExcelExportContext context) { } // use a special link with no # in it, since Excel has a bug with links containing # - String profileLink = UrlConstructor.userProfileLinkWithNoHash(playerId); + String profileLink = UrlConstructor.userProfileLinkWithoutHash(playerId); context.setIntegerHyperlink(profileLink, playerId); // todo: think about this,this will also set link integer format } } diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/IndexPageExporter.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/IndexPageExporter.java index ca1ff00a1..1e3e692e3 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/IndexPageExporter.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/IndexPageExporter.java @@ -4,8 +4,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; +import ru.klavogonki.common.UrlConstructor; import ru.klavogonki.kgparser.Rank; -import ru.klavogonki.kgparser.http.UrlConstructor; import ru.klavogonki.statistics.dto.PlayersByRankCount; import ru.klavogonki.statistics.entity.PlayerEntity; import ru.klavogonki.statistics.freemarker.IndexPageTemplate; diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/mapper/PlayerVocabularyDtoMapper.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/mapper/PlayerVocabularyDtoMapper.java index 68128e24a..d019cc573 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/mapper/PlayerVocabularyDtoMapper.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/mapper/PlayerVocabularyDtoMapper.java @@ -6,8 +6,8 @@ import org.mapstruct.Mapping; import org.mapstruct.MappingTarget; import org.mapstruct.Named; +import ru.klavogonki.common.UrlConstructor; import ru.klavogonki.kgparser.Rank; -import ru.klavogonki.kgparser.http.UrlConstructor; import ru.klavogonki.statistics.dto.PlayerVocabularyDto; import ru.klavogonki.statistics.entity.PlayerVocabularyStatsEntity; import ru.klavogonki.statistics.freemarker.HaulUtils; From 607cd335fce7c65c4055da6a6a0d0257f474e924 Mon Sep 17 00:00:00 2001 From: dmitry-weirdo Date: Mon, 25 Nov 2024 22:37:10 +0100 Subject: [PATCH 23/30] feat: #81 #102 Move `Dictionary` and `StandardDictionary` to `kg-common` and convert them to Kotlin. Make fields of `Car` visible to Java. --- .../main/kotlin/ru/klavogonki/common/Car.kt | 39 ++++------------ .../ru/klavogonki/common/DictionaryMode.kt | 33 +++++++++++++ .../klavogonki/common/StandardDictionary.kt | 34 ++++++++++---- .../klavogonki/kgparser/DictionaryMode.java | 46 ------------------- .../statistics/download/PlayerJsonParser.java | 4 +- .../entity/PlayerVocabularyStatsEntity.java | 4 +- .../mapper/PlayerVocabularyStatsMapper.java | 8 ++-- .../statistics/util/JacksonUtilsTest.java | 8 ++-- 8 files changed, 78 insertions(+), 98 deletions(-) create mode 100644 kgCommon/src/main/kotlin/ru/klavogonki/common/DictionaryMode.kt delete mode 100644 kgparserSrv/src/main/java/ru/klavogonki/kgparser/DictionaryMode.java diff --git a/kgCommon/src/main/kotlin/ru/klavogonki/common/Car.kt b/kgCommon/src/main/kotlin/ru/klavogonki/common/Car.kt index 3ed8744f2..b32c6653d 100644 --- a/kgCommon/src/main/kotlin/ru/klavogonki/common/Car.kt +++ b/kgCommon/src/main/kotlin/ru/klavogonki/common/Car.kt @@ -4,7 +4,12 @@ package ru.klavogonki.common * List of cars with ids and Russian names. */ @SuppressWarnings("MagicNumber") -enum class Car { +enum class Car( + @JvmField val id: Int, + @JvmField val displayName: String, + @JvmField val ownerId: Int?, // for personal autos + @JvmField val personalId: Int?, // for personal autos that have been made public +) { // common/public autos ZAZ_965(1, "ЗАЗ 965"), VAZ_2104(2, "ВАЗ 2104"), @@ -106,31 +111,10 @@ enum class Car { FERRARI_F2(1024, "Ferrari F12", 320247), // http://klavogonki.ru/u/#/320247/car/ ; - constructor(id: Int, displayName: String) { - this.id = id - this.displayName = displayName - this.ownerId = null - this.personalId = null - } + constructor(id: Int, displayName: String) : this(id, displayName, null, null) - constructor(id: Int, displayName: String, ownerId: Int) { // for personal cars that have not been made public - this.id = id - this.displayName = displayName - this.ownerId = ownerId - this.personalId = null - } - - constructor( - id: Int, - displayName: String, - ownerId: Int, - personalId: Int - ) { // for personal cars that have not been made public - this.id = id - this.displayName = displayName - this.ownerId = ownerId - this.personalId = personalId - } + // for personal cars that have not been made public + constructor(id: Int, displayName: String, ownerId: Int) : this(id, displayName, ownerId, null) @Suppress("Unused") fun isPersonalOnly() = (ownerId != null) && (personalId == null) @@ -141,11 +125,6 @@ enum class Car { @Suppress("Unused") fun isPublic() = (id < FIRST_PERSONAL_CAR_ID) - val id: Int - val displayName: String - val ownerId: Int? // for personal autos - val personalId: Int? // for personal autos that have been made public - companion object { fun isPersonalId(carId: Int): Boolean { return carId >= FIRST_PERSONAL_CAR_ID diff --git a/kgCommon/src/main/kotlin/ru/klavogonki/common/DictionaryMode.kt b/kgCommon/src/main/kotlin/ru/klavogonki/common/DictionaryMode.kt new file mode 100644 index 000000000..82a5ec2ad --- /dev/null +++ b/kgCommon/src/main/kotlin/ru/klavogonki/common/DictionaryMode.kt @@ -0,0 +1,33 @@ +package ru.klavogonki.common + +import ru.klavogonki.common.DictionaryUtils.isStandard + +enum class DictionaryMode( + + /** + * Имя в API клавогонок. Все буквы в нижнем регистре. + */ + @JvmField val klavogonkiName: String, +) { + normal("normal"), + + noerror("noerror"), + + sprint("sprint"), + + marathon("marathon"), + ; + + companion object { + + @JvmStatic + fun getDictionaryMode(dictionaryCode: String): DictionaryMode { + if (!isStandard(dictionaryCode)) { + return normal + } + + val standardDictionary = StandardDictionary.getByKlavogonkiName(dictionaryCode) + return standardDictionary.dictionaryMode + } + } +} diff --git a/kgCommon/src/main/kotlin/ru/klavogonki/common/StandardDictionary.kt b/kgCommon/src/main/kotlin/ru/klavogonki/common/StandardDictionary.kt index 9f91001a0..bfc443999 100644 --- a/kgCommon/src/main/kotlin/ru/klavogonki/common/StandardDictionary.kt +++ b/kgCommon/src/main/kotlin/ru/klavogonki/common/StandardDictionary.kt @@ -3,7 +3,7 @@ package ru.klavogonki.common /** * Энум с названиями стандартных словарей (режимов), как они используются в AJAX-API. */ -@SuppressWarnings("MagicNumber") +@SuppressWarnings("MagicNumber", "LongParameterList") enum class StandardDictionary( /** @@ -35,7 +35,13 @@ enum class StandardDictionary( * Тип текста словаря. * Для нестандартных словарей будет равен идентификатору словаря. */ - @JvmField val textType: Int + @JvmField val textType: Int, + + /** + * Режим текста словаря. + * Возвращается в поле `mode` в `/get-stats-overview -> ... -> info`. + */ + @JvmField val dictionaryMode: DictionaryMode ) { /** * Обычный. @@ -46,7 +52,8 @@ enum class StandardDictionary( displayNamePrepositional = "Обычном", color = "#333333", wikiPageUrl = Wiki.getUrl("%D0%9E%D0%B1%D1%8B%D1%87%D0%BD%D1%8B%D0%B9"), - textType = 0 + textType = 0, + dictionaryMode = DictionaryMode.normal ), /** @@ -58,7 +65,8 @@ enum class StandardDictionary( displayNamePrepositional = "Безошибочном", color = "#4692AA", wikiPageUrl = Wiki.getUrl("%D0%91%D0%B5%D0%B7%D0%BE%D1%88%D0%B8%D0%B1%D0%BE%D1%87%D0%BD%D1%8B%D0%B9"), - textType = 0 + textType = 0, + dictionaryMode = DictionaryMode.noerror ), /** @@ -70,7 +78,8 @@ enum class StandardDictionary( displayNamePrepositional = "Буквах", color = "#B55900", wikiPageUrl = Wiki.getUrl("%D0%91%D1%83%D0%BA%D0%B2%D1%8B"), - textType = -4 + textType = -4, + dictionaryMode = DictionaryMode.normal ), /** @@ -82,7 +91,8 @@ enum class StandardDictionary( displayNamePrepositional = "Марафоне", color = "#D43E68", wikiPageUrl = Wiki.getUrl("%D0%9C%D0%B0%D1%80%D0%B0%D1%84%D0%BE%D0%BD"), - textType = 0 + textType = 0, + dictionaryMode = DictionaryMode.marathon ), /** @@ -94,7 +104,8 @@ enum class StandardDictionary( displayNamePrepositional = "Абракадабре", color = "#3D4856", wikiPageUrl = Wiki.getUrl("%D0%90%D0%B1%D1%80%D0%B0%D0%BA%D0%B0%D0%B4%D0%B0%D0%B1%D1%80%D0%B0"), - textType = -1 + textType = -1, + dictionaryMode = DictionaryMode.normal ), /** @@ -106,7 +117,8 @@ enum class StandardDictionary( displayNamePrepositional = "Яндекс.Рефератах", color = "#698725", wikiPageUrl = Wiki.getUrl("%D0%AF%D0%BD%D0%B4%D0%B5%D0%BA%D1%81.%D0%A0%D0%B5%D1%84%D0%B5%D1%80%D0%B0%D1%82%D1%8B"), - textType = -3 + textType = -3, + dictionaryMode = DictionaryMode.normal ), /** @@ -118,7 +130,8 @@ enum class StandardDictionary( displayNamePrepositional = "Цифрах", color = "#777777", wikiPageUrl = Wiki.getUrl("%D0%A6%D0%B8%D1%84%D1%80%D1%8B"), - textType = -2 + textType = -2, + dictionaryMode = DictionaryMode.normal ), /** @@ -130,7 +143,8 @@ enum class StandardDictionary( displayNamePrepositional = "Спринте", color = "#833F3A", wikiPageUrl = Wiki.getUrl("%D0%A1%D0%BF%D1%80%D0%B8%D0%BD%D1%82"), - textType = 0 + textType = 0, + dictionaryMode = DictionaryMode.sprint ), ; diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/DictionaryMode.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/DictionaryMode.java deleted file mode 100644 index 3570729b1..000000000 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/DictionaryMode.java +++ /dev/null @@ -1,46 +0,0 @@ -package ru.klavogonki.kgparser; - -import ru.klavogonki.common.DictionaryUtils; -import ru.klavogonki.common.StandardDictionary; - -public enum DictionaryMode { - - normal, - - noerror, - - sprint, - - marathon, - - ; - - public static DictionaryMode getDictionaryMode(String dictionaryCode) { - if (!DictionaryUtils.isStandard(dictionaryCode)) { - return normal; - } - - StandardDictionary standardDictionary = StandardDictionary.getByKlavogonkiName(dictionaryCode); - - switch (standardDictionary) { - case normal: - case chars: - case abra: - case referats: - case digits: - return normal; - - case sprint: - return sprint; - - case noerror: - return noerror; - - case marathon: - return marathon; - - default: - throw new IllegalArgumentException(String.format("Unknown standard dictionary code: %s", dictionaryCode)); - } - } -} diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/download/PlayerJsonParser.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/download/PlayerJsonParser.java index c1ae42c8c..ce31e5975 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/download/PlayerJsonParser.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/download/PlayerJsonParser.java @@ -4,9 +4,9 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import ru.klavogonki.common.Car; +import ru.klavogonki.common.DictionaryMode; import ru.klavogonki.common.DictionaryUtils; import ru.klavogonki.common.StandardDictionary; -import ru.klavogonki.kgparser.DictionaryMode; import ru.klavogonki.kgparser.Rank; import ru.klavogonki.openapi.model.GetIndexDataResponse; import ru.klavogonki.openapi.model.GetIndexDataStats; @@ -608,7 +608,7 @@ private static void validateInfo(final int playerId, final String statsOverviewF DictionaryMode expectedMode = DictionaryMode.getDictionaryMode(vocabularyCode); // todo: mapper conversion VocabularyMode -> DictionaryMode? - if (!mode.toString().equals(expectedMode.toString())) { + if (!mode.toString().equals(expectedMode.klavogonkiName)) { throw new ParserException("Stats overview file %s: Vocabulary %s: info.mode %s is not equal to expected mode = %d.", statsOverviewFilePath, vocabularyCode, mode, expectedMode); } diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/entity/PlayerVocabularyStatsEntity.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/entity/PlayerVocabularyStatsEntity.java index f228c1a89..2913ff388 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/entity/PlayerVocabularyStatsEntity.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/entity/PlayerVocabularyStatsEntity.java @@ -1,7 +1,7 @@ package ru.klavogonki.statistics.entity; import lombok.Data; -import ru.klavogonki.kgparser.DictionaryMode; +import ru.klavogonki.common.DictionaryMode; import ru.klavogonki.kgparser.NonStandardDictionaryType; import javax.persistence.Entity; @@ -67,7 +67,7 @@ public class PlayerVocabularyStatsEntity implements Serializable { * * @see DictionaryMode#getDictionaryMode */ - @Enumerated(EnumType.STRING) + @Enumerated(EnumType.STRING) // todo: save using the klavogonikiName field, NOT the enum itself private DictionaryMode vocabularyMode; /** diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/mapper/PlayerVocabularyStatsMapper.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/mapper/PlayerVocabularyStatsMapper.java index 7d65342a4..f74c890e5 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/mapper/PlayerVocabularyStatsMapper.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/mapper/PlayerVocabularyStatsMapper.java @@ -7,15 +7,15 @@ import org.mapstruct.MappingTarget; import org.mapstruct.ValueMapping; import org.mapstruct.ValueMappings; -import ru.klavogonki.kgparser.DictionaryMode; +import ru.klavogonki.common.DictionaryMode; import ru.klavogonki.kgparser.NonStandardDictionaryType; -import ru.klavogonki.statistics.entity.PlayerEntity; -import ru.klavogonki.statistics.entity.PlayerVocabularyStatsEntity; -import ru.klavogonki.statistics.util.DateUtils; import ru.klavogonki.openapi.model.GetStatsOverviewGameType; import ru.klavogonki.openapi.model.GetStatsOverviewResponse; import ru.klavogonki.openapi.model.NonStandardVocabularyType; import ru.klavogonki.openapi.model.VocabularyMode; +import ru.klavogonki.statistics.entity.PlayerEntity; +import ru.klavogonki.statistics.entity.PlayerVocabularyStatsEntity; +import ru.klavogonki.statistics.util.DateUtils; import java.time.LocalDateTime; diff --git a/kgstatsSrv/src/test/java/ru/klavogonki/statistics/util/JacksonUtilsTest.java b/kgstatsSrv/src/test/java/ru/klavogonki/statistics/util/JacksonUtilsTest.java index c854680d5..c610ddf58 100644 --- a/kgstatsSrv/src/test/java/ru/klavogonki/statistics/util/JacksonUtilsTest.java +++ b/kgstatsSrv/src/test/java/ru/klavogonki/statistics/util/JacksonUtilsTest.java @@ -87,7 +87,7 @@ void existingPlayer() { CarAssert .assertThat(car) .isNotNull() - .hasCar(Car.F1.getId()) + .hasCar(Car.F1.id) .hasColor("#BF1300"); Map tuning = getNonEmptyTuning(car); @@ -132,7 +132,7 @@ void playerWithPersonalCarId() { CarAssert .assertThat(car) .isNotNull() - .hasCar(Car.CARAVEL.getPersonalId()) + .hasCar(Car.CARAVEL.personalId) .hasColor("#000000"); assertEmptyTunning(car); @@ -172,7 +172,7 @@ void brandNewPlayer() { CarAssert .assertThat(car) .isNotNull() - .hasCar(Car.ZAZ_965.getId()) + .hasCar(Car.ZAZ_965.id) .hasColor("#777777"); assertEmptyTunning(car); @@ -213,7 +213,7 @@ void klavoMechanicWithHiddenProfile() { CarAssert .assertThat(car) .isNotNull() - .hasCar(Car.AUDI_TT.getId()) + .hasCar(Car.AUDI_TT.id) .hasColor("#893425"); Map tuning = getNonEmptyTuning(car); From 8239c58aeb83d177fdee09f982d4e43bb14b821c Mon Sep 17 00:00:00 2001 From: dmitry-weirdo Date: Mon, 25 Nov 2024 22:46:43 +0100 Subject: [PATCH 24/30] feat: #81 #102 Move `NonStandardDictionaryType` to `kg-common` and convert it to Kotlin. --- .../ru/klavogonki/common/DictionaryMode.kt | 2 +- .../common/NonStandardDictionaryType.kt | 41 +++++++++++++++++++ .../kgparser/NonStandardDictionaryType.java | 39 ------------------ .../entity/PlayerVocabularyStatsEntity.java | 6 +-- .../mapper/PlayerVocabularyStatsMapper.java | 2 +- 5 files changed, 46 insertions(+), 44 deletions(-) create mode 100644 kgCommon/src/main/kotlin/ru/klavogonki/common/NonStandardDictionaryType.kt delete mode 100644 kgparserSrv/src/main/java/ru/klavogonki/kgparser/NonStandardDictionaryType.java diff --git a/kgCommon/src/main/kotlin/ru/klavogonki/common/DictionaryMode.kt b/kgCommon/src/main/kotlin/ru/klavogonki/common/DictionaryMode.kt index 82a5ec2ad..5f3ff1160 100644 --- a/kgCommon/src/main/kotlin/ru/klavogonki/common/DictionaryMode.kt +++ b/kgCommon/src/main/kotlin/ru/klavogonki/common/DictionaryMode.kt @@ -7,7 +7,7 @@ enum class DictionaryMode( /** * Имя в API клавогонок. Все буквы в нижнем регистре. */ - @JvmField val klavogonkiName: String, + @JvmField val klavogonkiName: String ) { normal("normal"), diff --git a/kgCommon/src/main/kotlin/ru/klavogonki/common/NonStandardDictionaryType.kt b/kgCommon/src/main/kotlin/ru/klavogonki/common/NonStandardDictionaryType.kt new file mode 100644 index 000000000..4e81f2b9b --- /dev/null +++ b/kgCommon/src/main/kotlin/ru/klavogonki/common/NonStandardDictionaryType.kt @@ -0,0 +1,41 @@ +package ru.klavogonki.common + +/** + * Тип нестандартного словаря. + */ +enum class NonStandardDictionaryType( + /** + * Имя в API клавогонок. Все буквы в нижнем регистре. + */ + @JvmField val klavogonkiName: String +) { + /** + * Слова. + */ + words("words"), + + /** + * Фразы. + */ + phrases("phrases"), + + /** + * Тексты. + */ + texts("texts"), + + /** + * URL. + */ + url("url"), + + /** + * Книга. + */ + book("book"), + + /** + * Генератор. + */ + generator("generator"), +} \ No newline at end of file diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/NonStandardDictionaryType.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/NonStandardDictionaryType.java deleted file mode 100644 index e4304d0ac..000000000 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/NonStandardDictionaryType.java +++ /dev/null @@ -1,39 +0,0 @@ -package ru.klavogonki.kgparser; - -/** - * Тип нестандартного словаря - */ -public enum NonStandardDictionaryType { - - /** - * Слова. - */ - words, - - /** - * Фразы. - */ - phrases, - - /** - * Тексты. - */ - texts, - - /** - * URL. - */ - url, - - /** - * Книга. - */ - book, - - /** - * Генератор. - */ - generator, - - ; -} diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/entity/PlayerVocabularyStatsEntity.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/entity/PlayerVocabularyStatsEntity.java index 2913ff388..28a0f8a43 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/entity/PlayerVocabularyStatsEntity.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/entity/PlayerVocabularyStatsEntity.java @@ -2,7 +2,7 @@ import lombok.Data; import ru.klavogonki.common.DictionaryMode; -import ru.klavogonki.kgparser.NonStandardDictionaryType; +import ru.klavogonki.common.NonStandardDictionaryType; import javax.persistence.Entity; import javax.persistence.EnumType; @@ -49,7 +49,7 @@ public class PlayerVocabularyStatsEntity implements Serializable { private String vocabularyName; - @Enumerated(EnumType.STRING) + @Enumerated(EnumType.STRING) // todo: save using the klavogonikiName field, NOT the enum itself (to save compatibility with the old databases) private NonStandardDictionaryType vocabularyType; private Integer vocabularySymbols; // for non-standard dictionaries only @@ -67,7 +67,7 @@ public class PlayerVocabularyStatsEntity implements Serializable { * * @see DictionaryMode#getDictionaryMode */ - @Enumerated(EnumType.STRING) // todo: save using the klavogonikiName field, NOT the enum itself + @Enumerated(EnumType.STRING) // todo: save using the klavogonikiName field, NOT the enum itself (to save compatibility with the old databases) private DictionaryMode vocabularyMode; /** diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/mapper/PlayerVocabularyStatsMapper.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/mapper/PlayerVocabularyStatsMapper.java index f74c890e5..1da14ed31 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/mapper/PlayerVocabularyStatsMapper.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/mapper/PlayerVocabularyStatsMapper.java @@ -8,7 +8,7 @@ import org.mapstruct.ValueMapping; import org.mapstruct.ValueMappings; import ru.klavogonki.common.DictionaryMode; -import ru.klavogonki.kgparser.NonStandardDictionaryType; +import ru.klavogonki.common.NonStandardDictionaryType; import ru.klavogonki.openapi.model.GetStatsOverviewGameType; import ru.klavogonki.openapi.model.GetStatsOverviewResponse; import ru.klavogonki.openapi.model.NonStandardVocabularyType; From 013f49c8214c8cc206d280578e3844e4f3707720 Mon Sep 17 00:00:00 2001 From: dmitry-weirdo Date: Mon, 25 Nov 2024 22:57:40 +0100 Subject: [PATCH 25/30] feat: #81 #102 Move `NonStandardDictionary` to `kg-common` and convert it to Kotlin. --- .../main/kotlin/ru/klavogonki/common/Car.kt | 2 +- .../common/NonStandardDictionary.kt | 39 +++++++++---------- .../klavogonki/common/StandardDictionary.kt | 2 +- .../DigitsOneHundredTopExporter.java | 2 +- .../FrequencyVocabularyTopExporter.java | 2 +- .../non_standard/MiniMarathonTopExporter.java | 2 +- .../NonStandardVocabularyTopExporter.java | 2 +- .../NormalInEnglishTopExporter.java | 2 +- .../OneHundredRussianTopExporter.java | 2 +- .../non_standard/PinkiesPlusTopExporter.java | 2 +- .../non_standard/RingFingersTopExporter.java | 2 +- .../non_standard/ShortTextsTopExporter.java | 2 +- .../TrainingIndexFingersTopExporter.java | 2 +- .../export/vocabulary/VocabularyTopUtils.kt | 2 +- 14 files changed, 31 insertions(+), 34 deletions(-) rename kgparserSrv/src/main/java/ru/klavogonki/kgparser/NonStandardDictionary.java => kgCommon/src/main/kotlin/ru/klavogonki/common/NonStandardDictionary.kt (84%) diff --git a/kgCommon/src/main/kotlin/ru/klavogonki/common/Car.kt b/kgCommon/src/main/kotlin/ru/klavogonki/common/Car.kt index b32c6653d..375872fc7 100644 --- a/kgCommon/src/main/kotlin/ru/klavogonki/common/Car.kt +++ b/kgCommon/src/main/kotlin/ru/klavogonki/common/Car.kt @@ -3,7 +3,7 @@ package ru.klavogonki.common /** * List of cars with ids and Russian names. */ -@SuppressWarnings("MagicNumber") +@Suppress("MagicNumber") enum class Car( @JvmField val id: Int, @JvmField val displayName: String, diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/NonStandardDictionary.java b/kgCommon/src/main/kotlin/ru/klavogonki/common/NonStandardDictionary.kt similarity index 84% rename from kgparserSrv/src/main/java/ru/klavogonki/kgparser/NonStandardDictionary.java rename to kgCommon/src/main/kotlin/ru/klavogonki/common/NonStandardDictionary.kt index 3a2405540..e837300a4 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/NonStandardDictionary.java +++ b/kgCommon/src/main/kotlin/ru/klavogonki/common/NonStandardDictionary.kt @@ -1,12 +1,14 @@ -package ru.klavogonki.kgparser; - -import ru.klavogonki.common.DictionaryUtils; +package ru.klavogonki.common /** * Популярные нестандартные словари. */ -public enum NonStandardDictionary { - +@Suppress("MagicNumber", "Unused") +enum class NonStandardDictionary( + @JvmField val code: String, + @JvmField val displayName: String, + @JvmField val displayNamePrepositional: String +) { // most popular non-standard dictionaries NORMAL_IN_ENGLISH(5539, "Обычный in English", "Обычном in English"), ONE_HUNDRED_RUSSIAN(25856, "Соточка", "Соточке"), @@ -50,7 +52,7 @@ public enum NonStandardDictionary { HRUST_EXERCISE_21(32013, "Упражнение №21", "Упражнении №21"), HRUST_EXERCISE_22(32014, "Упражнение №22", "Упражнении №22"), HRUST_EXERCISE_23(32015, "Упражнение №23", "Упражнении №23"), -// HRUST_EXERCISE_24(32016, "Упражнение №24", "Упражнении №24"), + // HRUST_EXERCISE_24(32016, "Упражнение №24", "Упражнении №24"), HRUST_EXERCISE_24(32016, "Упражнение заключительное", "Упражнении заключительном"), // Мультилингва @@ -60,18 +62,13 @@ public enum NonStandardDictionary { // номера словарей по возрастанию: normal 5539 8950 25130 29236 29464 29468 29510 29513 29521 29537 29616 29667 30395 30641 35239 40559 106181 106487 106554 106688 114083 114825 115209 115378 115424 115943 116073 116553 116554 116745 117862 122698 122702 122761 122888 122891 123163 130272 136302 136354 136403 136795 136908 137357 138500 141412 141415 141423 141609 141610 141960 ; - - NonStandardDictionary(final int code, final String displayName, final String displayNamePrepositional) { - this(DictionaryUtils.NON_STANDARD_DICTIONARY_ID_PREFIX + code, displayName, displayNamePrepositional); - } - - NonStandardDictionary(final String code, final String displayName, final String displayNamePrepositional) { - this.code = code; - this.displayName = displayName; - this.displayNamePrepositional = displayNamePrepositional; - } - - public final String code; - public final String displayName; - public final String displayNamePrepositional; -} + constructor( + code: Int, + displayName: String, + displayNamePrepositional: String + ) : this( + DictionaryUtils.getDictionaryCode(code), + displayName, + displayNamePrepositional + ) +} \ No newline at end of file diff --git a/kgCommon/src/main/kotlin/ru/klavogonki/common/StandardDictionary.kt b/kgCommon/src/main/kotlin/ru/klavogonki/common/StandardDictionary.kt index bfc443999..52a8ba673 100644 --- a/kgCommon/src/main/kotlin/ru/klavogonki/common/StandardDictionary.kt +++ b/kgCommon/src/main/kotlin/ru/klavogonki/common/StandardDictionary.kt @@ -3,7 +3,7 @@ package ru.klavogonki.common /** * Энум с названиями стандартных словарей (режимов), как они используются в AJAX-API. */ -@SuppressWarnings("MagicNumber", "LongParameterList") +@Suppress("MagicNumber", "LongParameterList") enum class StandardDictionary( /** diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/DigitsOneHundredTopExporter.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/DigitsOneHundredTopExporter.java index 2c7ac50f5..ed3b6de19 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/DigitsOneHundredTopExporter.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/DigitsOneHundredTopExporter.java @@ -4,7 +4,7 @@ import org.apache.logging.log4j.Logger; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; -import ru.klavogonki.kgparser.NonStandardDictionary; +import ru.klavogonki.common.NonStandardDictionary; import ru.klavogonki.statistics.export.vocabulary.standard.NonStandardVocabularyTopExporterDefaultImpl; import ru.klavogonki.statistics.springboot.Profiles; diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/FrequencyVocabularyTopExporter.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/FrequencyVocabularyTopExporter.java index 645be6eb7..9e9377a9f 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/FrequencyVocabularyTopExporter.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/FrequencyVocabularyTopExporter.java @@ -4,7 +4,7 @@ import org.apache.logging.log4j.Logger; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; -import ru.klavogonki.kgparser.NonStandardDictionary; +import ru.klavogonki.common.NonStandardDictionary; import ru.klavogonki.statistics.export.vocabulary.standard.NonStandardVocabularyTopExporterDefaultImpl; import ru.klavogonki.statistics.springboot.Profiles; diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/MiniMarathonTopExporter.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/MiniMarathonTopExporter.java index ed10cf519..e7bac67c2 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/MiniMarathonTopExporter.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/MiniMarathonTopExporter.java @@ -4,7 +4,7 @@ import org.apache.logging.log4j.Logger; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; -import ru.klavogonki.kgparser.NonStandardDictionary; +import ru.klavogonki.common.NonStandardDictionary; import ru.klavogonki.statistics.export.vocabulary.standard.NonStandardVocabularyTopExporterDefaultImpl; import ru.klavogonki.statistics.springboot.Profiles; diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/NonStandardVocabularyTopExporter.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/NonStandardVocabularyTopExporter.java index fdcbd7abb..7ca3c4fb9 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/NonStandardVocabularyTopExporter.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/NonStandardVocabularyTopExporter.java @@ -1,6 +1,6 @@ package ru.klavogonki.statistics.export.vocabulary.non_standard; -import ru.klavogonki.kgparser.NonStandardDictionary; +import ru.klavogonki.common.NonStandardDictionary; import ru.klavogonki.statistics.export.vocabulary.VocabularyTopExporter; import ru.klavogonki.statistics.export.vocabulary.VocabularyTopUtils; diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/NormalInEnglishTopExporter.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/NormalInEnglishTopExporter.java index 36cddcd28..c6c41e1cb 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/NormalInEnglishTopExporter.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/NormalInEnglishTopExporter.java @@ -4,7 +4,7 @@ import org.apache.logging.log4j.Logger; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; -import ru.klavogonki.kgparser.NonStandardDictionary; +import ru.klavogonki.common.NonStandardDictionary; import ru.klavogonki.statistics.export.vocabulary.standard.NonStandardVocabularyTopExporterDefaultImpl; import ru.klavogonki.statistics.springboot.Profiles; diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/OneHundredRussianTopExporter.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/OneHundredRussianTopExporter.java index 22d46c44c..2a3b51a8c 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/OneHundredRussianTopExporter.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/OneHundredRussianTopExporter.java @@ -4,7 +4,7 @@ import org.apache.logging.log4j.Logger; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; -import ru.klavogonki.kgparser.NonStandardDictionary; +import ru.klavogonki.common.NonStandardDictionary; import ru.klavogonki.statistics.export.vocabulary.standard.NonStandardVocabularyTopExporterDefaultImpl; import ru.klavogonki.statistics.springboot.Profiles; diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/PinkiesPlusTopExporter.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/PinkiesPlusTopExporter.java index 21f9bdd82..b4099429d 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/PinkiesPlusTopExporter.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/PinkiesPlusTopExporter.java @@ -4,7 +4,7 @@ import org.apache.logging.log4j.Logger; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; -import ru.klavogonki.kgparser.NonStandardDictionary; +import ru.klavogonki.common.NonStandardDictionary; import ru.klavogonki.statistics.export.vocabulary.standard.NonStandardVocabularyTopExporterDefaultImpl; import ru.klavogonki.statistics.springboot.Profiles; diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/RingFingersTopExporter.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/RingFingersTopExporter.java index 14a463bc6..5a70e8884 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/RingFingersTopExporter.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/RingFingersTopExporter.java @@ -4,7 +4,7 @@ import org.apache.logging.log4j.Logger; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; -import ru.klavogonki.kgparser.NonStandardDictionary; +import ru.klavogonki.common.NonStandardDictionary; import ru.klavogonki.statistics.export.vocabulary.standard.NonStandardVocabularyTopExporterDefaultImpl; import ru.klavogonki.statistics.springboot.Profiles; diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/ShortTextsTopExporter.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/ShortTextsTopExporter.java index 2e98964eb..f824da1d6 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/ShortTextsTopExporter.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/ShortTextsTopExporter.java @@ -4,7 +4,7 @@ import org.apache.logging.log4j.Logger; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; -import ru.klavogonki.kgparser.NonStandardDictionary; +import ru.klavogonki.common.NonStandardDictionary; import ru.klavogonki.statistics.export.vocabulary.standard.NonStandardVocabularyTopExporterDefaultImpl; import ru.klavogonki.statistics.springboot.Profiles; diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/TrainingIndexFingersTopExporter.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/TrainingIndexFingersTopExporter.java index b09c7236b..38e304dd3 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/TrainingIndexFingersTopExporter.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/vocabulary/non_standard/TrainingIndexFingersTopExporter.java @@ -4,7 +4,7 @@ import org.apache.logging.log4j.Logger; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; -import ru.klavogonki.kgparser.NonStandardDictionary; +import ru.klavogonki.common.NonStandardDictionary; import ru.klavogonki.statistics.export.vocabulary.standard.NonStandardVocabularyTopExporterDefaultImpl; import ru.klavogonki.statistics.springboot.Profiles; diff --git a/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/export/vocabulary/VocabularyTopUtils.kt b/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/export/vocabulary/VocabularyTopUtils.kt index 30b260199..9a5ea6527 100644 --- a/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/export/vocabulary/VocabularyTopUtils.kt +++ b/kgstatsSrv/src/main/kotlin/ru/klavogonki/statistics/export/vocabulary/VocabularyTopUtils.kt @@ -1,8 +1,8 @@ package ru.klavogonki.statistics.export.vocabulary import org.apache.logging.log4j.kotlin.Logging +import ru.klavogonki.common.NonStandardDictionary import ru.klavogonki.common.StandardDictionary -import ru.klavogonki.kgparser.NonStandardDictionary import ru.klavogonki.statistics.excel.ExcelExporter @Suppress("TooManyFunctions") From bbea1211b14b596ea3e21d00e503b3b10a03b324 Mon Sep 17 00:00:00 2001 From: dmitry-weirdo Date: Mon, 25 Nov 2024 23:31:37 +0100 Subject: [PATCH 26/30] feat: #81 #102 Move `Rank` to `kg-common` and convert it to Kotlin. No more dependencies from `kgstats-srv` to `kgparser-srv`!!! --- .../main/kotlin/ru/klavogonki/common/Rank.kt | 131 +++++++++++++++++ .../ru/klavogonki/kgparser/Competition.java | 1 + .../java/ru/klavogonki/kgparser/Player.java | 1 + .../java/ru/klavogonki/kgparser/Rank.java | 137 ------------------ .../klavogonki/kgparser/RankComparator.java | 2 + .../java/ru/klavogonki/kgparser/RankDto.java | 1 + .../dataparser/VoidmainJsonParser.java | 2 +- .../kgparser/http/HttpClientTest.java | 2 +- .../processing/ErrorsCountChartFiller.java | 2 +- .../kgparser/processing/SpeedChartFiller.java | 2 +- .../model/basic_info/PlayerBasicInfo.java | 2 +- .../statistics/download/PlayerJsonParser.java | 2 +- .../klavogonki/statistics/dto/PlayerDto.java | 2 +- .../statistics/dto/PlayerVocabularyDto.java | 2 +- .../statistics/dto/PlayersByRankCount.java | 2 +- .../statistics/entity/PlayerEntity.java | 2 +- .../statistics/excel/ExcelExporter.java | 2 +- .../statistics/excel/ExcelStylesMap.java | 2 +- .../statistics/excel/ExcelUtils.java | 2 +- .../excel/data/ExcelExportContextData.java | 2 +- .../statistics/excel/player/LoginColumn.java | 2 +- .../statistics/export/IndexPageExporter.java | 2 +- .../freemarker/ExampleTemplate.java | 2 +- .../statistics/mapper/PlayerDtoMapper.java | 2 +- .../mapper/PlayerVocabularyDtoMapper.java | 2 +- .../statistics/util/JacksonUtilsTest.java | 2 +- .../src/main/webapp/2020-12-09/css/stats.css | 2 +- kgstatsWeb/src/main/webapp/css/stats.css | 2 +- 28 files changed, 158 insertions(+), 159 deletions(-) create mode 100644 kgCommon/src/main/kotlin/ru/klavogonki/common/Rank.kt delete mode 100644 kgparserSrv/src/main/java/ru/klavogonki/kgparser/Rank.java diff --git a/kgCommon/src/main/kotlin/ru/klavogonki/common/Rank.kt b/kgCommon/src/main/kotlin/ru/klavogonki/common/Rank.kt new file mode 100644 index 000000000..36688555a --- /dev/null +++ b/kgCommon/src/main/kotlin/ru/klavogonki/common/Rank.kt @@ -0,0 +1,131 @@ +package ru.klavogonki.common + +/** + * Ранг игрока. Различается в зависимости от рекорда в обычном режиме. + */ +@Suppress("MagicNumber") +enum class Rank( + + /** + * Имя в API клавогонок. Все буквы в нижнем регистре. + * + * // todo: на самом деле, в API Клавогонок нет таких буквенных обозначений, только числовой код ранга. + */ + @Suppress("unused") + @JvmField val klavogonkiName: String, + + /** + * Числовой код ранга (level). + */ + @JvmField val level: Int, + + /** + * Русское название ранга для отображения. + */ + @JvmField val displayName: String, + + /** + * Цвет на КГ, соответствующий рангу, в форме "#00FF02". + */ + @JvmField val color: String +) { + /** + * Новичок. Рекорд < 100. + */ + novice("novice", 1, "Новичок", "#8D8D8D"), + + /** + * Любитель. Рекорд от 100 до 199. + */ + amateur("amateur", 2, "Любитель", "#4F9A97"), + + /** + * Таксист. Рекорд от 200 до 299. + */ + cabman("cabman", 3, "Таксист", "#187818"), + + /** + * Профи. Рекорд от 300 до 399. + */ + pro("pro", 4, "Профи", "#8C8100"), + + /** + * Гонщик. Рекорд от 400 до 499. + */ + racer("racer", 5, "Гонщик", "#BA5800"), + + /** + * Маньяк. Рекорд от 500 до 599. + */ + maniac("maniac", 6, "Маньяк", "#BC0143"), + + /** + * Супермен. Рекорд от 600 до 699. + */ + superman("superman", 7, "Супермен", "#5E0B9E"), + + /** + * Кибергонщик. Рекорд от 700 до 799. + */ + cyberracer("cyberracer", 8, "Кибергонщик", "#00037C"), + + /** + * Экстракибер. Рекорд >= 800. + */ + extracyber("extracyber", 9, "Экстракибер", "#061956"), + ; + + companion object { + /** + * @param normalRecord рекорд в [режиме "Обычный"][StandardDictionary.normal] + * @return ранг, соответствующий указанному рекорду + */ + @JvmStatic + @Suppress("MagicNumber", "ReturnCount") + fun getRankByNormalRecord(normalRecord: Int): Rank { + if (normalRecord < 100) return novice + + if (normalRecord < 200) return amateur + + if (normalRecord < 300) return cabman + + if (normalRecord < 400) return pro + + if (normalRecord < 500) return racer + + if (normalRecord < 600) return maniac + + if (normalRecord < 700) return superman + + if (normalRecord < 800) return cyberracer + + return extracyber // рекорд в обычном >= 700 -> экстракибер + } + + @JvmStatic + fun getDisplayName(level: Int): String { + return getRank(level).displayName + } + + /** + * @param level числовой код ранга + * @return ранг с указанным числовым кодом + */ + @JvmStatic + fun getRank(level: Int): Rank { + return entries + .firstOrNull { it.level == level } + ?: throw IllegalArgumentException("Incorrect rank level: $level.") + } + + /** + * Цвет игрока-гостя. + */ + const val GUEST_COLOR: String = "#222222" + + /** + * У клавомехаников свойство `title` заполнено словом "Клавомеханик", а не названием ранга. + */ + const val KLAVO_MECHANIC_TITLE: String = "Клавомеханик" + } +} \ No newline at end of file diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Competition.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Competition.java index 15f881466..dfa27c091 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Competition.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Competition.java @@ -2,6 +2,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import ru.klavogonki.common.Rank; import ru.klavogonki.common.StandardDictionary; import ru.klavogonki.kgparser.http.HttpClientTest; import su.opencode.kefir.srv.json.Json; diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Player.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Player.java index a641841df..0973d2e23 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Player.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Player.java @@ -1,5 +1,6 @@ package ru.klavogonki.kgparser; +import ru.klavogonki.common.Rank; import ru.klavogonki.common.UrlConstructor; import su.opencode.kefir.srv.json.Json; import su.opencode.kefir.srv.json.JsonObject; diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Rank.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Rank.java deleted file mode 100644 index e771f8268..000000000 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/Rank.java +++ /dev/null @@ -1,137 +0,0 @@ -package ru.klavogonki.kgparser; - -import ru.klavogonki.common.StandardDictionary; - -import java.util.Arrays; - -/** - * Ранг игрока. Различается в зависимости от рекорда в обычном режиме. - */ -public enum Rank -{ - /** - * Новичок. Рекорд < 100. - */ - novice(1, "Новичок", "#8D8D8D"), - - /** - * Любитель. Рекорд от 100 до 199. - */ - amateur(2, "Любитель", "#4F9A97"), - - /** - * Таксист. Рекорд от 200 до 299. - */ - cabman(3, "Таксист", "#187818"), - - /** - * Профи. Рекорд от 300 до 399. - */ - pro(4, "Профи", "#8C8100"), - - /** - * Гонщик. Рекорд от 400 до 499. - */ - racer(5, "Гонщик", "#BA5800"), - - /** - * Маньяк. Рекорд от 500 до 599. - */ - maniac(6, "Маньяк", "#BC0143"), - - /** - * Супермен. Рекорд от 600 до 699. - */ - superman(7, "Супермен", "#5E0B9E"), - - /** - * Кибергонщик. Рекорд от 700 до 799. - */ - cyberracer(8, "Кибергонщик", "#00037C"), - - /** - * Экстракибер. Рекорд >= 800. - */ - extracyber(9, "Экстракибер", "#061956"), - ; - - Rank(int level, String displayName, String color) { - this.level = level; - this.displayName = displayName; - this.color = color; - } - - /** - * Числовой код ранга (level). - */ - public final int level; - - /** - * Русское название ранга для отображения. - */ - public final String displayName; - - /** - * Цвет на КГ, соответствующий рангу, в форме "#00FF02". - */ - public final String color; - - /** - * @param normalRecord рекорд в {@linkplain StandardDictionary#normal режиме "Обычный"} - * @return ранг, соответствующий указанному рекорду - */ - public static Rank getRankByNormalRecord(int normalRecord) { - if (normalRecord < 100) - return Rank.novice; - - if (normalRecord < 200) - return Rank.amateur; - - if (normalRecord < 300) - return Rank.cabman; - - if (normalRecord < 400) - return Rank.pro; - - if (normalRecord < 500) - return Rank.racer; - - if (normalRecord < 600) - return Rank.maniac; - - if (normalRecord < 700) - return Rank.superman; - - if (normalRecord < 800) - return Rank.cyberracer; - - return Rank.extracyber; // рекорд в обычном >= 700 -> экстракибер - } - - public static String getDisplayName(int level) { - return Rank.getRank(level).displayName; - } - - /** - * @param level числовой код ранга - * @return ранг с указанным числовым кодом - */ - public static Rank getRank(int level) { - return Arrays.stream(Rank.values()) - .filter( rank -> rank.level == level ) - .findFirst() - .orElseThrow(() -> - new IllegalArgumentException( String.format("Incorrect rank level: %d.", level) ) - ); - } - - /** - * Цвет игрока-гостя. - */ - public static final String GUEST_COLOR = "#222222"; - - /** - * У клавомехаников свойство {@code title} заполнено словом "Клавомеханик", а не названием ранга. - */ - public static final String KLAVO_MECHANIC_TITLE = "Клавомеханик"; -} diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/RankComparator.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/RankComparator.java index f96de76ef..9bc76f553 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/RankComparator.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/RankComparator.java @@ -1,5 +1,7 @@ package ru.klavogonki.kgparser; +import ru.klavogonki.common.Rank; + import java.util.Comparator; /** diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/RankDto.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/RankDto.java index c1f03b152..4a98b2d28 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/RankDto.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/RankDto.java @@ -1,5 +1,6 @@ package ru.klavogonki.kgparser; +import ru.klavogonki.common.Rank; import su.opencode.kefir.srv.json.JsonObject; /** diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/dataparser/VoidmainJsonParser.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/dataparser/VoidmainJsonParser.java index 4b69c1704..24c6ba1da 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/dataparser/VoidmainJsonParser.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/dataparser/VoidmainJsonParser.java @@ -7,11 +7,11 @@ import org.apache.logging.log4j.core.config.DefaultConfiguration; import org.json.JSONArray; import org.json.JSONObject; +import ru.klavogonki.common.Rank; import ru.klavogonki.kgparser.Competition; import ru.klavogonki.kgparser.Dictionary; import ru.klavogonki.kgparser.Player; import ru.klavogonki.kgparser.PlayerRoundResult; -import ru.klavogonki.kgparser.Rank; import ru.klavogonki.kgparser.Round; import su.opencode.kefir.util.DateUtils; import su.opencode.kefir.util.FileUtils; diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/http/HttpClientTest.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/http/HttpClientTest.java index 12ddecb45..5109b7707 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/http/HttpClientTest.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/http/HttpClientTest.java @@ -12,9 +12,9 @@ import org.apache.logging.log4j.core.config.Configurator; import org.apache.logging.log4j.core.config.DefaultConfiguration; import org.json.JSONObject; +import ru.klavogonki.common.Rank; import ru.klavogonki.common.StandardDictionary; import ru.klavogonki.common.UrlConstructor; -import ru.klavogonki.kgparser.Rank; import su.opencode.kefir.util.JsonUtils; import su.opencode.kefir.util.ObjectUtils; import su.opencode.kefir.util.StringUtils; diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/processing/ErrorsCountChartFiller.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/processing/ErrorsCountChartFiller.java index 31684cd5b..747c6495c 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/processing/ErrorsCountChartFiller.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/processing/ErrorsCountChartFiller.java @@ -2,10 +2,10 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import ru.klavogonki.common.Rank; import ru.klavogonki.kgparser.Competition; import ru.klavogonki.kgparser.Player; import ru.klavogonki.kgparser.PlayerRoundResult; -import ru.klavogonki.kgparser.Rank; import ru.klavogonki.kgparser.RankDto; import ru.klavogonki.kgparser.Round; diff --git a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/processing/SpeedChartFiller.java b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/processing/SpeedChartFiller.java index e39618989..c61ae0932 100644 --- a/kgparserSrv/src/main/java/ru/klavogonki/kgparser/processing/SpeedChartFiller.java +++ b/kgparserSrv/src/main/java/ru/klavogonki/kgparser/processing/SpeedChartFiller.java @@ -2,10 +2,10 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import ru.klavogonki.common.Rank; import ru.klavogonki.kgparser.Competition; import ru.klavogonki.kgparser.Player; import ru.klavogonki.kgparser.PlayerRoundResult; -import ru.klavogonki.kgparser.Rank; import ru.klavogonki.kgparser.RankDto; import ru.klavogonki.kgparser.Round; diff --git a/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/model/basic_info/PlayerBasicInfo.java b/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/model/basic_info/PlayerBasicInfo.java index 3c9b8b849..828fab5f6 100644 --- a/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/model/basic_info/PlayerBasicInfo.java +++ b/kgparserWeb/src/main/java/ru/klavogonki/kgparser/servlet/model/basic_info/PlayerBasicInfo.java @@ -1,7 +1,7 @@ package ru.klavogonki.kgparser.servlet.model.basic_info; +import ru.klavogonki.common.Rank; import ru.klavogonki.kgparser.Player; -import ru.klavogonki.kgparser.Rank; import su.opencode.kefir.srv.json.JsonObject; import java.util.Map; diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/download/PlayerJsonParser.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/download/PlayerJsonParser.java index ce31e5975..96d7e3343 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/download/PlayerJsonParser.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/download/PlayerJsonParser.java @@ -6,8 +6,8 @@ import ru.klavogonki.common.Car; import ru.klavogonki.common.DictionaryMode; import ru.klavogonki.common.DictionaryUtils; +import ru.klavogonki.common.Rank; import ru.klavogonki.common.StandardDictionary; -import ru.klavogonki.kgparser.Rank; import ru.klavogonki.openapi.model.GetIndexDataResponse; import ru.klavogonki.openapi.model.GetIndexDataStats; import ru.klavogonki.openapi.model.GetStatsOverviewGameType; diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/dto/PlayerDto.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/dto/PlayerDto.java index 8276e4b47..36b771ac0 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/dto/PlayerDto.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/dto/PlayerDto.java @@ -1,7 +1,7 @@ package ru.klavogonki.statistics.dto; import lombok.Data; -import ru.klavogonki.kgparser.Rank; +import ru.klavogonki.common.Rank; import ru.klavogonki.statistics.excel.data.ExcelExportContextData; import ru.klavogonki.statistics.excel.data.OrderNumberExcelData; import ru.klavogonki.statistics.freemarker.OrderUtils; diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/dto/PlayerVocabularyDto.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/dto/PlayerVocabularyDto.java index 7cd762e53..0bccf19ce 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/dto/PlayerVocabularyDto.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/dto/PlayerVocabularyDto.java @@ -1,7 +1,7 @@ package ru.klavogonki.statistics.dto; import lombok.Data; -import ru.klavogonki.kgparser.Rank; +import ru.klavogonki.common.Rank; import ru.klavogonki.statistics.excel.data.ExcelExportContextData; import ru.klavogonki.statistics.excel.data.OrderNumberExcelData; import ru.klavogonki.statistics.freemarker.OrderUtils; diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/dto/PlayersByRankCount.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/dto/PlayersByRankCount.java index 747319fda..706f3327b 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/dto/PlayersByRankCount.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/dto/PlayersByRankCount.java @@ -1,7 +1,7 @@ package ru.klavogonki.statistics.dto; import lombok.Data; -import ru.klavogonki.kgparser.Rank; +import ru.klavogonki.common.Rank; @Data public class PlayersByRankCount { diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/entity/PlayerEntity.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/entity/PlayerEntity.java index 99056f5b9..b756cad0b 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/entity/PlayerEntity.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/entity/PlayerEntity.java @@ -3,8 +3,8 @@ import lombok.Data; import lombok.ToString; import org.hibernate.annotations.NaturalId; +import ru.klavogonki.common.Rank; import ru.klavogonki.common.UrlConstructor; -import ru.klavogonki.kgparser.Rank; import javax.persistence.AttributeOverride; import javax.persistence.AttributeOverrides; diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/ExcelExporter.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/ExcelExporter.java index 2ad25e688..6d6a2152f 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/ExcelExporter.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/ExcelExporter.java @@ -6,9 +6,9 @@ import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import ru.klavogonki.common.Rank; import ru.klavogonki.common.StandardDictionary; import ru.klavogonki.common.UrlConstructor; -import ru.klavogonki.kgparser.Rank; import ru.klavogonki.statistics.dto.PlayerDto; import ru.klavogonki.statistics.dto.PlayerVocabularyDto; import ru.klavogonki.statistics.excel.data.ExcelExportContextData; diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/ExcelStylesMap.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/ExcelStylesMap.java index e0259cc7c..0e450a16b 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/ExcelStylesMap.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/ExcelStylesMap.java @@ -6,7 +6,7 @@ import org.apache.poi.xssf.usermodel.XSSFCellStyle; import org.apache.poi.xssf.usermodel.XSSFColor; import org.apache.poi.xssf.usermodel.XSSFFont; -import ru.klavogonki.kgparser.Rank; +import ru.klavogonki.common.Rank; import ru.klavogonki.statistics.excel.data.ExcelExportContextData; import java.util.EnumMap; diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/ExcelUtils.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/ExcelUtils.java index 26937573e..2d52d04fb 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/ExcelUtils.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/ExcelUtils.java @@ -15,7 +15,7 @@ import org.apache.poi.xssf.usermodel.XSSFColor; import org.apache.poi.xssf.usermodel.XSSFFont; import org.apache.poi.xssf.usermodel.XSSFWorkbook; -import ru.klavogonki.kgparser.Rank; +import ru.klavogonki.common.Rank; import java.awt.*; import java.io.FileOutputStream; diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/data/ExcelExportContextData.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/data/ExcelExportContextData.java index d2f30da67..3899147b9 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/data/ExcelExportContextData.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/data/ExcelExportContextData.java @@ -1,6 +1,6 @@ package ru.klavogonki.statistics.excel.data; -import ru.klavogonki.kgparser.Rank; +import ru.klavogonki.common.Rank; /** * Root class used as Excel export data. diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/player/LoginColumn.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/player/LoginColumn.java index e28bd9556..de8ce15cb 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/player/LoginColumn.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/excel/player/LoginColumn.java @@ -1,7 +1,7 @@ package ru.klavogonki.statistics.excel.player; import lombok.extern.log4j.Log4j2; -import ru.klavogonki.kgparser.Rank; +import ru.klavogonki.common.Rank; import ru.klavogonki.statistics.excel.ExcelExportContext; import ru.klavogonki.statistics.excel.data.ExcelExportContextData; diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/IndexPageExporter.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/IndexPageExporter.java index 1e3e692e3..09a6cd5bd 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/IndexPageExporter.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/export/IndexPageExporter.java @@ -4,8 +4,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; +import ru.klavogonki.common.Rank; import ru.klavogonki.common.UrlConstructor; -import ru.klavogonki.kgparser.Rank; import ru.klavogonki.statistics.dto.PlayersByRankCount; import ru.klavogonki.statistics.entity.PlayerEntity; import ru.klavogonki.statistics.freemarker.IndexPageTemplate; diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/freemarker/ExampleTemplate.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/freemarker/ExampleTemplate.java index 34712664e..4b99efc3a 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/freemarker/ExampleTemplate.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/freemarker/ExampleTemplate.java @@ -1,7 +1,7 @@ package ru.klavogonki.statistics.freemarker; import lombok.extern.log4j.Log4j2; -import ru.klavogonki.kgparser.Rank; +import ru.klavogonki.common.Rank; import ru.klavogonki.statistics.entity.PlayerEntity; import java.util.Map; diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/mapper/PlayerDtoMapper.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/mapper/PlayerDtoMapper.java index 7fb9fa3c8..d028ad7bc 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/mapper/PlayerDtoMapper.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/mapper/PlayerDtoMapper.java @@ -5,7 +5,7 @@ import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.MappingTarget; -import ru.klavogonki.kgparser.Rank; +import ru.klavogonki.common.Rank; import ru.klavogonki.statistics.dto.PlayerDto; import ru.klavogonki.statistics.entity.PlayerEntity; import ru.klavogonki.statistics.freemarker.OrderUtils; diff --git a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/mapper/PlayerVocabularyDtoMapper.java b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/mapper/PlayerVocabularyDtoMapper.java index d019cc573..37c75d5c3 100644 --- a/kgstatsSrv/src/main/java/ru/klavogonki/statistics/mapper/PlayerVocabularyDtoMapper.java +++ b/kgstatsSrv/src/main/java/ru/klavogonki/statistics/mapper/PlayerVocabularyDtoMapper.java @@ -6,8 +6,8 @@ import org.mapstruct.Mapping; import org.mapstruct.MappingTarget; import org.mapstruct.Named; +import ru.klavogonki.common.Rank; import ru.klavogonki.common.UrlConstructor; -import ru.klavogonki.kgparser.Rank; import ru.klavogonki.statistics.dto.PlayerVocabularyDto; import ru.klavogonki.statistics.entity.PlayerVocabularyStatsEntity; import ru.klavogonki.statistics.freemarker.HaulUtils; diff --git a/kgstatsSrv/src/test/java/ru/klavogonki/statistics/util/JacksonUtilsTest.java b/kgstatsSrv/src/test/java/ru/klavogonki/statistics/util/JacksonUtilsTest.java index c610ddf58..43209e0e6 100644 --- a/kgstatsSrv/src/test/java/ru/klavogonki/statistics/util/JacksonUtilsTest.java +++ b/kgstatsSrv/src/test/java/ru/klavogonki/statistics/util/JacksonUtilsTest.java @@ -6,8 +6,8 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import ru.klavogonki.common.Car; +import ru.klavogonki.common.Rank; import ru.klavogonki.common.StandardDictionary; -import ru.klavogonki.kgparser.Rank; import ru.klavogonki.openapi.model.Bio; import ru.klavogonki.openapi.model.BioAssert; import ru.klavogonki.openapi.model.CarAssert; diff --git a/kgstatsWeb/src/main/webapp/2020-12-09/css/stats.css b/kgstatsWeb/src/main/webapp/2020-12-09/css/stats.css index e9004cd47..a21812c0c 100644 --- a/kgstatsWeb/src/main/webapp/2020-12-09/css/stats.css +++ b/kgstatsWeb/src/main/webapp/2020-12-09/css/stats.css @@ -34,7 +34,7 @@ a:hover { } /* rank colors, apply to any elements */ -/* see ru.klavogonki.kgparser.Rank#getColor */ +/* see ru.klavogonki.common.Rank#getColor */ .novice { color: #8D8D8D } .amateur { color: #4F9A97 } .cabman { color: #187818 } diff --git a/kgstatsWeb/src/main/webapp/css/stats.css b/kgstatsWeb/src/main/webapp/css/stats.css index 89a39fe6c..699d9e841 100644 --- a/kgstatsWeb/src/main/webapp/css/stats.css +++ b/kgstatsWeb/src/main/webapp/css/stats.css @@ -39,7 +39,7 @@ a:hover { } /* rank colors, apply to any elements */ -/* see ru.klavogonki.kgparser.Rank#getColor */ +/* see ru.klavogonki.common.Rank#getColor */ .novice { color: #8D8D8D; } .amateur { color: #4F9A97; } .cabman { color: #187818; } From ff092c73e501c0fc9eb94a112f7c505351d98467 Mon Sep 17 00:00:00 2001 From: dmitry-weirdo Date: Mon, 25 Nov 2024 23:48:25 +0100 Subject: [PATCH 27/30] feat: #102 Remove `kgparserSrv` dependencies from `kgstatsSrv` and kgstatsWeb`. Add missing inherited jackson and javaee dependencies to kgstatsSrv. --- kgstatsSrv/pom.xml | 23 ++++++++++++++++++----- kgstatsWeb/pom.xml | 5 ----- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/kgstatsSrv/pom.xml b/kgstatsSrv/pom.xml index 9bb32b0b0..40982f1d9 100644 --- a/kgstatsSrv/pom.xml +++ b/kgstatsSrv/pom.xml @@ -23,11 +23,11 @@ assertj-core
    + com.fasterxml.jackson.core jackson-core - com.fasterxml.jackson.core jackson-databind @@ -36,7 +36,13 @@ com.fasterxml.jackson.core jackson-annotations + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + + + org.junit.jupiter junit-jupiter-api @@ -47,6 +53,7 @@ junit-jupiter-engine + org.springframework.boot spring-boot-starter-data-jpa @@ -86,11 +93,17 @@ kg-common - - + - ru.klavogonki.kgparser - kgparser-srv + javax + javaee-api diff --git a/kgstatsWeb/pom.xml b/kgstatsWeb/pom.xml index d619449a7..e89ee6817 100644 --- a/kgstatsWeb/pom.xml +++ b/kgstatsWeb/pom.xml @@ -18,11 +18,6 @@ - - - ru.klavogonki.kgparser - kgparser-srv - From 22d80fad894ccd6964d5a18be19092e5cdce4495 Mon Sep 17 00:00:00 2001 From: dmitry-weirdo Date: Tue, 26 Nov 2024 00:19:07 +0100 Subject: [PATCH 28/30] feat: #102 Legacy modules `kgparserSrv` and `kgparserWeb` are now turned on via the `legacy-kgparser` maven module that is disabled by default. --- README.md | 16 +++++ pom.xml | 180 +++++++++++++++++++++++++++++++----------------------- 2 files changed, 119 insertions(+), 77 deletions(-) diff --git a/README.md b/README.md index 3c0331f05..d04c5f1b2 100644 --- a/README.md +++ b/README.md @@ -190,3 +190,19 @@ mvn compile :exclamation: Now after making changes in `kgparserSrv`, you have to `mvn install` this module before running MapStruct in `kgstatsSrv`. + +## Legacy module and Maven profile + +By default, the legacy modules `kgparserSrv` and `kgparserWeb` are excluded from the build. + +If you want to turn them on, you have to switch on the Maven `legacy-kgparser` profile. + +For example: + +```bash +mvn clean -P legacy-kgparser +``` + +```bash +mvn install -P legacy-kgparser +``` \ No newline at end of file diff --git a/pom.xml b/pom.xml index e4aea877d..618e2e348 100644 --- a/pom.xml +++ b/pom.xml @@ -10,8 +10,6 @@ kgCommon - kgparserSrv - kgparserWeb kgstatsSrv kgstatsWeb @@ -34,8 +32,6 @@ 8.0.28 3.17.0 2.17.0 - 1.5 - 4.5.13 0.2.0 @@ -72,13 +68,8 @@ 0.8.12 - 2.5 1.0 6.0 - 20240303 - 2.1 - 1.0 - 1.0 UTF-8 @@ -318,40 +309,6 @@ -->
    - - javax.servlet - servlet-api - ${servlet-api.version} - provided - true - - - - org.json - json - ${org.json.json.version} - provided - true - - - - su.opencode.kefir - kefir-util - ${kefir-util.version} - true - system - ${maven.multiModuleProjectDirectory}/jboss-libs/kefir-util-1.0.jar - - - - su.opencode.kefir - kefir-srv - ${kefir-srv.version} - true - system - ${maven.multiModuleProjectDirectory}/jboss-libs/kefir-srv-1.0.jar - - ru.klavogonki.kgparser @@ -361,23 +318,6 @@ true - - - ru.klavogonki.kgparser - kgparser-srv - 1.0 - compile - true - - - - commons-fileupload - commons-fileupload - ${commons-fileupload.version} - provided - true - - javax.persistence persistence-api @@ -394,23 +334,6 @@ true - - org.apache.httpcomponents - httpclient - ${httpclient.version} - compile - true - - - - - org.htmlparser - thumbelina - ${org.htmlparser.thumbelina.version} - provided - true - - commons-io commons-io @@ -510,6 +433,109 @@
    + + + legacy-kgparser + + + false + + + + kgparserSrv + kgparserWeb + + + + 2.5 + 20240303 + 1.0 + 1.0 + 2.1 + 1.5 + 4.5.13 + + + + + + + su.opencode.kefir + kefir-util + ${kefir-util.version} + true + system + ${maven.multiModuleProjectDirectory}/jboss-libs/kefir-util-1.0.jar + + + + su.opencode.kefir + kefir-srv + ${kefir-srv.version} + true + system + ${maven.multiModuleProjectDirectory}/jboss-libs/kefir-srv-1.0.jar + + + + + ru.klavogonki.kgparser + kgparser-srv + 1.0 + compile + true + + + + + org.htmlparser + thumbelina + ${org.htmlparser.thumbelina.version} + provided + true + + + + + commons-fileupload + commons-fileupload + ${commons-fileupload.version} + provided + true + + + + + javax.servlet + servlet-api + ${servlet-api.version} + provided + true + + + + + org.json + json + ${org.json.json.version} + provided + true + + + + + org.apache.httpcomponents + httpclient + ${httpclient.version} + compile + true + + + + + + + nosferatum From 501a9ea41111da3ae81d43ae34e3f599eacc53b1 Mon Sep 17 00:00:00 2001 From: dmitry-weirdo Date: Tue, 26 Nov 2024 00:22:08 +0100 Subject: [PATCH 29/30] chore: #102 Removed the commented-out dependencies from `kg-common` module (mainly Lombok). Not everything removed, but cleaner now. --- kgCommon/pom.xml | 126 +---------------------------------------------- 1 file changed, 1 insertion(+), 125 deletions(-) diff --git a/kgCommon/pom.xml b/kgCommon/pom.xml index 7d825b809..d1a45a09a 100644 --- a/kgCommon/pom.xml +++ b/kgCommon/pom.xml @@ -11,12 +11,11 @@ kg-common kg-common - Common module with basic Klavogonki classes, uses by both legacy kgparser and kgstats + Common module with basic Klavogonki classes, uses by both legacy kgparser and kgstats. jar - org.assertj @@ -47,49 +46,6 @@ junit-jupiter-engine - - - - - - mysql - mysql-connector-java - - - - - - - - - org.mapstruct @@ -113,21 +69,6 @@ - @@ -137,17 +78,6 @@ ${kotlin.version} true - - compile @@ -183,14 +113,6 @@ kotlin-maven-lombok ${kotlin.version} - @@ -248,57 +170,11 @@ ${lombok-mapstruct-binding.version} - - - - - - - From 05d0671636cfe20659258c57f76affca46c1cd1d Mon Sep 17 00:00:00 2001 From: dmitry-weirdo Date: Tue, 26 Nov 2024 00:23:53 +0100 Subject: [PATCH 30/30] docs: #102 Fix the strategic typo in the new section of `README.md`. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d04c5f1b2..279ef94a1 100644 --- a/README.md +++ b/README.md @@ -191,7 +191,7 @@ mvn compile :exclamation: Now after making changes in `kgparserSrv`, you have to `mvn install` this module before running MapStruct in `kgstatsSrv`. -## Legacy module and Maven profile +## Legacy modules and Maven profile By default, the legacy modules `kgparserSrv` and `kgparserWeb` are excluded from the build.