新增记录用户游玩记录接口
This commit is contained in:
parent
020fc3e543
commit
4f53c6a9e8
@ -1,5 +1,6 @@
|
||||
package com.red.circle.other.adapter.app.game;
|
||||
|
||||
import com.red.circle.common.business.dto.cmd.AppExtCommand;
|
||||
import com.red.circle.common.business.dto.cmd.app.AppIdLongCmd;
|
||||
import com.red.circle.common.business.dto.cmd.app.AppRoomIdCmd;
|
||||
import com.red.circle.other.app.convertor.user.UserProfileAppConvertor;
|
||||
@ -8,7 +9,10 @@ import com.red.circle.other.app.dto.cmd.game.GameLudoCreateCmd;
|
||||
import com.red.circle.other.app.dto.cmd.game.GameLudoEndCmd;
|
||||
import com.red.circle.other.app.dto.cmd.game.GameLudoJoinCmd;
|
||||
import com.red.circle.other.app.dto.cmd.game.GameLudoStartCmd;
|
||||
import com.red.circle.other.app.dto.clientobject.game.GamePlayHistoryCO;
|
||||
import com.red.circle.other.app.dto.cmd.game.GamePlayHistoryRecordCmd;
|
||||
import com.red.circle.other.app.service.game.GameLudoService;
|
||||
import com.red.circle.other.app.service.game.GamePlayHistoryService;
|
||||
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
|
||||
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
|
||||
import java.util.Arrays;
|
||||
@ -39,6 +43,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
public class GameLudoAppRestController {
|
||||
|
||||
private final GameLudoService gameLudoService;
|
||||
private final GamePlayHistoryService gamePlayHistoryService;
|
||||
private final UserProfileGateway userProfileGateway;
|
||||
private final UserProfileAppConvertor userProfileAppConvertor;
|
||||
|
||||
@ -161,7 +166,32 @@ public class GameLudoAppRestController {
|
||||
return userProfileAppConvertor.toUserProfileDTO(
|
||||
userProfileGateway.getByUserId(userId)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录游玩历史.
|
||||
*
|
||||
* @eo.name 记录游玩历史
|
||||
* @eo.url /history/record
|
||||
* @eo.method post
|
||||
* @eo.request-type json
|
||||
*/
|
||||
@PostMapping("/history/record")
|
||||
public void recordHistory(@RequestBody @Validated GamePlayHistoryRecordCmd cmd) {
|
||||
gamePlayHistoryService.record(cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询最近游玩历史(最多5条).
|
||||
*
|
||||
* @eo.name 查询最近游玩历史
|
||||
* @eo.url /history/recent
|
||||
* @eo.method get
|
||||
* @eo.request-type formdata
|
||||
*/
|
||||
@GetMapping("/history/recent")
|
||||
public List<GamePlayHistoryCO> listRecentHistory(@Validated AppExtCommand cmd) {
|
||||
return gamePlayHistoryService.listRecent(cmd.requireReqSysOrigin(), cmd.requiredReqUserId());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,46 @@
|
||||
package com.red.circle.other.app.command.game;
|
||||
|
||||
import com.red.circle.other.app.dto.clientobject.game.GamePlayHistoryCO;
|
||||
import com.red.circle.other.infra.database.mongo.entity.game.UserGamePlayHistory;
|
||||
import com.red.circle.other.infra.database.mongo.service.game.UserGamePlayHistoryService;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 查询用户游玩历史.
|
||||
*
|
||||
* @author tf
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class GamePlayHistoryQryExe {
|
||||
|
||||
private static final int RECENT_LIMIT = 5;
|
||||
|
||||
private final UserGamePlayHistoryService userGamePlayHistoryService;
|
||||
|
||||
public List<GamePlayHistoryCO> execute(String sysOrigin, Long userId) {
|
||||
List<UserGamePlayHistory> historyList =
|
||||
userGamePlayHistoryService.listRecent(sysOrigin, userId, RECENT_LIMIT);
|
||||
|
||||
return historyList.stream()
|
||||
.filter(h -> Objects.nonNull(h.getGameInfo()))
|
||||
.map(this::toCO)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private GamePlayHistoryCO toCO(UserGamePlayHistory history) {
|
||||
UserGamePlayHistory.GameInfo info = history.getGameInfo();
|
||||
GamePlayHistoryCO co = new GamePlayHistoryCO();
|
||||
co.setId(info.getId());
|
||||
co.setGameId(info.getGameId());
|
||||
co.setName(info.getName());
|
||||
co.setCover(info.getCover());
|
||||
co.setGameCode(info.getGameCode());
|
||||
co.setPlayTime(history.getPlayTime());
|
||||
return co;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
package com.red.circle.other.app.command.game;
|
||||
|
||||
import com.red.circle.framework.core.asserts.ResponseAssert;
|
||||
import com.red.circle.other.app.dto.cmd.game.GamePlayHistoryRecordCmd;
|
||||
import com.red.circle.other.infra.database.mongo.entity.game.UserGamePlayHistory;
|
||||
import com.red.circle.other.infra.database.mongo.entity.game.UserGamePlayHistory.GameInfo;
|
||||
import com.red.circle.other.infra.database.mongo.service.game.UserGamePlayHistoryService;
|
||||
import com.red.circle.other.infra.database.rds.entity.sys.GameListConfig;
|
||||
import com.red.circle.other.infra.database.rds.service.sys.GameListConfigService;
|
||||
import com.red.circle.other.inner.asserts.GameErrorCode;
|
||||
import com.red.circle.tool.core.date.TimestampUtils;
|
||||
import java.util.Objects;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 记录用户游玩历史.
|
||||
*
|
||||
* @author tf
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class GamePlayHistoryRecordCmdExe {
|
||||
|
||||
private final GameListConfigService gameListConfigService;
|
||||
private final UserGamePlayHistoryService userGamePlayHistoryService;
|
||||
|
||||
public void execute(GamePlayHistoryRecordCmd cmd) {
|
||||
GameListConfig config = gameListConfigService.getById(cmd.getGameListConfigId());
|
||||
ResponseAssert.notNull(GameErrorCode.GAME_NOT_EXIST, config);
|
||||
|
||||
GameInfo gameInfo = new GameInfo();
|
||||
gameInfo.setId(config.getId());
|
||||
gameInfo.setGameId(config.getGameId());
|
||||
gameInfo.setName(config.getName());
|
||||
gameInfo.setCover(config.getCover());
|
||||
gameInfo.setGameCode(config.getGameCode());
|
||||
|
||||
UserGamePlayHistory history = new UserGamePlayHistory();
|
||||
history.setSysOrigin(cmd.getReqSysOrigin().getOrigin());
|
||||
history.setUserId(cmd.requiredReqUserId());
|
||||
history.setGameListConfigId(cmd.getGameListConfigId());
|
||||
history.setGameInfo(gameInfo);
|
||||
history.setPlayTime(TimestampUtils.now());
|
||||
history.setExpiredTime(TimestampUtils.nowPlusDays(90));
|
||||
|
||||
userGamePlayHistoryService.record(history);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
package com.red.circle.other.app.service.game;
|
||||
|
||||
import com.red.circle.other.app.command.game.GamePlayHistoryQryExe;
|
||||
import com.red.circle.other.app.command.game.GamePlayHistoryRecordCmdExe;
|
||||
import com.red.circle.other.app.dto.clientobject.game.GamePlayHistoryCO;
|
||||
import com.red.circle.other.app.dto.cmd.game.GamePlayHistoryRecordCmd;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author tf
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class GamePlayHistoryServiceImpl implements GamePlayHistoryService {
|
||||
|
||||
private final GamePlayHistoryRecordCmdExe gamePlayHistoryRecordCmdExe;
|
||||
private final GamePlayHistoryQryExe gamePlayHistoryQryExe;
|
||||
|
||||
@Override
|
||||
public void record(GamePlayHistoryRecordCmd cmd) {
|
||||
gamePlayHistoryRecordCmdExe.execute(cmd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GamePlayHistoryCO> listRecent(String sysOrigin, Long userId) {
|
||||
return gamePlayHistoryQryExe.execute(sysOrigin, userId);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package com.red.circle.other.app.dto.clientobject.game;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import java.sql.Timestamp;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 用户游戏游玩历史.
|
||||
*
|
||||
* @author tf
|
||||
*/
|
||||
@Data
|
||||
public class GamePlayHistoryCO {
|
||||
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long id;
|
||||
|
||||
private String gameId;
|
||||
|
||||
private String name;
|
||||
|
||||
private String cover;
|
||||
|
||||
private String gameCode;
|
||||
|
||||
private Timestamp playTime;
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package com.red.circle.other.app.dto.cmd.game;
|
||||
|
||||
import com.red.circle.common.business.dto.cmd.AppExtCommand;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 记录用户游玩游戏.
|
||||
*
|
||||
* @author tf
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class GamePlayHistoryRecordCmd extends AppExtCommand {
|
||||
|
||||
/** GameListConfig 主键 */
|
||||
@NotNull(message = "gameListConfigId required.")
|
||||
private Long gameListConfigId;
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package com.red.circle.other.app.service.game;
|
||||
|
||||
import com.red.circle.other.app.dto.clientobject.game.GamePlayHistoryCO;
|
||||
import com.red.circle.other.app.dto.cmd.game.GamePlayHistoryRecordCmd;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 游戏游玩历史服务.
|
||||
*
|
||||
* @author tf
|
||||
*/
|
||||
public interface GamePlayHistoryService {
|
||||
|
||||
void record(GamePlayHistoryRecordCmd cmd);
|
||||
|
||||
List<GamePlayHistoryCO> listRecent(String sysOrigin, Long userId);
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
package com.red.circle.other.infra.database.mongo.entity.game;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.sql.Timestamp;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.mongodb.core.index.CompoundIndex;
|
||||
import org.springframework.data.mongodb.core.index.CompoundIndexes;
|
||||
import org.springframework.data.mongodb.core.index.Indexed;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
|
||||
/**
|
||||
* 用户游戏游玩历史.
|
||||
*
|
||||
* @author tf
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Document("user_game_play_history")
|
||||
@CompoundIndexes({
|
||||
@CompoundIndex(name = "idx_user_play_time", def = "{'userId': 1, 'playTime': -1}"),
|
||||
@CompoundIndex(name = "idx_user_game", def = "{'userId': 1, 'gameListConfigId': 1}", unique = true)
|
||||
})
|
||||
public class UserGamePlayHistory implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Id
|
||||
private String id;
|
||||
|
||||
private String sysOrigin;
|
||||
|
||||
private Long userId;
|
||||
|
||||
/** GameListConfig 主键 */
|
||||
private Long gameListConfigId;
|
||||
|
||||
/** 游戏信息快照 */
|
||||
private GameInfo gameInfo;
|
||||
|
||||
/** 最近游玩时间 */
|
||||
@Indexed
|
||||
private Timestamp playTime;
|
||||
|
||||
/** 过期时间,90天TTL自动清理 */
|
||||
@Indexed(expireAfterSeconds = 0)
|
||||
private Timestamp expiredTime;
|
||||
|
||||
@Data
|
||||
public static class GameInfo {
|
||||
private Long id;
|
||||
private String gameId;
|
||||
private String name;
|
||||
private String cover;
|
||||
private String gameCode;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
package com.red.circle.other.infra.database.mongo.service.game;
|
||||
|
||||
import com.red.circle.other.infra.database.mongo.entity.game.UserGamePlayHistory;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户游戏游玩历史服务.
|
||||
*
|
||||
* @author tf
|
||||
*/
|
||||
public interface UserGamePlayHistoryService {
|
||||
|
||||
/**
|
||||
* 记录游玩(同一用户同一游戏 upsert,仅更新 playTime 和快照).
|
||||
*/
|
||||
void record(UserGamePlayHistory history);
|
||||
|
||||
/**
|
||||
* 查询用户最近游玩的游戏,按 playTime 倒序,最多 limit 条.
|
||||
*/
|
||||
List<UserGamePlayHistory> listRecent(String sysOrigin, Long userId, int limit);
|
||||
}
|
||||
@ -0,0 +1,56 @@
|
||||
package com.red.circle.other.infra.database.mongo.service.game.impl;
|
||||
|
||||
import com.red.circle.other.infra.database.mongo.entity.game.UserGamePlayHistory;
|
||||
import com.red.circle.other.infra.database.mongo.service.game.UserGamePlayHistoryService;
|
||||
import com.red.circle.tool.core.date.TimestampUtils;
|
||||
import com.red.circle.tool.core.sequence.IdWorkerUtils;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.core.query.Criteria;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.mongodb.core.query.Update;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author tf
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class UserGamePlayHistoryServiceImpl implements UserGamePlayHistoryService {
|
||||
|
||||
private final MongoTemplate mongoTemplate;
|
||||
|
||||
@Override
|
||||
public void record(UserGamePlayHistory history) {
|
||||
Query query = Query.query(
|
||||
Criteria.where("userId").is(history.getUserId())
|
||||
.and("gameListConfigId").is(history.getGameListConfigId())
|
||||
);
|
||||
|
||||
boolean exists = mongoTemplate.exists(query, UserGamePlayHistory.class);
|
||||
if (exists) {
|
||||
mongoTemplate.updateFirst(query,
|
||||
new Update()
|
||||
.set("gameInfo", history.getGameInfo())
|
||||
.set("playTime", history.getPlayTime())
|
||||
.set("expiredTime", history.getExpiredTime()),
|
||||
UserGamePlayHistory.class);
|
||||
} else {
|
||||
history.setId(String.valueOf(IdWorkerUtils.getId()));
|
||||
history.setPlayTime(TimestampUtils.now());
|
||||
history.setExpiredTime(TimestampUtils.nowPlusDays(90));
|
||||
mongoTemplate.save(history);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserGamePlayHistory> listRecent(String sysOrigin, Long userId, int limit) {
|
||||
return mongoTemplate.find(
|
||||
Query.query(Criteria.where("sysOrigin").is(sysOrigin).and("userId").is(userId))
|
||||
.with(Sort.by(Sort.Order.desc("playTime")))
|
||||
.limit(limit),
|
||||
UserGamePlayHistory.class);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user