@@ -17,17 +17,20 @@ public final class InviteCacheDTO { | |||
private Long meetingId; | |||
private Boolean invitedRefused; | |||
/** | |||
* 拒绝的专家是否可以再次邀请 | |||
*/ | |||
private Boolean reInvite; | |||
/** | |||
* 任务触发时间 | |||
*/ | |||
private LocalDateTime taskStartTime; | |||
public static InviteCacheDTO of(Long meetingId, Boolean invitedRefused, LocalDateTime startTime) { | |||
public static InviteCacheDTO of(Long meetingId, Boolean reInvite, LocalDateTime startTime) { | |||
InviteCacheDTO bo = new InviteCacheDTO(); | |||
bo.setMeetingId(meetingId); | |||
bo.setInvitedRefused(invitedRefused); | |||
bo.setReInvite(reInvite); | |||
bo.setTaskStartTime(startTime); | |||
return bo; | |||
} | |||
@@ -0,0 +1,114 @@ | |||
package com.ningdatech.pmapi.meeting.helper; | |||
import cn.hutool.core.util.RandomUtil; | |||
import com.ningdatech.pmapi.expert.entity.ExpertUserFullInfo; | |||
import com.ningdatech.pmapi.meeting.entity.domain.MeetingExpert; | |||
import org.apache.commons.collections4.MapUtils; | |||
import org.apache.commons.lang3.RandomUtils; | |||
import java.util.ArrayList; | |||
import java.util.Collections; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.stream.Collectors; | |||
/** | |||
* <p> | |||
* 专家抽取算法 | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 2023/4/14 | |||
**/ | |||
public class ExpertRandomInviteAlgorithm { | |||
/** | |||
* 每个单位只抽取一人 | |||
* | |||
* @param expertGroupByUnit 需要抽取的人 | |||
* @param expertsByRecentMeeting 最近会议抽取到的专家 | |||
* @param count 抽取数量 | |||
* @return 抽取到的专家信息 | |||
* @author WendyYang | |||
**/ | |||
public static List<ExpertUserFullInfo> inviteGroupByCompany(Map<String, List<ExpertUserFullInfo>> expertGroupByUnit, | |||
List<List<MeetingExpert>> expertsByRecentMeeting, | |||
Integer count) { | |||
if (MapUtils.isEmpty(expertGroupByUnit)) { | |||
return Collections.emptyList(); | |||
} | |||
if (expertsByRecentMeeting.isEmpty()) { | |||
return expertGroupByUnit.values().stream() | |||
.map(RandomUtil::randomEle) | |||
.limit(count).collect(Collectors.toList()); | |||
} else { | |||
List<ExpertUserFullInfo> result = new ArrayList<>(); | |||
List<String> keySet = new ArrayList<>(expertGroupByUnit.keySet()); | |||
for (int i = 0; i < count; i++) { | |||
String company = keySet.get(RandomUtils.nextInt(0, keySet.size())); | |||
List<ExpertUserFullInfo> expertsByCompany = expertGroupByUnit.get(company); | |||
for (List<MeetingExpert> experts : expertsByRecentMeeting) { | |||
List<ExpertUserFullInfo> notInvitedUsers = expertsByCompany.stream() | |||
.filter(w -> experts.stream().noneMatch(expert -> expert.getExpertId().equals(w.getUserId()))) | |||
.collect(Collectors.toList()); | |||
if (!notInvitedUsers.isEmpty()) { | |||
result.add(RandomUtil.randomEle(notInvitedUsers)); | |||
break; | |||
} else if (expertsByRecentMeeting.indexOf(experts) == (expertsByRecentMeeting.size() - 1)) { | |||
result.add(RandomUtil.randomEle(expertsByCompany)); | |||
} | |||
} | |||
if (result.size() < count) { | |||
keySet.remove(company); | |||
if (keySet.isEmpty()) { | |||
break; | |||
} | |||
} | |||
} | |||
return result; | |||
} | |||
} | |||
/** | |||
* 随机抽取专家 | |||
* | |||
* @param userFullInfos 可抽取的所有专家 | |||
* @param expertsByRecentMeeting 最近会议抽取到的专家 | |||
* @param count 抽取数量 | |||
* @return 抽取到的专家信息 | |||
* @author WendyYang | |||
**/ | |||
public static List<ExpertUserFullInfo> inviteWithoutCompany(List<ExpertUserFullInfo> userFullInfos, | |||
List<List<MeetingExpert>> expertsByRecentMeeting, | |||
Integer count) { | |||
List<ExpertUserFullInfo> result; | |||
if (expertsByRecentMeeting.isEmpty()) { | |||
result = RandomUtil.randomEleList(userFullInfos, count); | |||
} else { | |||
result = new ArrayList<>(); | |||
for (List<MeetingExpert> experts : expertsByRecentMeeting) { | |||
List<ExpertUserFullInfo> notInvitedUsers = userFullInfos.stream() | |||
.filter(w -> experts.stream().noneMatch(expert -> expert.getExpertId().equals(w.getUserId()))) | |||
.collect(Collectors.toList()); | |||
if (!notInvitedUsers.isEmpty()) { | |||
result.addAll(notInvitedUsers); | |||
if (result.size() >= count) { | |||
return result.subList(0, count); | |||
} | |||
userFullInfos.removeAll(notInvitedUsers); | |||
} | |||
} | |||
if (userFullInfos.size() == 0) { | |||
return result; | |||
} | |||
int restCnt = Math.min(count - result.size(), userFullInfos.size()); | |||
if (userFullInfos.size() > restCnt) { | |||
result.addAll(RandomUtil.randomEleList(userFullInfos, restCnt)); | |||
} else { | |||
result.addAll(userFullInfos); | |||
} | |||
} | |||
return result; | |||
} | |||
} |
@@ -28,22 +28,20 @@ import com.ningdatech.pmapi.meta.model.entity.ExpertDictionary; | |||
import com.ningdatech.pmapi.meta.model.entity.ExpertTag; | |||
import com.ningdatech.pmapi.meta.service.IExpertDictionaryService; | |||
import com.ningdatech.pmapi.meta.service.IExpertTagService; | |||
import lombok.AllArgsConstructor; | |||
import lombok.RequiredArgsConstructor; | |||
import org.apache.commons.collections4.CollectionUtils; | |||
import org.apache.commons.collections4.MapUtils; | |||
import org.apache.commons.collections4.Predicate; | |||
import org.apache.commons.lang3.ObjectUtils; | |||
import org.apache.commons.lang3.RandomUtils; | |||
import org.springframework.beans.factory.annotation.Value; | |||
import org.springframework.stereotype.Component; | |||
import java.time.LocalDate; | |||
import java.time.LocalDateTime; | |||
import java.util.*; | |||
import java.util.stream.Collectors; | |||
import java.util.stream.Stream; | |||
import static com.ningdatech.pmapi.meeting.entity.enumeration.ExpertAttendStatusEnum.*; | |||
import static com.ningdatech.pmapi.meeting.helper.ExpertInviteHelper.getExpertInviteRule; | |||
import static com.ningdatech.pmapi.meeting.helper.ExpertRandomInviteAlgorithm.inviteGroupByCompany; | |||
/** | |||
* <p> | |||
@@ -54,7 +52,7 @@ import static com.ningdatech.pmapi.meeting.helper.ExpertInviteHelper.getExpertIn | |||
* @since 18:05 2022/8/8 | |||
*/ | |||
@Component | |||
@AllArgsConstructor | |||
@RequiredArgsConstructor | |||
public class ExpertInviteManage { | |||
private final IExpertDictionaryService expertDictionaryService; | |||
@@ -69,6 +67,9 @@ public class ExpertInviteManage { | |||
private final IExpertAvoidCompanyService expertAvoidCompanyService; | |||
private final YxtCallOrSmsHelper yxtCallOrSmsHelper; | |||
@Value("#{randomInviteProperties.recentMeetingCount}") | |||
private Integer recentMeetingCount; | |||
private static final Predicate<Collection<?>> COLL_EMPTY = (coll) -> coll != null && coll.isEmpty(); | |||
private LambdaQueryWrapper<ExpertUserFullInfo> buildBaseExpertQuery() { | |||
@@ -322,7 +323,8 @@ public class ExpertInviteManage { | |||
} | |||
Map<String, List<ExpertUserFullInfo>> userGroupByUnit = CollUtils.group(userInfoList, ExpertUserFullInfo::getCompanyUniqCode); | |||
result.setTotal(userGroupByUnit.size()); | |||
result.setExperts(inviteGroupByCompany(userGroupByUnit, randomRule.getCount())); | |||
result.setExperts(inviteGroupByCompany(userGroupByUnit, expertsByRecentMeeting(), randomRule.getCount())); | |||
return result; | |||
} | |||
@@ -431,15 +433,15 @@ public class ExpertInviteManage { | |||
} | |||
Map<String, List<ExpertUserFullInfo>> userGroupByUnit = CollUtils.group(userFullInfos, ExpertUserFullInfo::getCompanyUniqCode); | |||
result.setTotal(userGroupByUnit.size()); | |||
result.setExperts(inviteGroupByCompany(userGroupByUnit, count)); | |||
result.setExperts(inviteGroupByCompany(userGroupByUnit, expertsByRecentMeeting(), count)); | |||
return result; | |||
} | |||
private List<List<MeetingExpert>> selectMeetingExpertByCount() { | |||
private List<List<MeetingExpert>> expertsByRecentMeeting() { | |||
LambdaQueryWrapper<Meeting> query = Wrappers.lambdaQuery(Meeting.class) | |||
.select(Meeting::getId) | |||
.orderByDesc(Meeting::getCreateOn) | |||
.last("limit " + 5); | |||
.last("limit " + recentMeetingCount); | |||
List<Long> meetingIds = CollUtils.fieldList(meetingService.list(query), Meeting::getId); | |||
if (meetingIds.isEmpty()) { | |||
return Collections.emptyList(); | |||
@@ -453,97 +455,6 @@ public class ExpertInviteManage { | |||
} | |||
/** | |||
* 每个单位只抽取一人 | |||
* | |||
* @param expertGroupByUnit 需要抽取的人 | |||
* @param count 抽取数量 | |||
* @return 抽取到的专家信息 | |||
* @author WendyYang | |||
**/ | |||
private List<ExpertUserFullInfo> inviteGroupByCompany(Map<String, List<ExpertUserFullInfo>> expertGroupByUnit, Integer count) { | |||
if (MapUtils.isEmpty(expertGroupByUnit)) { | |||
return Collections.emptyList(); | |||
} | |||
List<List<MeetingExpert>> meetingExperts = selectMeetingExpertByCount(); | |||
if (meetingExperts.isEmpty()) { | |||
return expertGroupByUnit.values().stream() | |||
.map(expertUsers -> expertUsers.get(RandomUtils.nextInt(0, expertUsers.size()))) | |||
.limit(count).collect(Collectors.toList()); | |||
} else { | |||
List<ExpertUserFullInfo> result = new ArrayList<>(); | |||
List<String> keySet = new ArrayList<>(expertGroupByUnit.keySet()); | |||
for (int i = 0; i < count; i++) { | |||
String key = keySet.get(RandomUtils.nextInt(0, keySet.size())); | |||
List<ExpertUserFullInfo> expertUserFullInfos = expertGroupByUnit.get(key); | |||
for (List<MeetingExpert> expertList : meetingExperts) { | |||
List<ExpertUserFullInfo> tempList = expertUserFullInfos.stream() | |||
.filter(w -> expertList.stream().noneMatch(expert -> expert.getExpertId().equals(w.getUserId()))) | |||
.collect(Collectors.toList()); | |||
if (!tempList.isEmpty()) { | |||
result.add(tempList.get(RandomUtils.nextInt(0, tempList.size()))); | |||
break; | |||
} else if (meetingExperts.indexOf(expertList) == (meetingExperts.size() - 1)) { | |||
result.add(expertUserFullInfos.get(RandomUtils.nextInt(0, expertUserFullInfos.size()))); | |||
} | |||
} | |||
if (result.size() < count) { | |||
keySet.remove(key); | |||
if (keySet.isEmpty()) { | |||
break; | |||
} | |||
} | |||
} | |||
return result; | |||
} | |||
} | |||
private List<ExpertUserFullInfo> inviteWithoutCompany(List<ExpertUserFullInfo> userFullInfos, Integer count) { | |||
List<ExpertUserFullInfo> result = new ArrayList<>(); | |||
List<List<MeetingExpert>> meetingExpertList = selectMeetingExpertByCount(); | |||
if (meetingExpertList.isEmpty()) { | |||
for (int i = 0; i < count; i++) { | |||
int randomIndex = RandomUtils.nextInt(0, userFullInfos.size()); | |||
result.add(userFullInfos.remove(randomIndex)); | |||
if (userFullInfos.size() == 0) { | |||
break; | |||
} | |||
} | |||
} else { | |||
for (List<MeetingExpert> meetingExperts : meetingExpertList) { | |||
List<ExpertUserFullInfo> unSelectedUsers = userFullInfos.stream() | |||
.filter(w -> meetingExperts.stream().noneMatch(expert -> expert.getExpertId().equals(w.getUserId()))) | |||
.collect(Collectors.toList()); | |||
if (!unSelectedUsers.isEmpty()) { | |||
result.addAll(unSelectedUsers); | |||
if (result.size() >= count) { | |||
return result.subList(0, count); | |||
} | |||
userFullInfos.removeAll(unSelectedUsers); | |||
} | |||
} | |||
if (userFullInfos.size() == 0) { | |||
return result; | |||
} | |||
int restCount = Math.min(count - result.size(), userFullInfos.size()); | |||
int groupCount = userFullInfos.size() / restCount; | |||
if (userFullInfos.size() > restCount) { | |||
Stream.iterate(0, t -> t + 1).limit(restCount) | |||
.forEach(t -> { | |||
int start = t * groupCount; | |||
int end = start + groupCount; | |||
if (end >= groupCount * restCount) { | |||
end = userFullInfos.size(); | |||
} | |||
result.add(userFullInfos.get(RandomUtils.nextInt(start, end))); | |||
}); | |||
} else { | |||
result.addAll(userFullInfos); | |||
} | |||
} | |||
return result; | |||
} | |||
/** | |||
* 专家抽取(会议创建时抽取) | |||
* | |||
* @param randomRules 随机抽取规则 | |||
@@ -39,13 +39,13 @@ import java.time.Duration; | |||
import java.time.Instant; | |||
import java.time.LocalDateTime; | |||
import java.time.ZoneId; | |||
import java.util.HashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.concurrent.ConcurrentHashMap; | |||
import java.util.concurrent.ConcurrentMap; | |||
import java.util.concurrent.ScheduledFuture; | |||
import java.util.concurrent.atomic.AtomicInteger; | |||
import java.util.stream.Collectors; | |||
/** | |||
@@ -67,7 +67,6 @@ public class ExpertInviteTask { | |||
private static final Duration EXPIRE_TIME = Duration.ofDays(60); | |||
private final CachePlusOps cachePlusOps; | |||
@Qualifier("expertInviteScheduler") | |||
@Resource(name = "expertInviteScheduler") | |||
private ThreadPoolTaskScheduler scheduler; | |||
private final IMeetingExpertService meetingExpertService; | |||
@@ -82,13 +81,13 @@ public class ExpertInviteTask { | |||
*/ | |||
private static final ConcurrentMap<Long, ScheduledFuture<?>> INVITE_TASK_MAP = new ConcurrentHashMap<>(); | |||
public ExpertInviteTask currProxy() { | |||
private ExpertInviteTask currProxy() { | |||
return (ExpertInviteTask) AopContext.currentProxy(); | |||
} | |||
private CacheHashKey getCacheKey(Long meetingId) { | |||
String meetingIdStr = meetingId == null ? null : meetingId.toString(); | |||
return new CacheHashKey(MEETING_ID_INVITE_RANDOM, meetingIdStr, EXPIRE_TIME); | |||
String field = meetingId == null ? null : meetingId.toString(); | |||
return new CacheHashKey(MEETING_ID_INVITE_RANDOM, field, EXPIRE_TIME); | |||
} | |||
@PostConstruct | |||
@@ -97,13 +96,13 @@ public class ExpertInviteTask { | |||
log.warn("随机邀请已关闭……"); | |||
return; | |||
} | |||
initInviteTaskAfterAppStarted(); | |||
initInviteTaskAfterStarted(); | |||
} | |||
/** | |||
* 项目重启之后重新初始化邀请任务 | |||
*/ | |||
private void initInviteTaskAfterAppStarted() { | |||
private void initInviteTaskAfterStarted() { | |||
Map<Long, InviteCacheDTO> caches = cachePlusOps.hGetAll(getCacheKey(null)); | |||
if (MapUtils.isEmpty(caches)) { | |||
log.info("暂无需要初始化的抽取会议信息"); | |||
@@ -111,9 +110,9 @@ public class ExpertInviteTask { | |||
} | |||
Integer inviteDelay = properties.getInviteDelay(); | |||
for (InviteCacheDTO cache : caches.values()) { | |||
Boolean invitedRefused = cache.getInvitedRefused(); | |||
Boolean reInvite = cache.getReInvite(); | |||
LocalDateTime tsTime = cache.getTaskStartTime(); | |||
boolean added = addInviteTask(cache.getMeetingId(), true, inviteDelay, invitedRefused, tsTime); | |||
boolean added = addInviteTask(cache.getMeetingId(), true, inviteDelay, reInvite, tsTime); | |||
if (!added) { | |||
cachePlusOps.hDel(getCacheKey(cache.getMeetingId())); | |||
} | |||
@@ -135,7 +134,7 @@ public class ExpertInviteTask { | |||
LambdaQueryWrapper<MeetingExpert> query = Wrappers.lambdaQuery(MeetingExpert.class) | |||
.select(MeetingExpert::getRuleId, MeetingExpert::getStatus) | |||
.in(MeetingExpert::getRuleId, ruleMap.keySet()) | |||
.in(MeetingExpert::getStatus, ExpertAttendStatusEnum.AGREED.getCode()); | |||
.eq(MeetingExpert::getStatus, ExpertAttendStatusEnum.AGREED.getCode()); | |||
List<MeetingExpert> experts = meetingExpertService.list(query); | |||
if (experts.isEmpty()) { | |||
return Boolean.TRUE; | |||
@@ -153,23 +152,20 @@ public class ExpertInviteTask { | |||
/** | |||
* 唤醒某个会议的抽取任务 | |||
* | |||
* @param meetingId 会议ID | |||
* @param invitedRefused 是否可邀请已拒绝的专家 | |||
* @param meetingId 会议ID | |||
* @param reInvite 是否可邀请已拒绝的专家 | |||
* @author WendyYang | |||
**/ | |||
public void notifyInviteTask(Long meetingId, boolean... invitedRefused) { | |||
boolean tmpInvitedRefused = true; | |||
if (ArrayUtil.isNotEmpty(invitedRefused)) { | |||
tmpInvitedRefused = invitedRefused[0]; | |||
} | |||
public void notifyInviteTask(Long meetingId, boolean... reInvite) { | |||
boolean tmpReInvite = !ArrayUtil.isNotEmpty(reInvite) || reInvite[0]; | |||
if (!INVITE_TASK_MAP.containsKey(meetingId)) { | |||
if (addInviteTask(meetingId, false, properties.getInviteDelay(), tmpInvitedRefused, LocalDateTime.now())) { | |||
if (addInviteTask(meetingId, false, properties.getInviteDelay(), tmpReInvite, LocalDateTime.now())) { | |||
log.info("重置会议的随机抽取状态:{}", meetingId); | |||
LambdaUpdateWrapper<Meeting> update = Wrappers.lambdaUpdate(Meeting.class); | |||
update.set(Meeting::getInviteStatus, false); | |||
update.eq(Meeting::getId, meetingId); | |||
meetingService.update(update); | |||
InviteCacheDTO cacheVal = InviteCacheDTO.of(meetingId, tmpInvitedRefused, LocalDateTime.now()); | |||
InviteCacheDTO cacheVal = InviteCacheDTO.of(meetingId, tmpReInvite, LocalDateTime.now()); | |||
cachePlusOps.hSet(getCacheKey(meetingId), cacheVal); | |||
} | |||
} | |||
@@ -178,23 +174,24 @@ public class ExpertInviteTask { | |||
/** | |||
* 添加专家抽取校验任务 | |||
* | |||
* @param meetingId 会议ID | |||
* @param checked 是否前置校验 | |||
* @param delayedMinutes 延迟执行时间 | |||
* @param invitedRefused 是否可以邀请被拒绝的专家 | |||
* @param meetingId 会议ID | |||
* @param checked 是否前置校验 | |||
* @param delayTime 延迟执行时间 | |||
* @param reInvite 是否可以邀请被拒绝的专家 | |||
* @param tsTime 任务启动时间 | |||
* @return 是否添加任务成功 | |||
* @author WendyYang | |||
**/ | |||
public boolean addInviteTask(Long meetingId, boolean checked, int delayedMinutes, boolean invitedRefused, LocalDateTime tsTime) { | |||
private boolean addInviteTask(Long meetingId, boolean checked, int delayTime, boolean reInvite, LocalDateTime tsTime) { | |||
if (checked && !inviteCountCheck(meetingId)) { | |||
// 如果抽取数量满足直接返回 | |||
return Boolean.FALSE; | |||
} | |||
Instant startTime = LocalDateTime.now().plusMinutes(delayedMinutes).atZone(ZoneId.systemDefault()).toInstant(); | |||
Instant startTime = LocalDateTime.now().plusMinutes(delayTime).atZone(ZoneId.systemDefault()).toInstant(); | |||
ScheduledFuture<?> future = scheduler.scheduleAtFixedRate(() -> { | |||
ExpertInviteTask bean = SpringContextHolder.getBean(ExpertInviteTask.class); | |||
try { | |||
bean.invite(meetingId, invitedRefused, tsTime); | |||
bean.invite(meetingId, reInvite, tsTime); | |||
} catch (Exception e) { | |||
log.error("执行专家邀请任务异常:{}", meetingId, e); | |||
} | |||
@@ -207,14 +204,14 @@ public class ExpertInviteTask { | |||
/** | |||
* 创建会议时添加抽取任务 | |||
* | |||
* @param meetingId 会议ID | |||
* @param delayedMinutes 延迟时间 | |||
* @param tsTime 开始时间 | |||
* @param meetingId 会议ID | |||
* @param delayTime 延迟时间 | |||
* @param tsTime 开始时间 | |||
* @author WendyYang | |||
**/ | |||
public void addInviteTaskByMeetingCreate(Long meetingId, int delayedMinutes, LocalDateTime tsTime) { | |||
public void addInviteTaskByMeetingCreate(Long meetingId, int delayTime, LocalDateTime tsTime) { | |||
Assert.isTrue(properties.getEnable(), "随机邀请已关闭"); | |||
addInviteTask(meetingId, false, delayedMinutes, false, tsTime); | |||
addInviteTask(meetingId, false, delayTime, false, tsTime); | |||
InviteCacheDTO cacheVal = InviteCacheDTO.of(meetingId, false, tsTime); | |||
cachePlusOps.hSet(getCacheKey(meetingId), cacheVal); | |||
} | |||
@@ -222,12 +219,12 @@ public class ExpertInviteTask { | |||
/** | |||
* 抽取过程 | |||
* | |||
* @param meetingId 会议ID | |||
* @param invitedRefused 是否可以邀请已拒绝的专家 | |||
* @param tsTime 任务开启时间 | |||
* @param meetingId 会议ID | |||
* @param reInvite 是否可以邀请已拒绝的专家 | |||
* @param tsTime 任务开启时间 | |||
*/ | |||
@Transactional(rollbackFor = Exception.class) | |||
public void invite(Long meetingId, Boolean invitedRefused, LocalDateTime tsTime) { | |||
public void invite(Long meetingId, Boolean reInvite, LocalDateTime tsTime) { | |||
log.info("开始进行专家后台抽取:{}", meetingId); | |||
Meeting meeting = meetingService.getById(meetingId); | |||
if (meeting.getStartTime().isBefore(LocalDateTime.now())) { | |||
@@ -248,7 +245,7 @@ public class ExpertInviteTask { | |||
List<MeetingExpert> tmpExperts = meetingExpertService.listExpertLastByMeetingId(meetingId); | |||
Map<Long, MeetingExpert> expertMap = CollUtils.listToMap(tmpExperts, MeetingExpert::getExpertId); | |||
// 统计通知中与同意参加专家数量 | |||
Map<Long, ExpertCntBO> countMap = countByAgree(expertMap); | |||
Map<Long, ExpertCntBO> countMap = countByAttendStatus(expertMap); | |||
ExpertCntBO cnt = countMap.getOrDefault(ruleId, ExpertCntBO.zeroInit()); | |||
int wouldAttendCnt = cnt.getAgreeCnt() + cnt.getNoticeCnt(); | |||
if (wouldAttendCnt == value.getCount()) { | |||
@@ -259,7 +256,7 @@ public class ExpertInviteTask { | |||
} | |||
int needInviteCnt = value.getCount() - wouldAttendCnt; | |||
ExpertChooseDTO expertChoose = expertInviteManage.expertReplaceByRandomRule(avoidRule, value, | |||
tmpExperts, needInviteCnt, msTime, meTime, tsTime, invitedRefused); | |||
tmpExperts, needInviteCnt, msTime, meTime, tsTime, reInvite); | |||
if (expertChoose.getTotal() > 0) { | |||
List<MeetingExpert> expertMeetings = CollUtils.convert(expertChoose.getExperts(), w -> { | |||
@@ -297,20 +294,18 @@ public class ExpertInviteTask { | |||
//================================================================================================================== | |||
private Map<Long, ExpertCntBO> countByAgree(Map<Long, MeetingExpert> expertMap) { | |||
return expertMap.entrySet().stream() | |||
.collect(Collectors.groupingBy(w -> w.getValue().getRuleId(), | |||
Collectors.collectingAndThen(Collectors.mapping(Map.Entry::getValue, Collectors.toList()), w -> { | |||
ExpertCntBO cnt = ExpertCntBO.zeroInit(); | |||
for (MeetingExpert expert : w) { | |||
if (ExpertAttendStatusEnum.AGREED.eq(expert.getStatus())) { | |||
cnt.incrAgreeCnt(); | |||
} else if (ExpertAttendStatusEnum.NOTICING.eq(expert.getStatus())) { | |||
cnt.incrNoticeCnt(); | |||
} | |||
} | |||
return cnt; | |||
}))); | |||
private Map<Long, ExpertCntBO> countByAttendStatus(Map<Long, MeetingExpert> expertMap) { | |||
Map<Long, ExpertCntBO> cntMap = new HashMap<>(8); | |||
expertMap.values().forEach(w -> { | |||
Long ruleId = w.getRuleId(); | |||
ExpertCntBO cnt = cntMap.computeIfAbsent(ruleId, k -> ExpertCntBO.zeroInit()); | |||
if (ExpertAttendStatusEnum.AGREED.eq(w.getStatus())) { | |||
cnt.incrAgreeCnt(); | |||
} else if (ExpertAttendStatusEnum.NOTICING.eq(w.getStatus())) { | |||
cnt.incrNoticeCnt(); | |||
} | |||
}); | |||
return cntMap; | |||
} | |||
@Data | |||
@@ -37,4 +37,9 @@ public class RandomInviteProperties { | |||
* 会议抽取完成通知 管理员下发会议通知 | |||
*/ | |||
private Integer meetingInviteCompleteNoticeRate = 1; | |||
/** | |||
* 近期会议数量(以此来降低专家抽中间隔) | |||
*/ | |||
private Integer recentMeetingCount = 5; | |||
} |