Files
xiu_b/src/main/java/com/tailbet/service/impl/FakeUserServiceImpl.java
T
2026-08-09 12:30:23 +08:00

194 lines
6.3 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.math.BigDecimal;
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(BigDecimal.valueOf(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)];
BigDecimal amount = BigDecimal.valueOf((1 + RANDOM.nextInt(10)) * 10L); // 10,20,30...100
try {
betService.placeBet(fakeId, groupId, "fake_" + UUID.randomUUID(), playType, amount);
log.debug("假人{}下注: {} {}", fakeId, playType, amount.toPlainString());
} 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));
}
/**
* 从现有假人中随机挑选指定数量
*/
@Override
public List<User> pickFakeUsers(int count) {
List<User> fakes = getFakeUsers();
if (fakes.isEmpty()) {
return List.of();
}
Collections.shuffle(fakes, RANDOM);
int size = Math.min(count, fakes.size());
return new ArrayList<>(fakes.subList(0, size));
}
}