From 777b85391ea3abaeafa30507f39ae35ebd3194b7 Mon Sep 17 00:00:00 2001 From: gsd Date: Wed, 1 May 2024 18:39:31 +0300 Subject: [PATCH] online stats features v2 --- .../java/app/controllers/StatsController.java | 11 +- src/main/java/app/updates/OnlineUpdater.java | 100 +++++++++++++++++- 2 files changed, 108 insertions(+), 3 deletions(-) diff --git a/src/main/java/app/controllers/StatsController.java b/src/main/java/app/controllers/StatsController.java index 58af121..e20f8c3 100644 --- a/src/main/java/app/controllers/StatsController.java +++ b/src/main/java/app/controllers/StatsController.java @@ -5,6 +5,7 @@ import app.annotations.interfaces.BurstUpdatePlayers; import app.annotations.interfaces.CollectStatistic; import app.entities.Stats; import app.services.ExternalServices; +import app.updates.OnlineUpdater; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -20,17 +21,20 @@ import java.util.List; public class StatsController { private Stats stats; private ExternalServices externalServices; + private OnlineUpdater onlineUpdater; @Autowired - public StatsController(Stats stats, ExternalServices externalServices){ + public StatsController(Stats stats, ExternalServices externalServices, OnlineUpdater onlineUpdater){ this.stats = stats; this.externalServices = externalServices; + this.onlineUpdater = onlineUpdater; } @GetMapping @BurstUpdatePlayers @CollectStatistic public ResponseEntity GetStats(@RequestParam(name = "filter", required = false) String filter){ + stats.getStatistic().setPlayer_max(onlineUpdater.getCurrent_day_max_player_count()); if (filter != null && !filter.isEmpty()) { return new ResponseEntity(stats.getOnlyThis(filter), HttpStatus.OK); } @@ -42,4 +46,9 @@ public class StatsController { public ResponseEntity GetServices() { return new ResponseEntity(externalServices.getServices(), HttpStatus.OK); } + + @GetMapping("/graph") + public ResponseEntity GetPeakOfDays() { + return new ResponseEntity(onlineUpdater.getPeakOfDays(7), HttpStatus.OK); + } } diff --git a/src/main/java/app/updates/OnlineUpdater.java b/src/main/java/app/updates/OnlineUpdater.java index 492d184..0c7a1d8 100644 --- a/src/main/java/app/updates/OnlineUpdater.java +++ b/src/main/java/app/updates/OnlineUpdater.java @@ -14,6 +14,8 @@ import java.sql.SQLException; import java.sql.Timestamp; import java.time.Instant; import java.time.LocalDate; +import java.util.ArrayList; +import java.util.Date; import java.util.List; @Component @@ -32,6 +34,8 @@ public class OnlineUpdater extends BaseUpdater { private final static int sleep_time = 30 * 1000; + private int current_day_max_player_count = 0; + @Autowired public OnlineUpdater(Stats stats) { this.stats = stats; @@ -44,6 +48,7 @@ public class OnlineUpdater extends BaseUpdater { logger.info("{} created online updater", server_name); CreateTaskUpdater(() -> AppendOnlineStats(server_name), sleep_time); }); + CreateTaskUpdater(this::updateCurrentDayPeak, sleep_time); } public boolean AppendOnlineStats(String server_id) { @@ -64,16 +69,107 @@ public class OnlineUpdater extends BaseUpdater { //todo abstract on all public List getStatsOnPerDay(String server_id) { return jdbcTemplate_ro.query("SELECT avg(`player_count`) as player_count, FROM_UNIXTIME(`utime`) as fulldate, `utime` as ts FROM `servers_online` WHERE `player_count` != 0 and `server_id` like ? GROUP BY FROM_UNIXTIME(`utime`) div ? ORDER BY `ts` ASC", - new Object[]{server_id, PerDayStats.period}, + new Object[]{server_id == null || server_id.isEmpty() ? "%": server_id, PerDayStats.period}, (rs, rowNum) -> new PerDayStats(rs)); } public List getStatsOnPerFiveMinutes(String server_id) { return jdbcTemplate_ro.query("SELECT avg(`player_count`) as player_count, FROM_UNIXTIME(`utime`) as fulldate, `utime` as ts FROM `servers_online` WHERE `player_count` != 0 and `server_id` like ? GROUP BY FROM_UNIXTIME(`utime`) div ? ORDER BY `ts` ASC", - new Object[]{server_id, PerFiveMinutesStats.period}, + new Object[]{server_id == null || server_id.isEmpty() ? "%": server_id, PerFiveMinutesStats.period}, (rs, rowNum) -> new PerFiveMinutesStats(rs)); } + private boolean updateCurrentDayPeak() { + this.current_day_max_player_count = getMaxPeakOfDays(1).get(0).getPlayer_count(); + return true; + } + + public int getCurrent_day_max_player_count() { + return current_day_max_player_count; + } + + public List getMaxPeakOfDays(int limit) { + return jdbcTemplate_ro.query("SELECT SUM(s.player_count) as player_count, s.fulldate as fl FROM (SELECT max(`player_count`) as player_count, cast(FROM_UNIXTIME(`utime`) as date) as fulldate,`server_id` FROM `servers_online` WHERE `player_count` != 0 and `server_id` like '%' GROUP BY cast(FROM_UNIXTIME(`utime`) as date), server_id ORDER BY `fulldate` DESC) s GROUP BY s.fulldate ORDER BY `s`.`fulldate` DESC LIMIT ?", + new Object[]{limit}, + (rs, rowNum) -> new MaxPeakOfDay(rs)); + } + + public List getAvgPeakOfDays(int limit) { + return jdbcTemplate_ro.query("SELECT SUM(s.player_count) as player_count, s.fulldate as fl FROM (SELECT avg(`player_count`) as player_count, cast(FROM_UNIXTIME(`utime`) as date) as fulldate,`server_id` FROM `servers_online` WHERE `player_count` != 0 and `server_id` like '%' GROUP BY cast(FROM_UNIXTIME(`utime`) as date), server_id ORDER BY `fulldate` DESC) s GROUP BY s.fulldate ORDER BY `s`.`fulldate` DESC LIMIT ?", + new Object[]{limit}, + (rs, rowNum) -> new AvgPeakOfDay(rs)); + } + + public List getPeakOfDays(int limit) { + List maxPeakOfDays = getMaxPeakOfDays(limit); + List avgPeakOfDays = getAvgPeakOfDays(limit); + List statsOfPeakOfDays = new ArrayList<>(); + for (int i = 0; i < maxPeakOfDays.size(); i++) { + statsOfPeakOfDays.add(new StatsOfPeakOfDay(avgPeakOfDays.get(i), maxPeakOfDays.get(i))); + } + return statsOfPeakOfDays; + } + + public class StatsOfPeakOfDay { + private final Date date; + private final int max; + private final int avg; + + StatsOfPeakOfDay(AvgPeakOfDay avgPeakOfDay, MaxPeakOfDay maxPeakOfDay) { + date = avgPeakOfDay.getDate(); + avg = avgPeakOfDay.getPlayer_count(); + max = maxPeakOfDay.getPlayer_count(); + } + + public Date getDate() { + return date; + } + + public int getMax() { + return max; + } + + public int getAvg() { + return avg; + } + } + + public class AvgPeakOfDay extends PeakOfDay { + private final double player_count; + public AvgPeakOfDay(ResultSet rs) throws SQLException { + super(rs); + this.player_count = rs.getDouble("player_count"); + } + + public int getPlayer_count() { + return (int) Math.round(player_count); + } + } + + public class MaxPeakOfDay extends PeakOfDay { + private final int player_count; + public MaxPeakOfDay(ResultSet rs) throws SQLException { + super(rs); + this.player_count = rs.getInt("player_count"); + } + + public int getPlayer_count() { + return player_count; + } + } + + public abstract class PeakOfDay { + private final Date date; + + PeakOfDay(ResultSet rs) throws SQLException { + this.date = rs.getDate("fl"); + } + + public Date getDate() { + return date; + } + } + //CREATE TABLE `tf2.facti13`.`servers_online` (`id` INT NOT NULL AUTO_INCREMENT , `utime` INT NOT NULL , `player_count` INT NOT NULL , `max_players` INT NOT NULL , `server_id` VARCHAR(32) NOT NULL , PRIMARY KEY (`id`)) ENGINE = InnoDB; public class ServerOnline { private int id;