178 lines
5.8 KiB
Java
178 lines
5.8 KiB
Java
package com.tailbet.service.impl;
|
|
|
|
import com.tailbet.model.entity.User;
|
|
import com.tailbet.model.entity.GameRound;
|
|
import com.tailbet.mapper.UserMapper;
|
|
import com.tailbet.mapper.GameRoundMapper;
|
|
import com.tailbet.service.IFakeUserService;
|
|
import com.tailbet.service.IBetService;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
import lombok.RequiredArgsConstructor;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
|
import org.springframework.scheduling.annotation.Scheduled;
|
|
import org.springframework.stereotype.Service;
|
|
|
|
import java.util.*;
|
|
|
|
/**
|
|
* 假人服务实现
|
|
*/
|
|
@Slf4j
|
|
@RequiredArgsConstructor
|
|
@Service
|
|
public class FakeUserServiceImpl implements IFakeUserService {
|
|
|
|
private final UserMapper userMapper;
|
|
private final GameRoundMapper gameRoundMapper;
|
|
private final IBetService betService;
|
|
private final StringRedisTemplate redisTemplate;
|
|
|
|
private static final String FAKE_ACTIVE_KEY = "fake:active:";
|
|
private static final Random RANDOM = new Random();
|
|
|
|
// 假人昵称素材
|
|
private static final String[] NICKNAME_PREFIXES = {"小", "老", "阿", "超", "酷"};
|
|
private static final String[] NICKNAME_SUFFIXES = {"哥", "弟", "姐", "妹", "宝"};
|
|
|
|
/**
|
|
* 初始化群假人
|
|
*/
|
|
@Override
|
|
public void initGroupFakeUsers(Long groupId, int minCount, int maxCount) {
|
|
int count = minCount + RANDOM.nextInt(maxCount - minCount + 1);
|
|
log.info("为群{}初始化{}个假人", groupId, count);
|
|
|
|
for (int i = 0; i < count; i++) {
|
|
createFakeUser(groupId);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 创建单个假人
|
|
*/
|
|
@Override
|
|
public User createFakeUser(Long groupId) {
|
|
User fake = new User();
|
|
fake.setUsername("fake_" + UUID.randomUUID().toString().replace("-", "").substring(0, 12));
|
|
fake.setNickname(generateNickname());
|
|
fake.setPoints((long) (1000 + RANDOM.nextInt(49000)));
|
|
fake.setIsFake(1);
|
|
fake.setIsBot(0);
|
|
fake.setIsOps(0);
|
|
fake.setIsWhite(0);
|
|
fake.setStatus(1);
|
|
userMapper.insert(fake);
|
|
return fake;
|
|
}
|
|
|
|
/**
|
|
* 生成随机昵称
|
|
*/
|
|
private String generateNickname() {
|
|
String prefix = NICKNAME_PREFIXES[RANDOM.nextInt(NICKNAME_PREFIXES.length)];
|
|
String suffix = NICKNAME_SUFFIXES[RANDOM.nextInt(NICKNAME_SUFFIXES.length)];
|
|
int number = RANDOM.nextInt(1000);
|
|
return prefix + suffix + number;
|
|
}
|
|
|
|
/**
|
|
* 每日重置活跃假人
|
|
*/
|
|
@Override
|
|
@Scheduled(cron = "0 0 0 * * ?")
|
|
public void resetDailyActiveFakes() {
|
|
// 清理昨天的活跃标记
|
|
Set<String> keys = redisTemplate.opsForSet().members(FAKE_ACTIVE_KEY + "yesterday");
|
|
if (keys != null) {
|
|
for (String userId : keys) {
|
|
redisTemplate.opsForSet().remove(FAKE_ACTIVE_KEY + "yesterday", userId);
|
|
}
|
|
}
|
|
|
|
// 查询所有假人
|
|
List<User> fakes = userMapper.selectList(new LambdaQueryWrapper<User>()
|
|
.eq(User::getIsFake, 1)
|
|
.eq(User::getStatus, 1));
|
|
|
|
if (fakes.isEmpty()) {
|
|
return;
|
|
}
|
|
|
|
// 随机选15-20个作为今日活跃
|
|
int activeCount = 15 + RANDOM.nextInt(6);
|
|
activeCount = Math.min(activeCount, fakes.size());
|
|
|
|
Collections.shuffle(fakes);
|
|
List<String> activeUserIds = new ArrayList<>();
|
|
for (int i = 0; i < activeCount; i++) {
|
|
activeUserIds.add(String.valueOf(fakes.get(i).getId()));
|
|
}
|
|
|
|
// 存入Redis
|
|
String today = java.time.LocalDate.now().toString();
|
|
redisTemplate.opsForSet().add(FAKE_ACTIVE_KEY + today, activeUserIds.toArray(new String[0]));
|
|
|
|
log.info("今日活跃假人已更新: {}个", activeCount);
|
|
}
|
|
|
|
/**
|
|
* 检查用户是否是今日活跃假人
|
|
*/
|
|
@Override
|
|
public boolean isTodayActiveFake(Long userId) {
|
|
String today = java.time.LocalDate.now().toString();
|
|
Boolean isMember = redisTemplate.opsForSet().isMember(FAKE_ACTIVE_KEY + today, String.valueOf(userId));
|
|
return Boolean.TRUE.equals(isMember);
|
|
}
|
|
|
|
/**
|
|
* 假人下注
|
|
*/
|
|
@Override
|
|
public void fakeBet(Long groupId) {
|
|
// 获取今日活跃假人
|
|
String today = java.time.LocalDate.now().toString();
|
|
Set<String> activeFakes = redisTemplate.opsForSet().members(FAKE_ACTIVE_KEY + today);
|
|
if (activeFakes == null || activeFakes.isEmpty()) {
|
|
return;
|
|
}
|
|
|
|
// 随机选一个假人
|
|
List<String> fakeList = new ArrayList<>(activeFakes);
|
|
String fakeIdStr = fakeList.get(RANDOM.nextInt(fakeList.size()));
|
|
Long fakeId = Long.parseLong(fakeIdStr);
|
|
|
|
// 检查是否有下注中的局
|
|
GameRound round = gameRoundMapper.selectOne(new LambdaQueryWrapper<GameRound>()
|
|
.eq(GameRound::getGroupId, groupId)
|
|
.eq(GameRound::getStatus, com.tailbet.service.IGameService.STATUS_BETTING));
|
|
|
|
if (round == null) {
|
|
return;
|
|
}
|
|
|
|
// 随机玩法和金额
|
|
String[] playTypes = {"单", "双", "大", "小"};
|
|
String playType = playTypes[RANDOM.nextInt(playTypes.length)];
|
|
int amount = (1 + RANDOM.nextInt(10)) * 10; // 10,20,30...100
|
|
|
|
try {
|
|
betService.placeBet(fakeId, groupId, "fake_" + UUID.randomUUID(), playType, amount);
|
|
log.debug("假人{}下注: {} {}", fakeId, playType, amount);
|
|
} catch (Exception e) {
|
|
log.debug("假人下注失败: {}", e.getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取假人列表
|
|
*/
|
|
@Override
|
|
public List<User> getFakeUsers() {
|
|
return userMapper.selectList(new LambdaQueryWrapper<User>()
|
|
.eq(User::getIsFake, 1)
|
|
.eq(User::getStatus, 1));
|
|
}
|
|
}
|