diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/constant/IeRedisKey.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/constant/IeRedisKey.java
index ae389db0..cd534746 100644
--- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/constant/IeRedisKey.java
+++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/constant/IeRedisKey.java
@@ -16,6 +16,9 @@ public final class IeRedisKey {
/** 鍖归厤姹狅細ZSET, key=ie:match:pool:{mode}:{mood}, member=userId, score=matchScore */
public static final String MATCH_POOL = PREFIX + "match:pool:";
+ /** 鏍″尯鍖归厤姹狅細ZSET, key=ie:match:pool:region:{regionId}:{mode}:{mood}, member=userId */
+ public static final String REGION_MATCH_POOL = PREFIX + "match:pool:region:";
+
/** 鐢ㄦ埛鎵鍦ㄥ尮閰嶆睜绱㈠紩锛歋TRING, key=ie:match:user-pool:{userId}, value=poolKey */
public static final String USER_MATCH_POOL = PREFIX + "match:user-pool:";
@@ -61,4 +64,8 @@ public final class IeRedisKey {
public static String matchPool(String mode, String mood) {
return MATCH_POOL + mode + ":" + mood;
}
+
+ public static String regionMatchPool(String regionId, String mode, String mood) {
+ return REGION_MATCH_POOL + regionId + ":" + mode + ":" + mood;
+ }
}
diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/dto/IeMatchStartDTO.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/dto/IeMatchStartDTO.java
index ba9eab0c..4a72b61e 100644
--- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/dto/IeMatchStartDTO.java
+++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/dto/IeMatchStartDTO.java
@@ -9,8 +9,11 @@ public class IeMatchStartDTO {
private String mode;
private String targetMode;
private String targetGender;
+ private String matchScope;
private String mood;
private Double longitude;
private Double latitude;
+ private String regionId;
+ private String regionName;
private List
interestTags;
}
diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/dto/IeProfileDTO.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/dto/IeProfileDTO.java
index 1c80676e..6faf9297 100644
--- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/dto/IeProfileDTO.java
+++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/dto/IeProfileDTO.java
@@ -16,4 +16,6 @@ public class IeProfileDTO {
private String currentMode;
private String targetModePreference;
private String targetGenderPreference;
+ private String regionId;
+ private String regionName;
}
diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/dto/IeStatusDTO.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/dto/IeStatusDTO.java
index a724a035..99639a04 100644
--- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/dto/IeStatusDTO.java
+++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/dto/IeStatusDTO.java
@@ -11,5 +11,7 @@ public class IeStatusDTO {
private String statusText;
private Double longitude;
private Double latitude;
+ private String regionId;
+ private String regionName;
private List interestTags;
}
diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/entity/IeMatchAttempt.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/entity/IeMatchAttempt.java
index 66672036..e2f55be0 100644
--- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/entity/IeMatchAttempt.java
+++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/entity/IeMatchAttempt.java
@@ -16,6 +16,8 @@ public class IeMatchAttempt extends IeBaseEntity {
private Integer status;
private String anonymousName;
private String avatarText;
+ private String targetRegionId;
+ private String targetRegionName;
private String stateText;
private String quoteText;
private String failReason;
diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/entity/IeUserProfile.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/entity/IeUserProfile.java
index 7d673ab8..4db57db2 100644
--- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/entity/IeUserProfile.java
+++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/entity/IeUserProfile.java
@@ -22,6 +22,8 @@ public class IeUserProfile extends IeBaseEntity {
private String recentPreference;
private String targetModePreference;
private String targetGenderPreference;
+ private String regionId;
+ private String regionName;
private Integer defaultRoomMinutes;
private Integer dailyQuota;
private Integer usedQuota;
diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/entity/IeUserStatus.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/entity/IeUserStatus.java
index f33662ac..d85908a1 100644
--- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/entity/IeUserStatus.java
+++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/entity/IeUserStatus.java
@@ -14,6 +14,8 @@ public class IeUserStatus extends IeBaseEntity {
private String mode;
private String mood;
private String statusText;
+ private String regionId;
+ private String regionName;
private Integer onlineStatus;
private Date lastActiveTime;
}
diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/service/IeRedisService.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/service/IeRedisService.java
index 92406287..29a01f2c 100644
--- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/service/IeRedisService.java
+++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/service/IeRedisService.java
@@ -17,7 +17,7 @@ public interface IeRedisService {
void unlockMatchUser(Long userId);
- List candidates(String mode, String mood, int limit);
+ List candidates(String mode, String mood, String regionId, boolean regionScope, int limit);
boolean isRecentlyMatched(Long userId, Long targetUserId);
@@ -51,7 +51,7 @@ public interface IeRedisService {
long onlineCount();
- long waitingCount(String mode, String mood);
+ long waitingCount(String mode, String mood, String regionId, boolean regionScope);
List hotStatuses(int limit);
}
diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/service/impl/IeMatchServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/service/impl/IeMatchServiceImpl.java
index a4359998..1f33d643 100644
--- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/service/impl/IeMatchServiceImpl.java
+++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/service/impl/IeMatchServiceImpl.java
@@ -62,7 +62,7 @@ public class IeMatchServiceImpl implements IeMatchService {
redisService.refreshOnline(userId);
IeHomeVO vo = new IeHomeVO();
vo.setOnlineCount(redisService.onlineCount());
- vo.setWaitingCount(redisService.waitingCount(profile.getCurrentMode(), "quiet"));
+ vo.setWaitingCount(redisService.waitingCount(profile.getCurrentMode(), "quiet", profile.getRegionId(), hasText(profile.getRegionId())));
vo.setDailyQuota(profile.getDailyQuota());
vo.setUsedQuota((int) redisService.todayUsedQuota(userId));
vo.setUnreadCount(totalUnreadCount(userId));
@@ -139,6 +139,8 @@ public class IeMatchServiceImpl implements IeMatchService {
profile.setRecentPreference(profile.getCurrentMode());
profile.setTargetModePreference(normalizeTargetMode(dto.getTargetModePreference()));
profile.setTargetGenderPreference(normalizeTargetGender(dto.getTargetGenderPreference()));
+ profile.setRegionId(defaultText(dto.getRegionId(), profile.getRegionId()));
+ profile.setRegionName(defaultText(dto.getRegionName(), profile.getRegionName()));
profile.setProfileCompleted(1);
profile.setLastActiveTime(new Date());
profile.setUpdateTime(new Date());
@@ -147,6 +149,8 @@ public class IeMatchServiceImpl implements IeMatchService {
statusDTO.setMode(profile.getCurrentMode());
statusDTO.setMood("quiet");
statusDTO.setStatusText(defaultText(profile.getIntro(), profile.getCurrentMode()));
+ statusDTO.setRegionId(profile.getRegionId());
+ statusDTO.setRegionName(profile.getRegionName());
statusDTO.setInterestTags(jsonToTags(profile.getInterestTags()));
updateStatus(userId, statusDTO);
return toProfileVO(profile);
@@ -163,7 +167,9 @@ public class IeMatchServiceImpl implements IeMatchService {
if (dto.getMood() == null) {
dto.setMood("quiet");
}
- ensureProfile(userId);
+ IeUserProfile profile = ensureProfile(userId);
+ dto.setRegionId(defaultText(dto.getRegionId(), profile.getRegionId()));
+ dto.setRegionName(defaultText(dto.getRegionName(), profile.getRegionName()));
IeUserStatus status = userStatusMapper.selectOne(new LambdaQueryWrapper()
.eq(IeUserStatus::getUserId, userId)
.last("limit 1"));
@@ -176,6 +182,8 @@ public class IeMatchServiceImpl implements IeMatchService {
status.setMode(dto.getMode());
status.setMood(dto.getMood());
status.setStatusText(dto.getStatusText());
+ status.setRegionId(dto.getRegionId());
+ status.setRegionName(dto.getRegionName());
status.setOnlineStatus(1);
status.setLastActiveTime(now);
status.setUpdateTime(now);
@@ -205,14 +213,23 @@ public class IeMatchServiceImpl implements IeMatchService {
}
IeStatusDTO statusDTO = new IeStatusDTO();
BeanUtils.copyProperties(dto == null ? new IeMatchStartDTO() : dto, statusDTO);
- updateStatus(userId, statusDTO);
String mode = normalizeMode(statusDTO.getMode(), profile.getCurrentMode());
String targetMode = normalizeTargetMode(dto == null ? null : dto.getTargetMode());
String requestedTargetGender = dto == null || dto.getTargetGender() == null ? profile.getTargetGenderPreference() : dto.getTargetGender();
String targetGender = normalizeTargetGender(requestedTargetGender);
+ String matchScope = normalizeMatchScope(dto == null ? null : dto.getMatchScope());
+ String regionId = defaultText(dto == null ? null : dto.getRegionId(), profile.getRegionId());
+ String regionName = defaultText(dto == null ? null : dto.getRegionName(), profile.getRegionName());
+ boolean regionScope = "school".equals(matchScope);
+ if (regionScope && !hasText(regionId)) {
+ return fail(userId, dto, "璇峰厛閫夋嫨鏍″尯鍚庡啀鍖归厤鏈牎鍖虹敤鎴");
+ }
+ statusDTO.setRegionId(regionId);
+ statusDTO.setRegionName(regionName);
+ updateStatus(userId, statusDTO);
String mood = statusDTO.getMood() == null ? "quiet" : statusDTO.getMood();
- List candidates = candidateUsers(targetMode, mode, mood);
+ List candidates = candidateUsers(targetMode, mode, mood, regionId, regionScope);
List matchedCandidates = new ArrayList<>();
for (Long candidateUserId : candidates) {
if (candidateUserId == null || candidateUserId.equals(userId)) {
@@ -225,7 +242,7 @@ public class IeMatchServiceImpl implements IeMatchService {
continue;
}
IeUserProfile candidateProfile = findProfileByUserId(candidateUserId);
- if (!matchCandidate(candidateProfile, targetMode, targetGender)) {
+ if (!matchCandidate(candidateProfile, targetMode, targetGender, regionId, regionScope)) {
continue;
}
matchedCandidates.add(new MatchCandidate(candidateUserId, matchScore(statusDTO, profile, candidateProfile)));
@@ -256,6 +273,8 @@ public class IeMatchServiceImpl implements IeMatchService {
match.setStatus(3);
match.setAnonymousName(defaultText(targetProfile.getAnonymousName(), "鍗婂尶鍚嶆紓娴佽"));
match.setAvatarText(defaultText(targetProfile.getAvatarText(), "鈼"));
+ match.setTargetRegionId(targetProfile.getRegionId());
+ match.setTargetRegionName(targetProfile.getRegionName());
match.setStateText(targetProfile.getCurrentMode() == null || "i".equals(targetProfile.getCurrentMode()) ? "鍋忓畨闈欙紝閫傚悎鎱㈡參闈犺繎" : "鍋忚交鏉撅紝鎰挎剰鍏堝紑鍦");
match.setQuoteText(defaultText(targetProfile.getIntro(), "鍙互鍏堝畨闈欏緟涓浼氾紝涓嶇敤鎬ョ潃鎵捐瘽棰樸"));
match.setCreateTime(new Date());
@@ -274,6 +293,8 @@ public class IeMatchServiceImpl implements IeMatchService {
vo.setRoomNo(room.getRoomNo());
vo.setAvatarUrl(targetProfile.getAvatarUrl());
vo.setGender(targetProfile.getGender());
+ vo.setRegionId(targetProfile.getRegionId());
+ vo.setRegionName(targetProfile.getRegionName());
vo.setIntro(targetProfile.getIntro());
vo.setInterestTags(jsonToTags(targetProfile.getInterestTags()));
vo.setPersonaImages(jsonToTags(targetProfile.getPersonaImages()));
@@ -349,6 +370,8 @@ public class IeMatchServiceImpl implements IeMatchService {
vo.setAnonymousName(defaultText(profile.getAnonymousName(), vo.getAnonymousName()));
vo.setAvatarText(defaultText(profile.getAvatarText(), vo.getAvatarText()));
vo.setAvatarUrl(profile.getAvatarUrl());
+ vo.setRegionId(defaultText(profile.getRegionId(), vo.getRegionId()));
+ vo.setRegionName(defaultText(profile.getRegionName(), vo.getRegionName()));
vo.setMode(defaultText(profile.getCurrentMode(), vo.getMode()));
vo.setQuoteText(defaultText(profile.getIntro(), vo.getQuoteText()));
}
@@ -419,6 +442,8 @@ public class IeMatchServiceImpl implements IeMatchService {
vo.setTargetUserId(match.getTargetUserId());
vo.setAnonymousName(match.getAnonymousName());
vo.setAvatarText(match.getAvatarText());
+ vo.setRegionId(match.getTargetRegionId());
+ vo.setRegionName(match.getTargetRegionName());
vo.setMode(match.getMode());
vo.setMood(match.getMood());
vo.setStateText(match.getStateText());
@@ -469,22 +494,22 @@ public class IeMatchServiceImpl implements IeMatchService {
.last("limit 1"));
}
- private List candidateUsers(String targetMode, String selfMode, String mood) {
+ private List candidateUsers(String targetMode, String selfMode, String mood, String regionId, boolean regionScope) {
LinkedHashSet set = new LinkedHashSet<>();
if (!"any".equals(targetMode)) {
- set.addAll(redisService.candidates(targetMode, mood, 50));
- set.addAll(statusCandidates(targetMode, 50));
- set.addAll(profileCandidates(targetMode, 50));
+ set.addAll(redisService.candidates(targetMode, mood, regionId, regionScope, 50));
+ set.addAll(statusCandidates(targetMode, regionId, regionScope, 50));
+ set.addAll(profileCandidates(targetMode, regionId, regionScope, 50));
return new ArrayList<>(set);
}
- set.addAll(redisService.candidates(selfMode, mood, 30));
- set.addAll(redisService.candidates("i".equals(selfMode) ? "e" : "i", mood, 30));
- set.addAll(redisService.candidates("i", mood, 20));
- set.addAll(redisService.candidates("e", mood, 20));
- set.addAll(statusCandidates(selfMode, 30));
- set.addAll(statusCandidates("i".equals(selfMode) ? "e" : "i", 30));
- set.addAll(profileCandidates(selfMode, 30));
- set.addAll(profileCandidates("i".equals(selfMode) ? "e" : "i", 30));
+ set.addAll(redisService.candidates(selfMode, mood, regionId, regionScope, 30));
+ set.addAll(redisService.candidates("i".equals(selfMode) ? "e" : "i", mood, regionId, regionScope, 30));
+ set.addAll(redisService.candidates("i", mood, regionId, regionScope, 20));
+ set.addAll(redisService.candidates("e", mood, regionId, regionScope, 20));
+ set.addAll(statusCandidates(selfMode, regionId, regionScope, 30));
+ set.addAll(statusCandidates("i".equals(selfMode) ? "e" : "i", regionId, regionScope, 30));
+ set.addAll(profileCandidates(selfMode, regionId, regionScope, 30));
+ set.addAll(profileCandidates("i".equals(selfMode) ? "e" : "i", regionId, regionScope, 30));
return new ArrayList<>(set);
}
@@ -499,12 +524,14 @@ public class IeMatchServiceImpl implements IeMatchService {
return count != null && count > 0;
}
- private List statusCandidates(String mode, int limit) {
- List statuses = userStatusMapper.selectList(new LambdaQueryWrapper()
+ private List statusCandidates(String mode, String regionId, boolean regionScope, int limit) {
+ LambdaQueryWrapper query = new LambdaQueryWrapper()
.eq(IeUserStatus::getOnlineStatus, 1)
.eq(IeUserStatus::getMode, normalizeMode(mode, "i"))
+ .eq(regionScope, IeUserStatus::getRegionId, regionId)
.orderByDesc(IeUserStatus::getLastActiveTime)
- .last("limit " + Math.max(1, Math.min(limit, 100))));
+ .last("limit " + Math.max(1, Math.min(limit, 100)));
+ List statuses = userStatusMapper.selectList(query);
List users = new ArrayList<>();
for (IeUserStatus status : statuses) {
if (status.getUserId() != null) {
@@ -514,13 +541,15 @@ public class IeMatchServiceImpl implements IeMatchService {
return users;
}
- private List profileCandidates(String mode, int limit) {
- List profiles = userProfileMapper.selectList(new LambdaQueryWrapper()
+ private List profileCandidates(String mode, String regionId, boolean regionScope, int limit) {
+ LambdaQueryWrapper query = new LambdaQueryWrapper()
.eq(IeUserProfile::getProfileCompleted, 1)
.eq(IeUserProfile::getCurrentMode, normalizeMode(mode, "i"))
.eq(IeUserProfile::getIsDeleted, 0)
+ .eq(regionScope, IeUserProfile::getRegionId, regionId)
.orderByDesc(IeUserProfile::getLastActiveTime)
- .last("limit " + Math.max(1, Math.min(limit, 100))));
+ .last("limit " + Math.max(1, Math.min(limit, 100)));
+ List profiles = userProfileMapper.selectList(query);
List users = new ArrayList<>();
for (IeUserProfile profile : profiles) {
if (profile.getUserId() != null) {
@@ -566,6 +595,8 @@ public class IeMatchServiceImpl implements IeMatchService {
vo.setRecentPreference(profile.getRecentPreference());
vo.setTargetModePreference(profile.getTargetModePreference());
vo.setTargetGenderPreference(profile.getTargetGenderPreference());
+ vo.setRegionId(profile.getRegionId());
+ vo.setRegionName(profile.getRegionName());
vo.setDefaultRoomMinutes(profile.getDefaultRoomMinutes());
vo.setDailyQuota(profile.getDailyQuota());
vo.setUsedQuota(profile.getUsedQuota());
@@ -612,10 +643,24 @@ public class IeMatchServiceImpl implements IeMatchService {
return "any";
}
- private boolean matchCandidate(IeUserProfile candidateProfile, String selfTargetMode, String selfTargetGender) {
+ private String normalizeMatchScope(String value) {
+ if ("world".equalsIgnoreCase(value)) {
+ return "world";
+ }
+ return "school";
+ }
+
+ private boolean hasText(String value) {
+ return value != null && !value.trim().isEmpty();
+ }
+
+ private boolean matchCandidate(IeUserProfile candidateProfile, String selfTargetMode, String selfTargetGender, String regionId, boolean regionScope) {
if (candidateProfile == null) {
return false;
}
+ if (regionScope && !Objects.equals(regionId, candidateProfile.getRegionId())) {
+ return false;
+ }
String candidateMode = normalizeMode(candidateProfile.getCurrentMode(), "i");
if (!"any".equals(selfTargetMode) && !selfTargetMode.equals(candidateMode)) {
return false;
diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/service/impl/IeRedisServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/service/impl/IeRedisServiceImpl.java
index 508f730a..aadebe7f 100644
--- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/service/impl/IeRedisServiceImpl.java
+++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/service/impl/IeRedisServiceImpl.java
@@ -47,6 +47,8 @@ public class IeRedisServiceImpl implements IeRedisService {
stringRedisTemplate.opsForHash().put(key, "statusText", defaultText(dto.getStatusText(), ""));
stringRedisTemplate.opsForHash().put(key, "longitude", dto.getLongitude() == null ? "" : String.valueOf(dto.getLongitude()));
stringRedisTemplate.opsForHash().put(key, "latitude", dto.getLatitude() == null ? "" : String.valueOf(dto.getLatitude()));
+ stringRedisTemplate.opsForHash().put(key, "regionId", defaultText(dto.getRegionId(), ""));
+ stringRedisTemplate.opsForHash().put(key, "regionName", defaultText(dto.getRegionName(), ""));
stringRedisTemplate.opsForHash().put(key, "interestTags", dto.getInterestTags() == null ? "[]" : JSONUtil.toJsonStr(dto.getInterestTags()));
stringRedisTemplate.opsForHash().put(key, "lastActiveTime", DateUtil.now());
stringRedisTemplate.expire(key, STATUS_SECONDS, TimeUnit.SECONDS);
@@ -60,7 +62,12 @@ public class IeRedisServiceImpl implements IeRedisService {
removeFromMatchPools(userId);
String mode = defaultText(dto.getMode(), "i");
String mood = defaultText(dto.getMood(), "quiet");
- String poolKey = IeRedisKey.matchPool(mode, mood);
+ List poolKeys = new ArrayList<>();
+ poolKeys.add(IeRedisKey.matchPool(mode, mood));
+ String regionId = defaultText(dto.getRegionId(), "");
+ if (!regionId.isEmpty()) {
+ poolKeys.add(IeRedisKey.regionMatchPool(regionId, mode, mood));
+ }
double score = System.currentTimeMillis();
if ("i".equals(mode)) {
score += 5000;
@@ -68,16 +75,20 @@ public class IeRedisServiceImpl implements IeRedisService {
if (dto.getInterestTags() != null) {
score += dto.getInterestTags().size() * 100;
}
- stringRedisTemplate.opsForZSet().add(poolKey, String.valueOf(userId), score);
- stringRedisTemplate.expire(poolKey, STATUS_SECONDS, TimeUnit.SECONDS);
- stringRedisTemplate.opsForValue().set(IeRedisKey.USER_MATCH_POOL + userId, poolKey, STATUS_SECONDS, TimeUnit.SECONDS);
+ for (String poolKey : poolKeys) {
+ stringRedisTemplate.opsForZSet().add(poolKey, String.valueOf(userId), score);
+ stringRedisTemplate.expire(poolKey, STATUS_SECONDS, TimeUnit.SECONDS);
+ }
+ stringRedisTemplate.opsForValue().set(IeRedisKey.USER_MATCH_POOL + userId, JSONUtil.toJsonStr(poolKeys), STATUS_SECONDS, TimeUnit.SECONDS);
}
@Override
public void removeFromMatchPools(Long userId) {
- String poolKey = stringRedisTemplate.opsForValue().get(IeRedisKey.USER_MATCH_POOL + userId);
- if (poolKey != null && poolKey.length() > 0) {
- stringRedisTemplate.opsForZSet().remove(poolKey, String.valueOf(userId));
+ String poolKeysJson = stringRedisTemplate.opsForValue().get(IeRedisKey.USER_MATCH_POOL + userId);
+ if (poolKeysJson != null && poolKeysJson.length() > 0) {
+ for (String poolKey : parsePoolKeys(poolKeysJson)) {
+ stringRedisTemplate.opsForZSet().remove(poolKey, String.valueOf(userId));
+ }
}
stringRedisTemplate.delete(IeRedisKey.USER_MATCH_POOL + userId);
}
@@ -94,17 +105,18 @@ public class IeRedisServiceImpl implements IeRedisService {
}
@Override
- public List candidates(String mode, String mood, int limit) {
+ public List candidates(String mode, String mood, String regionId, boolean regionScope, int limit) {
List keys = new ArrayList<>();
String targetMode = defaultText(mode, "i");
String targetMood = defaultText(mood, "quiet");
- keys.add(IeRedisKey.matchPool(targetMode, targetMood));
+ String safeRegionId = defaultText(regionId, "");
+ keys.add(matchPoolKey(targetMode, targetMood, safeRegionId, regionScope));
if (!"quiet".equals(targetMood)) {
- keys.add(IeRedisKey.matchPool(targetMode, "quiet"));
+ keys.add(matchPoolKey(targetMode, "quiet", safeRegionId, regionScope));
}
- addPoolKey(keys, targetMode, "talk");
- addPoolKey(keys, targetMode, "listen");
- addPoolKey(keys, targetMode, "drift");
+ addPoolKey(keys, targetMode, "talk", safeRegionId, regionScope);
+ addPoolKey(keys, targetMode, "listen", safeRegionId, regionScope);
+ addPoolKey(keys, targetMode, "drift", safeRegionId, regionScope);
List result = new ArrayList<>();
for (String key : keys) {
Set members = stringRedisTemplate.opsForZSet().reverseRange(key, 0, limit - 1L);
@@ -121,13 +133,20 @@ public class IeRedisServiceImpl implements IeRedisService {
return result;
}
- private void addPoolKey(List keys, String mode, String mood) {
- String key = IeRedisKey.matchPool(mode, mood);
+ private void addPoolKey(List keys, String mode, String mood, String regionId, boolean regionScope) {
+ String key = matchPoolKey(mode, mood, regionId, regionScope);
if (!keys.contains(key)) {
keys.add(key);
}
}
+ private String matchPoolKey(String mode, String mood, String regionId, boolean regionScope) {
+ if (regionScope && regionId != null && !regionId.isEmpty()) {
+ return IeRedisKey.regionMatchPool(regionId, mode, mood);
+ }
+ return IeRedisKey.matchPool(mode, mood);
+ }
+
@Override
public boolean isRecentlyMatched(Long userId, Long targetUserId) {
Boolean result = stringRedisTemplate.opsForSet().isMember(IeRedisKey.RECENT_MATCH + userId, String.valueOf(targetUserId));
@@ -257,8 +276,9 @@ public class IeRedisServiceImpl implements IeRedisService {
}
@Override
- public long waitingCount(String mode, String mood) {
- Long count = stringRedisTemplate.opsForZSet().zCard(IeRedisKey.matchPool(defaultText(mode, "i"), defaultText(mood, "quiet")));
+ public long waitingCount(String mode, String mood, String regionId, boolean regionScope) {
+ String key = matchPoolKey(defaultText(mode, "i"), defaultText(mood, "quiet"), defaultText(regionId, ""), regionScope);
+ Long count = stringRedisTemplate.opsForZSet().zCard(key);
return count == null ? 0L : count;
}
@@ -276,6 +296,16 @@ public class IeRedisServiceImpl implements IeRedisService {
return IeRedisKey.DAILY_QUOTA + date + ":" + userId;
}
+ private List parsePoolKeys(String value) {
+ List keys = new ArrayList<>();
+ try {
+ keys.addAll(JSONUtil.toList(JSONUtil.parseArray(value), String.class));
+ } catch (Exception ignored) {
+ keys.add(value);
+ }
+ return keys;
+ }
+
private String defaultText(String value, String defaultValue) {
return value == null || value.trim().isEmpty() ? defaultValue : value.trim();
}
diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/vo/IeMatchVO.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/vo/IeMatchVO.java
index 5217491e..a48e16e9 100644
--- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/vo/IeMatchVO.java
+++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/vo/IeMatchVO.java
@@ -14,6 +14,8 @@ public class IeMatchVO {
private String avatarText;
private String avatarUrl;
private String gender;
+ private String regionId;
+ private String regionName;
private String intro;
private List interestTags;
private List personaImages;
diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/vo/IeUserProfileVO.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/vo/IeUserProfileVO.java
index ba72d57d..a52bd113 100644
--- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/vo/IeUserProfileVO.java
+++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/ie/vo/IeUserProfileVO.java
@@ -18,6 +18,8 @@ public class IeUserProfileVO {
private String recentPreference;
private String targetModePreference;
private String targetGenderPreference;
+ private String regionId;
+ private String regionName;
private Integer defaultRoomMinutes;
private Integer dailyQuota;
private Integer usedQuota;
diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/mq/OrderAsyncConsumer.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/mq/OrderAsyncConsumer.java
index e63aa20e..912a841e 100644
--- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/mq/OrderAsyncConsumer.java
+++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/mq/OrderAsyncConsumer.java
@@ -243,7 +243,7 @@ public class OrderAsyncConsumer {
return;
}
try {
- ieMatchService.rewardMatchQuota(Long.valueOf(userId), 1);
+ ieMatchService.rewardMatchQuota(Long.valueOf(userId), 3);
} catch (NumberFormatException e) {
log.warn("閰嶉佸畬鎴愬紓姝ュ鍔爄/e鍖归厤鏈轰細澶辫触锛岀敤鎴稩D涓嶆槸鏁板瓧 userId={}", userId);
} catch (Exception e) {
diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/controller/PlanetController.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/controller/PlanetController.java
index 36723e2a..d2b97892 100644
--- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/controller/PlanetController.java
+++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/controller/PlanetController.java
@@ -4,6 +4,7 @@ import cc.hiver.core.common.exception.HiverException;
import cc.hiver.core.common.utils.ResultUtil;
import cc.hiver.core.common.vo.Result;
import cc.hiver.mall.planet.entity.PlanetDrawRecord;
+import cc.hiver.mall.planet.entity.PlanetTicket;
import cc.hiver.mall.planet.pojo.*;
import cc.hiver.mall.planet.service.*;
import io.swagger.annotations.Api;
@@ -335,6 +336,23 @@ public class PlanetController {
ticketService.pageLog(query.getUserId(), query.getRegionId(), query.getPageNumber(), query.getPageSize()));
}
+ @ApiOperation(value = "鎴戠殑瀹炴椂鏄熺悆鍒告暟閲")
+ @RequestMapping(value = "/ticket/count", method = RequestMethod.POST)
+ public Result ticketCount(@RequestBody PlanetQuery query) {
+ if (StringUtils.isEmpty(query.getUserId())) {
+ return ResultUtil.error("鐢ㄦ埛id涓嶈兘涓虹┖");
+ }
+ if (StringUtils.isEmpty(query.getRegionId())) {
+ return ResultUtil.error(REGION_REQUIRED);
+ }
+ final PlanetTicket ticket = ticketService.getByUser(query.getUserId(), query.getRegionId());
+ final int ticketCount = ticket == null || ticket.getTicketCount() == null ? 0 : ticket.getTicketCount();
+ final Map data = new HashMap<>(2);
+ data.put("ticketCount", ticketCount);
+ data.put("myTicketCount", ticketCount);
+ return new ResultUtil<>().setData(data);
+ }
+
@ApiOperation(value = "缁忚惀鐜╂硶鑱氬悎鏁版嵁")
@RequestMapping(value = "/operate/overview", method = RequestMethod.POST)
public Result operateOverview(@RequestBody PlanetQuery query) {
@@ -585,6 +603,15 @@ public class PlanetController {
return new ResultUtil<>().setData(adventureService.rankTop(query.getRegionId()));
}
+ @ApiOperation(value = "瀛﹂櫌鍔╂帹璧涙槰鏃ュ鍔辫褰")
+ @RequestMapping(value = "/adventure/yesterdayRewards", method = RequestMethod.POST)
+ public Result adventureYesterdayRewards(@RequestBody PlanetQuery query) {
+ if (StringUtils.isEmpty(query.getRegionId())) {
+ return ResultUtil.error(REGION_REQUIRED);
+ }
+ return new ResultUtil<>().setData(adventureService.yesterdayRewards(query.getRegionId()));
+ }
+
@ApiOperation(value = "瀛﹂櫌鍔╂帹璧涗粖鏃ユ渶蹇崳鑰姒")
@RequestMapping(value = "/adventure/glory", method = RequestMethod.POST)
public Result adventureGlory(@RequestBody PlanetQuery query) {
diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/pojo/PlanetAdventureRewardRecordVo.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/pojo/PlanetAdventureRewardRecordVo.java
new file mode 100644
index 00000000..7598ebbd
--- /dev/null
+++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/pojo/PlanetAdventureRewardRecordVo.java
@@ -0,0 +1,23 @@
+package cc.hiver.mall.planet.pojo;
+
+import io.swagger.annotations.ApiModel;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDate;
+
+@Data
+@ApiModel(value = "鐧藉珫鏄熺悆-瀛﹂櫌鍔╂帹璧涙槰鏃ュ鍔辫褰")
+public class PlanetAdventureRewardRecordVo implements Serializable {
+ private static final long serialVersionUID = 1L;
+ private Integer rankNo;
+ private String userId;
+ private String nickname;
+ private String avatar;
+ private String college;
+ private LocalDate rewardDate;
+ private Integer durationSeconds;
+ private Integer score;
+ private Integer rewardTickets;
+ private String rewardContent;
+}
diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetAdventureService.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetAdventureService.java
index d7038158..ecd81765 100644
--- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetAdventureService.java
+++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/PlanetAdventureService.java
@@ -5,10 +5,12 @@ import cc.hiver.mall.planet.entity.PlanetAdventureEvent;
import cc.hiver.mall.planet.entity.PlanetAdventureRank;
import cc.hiver.mall.planet.entity.PlanetAdventureSession;
import cc.hiver.mall.planet.pojo.PlanetAdventureHomeVo;
+import cc.hiver.mall.planet.pojo.PlanetAdventureRewardRecordVo;
import cc.hiver.mall.planet.pojo.PlanetAdventureStartVo;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.util.List;
+import java.util.Map;
public interface PlanetAdventureService {
@@ -23,6 +25,8 @@ public interface PlanetAdventureService {
List rankTop(String regionId);
+ Map> yesterdayRewards(String regionId);
+
int settleDueRanks();
Page pageEvents(PageVo pageVo, String regionId);
diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetAdventurePkServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetAdventurePkServiceImpl.java
index 7c967f34..4f24ac24 100644
--- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetAdventurePkServiceImpl.java
+++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetAdventurePkServiceImpl.java
@@ -300,6 +300,10 @@ public class PlanetAdventurePkServiceImpl implements PlanetAdventurePkService {
private void settleIfReady(PlanetAdventurePkRoom room) {
List players = playerMapper.selectList(new LambdaQueryWrapper()
.eq(PlanetAdventurePkPlayer::getRoomId, room.getId()));
+ int maxPlayers = room.getMaxPlayers() == null ? 2 : room.getMaxPlayers();
+ if (maxPlayers > 2 && players.size() < maxPlayers) {
+ return;
+ }
for (PlanetAdventurePkPlayer p : players) {
if (!terminal(p)) return;
}
diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetAdventureServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetAdventureServiceImpl.java
index 70348897..49d567ce 100644
--- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetAdventureServiceImpl.java
+++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetAdventureServiceImpl.java
@@ -12,6 +12,7 @@ import cc.hiver.mall.planet.mapper.PlanetAdventureRankMapper;
import cc.hiver.mall.planet.mapper.PlanetAdventureSessionMapper;
import cc.hiver.mall.planet.mapper.PlanetCollegeConfigMapper;
import cc.hiver.mall.planet.pojo.PlanetAdventureHomeVo;
+import cc.hiver.mall.planet.pojo.PlanetAdventureRewardRecordVo;
import cc.hiver.mall.planet.pojo.PlanetAdventureStartVo;
import cc.hiver.mall.planet.service.PlanetAdventureService;
import cc.hiver.mall.planet.service.PlanetTicketService;
@@ -32,6 +33,7 @@ public class PlanetAdventureServiceImpl implements PlanetAdventureService {
private static final int GAME_SECONDS = 180;
private static final LocalTime SETTLE_TIME = LocalTime.of(21, 30);
private static final int CLEAR_BASE_PROGRESS = 100;
+ private static final int[] PERSONAL_REWARD_CASH = {5, 4, 3, 2, 1};
@Autowired
private PlanetAdventureSessionMapper sessionMapper;
@@ -177,6 +179,15 @@ public class PlanetAdventureServiceImpl implements PlanetAdventureService {
.last("limit 20"));
}
+ @Override
+ public Map> yesterdayRewards(String regionId) {
+ LocalDate yesterday = LocalDate.now().minusDays(1);
+ Map> data = new HashMap<>(4);
+ data.put("personalRewardList", yesterdayPersonalRewards(regionId, yesterday));
+ data.put("collegeRewardList", yesterdayCollegeRewards(regionId, yesterday));
+ return data;
+ }
+
@Override
@Transactional(rollbackFor = Exception.class)
public int settleDueRanks() {
@@ -325,6 +336,59 @@ public class PlanetAdventureServiceImpl implements PlanetAdventureService {
return rank == null || rank.getRankNo() == null ? 0 : rank.getRankNo();
}
+ private List yesterdayPersonalRewards(String regionId, LocalDate date) {
+ List sessions = sessionMapper.selectList(new LambdaQueryWrapper()
+ .eq(PlanetAdventureSession::getRegionId, regionId)
+ .eq(PlanetAdventureSession::getPlayDate, date)
+ .eq(PlanetAdventureSession::getStatus, PlanetConstant.ADVENTURE_SESSION_SUBMITTED)
+ .eq(PlanetAdventureSession::getCheatFlag, "N")
+ .orderByAsc(PlanetAdventureSession::getDurationSeconds)
+ .last("limit 5"));
+ List records = new ArrayList<>();
+ for (int i = 0; i < sessions.size(); i++) {
+ PlanetAdventureSession s = sessions.get(i);
+ PlanetAdventureRewardRecordVo vo = new PlanetAdventureRewardRecordVo();
+ vo.setRankNo(i + 1);
+ vo.setUserId(s.getUserId());
+ vo.setNickname(s.getNickname());
+ vo.setAvatar(s.getAvatar());
+ vo.setCollege(s.getCollege());
+ vo.setRewardDate(date);
+ vo.setDurationSeconds(nz(s.getDurationSeconds()));
+ vo.setScore(nz(s.getScore()));
+ vo.setRewardContent("鐜伴噾濂栧姳" + PERSONAL_REWARD_CASH[i] + "鍏");
+ records.add(vo);
+ }
+ return records;
+ }
+
+ private List yesterdayCollegeRewards(String regionId, LocalDate date) {
+ List ranks = rankMapper.selectList(new LambdaQueryWrapper()
+ .eq(PlanetAdventureRank::getRegionId, regionId)
+ .eq(PlanetAdventureRank::getRankDate, date)
+ .orderByDesc(PlanetAdventureRank::getScore)
+ .orderByAsc(PlanetAdventureRank::getUpdateTime)
+ .last("limit 3"));
+ List records = new ArrayList<>();
+ for (int i = 0; i < ranks.size(); i++) {
+ PlanetAdventureRank r = ranks.get(i);
+ int rankNo = r.getRankNo() == null || r.getRankNo() <= 0 ? i + 1 : r.getRankNo();
+ int rewardTickets = Math.max(0, 4 - rankNo);
+ PlanetAdventureRewardRecordVo vo = new PlanetAdventureRewardRecordVo();
+ vo.setRankNo(rankNo);
+ vo.setUserId(r.getUserId());
+ vo.setNickname(r.getNickname());
+ vo.setAvatar(r.getAvatar());
+ vo.setCollege(r.getCollege());
+ vo.setRewardDate(date);
+ vo.setScore(nz(r.getScore()));
+ vo.setRewardTickets(rewardTickets);
+ vo.setRewardContent("瀛﹂櫌鎴愬憳姣忎汉" + rewardTickets + "寮犳槦鐞冨埜");
+ records.add(vo);
+ }
+ return records;
+ }
+
private String validateClear(int n, int g, int d, int r, Integer clientScore, int seconds) {
if (seconds < 20 || seconds > GAME_SECONDS + 20) return "闂叧鏃堕暱寮傚父";
if (n < 36) return "娑堥櫎鏁伴噺涓嶈冻";
diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetDrawServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetDrawServiceImpl.java
index fa11266c..207ca587 100644
--- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetDrawServiceImpl.java
+++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/planet/service/impl/PlanetDrawServiceImpl.java
@@ -272,22 +272,39 @@ public class PlanetDrawServiceImpl implements PlanetDrawService {
final Set cooldownUsers = recentWinnerUserIds(pool.getRegionId(), now);
boolean useCooldown = hasCandidate(poolCandidates, cooldownUsers);
int winnerCount = 0;
+ final List missedRewards = new ArrayList<>();
for (PlanetReward reward : rewards) {
final int quota = reward.getQuota() == null ? 0 : reward.getQuota();
for (int i = 0; i < quota; i++) {
List usable = usableCandidates(poolCandidates, useCooldown ? cooldownUsers : Collections.emptySet());
if (usable.isEmpty()) {
- break;
+ missedRewards.add(reward);
+ continue;
}
final Candidate winner = pickWeighted(usable);
if (winner == null) {
- break;
+ missedRewards.add(reward);
+ continue;
}
winner.win = true;
saveWinner(record, reward, winner.ticket, now);
winnerCount++;
}
}
+ // 绗竴杞伒寰師鏈夊喎鍗磋鍒欙紱鑻ヤ粛鏈夊椤规湭寮鍑猴紝鍒欎粠鏈腑濂栧弬涓庤呬腑琛ユ娊锛岀洿鍒板椤瑰紑瀹屾垨鍙備笌鑰呴兘涓銆
+ for (PlanetReward reward : missedRewards) {
+ final List usable = usableCandidates(poolCandidates, Collections.emptySet());
+ if (usable.isEmpty()) {
+ break;
+ }
+ final Candidate winner = pickWeighted(usable);
+ if (winner == null) {
+ break;
+ }
+ winner.win = true;
+ saveWinner(record, reward, winner.ticket, now);
+ winnerCount++;
+ }
record.setWinnerCount(winnerCount);
drawRecordMapper.insert(record);
diff --git a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallOrderServiceImpl.java b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallOrderServiceImpl.java
index 61ca3056..40e7322b 100644
--- a/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallOrderServiceImpl.java
+++ b/hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallOrderServiceImpl.java
@@ -1208,7 +1208,7 @@ public class MallOrderServiceImpl extends ServiceImpl