Skip to content

Commit

Permalink
feat: #11 Implemented index page generation, except for players by ra…
Browse files Browse the repository at this point in the history
…nk charts and tables.

- Added profileLink, rank and rankDisplayName usability getters to PlayerEntity, profileLink to PlayerDto.
- Links to user profile changed to https:// instead of http://.
- Html of <td> with user rank color, login and info with profile link extracted to a FTL macro that is imported into page FTLs.
- Added an ExampleTemplate and example.ftl to be able to test FreeMarker quickly.
- Re-generated top by speed files are not yet added.
- Order of players in "Действующие пользователи, у которых падает /get-index-data" is random, since java Map is not sorted.
- Link to method on the index page fixed: /get-summary instead of /get-stats-overview.
  • Loading branch information
dmitry-weirdo committed Dec 20, 2020
1 parent 2813a47 commit 66a9c71
Show file tree
Hide file tree
Showing 13 changed files with 438 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,22 @@
import org.springframework.stereotype.Component;
import ru.klavogonki.kgparser.freemarker.IndexPageTemplate;
import ru.klavogonki.kgparser.freemarker.PageUrls;
import ru.klavogonki.kgparser.http.UrlConstructor;
import ru.klavogonki.kgparser.jsonParser.dto.PlayersByRankCount;
import ru.klavogonki.kgparser.jsonParser.entity.PlayerEntity;
import ru.klavogonki.kgparser.jsonParser.repository.PlayerRepository;
import ru.klavogonki.kgparser.util.DateUtils;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Log4j2
@Component
public class IndexPageExporter implements DataExporter {

private static final int EXAMPLE_PLAYER_ID = 242585; // nosferatum :)

@Autowired
private PlayerRepository playerRepository;

Expand All @@ -36,6 +42,12 @@ public void export(ExportContext context) {
logger.debug("Players with error on /get-index-data count: {}", playersWithGetIndexDataError.size());
logger.debug("Players with error on /get-index-data: {}", playersWithGetIndexDataError);

Map<String, List<PlayerEntity>> playersWithIndexDataErrorGroupedByError = playersWithGetIndexDataError
.stream()
.collect(Collectors.groupingBy(PlayerEntity::getGetIndexDataError));

logger.debug("Players with error on /get-index-data grouped by error: {}", playersWithIndexDataErrorGroupedByError);

Integer actualPlayersWithoutRacesCount = playerRepository.countByGetSummaryErrorIsNullAndGetIndexDataErrorIsNullAndBlockedEqualsAndTotalRacesCountEquals(0, 0);
logger.debug("Actual players with no total races: {}", actualPlayersWithoutRacesCount);

Expand Down Expand Up @@ -98,14 +110,26 @@ public void export(ExportContext context) {
String indexPageFilePath = PageUrls.getIndexPageFilePath(context.webRootDir);

new IndexPageTemplate()
// todo: pass config (context) fields
.minPlayerId(context.minPlayerId)
.maxPlayerId(context.maxPlayerId)
.dataDownloadStartDate(DateUtils.formatDateTimeForUi(context.dataDownloadStartDate))
.dataDownloadEndDate(DateUtils.formatDateTimeForUi(context.dataDownloadEndDate))

// example player
.examplePlayerId(EXAMPLE_PLAYER_ID)
.examplePlayerProfileLink(UrlConstructor.userProfileLink(EXAMPLE_PLAYER_ID))
.examplePlayerGetSummaryUrl(UrlConstructor.getSummary(EXAMPLE_PLAYER_ID))
.examplePlayerGetIndexDataUrl(UrlConstructor.getIndexData(EXAMPLE_PLAYER_ID))

// global players metrics
.minExistingPlayerId(minExistingPlayerId)
.minExistingPlayerProfileLink(UrlConstructor.userProfileLink(minExistingPlayerId))
.maxExistingPlayerId(maxExistingPlayerId)
.maxExistingPlayerProfileLink(UrlConstructor.userProfileLink(maxExistingPlayerId))
.nonExistingPlayersCount(nonExistingPlayersCount)
.blockedPlayersCount(blockedPlayersCount)
.playersWithGetIndexDataError(playersWithGetIndexDataError)
.playersWithIndexDataErrorGroupedByError(playersWithIndexDataErrorGroupedByError)
.actualPlayersWithoutRacesCount(actualPlayersWithoutRacesCount)
.actualPlayersWithAtLeast1RaceCount(actualPlayersWithAtLeast1RaceCount)
.totalUsersInDatabase(totalUsersInDatabase)
Expand All @@ -123,7 +147,7 @@ public void export(ExportContext context) {

// top 1
.top1PlayerByTotalRacesCount(top1PlayerByTotalRacesCount)
.top1PlayerByBestSpeed(top1PlayerByTotalRacesCount)
.top1PlayerByBestSpeed(top1PlayerByBestSpeed)
.top1PlayerByRatingLevel(top1PlayerByRatingLevel)
.top1PlayerByAchievementsCount(top1PlayerByAchievementsCount)
.top1PlayerByFriendsCount(top1PlayerByFriendsCount)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package ru.klavogonki.kgparser.freemarker;

import lombok.extern.log4j.Log4j2;
import ru.klavogonki.kgparser.Rank;
import ru.klavogonki.kgparser.jsonParser.entity.PlayerEntity;

/**
* Used to try out the FreeMarker features without waiting for getting the data from the database.
*/
@Log4j2
public class ExampleTemplate extends FreemarkerTemplate {

@Override
public String getTemplatePath() {
return "ftl/example.ftl";
}

@Override
public void export(final String filePath) {
templateData.put("testInteger", 123456789);

PlayerEntity player = new PlayerEntity();
player.setLogin("nosferatum");
player.setPlayerId(242585);
player.setRankLevel(Rank.getLevel(Rank.superman).intValue());

templateData.put("testPlayer", player);

String result = super.exportToString();
logger.debug("result:\n{}", result);
}

public static void main(String[] args) {
new ExampleTemplate().export("example.html");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
import freemarker.template.TemplateException;
import freemarker.template.Version;
import lombok.extern.log4j.Log4j2;
import ru.klavogonki.kgparser.export.TopBySpeedExporter;

import java.io.FileWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
Expand All @@ -30,28 +31,51 @@ public abstract class FreemarkerTemplate {
public void export(String filePath) {
templateData.put(LINKS_KEY, new Links());

exportFreemarker(getTemplatePath(), filePath, templateData);
exportFreemarkerToFile(getTemplatePath(), filePath, templateData);
}

protected static void exportFreemarker(
public String exportToString() {
templateData.put(LINKS_KEY, new Links());

return exportFreemarkerToString(getTemplatePath(), templateData);
}

protected static void exportFreemarkerToFile(
final String ftlTemplate,
final String filePath,
final Map<String, Object> templateData
) {
try (FileWriter out = new FileWriter(filePath)) {
Configuration cfg = new Configuration(new Version(FREEMARKER_VERSION));

cfg.setClassForTemplateLoading(TopBySpeedExporter.class, "/");
cfg.setDefaultEncoding(StandardCharsets.UTF_8.displayName());

Template template = cfg.getTemplate(ftlTemplate);

template.process(templateData, out);
export(ftlTemplate, templateData, out);
}
catch (IOException | TemplateException e) {
throw new RuntimeException(e);
}
}

out.flush();
protected static String exportFreemarkerToString(
final String ftlTemplate,
final Map<String, Object> templateData
) {
try (Writer out = new StringWriter()) {
export(ftlTemplate, templateData, out);
return out.toString();
}
catch (IOException | TemplateException e) {
throw new RuntimeException(e);
}
}

private static void export(final String ftlTemplate, final Map<String, Object> templateData, final Writer out) throws IOException, TemplateException {
Configuration configuration = new Configuration(new Version(FREEMARKER_VERSION));

configuration.setClassForTemplateLoading(FreemarkerTemplate.class, "/");
configuration.setDefaultEncoding(StandardCharsets.UTF_8.displayName());

Template template = configuration.getTemplate(ftlTemplate);

template.process(templateData, out);

out.flush();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,35 @@
import ru.klavogonki.kgparser.jsonParser.entity.PlayerEntity;

import java.util.List;
import java.util.Map;

@SuppressWarnings("unchecked")
@Log4j2
public class IndexPageTemplate extends FreemarkerTemplate {

// todo: keys from config: minPlayerId, maxPlayerId, exportStartDate, exportEndDate
// fields from ExportContext
private static final String MIN_PLAYER_ID_KEY = "minPlayerId";
private static final String MAX_PLAYER_ID_KEY = "maxPlayerId";
private static final String DATA_DOWNLOAD_START_DATE_KEY = "dataDownloadStartDate";
private static final String DATA_DOWNLOAD_END_DATE_KEY = "dataDownloadEndDate";

// example player
private static final String EXAMPLE_PLAYER_ID_KEY = "examplePlayerId";
private static final String EXAMPLE_PLAYER_PROFILE_LINK_KEY = "examplePlayerProfileLink";
private static final String EXAMPLE_PLAYER_GET_SUMMARY_URL_KEY = "examplePlayerGetSummaryUrl";
private static final String EXAMPLE_PLAYER_GET_INDEX_DATA_URL_KEY = "examplePlayerGetIndexDataUrl";

// global players metrics
private static final String MIN_EXISTING_PLAYER_ID_KEY = "minExistingPlayerId";
private static final String MIN_EXISTING_PLAYER_PROFILE_LINK_KEY = "minExistingPlayerProfileLink";
private static final String MAX_EXISTING_PLAYER_ID_KEY = "maxExistingPlayerId";
private static final String MAX_EXISTING_PLAYER_PROFILE_LINK_KEY = "maxExistingPlayerProfileLink";

private static final String NON_EXISTING_PLAYER_COUNT_KEY = "nonExistingPlayersCount";
private static final String BLOCKED_PLAYERS_COUNT_KEY = "blockedPlayersCount";
private static final String PLAYERS_WITH_GET_INDEX_DATA_ERROR_KEY = "playersWithGetIndexDataError";
private static final String PLAYERS_WITH_GET_INDEX_DATA_ERROR_GROUPED_BY_ERROR_KEY = "playersWithIndexDataErrorGroupedByError";
private static final String ACTUAL_PLAYERS_WITHOUT_RACES_COUNT_KEY = "actualPlayersWithoutRacesCount";
private static final String ACTUAL_PLAYERS_WITH_AT_LEAST_1_RACE_COUNT_KEY = "actualPlayersWithAtLeast1RaceCount";
private static final String TOTAL_USERS_IN_DATABASE_KEY = "totalUsersInDatabase";
Expand Down Expand Up @@ -48,6 +63,79 @@ public String getTemplatePath() {
return "ftl/index-page.ftl";
}


public IndexPageTemplate minPlayerId(int minPlayerId) {
templateData.put(MIN_PLAYER_ID_KEY, minPlayerId);
return this;
}

public int getMinPlayerId() {
return (int) templateData.get(MIN_PLAYER_ID_KEY);
}

public IndexPageTemplate maxPlayerId(int maxPlayerId) {
templateData.put(MAX_PLAYER_ID_KEY, maxPlayerId);
return this;
}

public int getMaxPlayerId() {
return (int) templateData.get(MAX_PLAYER_ID_KEY);
}

public IndexPageTemplate dataDownloadStartDate(String dataDownloadStartDate) {
templateData.put(DATA_DOWNLOAD_START_DATE_KEY, dataDownloadStartDate);
return this;
}

public String getDataDownloadStartDate() {
return (String) templateData.get(DATA_DOWNLOAD_START_DATE_KEY);
}

public IndexPageTemplate dataDownloadEndDate(String dataDownloadEndDate) {
templateData.put(DATA_DOWNLOAD_END_DATE_KEY, dataDownloadEndDate);
return this;
}

public String getDataDownloadEndDate() {
return (String) templateData.get(DATA_DOWNLOAD_END_DATE_KEY);
}

public IndexPageTemplate examplePlayerId(int examplePlayerId) {
templateData.put(EXAMPLE_PLAYER_ID_KEY, examplePlayerId);
return this;
}

public int getExamplePlayerId() {
return (int) templateData.get(EXAMPLE_PLAYER_ID_KEY);
}

public IndexPageTemplate examplePlayerProfileLink(String examplePlayerProfileLink) {
templateData.put(EXAMPLE_PLAYER_PROFILE_LINK_KEY, examplePlayerProfileLink);
return this;
}

public String getExamplePlayerProfileLink() {
return (String) templateData.get(EXAMPLE_PLAYER_PROFILE_LINK_KEY);
}

public IndexPageTemplate examplePlayerGetSummaryUrl(String examplePlayerGetSummaryUrl) {
templateData.put(EXAMPLE_PLAYER_GET_SUMMARY_URL_KEY, examplePlayerGetSummaryUrl);
return this;
}

public String getExamplePlayerGetSummaryUrl() {
return (String) templateData.get(EXAMPLE_PLAYER_GET_SUMMARY_URL_KEY);
}

public IndexPageTemplate examplePlayerGetIndexDataUrl(String examplePlayerGetIndexDataUrl) {
templateData.put(EXAMPLE_PLAYER_GET_INDEX_DATA_URL_KEY, examplePlayerGetIndexDataUrl);
return this;
}

public String getExamplePlayerGetIndexDataUrl() {
return (String) templateData.get(EXAMPLE_PLAYER_GET_INDEX_DATA_URL_KEY);
}

public IndexPageTemplate minExistingPlayerId(int minExistingPlayerId) {
templateData.put(MIN_EXISTING_PLAYER_ID_KEY, minExistingPlayerId);
return this;
Expand All @@ -57,6 +145,15 @@ public int getMinExistingPlayerId() {
return (int) templateData.get(MIN_EXISTING_PLAYER_ID_KEY);
}

public IndexPageTemplate minExistingPlayerProfileLink(String minExistingPlayerProfileLink) {
templateData.put(MIN_EXISTING_PLAYER_PROFILE_LINK_KEY, minExistingPlayerProfileLink);
return this;
}

public String getMinExistingPlayerProfileLink() {
return (String) templateData.get(MIN_EXISTING_PLAYER_PROFILE_LINK_KEY);
}

public IndexPageTemplate maxExistingPlayerId(int maxExistingPlayerId) {
templateData.put(MAX_EXISTING_PLAYER_ID_KEY, maxExistingPlayerId);
return this;
Expand All @@ -66,6 +163,15 @@ public int getMaxExistingPlayerId() {
return (int) templateData.get(MAX_EXISTING_PLAYER_ID_KEY);
}

public IndexPageTemplate maxExistingPlayerProfileLink(String maxExistingPlayerProfileLink) {
templateData.put(MAX_EXISTING_PLAYER_PROFILE_LINK_KEY, maxExistingPlayerProfileLink);
return this;
}

public String getMaxExistingPlayerProfileLink() {
return (String) templateData.get(MAX_EXISTING_PLAYER_PROFILE_LINK_KEY);
}

public IndexPageTemplate nonExistingPlayersCount(int nonExistingPlayersCount) {
templateData.put(NON_EXISTING_PLAYER_COUNT_KEY, nonExistingPlayersCount);
return this;
Expand Down Expand Up @@ -93,6 +199,15 @@ public List<PlayerEntity> getPlayersWithGetIndexDataError() {
return (List<PlayerEntity>) templateData.get(BLOCKED_PLAYERS_COUNT_KEY);
}

public IndexPageTemplate playersWithIndexDataErrorGroupedByError(Map<String, List<PlayerEntity>> playersWithIndexDataErrorGroupedByError) {
templateData.put(PLAYERS_WITH_GET_INDEX_DATA_ERROR_GROUPED_BY_ERROR_KEY, playersWithIndexDataErrorGroupedByError);
return this;
}

public Map<String, List<PlayerEntity>> getPlayersWithIndexDataErrorGroupedByError() {
return (Map<String, List<PlayerEntity>>) templateData.get(PLAYERS_WITH_GET_INDEX_DATA_ERROR_GROUPED_BY_ERROR_KEY);
}

public IndexPageTemplate actualPlayersWithoutRacesCount(int actualPlayersWithoutRacesCount) {
templateData.put(ACTUAL_PLAYERS_WITHOUT_RACES_COUNT_KEY, actualPlayersWithoutRacesCount);
return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,6 @@ public class PlayerDto { // object to use in Freemarker templates
private Integer vocabulariesCount;

private Integer carsCount;

private String profileLink;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package ru.klavogonki.kgparser.jsonParser.entity;

import lombok.Data;
import ru.klavogonki.kgparser.Rank;
import ru.klavogonki.kgparser.http.UrlConstructor;

import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
Expand All @@ -10,6 +12,7 @@
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
import java.time.LocalDateTime;

@Data
Expand Down Expand Up @@ -71,4 +74,19 @@ public class PlayerEntity {
private Integer vocabulariesCount;

private Integer carsCount;

@Transient
public String getProfileLink() {
return UrlConstructor.userProfileLink(playerId);
}

@Transient
public String getRank() {
return Rank.getRank(rankLevel).name();
}

@Transient
public String getRankDisplayName() {
return Rank.getDisplayName(rankLevel);
}
}
Loading

0 comments on commit 66a9c71

Please sign in to comment.