From b222096b0d15ea51462f483c0387e621100a9833 Mon Sep 17 00:00:00 2001 From: gsd Date: Thu, 3 Apr 2025 20:26:24 +0300 Subject: [PATCH] =?UTF-8?q?=D0=BF=D0=B5=D0=BB=D1=8C=D0=BC=D0=B5=D0=BD?= =?UTF-8?q?=D1=8C=20=D0=B0=D0=BF=D0=B4=D0=B5=D0=B9=D1=82=203?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/app/MainApi.java | 2 + .../controllers/user/KillFeedController.java | 36 +- .../controllers/user/MessagesController.java | 10 +- src/main/java/app/entities/db/Gametime.java | 3 + .../java/app/entities/killfeed/FeedType.java | 5 + .../app/entities/killfeed/KillsInFeed.java | 127 +++++++ .../app/entities/killfeed/TF2iDBItem.java | 52 +++ .../java/app/entities/messages/Message.java | 11 +- .../app/entities/messages/MessageSearch.java | 4 +- .../app/repositories/GametimeRepository.java | 20 ++ .../app/repositories/KillfeedRepository.java | 81 +++++ .../java/app/services/db/DetectService.java | 15 +- .../java/app/services/db/KillfeedService.java | 309 +++++------------- .../java/app/services/db/MessageService.java | 9 - .../java/app/services/db/NicknameService.java | 53 --- 15 files changed, 417 insertions(+), 320 deletions(-) create mode 100644 src/main/java/app/entities/killfeed/FeedType.java create mode 100644 src/main/java/app/entities/killfeed/KillsInFeed.java create mode 100644 src/main/java/app/entities/killfeed/TF2iDBItem.java create mode 100644 src/main/java/app/repositories/GametimeRepository.java create mode 100644 src/main/java/app/repositories/KillfeedRepository.java delete mode 100644 src/main/java/app/services/db/NicknameService.java diff --git a/src/main/java/app/MainApi.java b/src/main/java/app/MainApi.java index 91c1da2..6b9b31e 100644 --- a/src/main/java/app/MainApi.java +++ b/src/main/java/app/MainApi.java @@ -2,10 +2,12 @@ package app; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cache.annotation.EnableCaching; import java.time.Instant; @SpringBootApplication +@EnableCaching public class MainApi { public static void main(String[] args) { try { diff --git a/src/main/java/app/controllers/user/KillFeedController.java b/src/main/java/app/controllers/user/KillFeedController.java index 246a89c..8406641 100644 --- a/src/main/java/app/controllers/user/KillFeedController.java +++ b/src/main/java/app/controllers/user/KillFeedController.java @@ -4,15 +4,22 @@ import app.annotations.enums.AuthMethod; import app.annotations.interfaces.CheckWebAccess; import app.annotations.interfaces.CollectStatistic; import app.annotations.interfaces.WaitAfterNext; +import app.entities.killfeed.FeedType; +import app.entities.killfeed.KillsInFeed; import app.entities.other.SteamID; import app.services.db.KillfeedService; import app.utils.SteamIDConverter; import jakarta.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import java.util.Collections; +import java.util.Map; + /** * контроллер для получение списка убийств\ассистов\смертей */ @@ -59,13 +66,14 @@ public class KillFeedController { @CookieValue(value = "steam64", defaultValue = "") String mysteam64, @RequestParam(required = false) String steam64, @RequestParam(required = false) String srv, - @RequestParam(required = false, defaultValue = "0") Integer offset, - @RequestParam(required = false, defaultValue = "20") Integer limit, + Pageable pageable, @RequestParam(required = false, defaultValue = "false") boolean current) { SteamID steamID = steam64 == null || steam64.isEmpty() ? SteamIDConverter.getSteamID(mysteam64) : SteamIDConverter.getSteamID(steam64); if (steamID == null) return new ResponseEntity(HttpStatus.NOT_FOUND); - if (limit > 20) return new ResponseEntity(HttpStatus.NOT_ACCEPTABLE); - return new ResponseEntity(killfeedService.getKills(steamID, srv, offset, limit, current), HttpStatus.OK); + if (pageable.getPageSize() > 20) return new ResponseEntity(HttpStatus.NOT_ACCEPTABLE); + Page res = killfeedService.getKills(pageable, Collections.singletonList(steamID), srv, current); + + return new ResponseEntity(Map.of("result", res.getContent(), "count", res.getTotalElements(), "type", FeedType.KILL.ordinal()), HttpStatus.OK); } @PutMapping @@ -76,13 +84,14 @@ public class KillFeedController { @CookieValue(value = "steam64", defaultValue = "") String mysteam64, @RequestParam(required = false) String steam64, @RequestParam(required = false) String srv, - @RequestParam(required = false, defaultValue = "0") Integer offset, - @RequestParam(required = false, defaultValue = "20") Integer limit, - @RequestParam(required = false, defaultValue = "false") boolean current) { + Pageable pageable, + @RequestParam(required = false, defaultValue = "false") boolean current) { SteamID steamID = steam64 == null || steam64.isEmpty() ? SteamIDConverter.getSteamID(mysteam64) : SteamIDConverter.getSteamID(steam64); if (steamID == null) return new ResponseEntity(HttpStatus.NOT_FOUND); - if (limit > 20) return new ResponseEntity(HttpStatus.NOT_ACCEPTABLE); - return new ResponseEntity(killfeedService.getAssists(steamID, srv, offset, limit, current), HttpStatus.OK); + if (pageable.getPageSize() > 20) return new ResponseEntity(HttpStatus.NOT_ACCEPTABLE); + Page res = killfeedService.getAssists(pageable, Collections.singletonList(steamID), srv, current); + + return new ResponseEntity(Map.of("result", res.getContent(), "count", res.getTotalElements(), "type", FeedType.ASSIST.ordinal()), HttpStatus.OK); } @DeleteMapping @@ -93,13 +102,14 @@ public class KillFeedController { @CookieValue(value = "steam64", defaultValue = "") String mysteam64, @RequestParam(required = false) String steam64, @RequestParam(required = false) String srv, - @RequestParam(required = false, defaultValue = "0") Integer offset, - @RequestParam(required = false, defaultValue = "20") Integer limit, + Pageable pageable, @RequestParam(required = false, defaultValue = "false") boolean current) { SteamID steamID = steam64 == null || steam64.isEmpty() ? SteamIDConverter.getSteamID(mysteam64) : SteamIDConverter.getSteamID(steam64); if (steamID == null) return new ResponseEntity(HttpStatus.NOT_FOUND); - if (limit > 20) return new ResponseEntity(HttpStatus.NOT_ACCEPTABLE); - return new ResponseEntity(killfeedService.getDeads(steamID, srv, offset, limit, current), HttpStatus.OK); + if (pageable.getPageSize() > 20) return new ResponseEntity(HttpStatus.NOT_ACCEPTABLE); + Page res = killfeedService.getDeads(pageable, Collections.singletonList(steamID), srv, current); + + return new ResponseEntity(Map.of("result", res.getContent(), "count", res.getTotalElements(), "type", FeedType.DEAD.ordinal()), HttpStatus.OK); } @DeleteMapping("/top") diff --git a/src/main/java/app/controllers/user/MessagesController.java b/src/main/java/app/controllers/user/MessagesController.java index cb5a5bb..7aaec32 100644 --- a/src/main/java/app/controllers/user/MessagesController.java +++ b/src/main/java/app/controllers/user/MessagesController.java @@ -7,6 +7,7 @@ import app.annotations.interfaces.WaitAfterNext; import app.entities.messages.Message; import app.entities.messages.MessageSearch; import app.entities.other.SteamID; +import app.repositories.GametimeRepository; import app.repositories.MessageRepository; import app.services.ProfileService; import app.services.db.MessageService; @@ -37,6 +38,9 @@ public class MessagesController { private ProfileService profileService; + @Autowired + private GametimeRepository gametimeRepository; + @Autowired public MessagesController(MessageService messageService, MessageRepository messageRepository, ProfileService profileService) { this.messageService = messageService; @@ -65,7 +69,7 @@ public class MessagesController { public Page getMessagesWithFilters(Pageable pageable, @RequestBody(required = false) MessageSearch filter) { if (filter == null) filter = new MessageSearch(); - return messageRepository.getMessages( + Page messages = messageRepository.getMessages( pageable, filter.getAccounts(profileService), filter.getBegin(), @@ -73,6 +77,10 @@ public class MessagesController { filter.getMessage(), filter.getServerId() ); + messages.getContent().forEach((msg) -> { + msg.setGametime(gametimeRepository.searchGametimeByAccountId(msg.getAccount_id())); + }); + return messages; } @PostMapping(value = "/account", consumes = {MediaType.APPLICATION_JSON_VALUE}) diff --git a/src/main/java/app/entities/db/Gametime.java b/src/main/java/app/entities/db/Gametime.java index be2c366..9e772b4 100644 --- a/src/main/java/app/entities/db/Gametime.java +++ b/src/main/java/app/entities/db/Gametime.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.annotation.JsonGetter; import com.fasterxml.jackson.annotation.JsonIgnore; import jakarta.persistence.*; import lombok.Data; +import org.hibernate.annotations.CacheConcurrencyStrategy; import java.sql.ResultSet; import java.sql.SQLException; @@ -26,6 +27,8 @@ CREATE TABLE `user_connections` ( */ @Data @Entity +@Cacheable +@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_ONLY) @Table(schema = "tf2_facti13", name = "user_connections") public class Gametime { diff --git a/src/main/java/app/entities/killfeed/FeedType.java b/src/main/java/app/entities/killfeed/FeedType.java new file mode 100644 index 0000000..e2644f2 --- /dev/null +++ b/src/main/java/app/entities/killfeed/FeedType.java @@ -0,0 +1,5 @@ +package app.entities.killfeed; + +public enum FeedType { + KILL, DEAD, ASSIST +} \ No newline at end of file diff --git a/src/main/java/app/entities/killfeed/KillsInFeed.java b/src/main/java/app/entities/killfeed/KillsInFeed.java new file mode 100644 index 0000000..5503784 --- /dev/null +++ b/src/main/java/app/entities/killfeed/KillsInFeed.java @@ -0,0 +1,127 @@ +package app.entities.killfeed; + +import app.entities.server.ServerDB; +import com.fasterxml.jackson.annotation.JsonIgnore; +import jakarta.persistence.*; +import lombok.Data; +import org.hibernate.annotations.CacheConcurrencyStrategy; + +import java.sql.ResultSet; +import java.sql.SQLException; + +/* + CREATE TABLE user_killfeed ( + id bigint(11) NOT NULL, + attacker_id int(11) NOT NULL, + victim_id int(11) NOT NULL, + assister_id int(11) NOT NULL, + utime bigint(20) NOT NULL, + weapon_name varchar(128) NOT NULL, + weapon_id int(11) NOT NULL, + weapon_classname varchar(128) NOT NULL, + weapon_index int(11) NOT NULL, + custom_kill int(11) NOT NULL, + crit_type int(11) NOT NULL, + server_id varchar(32) NOT NULL + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + */ +@Data +@Entity +@Cacheable +@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_ONLY) +@Table(schema = "tf2_facti13", name = "user_killfeed") +public class KillsInFeed { + @Id + private Long id; + + @Column(name = "attacker_id") + private Long attacker_id = -1L; + + // + private String attacker_name; + + @Column(name = "victim_id") + private Long victim_id = -1L; + + // + private String victim_name; + + @Column(name = "assister_id") + private Long assister_id = -1L; + + // + private String assister_name; + + @Column(name = "utime") + private long utime; + + @Column(name = "weapon_name", length = 128) + private String weapon_name; + + @JsonIgnore + @Column(name = "weapon_id") + private Long weapon_id; + + @Column(name = "weapon_classname") + private String weapon_classname; + + @JsonIgnore + @Column(name = "weapon_index") + private Long weapon_index; + + @JsonIgnore + @Column(name = "custom_kill") + private Long custom_kill; + + @JsonIgnore + @Column(name = "crit_type") + private Long crit_type; + + @Column(name = "server_id") + private String server_id; + + @JsonIgnore + @ManyToOne + @JoinColumn(name = "server_id", referencedColumnName = "srv_id", insertable = false, updatable = false) + private ServerDB serverDB; + + @JsonIgnore + @ManyToOne + @JoinColumn(name = "weapon_id", referencedColumnName = "id", insertable = false, updatable = false) + private TF2iDBItem tf2iDBItem; + + public KillsInFeed(Object obj) { + this.attacker_id = (long) ((Object[]) obj)[0]; + this.victim_id = (long) ((Object[]) obj)[1]; + this.assister_id = (long) ((Object[]) obj)[2]; + this.utime = (long) ((Object[]) obj)[3]; + this.weapon_name = (String) ((Object[]) obj)[4]; + this.server_id = (String) ((Object[]) obj)[5]; + this.weapon_classname = (String) ((Object[]) obj)[6]; + } + + public KillsInFeed(ResultSet rs) throws SQLException { + assister_id = rs.getLong(1); + victim_id = rs.getLong(2); + assister_id = rs.getLong(3); + utime = rs.getLong(4); + weapon_name = rs.getString(5); + server_id = rs.getString(6); + weapon_classname = rs.getString(7); + } + + public KillsInFeed() { + + } + + public String getWeapon_name(){ + //obj_sentrygun + if (this.weapon_classname.contains("obj_sentrygun")) + return "Турель " + (this.weapon_classname.replace("obj_sentrygun", "").isEmpty()?"1":this.weapon_classname.replace("obj_sentrygun", "")) + " уровня"; + return this.tf2iDBItem == null ? this.weapon_name : this.tf2iDBItem.getName(); + } + + public String getServerName() { + return this.serverDB == null ? "" : this.serverDB.getName(); + } +} \ No newline at end of file diff --git a/src/main/java/app/entities/killfeed/TF2iDBItem.java b/src/main/java/app/entities/killfeed/TF2iDBItem.java new file mode 100644 index 0000000..72b7a3e --- /dev/null +++ b/src/main/java/app/entities/killfeed/TF2iDBItem.java @@ -0,0 +1,52 @@ +package app.entities.killfeed; + +import jakarta.persistence.*; +import lombok.Data; +import org.hibernate.annotations.CacheConcurrencyStrategy; + +@Data +@Entity +@Cacheable +@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_ONLY) +@Table(schema = "tf2idb", name = "tf2idb_item") +public class TF2iDBItem { + @Id + @Column(name = "id") + private Long id; + + @Column(name = "name", length = 128) + private String name; + + @Column(name = "item_name", length = 64) + private String itemName; + + @Column(name = "class", length = 128) + private String clz; + + @Column(name = "slot", length = 128) + private String slot; + + @Column(name = "quality", length = 128) + private String quality; + + @Column(name = "tool_type", length = 128) + private String toolType; + + @Column(name = "min_ilevel") + private Long minILevel; + + @Column(name = "max_ilevel") + private Long maxILevel; + + @Column(name = "baseitem") + private Long baseItem; + + @Column(name = "holiday_restriction") + private String holidayRestriction; + + @Column(name = "has_string_attribute") + private Long hasStringAttribute; + + @Column(name = "propername") + private Long properName; +} diff --git a/src/main/java/app/entities/messages/Message.java b/src/main/java/app/entities/messages/Message.java index e55a9fa..2c4c6c1 100644 --- a/src/main/java/app/entities/messages/Message.java +++ b/src/main/java/app/entities/messages/Message.java @@ -2,17 +2,13 @@ package app.entities.messages; import app.entities.db.Gametime; import app.entities.server.ServerDB; -import app.services.db.NicknameService; import com.fasterxml.jackson.annotation.JsonIgnore; import jakarta.persistence.*; -import jakarta.persistence.OrderBy; import jakarta.persistence.Table; import lombok.Data; -import org.hibernate.annotations.*; import java.sql.ResultSet; import java.sql.SQLException; -import java.util.List; /* CREATE TABLE user_messages ( @@ -44,9 +40,8 @@ public class Message { String server_id; @JsonIgnore - @OneToMany - @JoinColumn(name = "account_id", referencedColumnName = "account_id", insertable=false, updatable=false) - private List gametime; + @Transient + private Gametime gametime; @ManyToOne @JoinColumn(name = "server_id", referencedColumnName = "srv_id", insertable = false, updatable = false) @@ -78,6 +73,6 @@ public class Message { } public String getAccount_name() { - return gametime == null | gametime.isEmpty() ? "" : gametime.get(0).getPlayer_name(); + return gametime == null ? "" : gametime.getPlayer_name(); } } \ No newline at end of file diff --git a/src/main/java/app/entities/messages/MessageSearch.java b/src/main/java/app/entities/messages/MessageSearch.java index 0aaa3ad..51c7713 100644 --- a/src/main/java/app/entities/messages/MessageSearch.java +++ b/src/main/java/app/entities/messages/MessageSearch.java @@ -7,6 +7,7 @@ import java.time.LocalDateTime; import java.time.ZoneId; import java.util.ArrayList; import java.util.List; +import java.util.Objects; public class MessageSearch { private List accounts; @@ -22,7 +23,8 @@ public class MessageSearch { if (accounts == null) return null; List filtered = accounts.stream() - .map(any -> profileService.GetSteamIDFromAnyData(any)) + .map(profileService::GetSteamIDFromAnyData) + .filter(Objects::nonNull) .map(sId -> sId.steam2) .map(Long::parseLong) .toList(); diff --git a/src/main/java/app/repositories/GametimeRepository.java b/src/main/java/app/repositories/GametimeRepository.java new file mode 100644 index 0000000..ff028a6 --- /dev/null +++ b/src/main/java/app/repositories/GametimeRepository.java @@ -0,0 +1,20 @@ +package app.repositories; + +import app.entities.db.Gametime; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.PagingAndSortingRepository; +import org.springframework.data.repository.query.Param; + +import java.util.List; + +public interface GametimeRepository extends PagingAndSortingRepository { + + @Query(value = "select g from Gametime g where g.player_name like :player_name order by g.id desc limit 1") + Gametime searchGameTimeByPlayerName(@Param("player_name") String player_name); + + @Query(value = "select g from Gametime g where g.account_id = :account_id order by g.id desc limit 1") + Gametime searchGametimeByAccountId(@Param("account_id") Long account_id); + + @Query(value = "select g.steam_id from Gametime g where g.account_id = :account_id and g.connect_ip not like '' and g.connect_ip not like '10.%' group by g.connect_ip, g.steam_id, g.id order by g.id desc") + List searchAccountsByAccountId(@Param("account_id") Long account_id); +} diff --git a/src/main/java/app/repositories/KillfeedRepository.java b/src/main/java/app/repositories/KillfeedRepository.java new file mode 100644 index 0000000..a330348 --- /dev/null +++ b/src/main/java/app/repositories/KillfeedRepository.java @@ -0,0 +1,81 @@ +package app.repositories; + +import app.entities.killfeed.KillsInFeed; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.PagingAndSortingRepository; +import org.springframework.data.repository.query.Param; + +import java.util.List; + +public interface KillfeedRepository extends PagingAndSortingRepository { + + //kills + @Query(value = "select count(k) from KillsInFeed k where " + + "(:utime is null or k.utime >= :utime) and " + + "(:server_id is null or k.server_id like :server_id) and" + + "(:account_id is null or (k.attacker_id = :account_id and k.attacker_id != k.victim_id))") + Long getKills( + @Param("account_id") Long account_id, + @Param("server_id") String server_id, + @Param("utime") Long utime); + + @Query(value = "select k from KillsInFeed k where " + + "(:utime is null or k.utime >= :utime) and " + + "(:server_id is null or k.server_id like :server_id) and" + + "(:account_id is null or (k.attacker_id in :accounts_id and k.attacker_id != k.victim_id))") + Page getKills(Pageable pageable, + @Param("accounts_id") List accounts_id, + @Param("server_id") String server_id, + @Param("utime") Long utime); + + //deads + @Query(value = "select count(k) from KillsInFeed k where " + + "(:utime is null or k.utime >= :utime) and " + + "(:server_id is null or k.server_id like :server_id) and" + + "(:account_id is null or (k.victim_id = :account_id and k.attacker_id != k.victim_id))") + Long getDeads( + @Param("account_id") Long account_id, + @Param("server_id") String server_id, + @Param("utime") Long utime); + + @Query(value = "select k from KillsInFeed k where " + + "(:utime is null or k.utime >= :utime) and " + + "(:server_id is null or k.server_id like :server_id) and" + + "(:account_id is null or (k.victim_id in :accounts_id and k.attacker_id != k.victim_id))") + Page getDeads(Pageable pageable, + @Param("accounts_id") List accounts_id, + @Param("server_id") String server_id, + @Param("utime") Long utime); + + //suisides + @Query(value = "select count(k) from KillsInFeed k where " + + "(:utime is null or k.utime >= :utime) and " + + "(:server_id is null or k.server_id like :server_id) and" + + "(:account_id is null or (k.victim_id = :account_id and k.attacker_id = k.victim_id))") + Long getSuicides( + @Param("account_id") Long account_id, + @Param("server_id") String server_id, + @Param("utime") Long utime); + + + //assists + @Query(value = "select count(k) from KillsInFeed k where " + + "(:utime is null or k.utime >= :utime) and " + + "(:server_id is null or k.server_id like :server_id) and" + + "(:account_id is null or k.assister_id = :account_id)") + Long getAssists( + @Param("account_id") Long account_id, + @Param("server_id") String server_id, + @Param("utime") Long utime); + + @Query(value = "select k from KillsInFeed k where " + + "(:utime is null or k.utime >= :utime) and " + + "(:server_id is null or k.server_id like :server_id) and" + + "(:account_id is null or k.assister_id in :accounts_id)") + Page getAssists(Pageable pageable, + @Param("accounts_id") List accounts_id, + @Param("server_id") String server_id, + @Param("utime") Long utime); +} diff --git a/src/main/java/app/services/db/DetectService.java b/src/main/java/app/services/db/DetectService.java index 72b18bc..3c6af96 100644 --- a/src/main/java/app/services/db/DetectService.java +++ b/src/main/java/app/services/db/DetectService.java @@ -3,6 +3,7 @@ package app.services.db; import app.entities.Stats; import app.entities.other.SteamID; import app.entities.server.Server; +import app.repositories.GametimeRepository; import app.utils.SteamIDConverter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -22,8 +23,7 @@ import java.util.concurrent.atomic.AtomicReference; public class DetectService { @Autowired - @Qualifier("jt_rw") - private JdbcTemplate jdbcTemplate_rw; + private GametimeRepository gametimeRepository; @Autowired @Qualifier("jt_ro") @@ -38,13 +38,14 @@ public class DetectService { } public List getAccountsPerSteamID(SteamID steamID) { - List founded_steamid = jdbcTemplate_ro.query("SELECT steam_id FROM user_connections WHERE steam_id LIKE ? AND connect_ip NOT LIKE '10.%' GROUP BY connect_ip, steam_id, id ORDER BY id DESC", - new Object[]{steamID.steam2}, - (rs, n) -> rs.getString("steam_id")); - return founded_steamid.stream().distinct().map(SteamIDConverter::getSteamID).filter(Objects::nonNull).toList(); + return gametimeRepository + .searchAccountsByAccountId(steamID.account_id) + .stream() + .map(SteamIDConverter::getSteamID) + .filter(Objects::nonNull) + .toList(); } - public List> getAttachedDiscordAccountPerSteam(SteamID steamID) { return jdbcTemplate_ro.query("SELECT discord_id, extract(epoch from timestamp) as utime, active FROM steam2discord WHERE steam_id LIKE ? GROUP BY discord_id, active, timestamp", new Object[]{ steamID.steam2 }, diff --git a/src/main/java/app/services/db/KillfeedService.java b/src/main/java/app/services/db/KillfeedService.java index c6db3b5..f4427bc 100644 --- a/src/main/java/app/services/db/KillfeedService.java +++ b/src/main/java/app/services/db/KillfeedService.java @@ -1,11 +1,17 @@ package app.services.db; import app.entities.Stats; +import app.entities.db.Gametime; +import app.entities.killfeed.KillsInFeed; import app.entities.other.SteamID; +import app.repositories.GametimeRepository; +import app.repositories.KillfeedRepository; import app.services.StatsService; import lombok.Data; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import org.springframework.stereotype.Service; @@ -16,6 +22,9 @@ import java.time.Instant; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; +import java.util.function.Function; +import java.util.stream.Collectors; @Service public class KillfeedService { @@ -23,29 +32,24 @@ public class KillfeedService { @Autowired @Qualifier("jt_ro") private JdbcTemplate jdbcTemplate; - private Stats stats; - private NicknameService nicknameService; private StatsService statsService; @Autowired - KillfeedService(Stats stats, NicknameService nicknameService, StatsService statsService) { - this.stats = stats; - this.nicknameService = nicknameService; + private GametimeRepository gametimeRepository; + + @Autowired + private KillfeedRepository killfeedRepository; + + @Autowired + KillfeedService(StatsService statsService) { this.statsService = statsService; } - public Long getKills(SteamID steamID, String server_id, Long utime) { - return jdbcTemplate.query("SELECT COUNT(*) as c " + - "FROM user_killfeed " + - "WHERE utime > ? AND attacker_id = ? AND attacker_id != victim_id AND (? = 0 or server_id like ?)", - new Object[]{ - utime==null?0:utime, - steamID.account_id, - server_id==null||server_id.isEmpty()?0:1, - server_id==null||server_id.isEmpty()?"%":server_id }, - (rs, n) -> rs.getLong("c")) - .stream().findFirst().orElse(0L); - } + private final Function accountId2Nickname = (account_id) -> { + if (account_id == null || account_id < 0) return ""; + Gametime gametime = gametimeRepository.searchGametimeByAccountId(account_id); + return gametime == null ? "Unknown" : gametime.getPlayer_name(); + }; public List getTopKills(String server_id) { return jdbcTemplate.query("SELECT attacker_id, count(*) as c, server_id " + @@ -56,20 +60,9 @@ public class KillfeedService { new Object[]{ server_id == null || server_id.isEmpty() ? 0 : 1, server_id == null || server_id.isEmpty() ? "%" : server_id}, - (rs, n) -> new TopInFeed(rs).setNicknames(nicknameService)); - } - - public Long getDeads(SteamID steamID, String server_id, Long utime) { - return jdbcTemplate.query("SELECT COUNT(*) as c " + - "FROM user_killfeed " + - "WHERE utime > ? AND victim_id = ? AND attacker_id != victim_id AND (? =0 or server_id like ?)", - new Object[]{ - utime==null?0:utime, - steamID.account_id, - server_id == null || server_id.isEmpty() ? 0 : 1, - server_id==null||server_id.isEmpty()?"%":server_id }, - (rs, n) -> rs.getLong("c")) - .stream().findFirst().orElse(0L); + (rs, n) -> new TopInFeed(rs)).stream().peek(t -> { + t.name = accountId2Nickname.apply(t.uid); + }).toList(); } public List getTopDeads(String server_id) { @@ -81,33 +74,9 @@ public class KillfeedService { new Object[]{ server_id == null || server_id.isEmpty() ? 0 : 1, server_id == null || server_id.isEmpty() ? "%" : server_id}, - (rs, n) -> new TopInFeed(rs).setNicknames(nicknameService)); - } - - public Long getSuicides(SteamID steamID, String server_id, Long utime) { - return jdbcTemplate.query("SELECT COUNT(*) as c " + - "FROM user_killfeed " + - "WHERE utime > ? AND victim_id = ? AND attacker_id = victim_id AND (? =0 or server_id like ?)", - new Object[]{ - utime==null?0:utime, - steamID.account_id, - server_id == null || server_id.isEmpty() ? 0 : 1, - server_id==null||server_id.isEmpty()?"%":server_id }, - (rs, n) -> rs.getLong("c")) - .stream().findFirst().orElse(0L); - } - - public Long getAssists(SteamID steamID, String server_id, Long utime) { - return jdbcTemplate.query("SELECT COUNT(*) as c " + - "FROM user_killfeed " + - "WHERE utime > ? AND assister_id = ? AND (? =0 or server_id like ?)", - new Object[]{ - utime==null?0:utime, - steamID.account_id, - server_id == null || server_id.isEmpty() ? 0 : 1, - server_id==null||server_id.isEmpty()?"%":server_id}, - (rs, n) -> rs.getLong("c")) - .stream().findFirst().orElse(0L); + (rs, n) -> new TopInFeed(rs)).stream().peek(t -> { + t.name = accountId2Nickname.apply(t.uid); + }).toList(); } public Map getPopulateWeapons(SteamID steamID, String server_id, int offset, int limit) { @@ -132,111 +101,65 @@ public class KillfeedService { return Map.of("result", result, "count", -1); } - public Map getKills(SteamID steamID, String server_id, int offset, int limit, boolean current) { - long current_utime = 0L; - if (current) { - Long currentPlayerSesTime = statsService.searchCurrentPlayerStartTime(steamID); - if (currentPlayerSesTime != null) current_utime = Instant.now().getEpochSecond() - currentPlayerSesTime; - else current_utime = Instant.now().getEpochSecond(); - } - - List result = jdbcTemplate.query("SELECT -1, u.victim_id, u.assister_id, u.utime, i.name, u.server_id, u.weapon_classname " + - "FROM user_killfeed as u " + - "INNER JOIN tf2idb.tf2idb_item as i ON u.weapon_index = i.id " + - "WHERE u.utime > ? AND u.attacker_id = ? AND u.attacker_id != u.victim_id AND (? =0 or u.server_id like ?) " + - "ORDER BY u.id DESC LIMIT ? OFFSET ?", - new Object[]{ - current_utime, - steamID.account_id, - server_id == null || server_id.isEmpty() ? 0 : 1, - server_id == null || server_id.isEmpty() ? "%" : server_id, - limit, - offset}, - (rs, n) -> new KillsInFeed(rs).setNicknames(nicknameService)); - - Long count = jdbcTemplate.query("SELECT COUNT(*) as c " + - "FROM user_killfeed " + - "WHERE utime > ? AND attacker_id = ? AND attacker_id != victim_id AND (? =0 or server_id like ?)", - new Object[]{ - current_utime, - steamID.account_id, - server_id == null || server_id.isEmpty() ? 0 : 1, - server_id==null||server_id.isEmpty()?"%":server_id }, - (rs, n) -> rs.getLong("c")) - .stream().findFirst().orElse(0L); - - return Map.of("result", result, "count", count, "type", FeedType.KILL.ordinal()); + public Long getKills(SteamID steamID, String server_id, Long utime) { + return killfeedRepository.getKills(steamID.account_id, server_id, utime); } - public Map getDeads(SteamID steamID, String server_id, int offset, int limit, boolean current) { - long current_utime = 0L; - if (current) { - Long currentPlayerSesTime = statsService.searchCurrentPlayerStartTime(steamID); - if (currentPlayerSesTime != null) current_utime = Instant.now().getEpochSecond() - currentPlayerSesTime; - else current_utime = Instant.now().getEpochSecond(); - } - - List result = jdbcTemplate.query("SELECT u.attacker_id, -1, u.assister_id, u.utime, i.name, u.server_id, u.weapon_classname " + - "FROM user_killfeed as u " + - "INNER JOIN tf2idb.tf2idb_item as i ON u.weapon_index = i.id " + - "WHERE u.utime > ? AND u.victim_id = ? AND u.attacker_id != u.victim_id AND (? =0 or u.server_id like ?) " + - "ORDER BY u.id DESC LIMIT ? OFFSET ?", - new Object[]{ - current_utime, - steamID.account_id, - server_id == null || server_id.isEmpty() ? 0 : 1, - server_id == null || server_id.isEmpty() ? "%" : server_id, - limit, - offset}, - (rs, n) -> new KillsInFeed(rs).setNicknames(nicknameService)); - - Long count = jdbcTemplate.query("SELECT COUNT(*) as c " + - "FROM user_killfeed " + - "WHERE utime > ? AND victim_id = ? AND attacker_id != victim_id AND (? =0 or server_id like ?)", - new Object[]{ - current_utime, - steamID.account_id, - server_id == null || server_id.isEmpty() ? 0 : 1, - server_id==null||server_id.isEmpty()?"%":server_id }, - (rs, n) -> rs.getLong("c")).stream().findFirst().orElse(0L); + public Long getDeads(SteamID steamID, String server_id, Long utime) { + return killfeedRepository.getDeads(steamID.account_id, server_id, utime); + } - return Map.of("result", result, "count", count, "type", FeedType.DEAD.ordinal()); + public Long getSuicides(SteamID steamID, String server_id, Long utime) { + return killfeedRepository.getSuicides(steamID.account_id, server_id, utime); } - public Map getAssists(SteamID steamID, String server_id, int offset, int limit, boolean current) { - long current_utime = 0L; - if (current) { - Long currentPlayerSesTime = statsService.searchCurrentPlayerStartTime(steamID); - if (currentPlayerSesTime != null) current_utime = Instant.now().getEpochSecond() - currentPlayerSesTime; - else current_utime = Instant.now().getEpochSecond(); - } + public Long getAssists(SteamID steamID, String server_id, Long utime) { + return killfeedRepository.getAssists(steamID.account_id, server_id, utime); + } - List result = jdbcTemplate.query("SELECT u.attacker_id, u.victim_id, -1, u.utime, i.name, u.server_id, u.weapon_classname " + - "FROM user_killfeed as u " + - "INNER JOIN tf2idb.tf2idb_item as i ON u.weapon_index = i.id " + - "WHERE u.utime > ? AND u.assister_id = ? AND (? =0 or u.server_id like ?) " + - "ORDER BY u.id DESC LIMIT ? OFFSET ?", - new Object[]{ - current_utime, - steamID.account_id, - server_id == null || server_id.isEmpty() ? 0 : 1, - server_id == null || server_id.isEmpty() ? "%" : server_id, - limit, - offset}, - (rs, n) -> new KillsInFeed(rs).setNicknames(nicknameService)); + public Page getKills(Pageable pageable, List accounts, String server_id, boolean current) { + Page result = killfeedRepository.getKills( + pageable, + accounts.stream() + .filter(Objects::nonNull) + .map(s -> s.account_id).toList(), + server_id, current ? Instant.now().getEpochSecond() : null); + result.getContent().forEach(k -> { + k.setAssister_name(accountId2Nickname.apply(k.getAssister_id())); + k.setVictim_name(accountId2Nickname.apply(k.getVictim_id())); + k.setAttacker_name(accountId2Nickname.apply(k.getAttacker_id())); + }); + return result; + } - Long count = jdbcTemplate.query("SELECT COUNT(*) as c " + - "FROM user_killfeed " + - "WHERE utime > ? AND assister_id = ? AND (? =0 or server_id like ?)", - new Object[]{ - current_utime, - steamID.account_id, - server_id == null || server_id.isEmpty() ? 0 : 1, - server_id==null||server_id.isEmpty()?"%":server_id }, - (rs, n) -> rs.getLong("c")) - .stream().findFirst().orElse(0L); + public Page getDeads(Pageable pageable, List accounts, String server_id, boolean current) { + Page result = killfeedRepository.getDeads( + pageable, + accounts.stream() + .filter(Objects::nonNull) + .map(s -> s.account_id).toList(), + server_id, current ? Instant.now().getEpochSecond() : null); + result.getContent().forEach(k -> { + k.setAssister_name(accountId2Nickname.apply(k.getAssister_id())); + k.setVictim_name(accountId2Nickname.apply(k.getVictim_id())); + k.setAttacker_name(accountId2Nickname.apply(k.getAttacker_id())); + }); + return result; + } - return Map.of("result", result, "count", count, "type", FeedType.ASSIST.ordinal()); + public Page getAssists(Pageable pageable, List accounts, String server_id, boolean current) { + Page result = killfeedRepository.getAssists( + pageable, + accounts.stream() + .filter(Objects::nonNull) + .map(s -> s.account_id).toList(), + server_id, current ? Instant.now().getEpochSecond() : null); + result.getContent().forEach(k -> { + k.setAssister_name(accountId2Nickname.apply(k.getAssister_id())); + k.setVictim_name(accountId2Nickname.apply(k.getVictim_id())); + k.setAttacker_name(accountId2Nickname.apply(k.getAttacker_id())); + }); + return result; } @Data @@ -257,95 +180,25 @@ public class KillfeedService { } } - enum FeedType { - KILL, DEAD, ASSIST - } - @Data class TopInFeed { - int uid; + Long uid; String name; long count; String server_id; TopInFeed(Object obj) { - this.uid = (int) ((Object[]) obj) [0]; + this.uid = (long) ((Object[]) obj) [0]; this.count = (long) ((Object[]) obj) [1]; this.server_id = (String) ((Object[]) obj) [2]; } //attacker_id, count(*) as c, server_id TopInFeed(ResultSet resultSet) throws SQLException { - uid = resultSet.getInt(1); + uid = resultSet.getLong(1); count = resultSet.getLong("c"); server_id = resultSet.getString("server_id"); } - - public TopInFeed setNicknames(NicknameService nicknameService) { - this.name = uid <= 0 || server_id.isEmpty() || server_id == null ?"":nicknameService.grabNickname(uid); - return this; - } } - /* - CREATE TABLE user_killfeed ( - id bigint(11) NOT NULL, - attacker_id int(11) NOT NULL, - victim_id int(11) NOT NULL, - assister_id int(11) NOT NULL, - utime bigint(20) NOT NULL, - weapon_name varchar(128) NOT NULL, - weapon_id int(11) NOT NULL, - weapon_classname varchar(128) NOT NULL, - weapon_index int(11) NOT NULL, - custom_kill int(11) NOT NULL, - crit_type int(11) NOT NULL, - server_id varchar(32) NOT NULL - ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - */ - @Data - class KillsInFeed { - int attacker_id; - String attacker_name; - int victim_id; - String victim_name; - int assister_id; - String assister_name; - long utime; - private String weapon_name; - private String weapon_classname; - String server_id; - KillsInFeed(Object obj) { - this.attacker_id = (int) ((Object[]) obj)[0]; - this.victim_id = (int) ((Object[]) obj)[1]; - this.assister_id = (int) ((Object[]) obj)[2]; - this.utime = (long) ((Object[]) obj)[3]; - this.weapon_name = (String) ((Object[]) obj)[4]; - this.server_id = (String) ((Object[]) obj)[5]; - this.weapon_classname = (String) ((Object[]) obj)[6]; - } - - KillsInFeed(ResultSet rs) throws SQLException { - assister_id = rs.getInt(1); - victim_id = rs.getInt(2); - assister_id = rs.getInt(3); - utime = rs.getLong(4); - weapon_name = rs.getString(5); - server_id = rs.getString(6); - weapon_classname = rs.getString(7); - } - - public KillsInFeed setNicknames(NicknameService nicknameService) { - this.attacker_name = attacker_id == -1 || server_id.isEmpty() || server_id == null?"":nicknameService.grabNickname(attacker_id); - this.victim_name = victim_id == -1 || server_id.isEmpty() || server_id == null?"":nicknameService.grabNickname(victim_id); - this.assister_name = assister_id == -1 || server_id.isEmpty() || server_id == null?"":nicknameService.grabNickname(assister_id); - return this; - } - public String getWeapon_name(){ - //obj_sentrygun - if (this.weapon_classname.contains("obj_sentrygun")) - return "Турель " + (this.weapon_classname.replace("obj_sentrygun", "").isEmpty()?"1":this.weapon_classname.replace("obj_sentrygun", "")) + " уровня"; - return this.weapon_name; - } - } } diff --git a/src/main/java/app/services/db/MessageService.java b/src/main/java/app/services/db/MessageService.java index 7087470..9662777 100644 --- a/src/main/java/app/services/db/MessageService.java +++ b/src/main/java/app/services/db/MessageService.java @@ -19,15 +19,6 @@ public class MessageService { @Qualifier("jt_ro") private JdbcTemplate jdbcTemplate; - private Stats stats; - - private NicknameService nicknameService; - - MessageService(Stats stats, NicknameService nicknameService) { - this.stats = stats; - this.nicknameService = nicknameService; - } - public Map getAllMessages(String server_id, String filter, long offset, int limit) { List result = jdbcTemplate.query("SELECT account_id,utime,message,server_id " + "FROM user_messages " + diff --git a/src/main/java/app/services/db/NicknameService.java b/src/main/java/app/services/db/NicknameService.java deleted file mode 100644 index f127134..0000000 --- a/src/main/java/app/services/db/NicknameService.java +++ /dev/null @@ -1,53 +0,0 @@ -package app.services.db; - -import app.entities.Stats; -import org.apache.commons.math3.util.Pair; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.core.RowMapper; -import org.springframework.stereotype.Service; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.time.Instant; -import java.util.HashMap; -import java.util.Optional; - -@Service -public class NicknameService { - - @Autowired - @Qualifier("jt_ro") - private JdbcTemplate jdbcTemplate; - private Stats stats; - private HashMap> nickname_cache = new HashMap<>(); - private long refresh_after = 900; - - NicknameService(Stats stats) { - this.stats = stats; - } - - public String grabNickname(int account_id) { - if (nickname_cache.containsKey(account_id)) { - if (Instant.now().getEpochSecond() - nickname_cache.get(account_id).getValue() < refresh_after) { - return nickname_cache.get(account_id).getKey(); - } - } - String nickname = grabNicknameFromDb(account_id); - nickname_cache.put(account_id, Pair.create(nickname, Instant.now().getEpochSecond())); - return nickname; - } - - private String grabNicknameFromDb(int account_id) { - try { - return jdbcTemplate.query("SELECT player_name FROM user_connections WHERE account_id = ? ORDER BY user_connections.id DESC LIMIT 1;", - new Object[]{account_id}, - (rs, n) -> rs.getString("player_name")) - .stream().findFirst().orElse("Unknown"); - } catch (Exception e) { - e.printStackTrace(); - return "Unknown"; - } - } -}