Commit a3f9b5f1 by 朱海

[chg]顾客批次,店内区域匹配修改逻辑

1 parent 351cd534
package com.viontech.keliu.dao;
import com.viontech.keliu.entity.DPersonBatch;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
/**
* Created with IntelliJ IDEA.
*
* @author: zhuhai
* Date: 2024-05-30
* Time: 18:04
*/
@Repository
public class DPersonBatchDao {
@Resource
private JdbcTemplate jdbcTemplate;
public List<DPersonBatch> getPersonBatchList(Long mallId, Date countDate) {
String sql = "select * from d_person_batch where mall_id = ? and count_date = ?";
return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(DPersonBatch.class), mallId, countDate);
}
}
...@@ -52,7 +52,7 @@ public class FaceRecognitionDao { ...@@ -52,7 +52,7 @@ public class FaceRecognitionDao {
} }
public List<Person> queryFaceRecognitionList(Long mallId, Date countDate) { public List<Person> queryFaceRecognitionList(Long mallId, Date countDate) {
String sql = "select account_id,mall_id,gate_id,person_unid,direction,countdate as countDate,person_type,age,gender," + String sql = "select account_id,mall_id,gate_id,person_unid,direction,track_time,countdate as countDate,person_type,age,gender," +
"counttime as countTime from d_face_recognition where mall_id = ? and countdate = ? " + "counttime as countTime from d_face_recognition where mall_id = ? and countdate = ? " +
"and direction in(-1,1,6) order by person_unid asc, counttime asc;"; "and direction in(-1,1,6) order by person_unid asc, counttime asc;";
......
package com.viontech.keliu.entity;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* Created with IntelliJ IDEA.
* 接待详情表
* @author: zhuhai
* Date: 2023-12-20
* Time: 16:23
*/
@Data
public class DPersonBatch implements Serializable {
private static final long serialVersionUID = -8440383229421767268L;
private Long id;
private Long accountId;
private Long mallId;
private String personUnid;
/**
* 进店时间
*/
private Date arriveTime;
/**
* 离店时间
*/
private Date leaveTime;
private Date countDate;
private String batchId;
}
\ No newline at end of file \ No newline at end of file
...@@ -24,5 +24,6 @@ public class Person { ...@@ -24,5 +24,6 @@ public class Person {
private Integer direction; private Integer direction;
private Integer age; private Integer age;
private Integer gender; private Integer gender;
private Integer trackTime;
} }
\ No newline at end of file \ No newline at end of file
package com.viontech.keliu.service.impl; package com.viontech.keliu.service.impl;
import cn.hutool.core.collection.ListUtil; import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Matcher; import cn.hutool.core.lang.Matcher;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.viontech.keliu.dao.BGateDao; import com.viontech.keliu.dao.BGateDao;
import com.viontech.keliu.dao.ConfigParamDao; import com.viontech.keliu.dao.ConfigParamDao;
import com.viontech.keliu.dao.DPersonBatchDao;
import com.viontech.keliu.dao.DPersonReceptionDao; import com.viontech.keliu.dao.DPersonReceptionDao;
import com.viontech.keliu.dao.DPersonRecordDao; import com.viontech.keliu.dao.DPersonRecordDao;
import com.viontech.keliu.dao.DPersonTrackDetailDao; import com.viontech.keliu.dao.DPersonTrackDetailDao;
import com.viontech.keliu.dao.FaceRecognitionDao; import com.viontech.keliu.dao.FaceRecognitionDao;
import com.viontech.keliu.entity.DPersonBatch;
import com.viontech.keliu.entity.DPersonReception; import com.viontech.keliu.entity.DPersonReception;
import com.viontech.keliu.entity.DPersonRecord; import com.viontech.keliu.entity.DPersonRecord;
import com.viontech.keliu.entity.DPersonTrackDetail; import com.viontech.keliu.entity.DPersonTrackDetail;
...@@ -19,6 +22,7 @@ import lombok.extern.slf4j.Slf4j; ...@@ -19,6 +22,7 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.ArrayList; import java.util.ArrayList;
...@@ -59,9 +63,17 @@ public class PersonRecordServiceImpl implements PersonRecordService { ...@@ -59,9 +63,17 @@ public class PersonRecordServiceImpl implements PersonRecordService {
@Resource @Resource
private DPersonTrackDetailDao dPersonTrackDetailDao; private DPersonTrackDetailDao dPersonTrackDetailDao;
@Resource
private DPersonBatchDao dPersonBatchDao;
@Value("${attention.time.threshold:30}") @Value("${attention.time.threshold:30}")
private Long attentionThreshold; private Long attentionThreshold;
@Value("${reid.person.batch.mall:}")
private List<Long> personBatchMallIds;
@Override @Override
public void handlePersonRecord(Long mallId, Date countDate) { public void handlePersonRecord(Long mallId, Date countDate) {
...@@ -136,10 +148,14 @@ public class PersonRecordServiceImpl implements PersonRecordService { ...@@ -136,10 +148,14 @@ public class PersonRecordServiceImpl implements PersonRecordService {
//按进店时间排序 //按进店时间排序
List<PersonInOutDetail> inOutDetailList = personInOutDetailList.stream().sorted(Comparator.comparing(PersonInOutDetail::getArriveTime)).collect(Collectors.toList()); List<PersonInOutDetail> inOutDetailList = personInOutDetailList.stream().sorted(Comparator.comparing(PersonInOutDetail::getArriveTime)).collect(Collectors.toList());
//处理分组信息 List<PersonInOutDetail> customerList = inOutDetailList.stream().filter(p -> p.getPersonType() == 0).collect(Collectors.toList());
inOutDetailList = personGroupCompute(mallId, inOutDetailList); //处理顾客分组信息
customerList = personGroupCompute(mallId, customerList, countDate);
List<DPersonRecord> dPersonRecordList = handlePersonRecordData(inOutDetailList); List<PersonInOutDetail> staffList = inOutDetailList.stream().filter(p -> p.getPersonType() == 1).collect(Collectors.toList());
List<PersonInOutDetail> allList = new ArrayList<>();
allList.addAll(customerList);
allList.addAll(staffList);
List<DPersonRecord> dPersonRecordList = handlePersonRecordData(allList);
for (DPersonRecord dPersonRecord : dPersonRecordList) { for (DPersonRecord dPersonRecord : dPersonRecordList) {
dPersonRecordDao.createDPersonRecordBatch(Collections.singletonList(dPersonRecord)); dPersonRecordDao.createDPersonRecordBatch(Collections.singletonList(dPersonRecord));
if (CollectionUtils.isNotEmpty(dPersonRecord.getPersonTrackDetailList())) { if (CollectionUtils.isNotEmpty(dPersonRecord.getPersonTrackDetailList())) {
...@@ -158,40 +174,60 @@ public class PersonRecordServiceImpl implements PersonRecordService { ...@@ -158,40 +174,60 @@ public class PersonRecordServiceImpl implements PersonRecordService {
* @param personList * @param personList
* @return * @return
*/ */
private List<PersonInOutDetail> personGroupCompute(Long mallId, List<PersonInOutDetail> personList) { private List<PersonInOutDetail> personGroupCompute(Long mallId, List<PersonInOutDetail> personList, Date countDate) {
List<PersonInOutDetail> resultList = new ArrayList<>(); List<PersonInOutDetail> resultList = new ArrayList<>();
//获取分组间隔配置 //获取分组间隔配置
String configValue = configParamDao.getConfigParamByMallIdAndConfigKey(mallId, "personGroupInterval"); String configValue = configParamDao.getConfigParamByMallIdAndConfigKey(mallId, "personGroupInterval");
if (configValue == null) { if (configValue == null) {
return personList; return personList;
} }
long interval = Long.parseLong(configValue); if (CollectionUtils.isNotEmpty(personBatchMallIds) && personBatchMallIds.contains(mallId)) {
for (int i = 0; i < personList.size() - 1; ++i) { //先判断是否从全天分析获取了批次信息,如果有,使用全天分析的批次结果
PersonInOutDetail pvo1 = personList.get(i); List<DPersonBatch> personBatchList = dPersonBatchDao.getPersonBatchList(mallId, countDate);
PersonInOutDetail pvo2 = personList.get(i + 1); if (CollectionUtils.isNotEmpty(personBatchList)) {
Long time1 = pvo1.getArriveTime().getTime(); Map<String, String> batchMap = personBatchList.stream().collect(Collectors.toMap(v -> v.getPersonUnid() + DateUtil.formatDateTime(v.getArriveTime()), DPersonBatch::getBatchId, (v1, v2) -> v1));
Long time2 = pvo2.getArriveTime().getTime(); for (PersonInOutDetail personInOutDetail : personList) {
long seconds = (time2 - time1) / 1000L; String key = personInOutDetail.getPersonUnid() + DateUtil.formatDateTime(personInOutDetail.getArriveTime());
//同一组顾客 String batchId = batchMap.get(key);
if (seconds < interval) { if (StringUtils.hasLength(batchId)) {
if (pvo1.getGroupUnid() == null) { personInOutDetail.setGroupUnid(batchId);
pvo1.setGroupUnid(UUID.randomUUID().toString()); } else {
} personInOutDetail.setGroupUnid(UUID.randomUUID().toString());
pvo2.setGroupUnid(pvo1.getGroupUnid()); }
resultList.add(personInOutDetail);
} else {
//不是同一组顾客
if (pvo1.getGroupUnid() == null) {
pvo1.setGroupUnid(UUID.randomUUID().toString());
} }
pvo2.setGroupUnid(UUID.randomUUID().toString()); return resultList;
}
resultList.add(pvo1);
if (i == personList.size() - 2) {
resultList.add(pvo2);
} }
} }
if (CollectionUtils.isEmpty(resultList)) {
long interval = Long.parseLong(configValue);
for (int i = 0; i < personList.size() - 1; ++i) {
PersonInOutDetail pvo1 = personList.get(i);
PersonInOutDetail pvo2 = personList.get(i + 1);
Long time1 = pvo1.getArriveTime().getTime();
Long time2 = pvo2.getArriveTime().getTime();
long seconds = (time2 - time1) / 1000L;
//同一组顾客
if (seconds < interval) {
if (pvo1.getGroupUnid() == null) {
pvo1.setGroupUnid(UUID.randomUUID().toString());
}
pvo2.setGroupUnid(pvo1.getGroupUnid());
} else {
//不是同一组顾客
if (pvo1.getGroupUnid() == null) {
pvo1.setGroupUnid(UUID.randomUUID().toString());
}
pvo2.setGroupUnid(UUID.randomUUID().toString());
}
resultList.add(pvo1);
if (i == personList.size() - 2) {
resultList.add(pvo2);
}
}
}
return resultList; return resultList;
} }
...@@ -303,21 +339,61 @@ public class PersonRecordServiceImpl implements PersonRecordService { ...@@ -303,21 +339,61 @@ public class PersonRecordServiceImpl implements PersonRecordService {
} }
//进出匹配的 //进出匹配的
if (person.getDirection() == -1 && arrivePerson != null) { if (person.getDirection() == -1 && arrivePerson != null) {
DPersonTrackDetail personTrackDetail = new DPersonTrackDetail(); Date arriveTime = arrivePerson.getCountTime();
personTrackDetail.setAccountId(person.getAccountId()); Date leaveTime = person.getCountTime();
personTrackDetail.setMallId(person.getMallId()); long milli = leaveTime.getTime() - arriveTime.getTime();
personTrackDetail.setGateId(person.getGateId()); //停留时长超过5分钟,需要将改匹配对进行拆分
personTrackDetail.setPersonUnid(person.getPersonUnid()); if (milli >= 300000L && personBatchMallIds.contains(person.getMallId())) {
personTrackDetail.setGroupUnid(groupUnid); log.info("personUnid:{},在区域内停留时间超过5分钟,进行拆分", person.getPersonUnid());
personTrackDetail.setArriveTime(arrivePerson.getCountTime()); Integer inTrackTime = arrivePerson.getTrackTime();
personTrackDetail.setLeaveTime(person.getCountTime()); if (inTrackTime != null && inTrackTime > 0) {
long milli = personTrackDetail.getLeaveTime().getTime() - personTrackDetail.getArriveTime().getTime(); DPersonTrackDetail personTrackDetail = new DPersonTrackDetail();
personTrackDetail.setVisitDuration(milli); personTrackDetail.setAccountId(person.getAccountId());
personTrackDetail.setIsEngage(isEngage); personTrackDetail.setMallId(person.getMallId());
personTrackDetail.setEngageTime(engageTime); personTrackDetail.setGateId(person.getGateId());
personTrackDetail.setCountDate(person.getCountDate()); personTrackDetail.setPersonUnid(person.getPersonUnid());
personTrackDetail.setGroupUnid(groupUnid);
personTrackDetail.setArriveTime(arriveTime);
personTrackDetail.setLeaveTime(DateUtil.offsetSecond(arriveTime, inTrackTime));
personTrackDetail.setVisitDuration(personTrackDetail.getLeaveTime().getTime() - personTrackDetail.getArriveTime().getTime());
personTrackDetail.setIsEngage(isEngage);
personTrackDetail.setEngageTime(engageTime);
personTrackDetail.setCountDate(person.getCountDate());
dPersonTrackDetailList.add(personTrackDetail);
}
Integer outTrackTime = person.getTrackTime();
if (outTrackTime != null && outTrackTime > 0) {
DPersonTrackDetail personTrackDetail = new DPersonTrackDetail();
personTrackDetail.setAccountId(person.getAccountId());
personTrackDetail.setMallId(person.getMallId());
personTrackDetail.setGateId(person.getGateId());
personTrackDetail.setPersonUnid(person.getPersonUnid());
personTrackDetail.setGroupUnid(groupUnid);
personTrackDetail.setArriveTime(DateUtil.offsetSecond(leaveTime, -outTrackTime));
personTrackDetail.setLeaveTime(leaveTime);
personTrackDetail.setVisitDuration(personTrackDetail.getLeaveTime().getTime() - personTrackDetail.getArriveTime().getTime());
personTrackDetail.setIsEngage(isEngage);
personTrackDetail.setEngageTime(engageTime);
personTrackDetail.setCountDate(person.getCountDate());
dPersonTrackDetailList.add(personTrackDetail);
}
} else {
DPersonTrackDetail personTrackDetail = new DPersonTrackDetail();
personTrackDetail.setAccountId(person.getAccountId());
personTrackDetail.setMallId(person.getMallId());
personTrackDetail.setGateId(person.getGateId());
personTrackDetail.setPersonUnid(person.getPersonUnid());
personTrackDetail.setGroupUnid(groupUnid);
personTrackDetail.setArriveTime(arriveTime);
personTrackDetail.setLeaveTime(leaveTime);
personTrackDetail.setVisitDuration(personTrackDetail.getLeaveTime().getTime() - personTrackDetail.getArriveTime().getTime());
personTrackDetail.setIsEngage(isEngage);
personTrackDetail.setEngageTime(engageTime);
personTrackDetail.setCountDate(person.getCountDate());
dPersonTrackDetailList.add(personTrackDetail);
}
arrivePerson = null; arrivePerson = null;
dPersonTrackDetailList.add(personTrackDetail);
} }
isEngage = 0; isEngage = 0;
engageTime = null; engageTime = null;
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!