Commit db4da0c2 by 朱海

[init]4s顾客批次统计项目初始化

0 parents
Showing 40 changed files with 2271 additions and 0 deletions
### Java template
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
replay_pid*
######################################################################
# Build Tools
.gradle
/build/
!gradle/wrapper/gradle-wrapper.jar
target/
!.mvn/wrapper/maven-wrapper.jar
######################################################################
# IDE
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
nbproject/private/
build/*
nbbuild/
dist/
nbdist/
.nb-gradle/
######################################################################
# Others
*.log
*.xml.versionsBackup
*.swp
!*/build/*.java
!*/build/*.html
!*/build/*.xml
### JRebel ###
rebel.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.viontech.keliu</groupId>
<artifactId>VVAS-PicGroup</artifactId>
<version>1.0-SNAPSHOT</version>
<name>VVAS-PicGroup</name>
<dependencies>
<!--<dependency>
<groupId>com.viontech.keliu</groupId>
<artifactId>VVAS-DataSync-Core</artifactId>
<version>${project.version}</version>
</dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.mks.api</groupId>
<artifactId>mksapi-jar</artifactId>
<version>4.10.9049</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.minidev</groupId>
<artifactId>json-smart</artifactId>
<version>2.2.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.10</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.9</version>
</dependency>
</dependencies>
<build>
<finalName>VVAS-PicGroup</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<excludes>
<exclude>application-*.properties</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file \ No newline at end of file
package com.viontech.keliu;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableScheduling;
import java.util.concurrent.CountDownLatch;
/**
* Created with IntelliJ IDEA.
*
* @author: zhuhai
* Date: 2022-10-31
* Time: 20:51
*/
@SpringBootApplication
@EnableScheduling
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
package com.viontech.keliu;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import java.util.Date;
/**
* Created with IntelliJ IDEA.
*
* @author: zhuhai
* Date: 2023-03-28
* Time: 10:57
*/
public class Test {
public static void main(String[] args) {
DateTime dateTime = DateUtil.beginOfHour(new Date());
System.out.println(dateTime);
System.out.println(DateUtil.hour(new Date(), true));
System.out.println(DateUtil.dayOfMonth(new Date()));
System.out.println(DateUtil.dayOfWeek(new Date()));
System.out.println(DateUtil.dayOfYear(new Date()));
}
}
\ No newline at end of file \ No newline at end of file
package com.viontech.keliu.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* Created with IntelliJ IDEA.
*
* @author: zhuhai
* Date: 2022-10-31
* Time: 23:08
*/
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
//1,允许任何来源
corsConfiguration.addAllowedOriginPattern("*");
//2,允许任何请求头
corsConfiguration.addAllowedHeader(CorsConfiguration.ALL);
//3,允许任何方法
corsConfiguration.addAllowedMethod(CorsConfiguration.ALL);
//4,允许凭证
corsConfiguration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", corsConfiguration);
return new CorsFilter(source);
}
}
\ No newline at end of file \ No newline at end of file
package com.viontech.keliu.config;
import cn.hutool.core.thread.RejectPolicy;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.ThreadPoolExecutor;
@Configuration
public class ThreadConfig {
@Value("${thread.max.pool.size:40}")
private Integer maxPoolSize;
@Value("${thread.core.pool.size:20}")
private Integer centerPoolSize;
@Bean
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
threadPoolTaskExecutor.setMaxPoolSize(maxPoolSize);
threadPoolTaskExecutor.setCorePoolSize(centerPoolSize);
threadPoolTaskExecutor.setQueueCapacity(50);
threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
threadPoolTaskExecutor.setThreadNamePrefix("personGroup-");
return threadPoolTaskExecutor;
}
}
package com.viontech.keliu.controller;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.fastjson.JSON;
import com.viontech.keliu.dao.DataCountDao;
import com.viontech.keliu.vo.MallVo;
import com.viontech.keliu.vo.PersonVo;
import com.viontech.keliu.vo.ResultVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* Created with IntelliJ IDEA.
*
* @author: zhuhai
* Date: 2022-10-31
* Time: 21:00
*/
@RestController
public class DataCountController {
@Autowired
private DataCountDao dataCountDao;
private static final Logger logger = LoggerFactory.getLogger(DataCountController.class);
public DataCountController() {
}
@GetMapping({"/personGroup"})
public Object getPersonGroup(@RequestParam("countdate") @DateTimeFormat(pattern = "yyyy-MM-dd") Date countdate, @RequestParam("accountid") Integer accountid) {
List<ResultVo> resultVos = new ArrayList();
try {
List<PersonVo> personVos = this.dataCountDao.get_person(countdate, accountid);
List<MallVo> mallVos = this.dataCountDao.get_malls(accountid);
resultVos = this.getPersonList(mallVos, personVos);
} catch (Exception ex) {
logger.info("抓拍数据分组出错{}",ex.getMessage());
}
HashMap<String, Object> result = new HashMap();
if (resultVos.size() > 0) {
List<ResultVo> resultVoList = resultVos.stream().sorted(Comparator.comparing(ResultVo::getCount_person).reversed()).collect(Collectors.toList());
result.put("msg_code", 200);
result.put("msg_info", "成功");
result.put("data", resultVoList);
} else {
result.put("msg_code", 506);
result.put("msg_info", "数据为空");
result.put("data", resultVos);
}
return result;
}
@GetMapping({"/personDownload"})
public void exportExcel(@RequestParam Integer accountid, @RequestParam("countdate") Date countdate, HttpServletResponse response) throws IOException {
List<PersonVo> personVos = this.dataCountDao.get_person(countdate, accountid);
List<MallVo> mallVos = this.dataCountDao.get_malls(accountid);
List<ResultVo> resultVos = this.getPersonList(mallVos, personVos);
try {
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
String fileName = URLEncoder.encode("抓拍分组-" + DateTimeFormatter.ofPattern("yyyyMMddHHmmss").format(LocalDateTime.now()), "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
((ExcelWriterBuilder) EasyExcel.write(response.getOutputStream(), ResultVo.class).head(this.titleHead())).autoCloseStream(Boolean.FALSE).sheet("模板").doWrite(resultVos);
} catch (IOException var9) {
response.reset();
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
Map<String, String> map = new HashMap(2);
map.put("status", "failure");
map.put("message", "下载文件失败" + var9.getMessage());
response.getWriter().println(JSON.toJSONString(map));
}
}
public List<ResultVo> getPersonList(List<MallVo> mallVos, List<PersonVo> personVos) {
List<ResultVo> resultVos = new ArrayList();
Iterator iterator = mallVos.iterator();
while(iterator.hasNext()) {
MallVo mall = (MallVo) iterator.next();
ResultVo resultVo = new ResultVo();
resultVo.setMall_name(mall.getName());
List<PersonVo> tempList = personVos.stream().filter((p) -> p.getMall_id().equals(mall.getId())).collect(Collectors.toList());
if (tempList.size() == 0) {
resultVo.setClerk_num("-");
resultVo.setCount_person("-");
resultVo.setCustomer_num("-");
resultVo.setCustomer_adult("-");
resultVo.setCustomer_child("-");
resultVo.setCustomer_alone("-");
resultVo.setCustomer_group("-");
resultVos.add(resultVo);
} else {
resultVo.setCount_person(String.valueOf(tempList.size()));
Integer clerkNum = (tempList.stream().filter((t) -> t.getPerson_type().equals(1)).collect(Collectors.toList())).size();
resultVo.setClerk_num(String.valueOf(clerkNum));
List<PersonVo> customerList = (tempList.stream().filter((t) -> t.getPerson_type().equals(0)).collect(Collectors.toList())).stream().sorted(Comparator.comparing(PersonVo::getCounttime)).collect(Collectors.toList());
resultVo.setCustomer_num(String.valueOf(customerList.size()));
Integer customerAdultNum = 0;
Integer customerChildNum = 0;
for (PersonVo personVo : customerList) {
Integer mood = personVo.getMood();
if (mood == null) {
continue;
}
if (mood.equals(108)) {
customerAdultNum += 1;
} else if (mood.equals(107)) {
customerChildNum += 1;
}
}
resultVo.setCustomer_adult(String.valueOf(customerAdultNum));
resultVo.setCustomer_child(String.valueOf(customerChildNum));
int customer_alone = 0;
int customer_group = 0;
StringBuilder str = new StringBuilder();
for (int i = 0; i < customerList.size() - 1; ++i) {
PersonVo pvo1 = customerList.get(i);
PersonVo pvo2 = customerList.get(i + 1);
Long time1 = pvo1.getCounttime().getTime();
Long time2 = pvo2.getCounttime().getTime();
int seconds = (int) ((time2 - time1) / 1000L);
if (i == 0) {
str.append(pvo1.getMood());
}
if (seconds <= 6) {
str.append(",").append(pvo2.getMood());
} else {
str.append("#").append(pvo2.getMood());
}
}
String[] group = str.toString().split("#");
for (String s : group) {
String[] split = s.split(",");
//单独的加一
if (split.length == 1) {
customer_alone += 1;
} else {
//分组加一
customer_group += 1;
}
}
resultVo.setCustomer_alone(String.valueOf(customer_alone));
resultVo.setCustomer_group(String.valueOf(customer_group));
resultVos.add(resultVo);
}
}
return resultVos;
}
private List<List<String>> titleHead() {
List<List<String>> list = new ArrayList();
List<String> head0 = new ArrayList();
head0.add("广场名称");
List<String> head1 = new ArrayList();
head1.add("总人数");
List<String> head2 = new ArrayList();
head2.add("店员人数");
List<String> head3 = new ArrayList();
head3.add("顾客人数");
List<String> head4 = new ArrayList();
head4.add("顾客组数(30秒)");
List<String> head5 = new ArrayList();
head5.add("顾客组数(60秒)");
list.add(head0);
list.add(head1);
list.add(head2);
list.add(head3);
list.add(head4);
list.add(head5);
return list;
}
}
\ No newline at end of file \ No newline at end of file
package com.viontech.keliu.controller;
import cn.hutool.core.collection.ListUtil;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Created with IntelliJ IDEA.
*
* @author: zhuhai
* Date: 2024-01-04
* Time: 14:10
*/
public class Test {
public static void main(String[] args) {
List<String> list = Arrays.asList("1","0","-1","-1");
int[] indexs = ListUtil.indexOfAll(list, "1"::equals);
for (int i = 0; i < indexs.length; i++) {
List<String> strings;
if (i == indexs.length - 1) {
strings = list.subList(indexs[i], list.size());
} else {
strings = list.subList(indexs[i],indexs[i+1]);
}
System.out.println(String.join(",", strings));
System.out.println("-------------------");
}
}
}
\ No newline at end of file \ No newline at end of file
package com.viontech.keliu.controller;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.viontech.keliu.service.PersonGroupService;
import com.viontech.keliu.service.PersonRecordService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
/**
* Created with IntelliJ IDEA.
*
* @author: zhuhai
* Date: 2022-11-03
* Time: 15:15
*/
@RestController
@RequestMapping("/tool")
public class ToolController {
@Resource
private PersonRecordService personRecordService;
/*@Resource
private PersonGroupService personGroupService;*/
/*@GetMapping("/buildData")
public String buildData(String startDate, String endDate) {
DateTime startDateTime = DateUtil.parse(startDate, "yyyy-MM-dd");
DateTime endDateTime = DateUtil.parse(endDate, "yyyy-MM-dd");
List<DateTime> dateTimes = DateUtil.rangeToList(startDateTime, endDateTime, DateField.DAY_OF_MONTH);
for (DateTime dateTime : dateTimes) {
personGroupService.personToGroup(mallIdList, dateTime);
}
return "success";
}*/
@GetMapping("/build/personRecord")
public String buildPersonRecord(Long mallId, String startDate, String endDate) {
DateTime startDateTime = DateUtil.parse(startDate, "yyyy-MM-dd");
DateTime endDateTime = DateUtil.parse(endDate, "yyyy-MM-dd");
List<DateTime> dateTimes = DateUtil.rangeToList(startDateTime, endDateTime, DateField.DAY_OF_MONTH);
for (DateTime dateTime : dateTimes) {
personRecordService.handlePersonRecord(mallId, dateTime);
}
return "success";
}
}
\ No newline at end of file \ No newline at end of file
package com.viontech.keliu.dao;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import javax.annotation.Resource;
import java.util.List;
/**
* Created with IntelliJ IDEA.
*
* @author: zhuhai
* Date: 2023-12-22
* Time: 17:38
*/
@Repository
public class BGateDao {
@Resource
private JdbcTemplate jdbcTemplate;
/**
* 获取门店出入口监控点
* @param mallId
* @return
*/
public List<Long> getMallInOutGateIds(Long mallId) {
String sql = "select id from b_gate where mall_id = ? and is_mall_gate = 1;";
return jdbcTemplate.queryForList(sql, Long.class, mallId);
}
/**
* 获取门店内的监控点
* @param mallId
* @return
*/
public List<Long> getMallInsideGateIds(Long mallId) {
String sql = "select id from b_gate where mall_id = ? and is_mall_gate = 0;";
return jdbcTemplate.queryForList(sql, Long.class, mallId);
}
}
\ No newline at end of file \ No newline at end of file
package com.viontech.keliu.dao;
import com.viontech.keliu.entity.SConfigParam;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;
/**
* Created with IntelliJ IDEA.
*
* @author: zhuhai
* Date: 2023-12-23
* Time: 14:29
*/
@Repository
public class ConfigParamDao {
@Resource
private JdbcTemplate jdbcTemplate;
public String getConfigParamByMallIdAndConfigKey(Long mallId, String configKey) {
String sql = "select mall_id, config_key, config_value from s_config_params where (mall_id = ? or mall_id is null) and config_key = ? order by mall_id asc limit 1;";
SConfigParam configParam = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(SConfigParam.class), mallId, configKey);
return configParam == null ? null : configParam.getConfigValue();
}
}
\ No newline at end of file \ No newline at end of file
package com.viontech.keliu.dao;
import com.viontech.keliu.entity.DMallPersonGroupDayCountData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import java.util.Date;
import java.util.List;
/**
* Created with IntelliJ IDEA.
*
* @author: zhuhai
* Date: 2022-11-02
* Time: 19:32
*/
@Repository
public class DMallPersonGroupDayCountDataDao {
@Autowired
private JdbcTemplate jdbcTemplate;
private static final String SQL_INSERT = "insert into d_mall_person_group_day_count_data(mall_id,count_date,total_person_num,staff_num,customer_num,customer_adult_num,customer_child_num,customer_alone,customer_group) values(?,?,?,?,?,?,?,?,?)";
private static final String SQL_QUERY = "select id, mall_id,count_date,total_person_num,staff_num,customer_num,customer_adult_num,customer_child_num,customer_alone,customer_group from d_mall_person_group_day_count_data where count_date=? and mall_id = ?";
private static final String SQL_UPDATE = "update d_mall_person_group_day_count_data set total_person_num = ?, staff_num = ?, customer_num = ?, customer_adult_num = ?, customer_child_num = ?, customer_alone = ?, customer_group = ? where id = ?";
public void create(DMallPersonGroupDayCountData countData) {
jdbcTemplate.update(SQL_INSERT, countData.getMallId(), countData.getCountDate(), countData.getTotalPersonNum(), countData.getStaffNum(), countData.getCustomerNum(), countData.getCustomerAdultNum(), countData.getCustomerChildNum(), countData.getCustomerAlone(), countData.getCustomerGroup());
}
public List<DMallPersonGroupDayCountData> selectByMallIdAndCountDate(Long mallId, Date countDate) {
RowMapper<DMallPersonGroupDayCountData> rowMapper = new BeanPropertyRowMapper<>(DMallPersonGroupDayCountData.class);
return jdbcTemplate.query(SQL_QUERY, rowMapper, countDate, mallId);
}
public void update(DMallPersonGroupDayCountData countData) {
jdbcTemplate.update(SQL_UPDATE, countData.getTotalPersonNum(), countData.getStaffNum(), countData.getCustomerNum(), countData.getCustomerAdultNum(), countData.getCustomerChildNum(), countData.getCustomerAlone(), countData.getCustomerGroup(), countData.getId());
}
}
\ No newline at end of file \ No newline at end of file
package com.viontech.keliu.dao;
import com.viontech.keliu.entity.DMallPersonGroupDayCountData;
import com.viontech.keliu.entity.DMallPersonGroupHourCountData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import java.util.Date;
import java.util.List;
/**
* Created with IntelliJ IDEA.
*
* @author: zhuhai
* Date: 2023-03-28
* Time: 19:32
*/
@Repository
public class DMallPersonGroupHourCountDataDao {
@Autowired
private JdbcTemplate jdbcTemplate;
private static final String SQL_INSERT = "insert into d_mall_person_group_hour_count_data(mall_id,count_date,total_person_num,staff_num,customer_num,customer_adult_num,customer_child_num,customer_alone,customer_group,count_time,hour) values(?,?,?,?,?,?,?,?,?,?,?)";
private static final String SQL_QUERY = "select id, mall_id,count_date,total_person_num,staff_num,customer_num,customer_adult_num,customer_child_num,customer_alone,customer_group,count_time,hour from d_mall_person_group_hour_count_data where count_date=? and mall_id = ? and count_time= ?";
private static final String SQL_UPDATE = "update d_mall_person_group_hour_count_data set total_person_num = ?, staff_num = ?, customer_num = ?, customer_adult_num = ?, customer_child_num = ?, customer_alone = ?, customer_group = ? where id = ?";
public void create(DMallPersonGroupHourCountData countData) {
jdbcTemplate.update(SQL_INSERT, countData.getMallId(), countData.getCountDate(), countData.getTotalPersonNum(), countData.getStaffNum(), countData.getCustomerNum(), countData.getCustomerAdultNum(), countData.getCustomerChildNum(), countData.getCustomerAlone(), countData.getCustomerGroup(), countData.getCountTime(), countData.getHour());
}
public List<DMallPersonGroupHourCountData> selectByMallIdAndCountDate(Long mallId, Date countDate, Date countTime) {
RowMapper<DMallPersonGroupHourCountData> rowMapper = new BeanPropertyRowMapper<>(DMallPersonGroupHourCountData.class);
return jdbcTemplate.query(SQL_QUERY, rowMapper, countDate, mallId, countTime);
}
public void update(DMallPersonGroupHourCountData countData) {
jdbcTemplate.update(SQL_UPDATE, countData.getTotalPersonNum(), countData.getStaffNum(), countData.getCustomerNum(), countData.getCustomerAdultNum(), countData.getCustomerChildNum(), countData.getCustomerAlone(), countData.getCustomerGroup(), countData.getId());
}
}
\ No newline at end of file \ No newline at end of file
package com.viontech.keliu.dao;
import com.viontech.keliu.entity.DPersonReception;
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: 2023-12-23
* Time: 15:51
*/
@Repository
public class DPersonReceptionDao {
@Resource
private JdbcTemplate jdbcTemplate;
public List<DPersonReception> getPersonReceptionList(Long mallId, Date countDate, String personUnid, Date startTime, Date endTime) {
String sql = "select * from d_person_reception where mall_id = ? and count_date = ? and person_unid = ? and start_time >= ? and end_time <= ? order by start_time;";
return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(DPersonReception.class), mallId, countDate, personUnid, startTime, endTime);
}
}
\ No newline at end of file \ No newline at end of file
package com.viontech.keliu.dao;
import com.viontech.keliu.entity.DPersonRecord;
import com.viontech.keliu.entity.DPersonTrackDetail;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.core.namedparam.SqlParameterSourceUtils;
import org.springframework.stereotype.Repository;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
/**
* Created with IntelliJ IDEA.
*
* @author: zhuhai
* Date: 2023-12-22
* Time: 9:28
*/
@Repository
public class DPersonRecordDao {
@Resource
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
@Resource
private JdbcTemplate jdbcTemplate;
public void createDPersonRecordBatch(List<DPersonRecord> personRecordList) {
SqlParameterSource[] batch = SqlParameterSourceUtils.createBatch(personRecordList.toArray());
String sql = "insert into d_person_record (mall_id,account_id,count_date,person_unid,group_unid,age,gender,person_type,arrive_time, leave_time, " +
"visit_count, visit_duration, engage_count,engage_time,reception_count,reception_duration,attention_count,attention_time)" +
" values(:mallId,:accountId,:countDate,:personUnid,:groupUnid,:age,:gender,:personType,:arriveTime,:leaveTime,:visitCount,:visitDuration," +
":engageCount,:engageTime,:receptionCount,:receptionDuration,:attentionCount,:attentionTime)";
namedParameterJdbcTemplate.batchUpdate(sql, batch);
}
public void deleteData(Long mallId, Date countDate) {
String sql = "delete from d_person_record where mall_id = ? and count_date = ?";
jdbcTemplate.update(sql, mallId, countDate);
}
}
\ No newline at end of file \ No newline at end of file
package com.viontech.keliu.dao;
import com.viontech.keliu.entity.DPersonTrackDetail;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.core.namedparam.SqlParameterSourceUtils;
import org.springframework.stereotype.Repository;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
/**
* Created with IntelliJ IDEA.
*
* @author: zhuhai
* Date: 2023-12-22
* Time: 9:28
*/
@Repository
public class DPersonTrackDetailDao {
@Resource
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
@Resource
private JdbcTemplate jdbcTemplate;
public void createDPersonTrackDetailBatch(List<DPersonTrackDetail> personTrackDetailList) {
SqlParameterSource[] batch = SqlParameterSourceUtils.createBatch(personTrackDetailList.toArray());
String sql = "insert into d_person_track_detail (mall_id,account_id,gate_id,count_date,person_unid,group_unid,arrive_time, leave_time, visit_duration, is_engage)" +
" values(:mallId,:accountId,:gateId,:countDate,:personUnid,:groupUnid,:arriveTime,:leaveTime,:visitDuration,:isEngage)";
namedParameterJdbcTemplate.batchUpdate(sql, batch);
}
public void deleteData(Long mallId, Date countDate) {
String sql = "delete from d_person_track_detail where mall_id = ? and count_date = ?";
jdbcTemplate.update(sql, mallId, countDate);
}
}
\ No newline at end of file \ No newline at end of file
package com.viontech.keliu.dao;
import com.viontech.keliu.entity.Person;
import com.viontech.keliu.vo.MallVo;
import com.viontech.keliu.vo.PersonVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
/**
* Created with IntelliJ IDEA.
*
* @author: zhuhai
* Date: 2022-10-31
* Time: 20:59
*/
@Repository
public class DataCountDao {
@Resource
private JdbcTemplate jdbcTemplate;
private static final Logger logger = LoggerFactory.getLogger(DataCountDao.class);
private String SITE_SQL_PERSON_QUERY = "select person_unid,mall_id,person_type,min(counttime) as counttime,max(mood) as mood from d_face_recognition where countdate=? and direction=1 and account_id=? and gate_id in (select id from b_gate where is_mall_gate=1) \ngroup by mall_id,person_unid,person_type order by mall_id,counttime ";
private String SITE_SQL_MALL_QUERY = "select id,name from b_mall where account_id=? and status=1 order by id";
private String SQL_QUERY_PERSON_BY_MALL_ID = "select person_unid as personUnid,mall_id as mallId,person_type as personType,min(counttime) as countTime,max(mood) as mood from d_face_recognition where countdate=? and direction=1 and mall_id=? and gate_id in (select id from b_gate where mall_id = ? and is_mall_gate=1) group by mall_id,person_unid,person_type order by mall_id,counttime";
public List<PersonVo> get_person(Date countdate, Integer accountid) {
return this.jdbcTemplate.query(this.SITE_SQL_PERSON_QUERY, new Object[]{countdate, accountid}, new BeanPropertyRowMapper(PersonVo.class));
}
public List<MallVo> get_malls(Integer accountid) {
return this.jdbcTemplate.query(this.SITE_SQL_MALL_QUERY, new Object[]{accountid}, new BeanPropertyRowMapper(MallVo.class));
}
public List<Person> getPersonByMallId(Long mallId, Date countDate) {
RowMapper<Person> rowMapper = new BeanPropertyRowMapper<>(Person.class);
return jdbcTemplate.query(SQL_QUERY_PERSON_BY_MALL_ID, rowMapper, countDate, mallId, mallId);
}
}
\ No newline at end of file \ No newline at end of file
package com.viontech.keliu.dao;
import com.viontech.keliu.entity.Person;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.boot.autoconfigure.batch.BatchProperties;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Repository;
import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* Created with IntelliJ IDEA.
*
* @author: zhuhai
* Date: 2023-12-21
* Time: 16:54
*/
@Repository
public class FaceRecognitionDao {
@Resource
private JdbcTemplate jdbcTemplate;
@Resource
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
@Resource
private BGateDao bGateDao;
public List<Person> queryGateFaceRecognitionList(Long mallId, Date countDate) {
List<Long> gateIds = bGateDao.getMallInsideGateIds(mallId);
if (CollectionUtils.isEmpty(gateIds)) {
return null;
}
String sql = "select account_id,mall_id,gate_id,person_unid,direction,countdate as countDate," +
"counttime as countTime from d_face_recognition " +
"where mall_id = :mallId and countdate = :countDate and gate_id in(:gateIds) " +
"and person_type = 0 and direction in(-1,1,6) order by person_unid asc,counttime asc;";
Map<String, Object> queryMap = new HashMap<>();
queryMap.put("mallId", mallId);
queryMap.put("countDate", countDate);
queryMap.put("gateIds", gateIds);
return namedParameterJdbcTemplate.query(sql, queryMap, new BeanPropertyRowMapper<>(Person.class));
}
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," +
"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;";
return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Person.class), mallId, countDate);
}
}
\ No newline at end of file \ No newline at end of file
package com.viontech.keliu.entity;
import lombok.Data;
import java.util.Date;
/**
* Created with IntelliJ IDEA.
*
* @author: zhuhai
* Date: 2022-11-02
* Time: 18:27
*/
@Data
public class DMallPersonGroupDayCountData {
private Long id;
/**
* 广场/门店id
*/
private Long mallId;
/**
* 日期
*/
private Date countDate;
/**
* 总人数
*/
private Integer totalPersonNum;
/**
* 店员人数
*/
private Integer staffNum;
/**
* 顾客人数
*/
private Integer customerNum;
/**
* 成人顾客人数
*/
private Integer customerAdultNum;
/**
* 儿童顾客人数
*/
private Integer customerChildNum;
/**
* 独自进店人数
*/
private Integer customerAlone;
/**
* 分组数
*/
private Integer customerGroup;
private Date createTime;
private Date modifyTime;
}
\ No newline at end of file \ No newline at end of file
package com.viontech.keliu.entity;
import lombok.Data;
import java.util.Date;
/**
* Created with IntelliJ IDEA.
*
* @author: zhuhai
* Date: 2023-03-28
* Time: 11:45
*/
@Data
public class DMallPersonGroupHourCountData {
private Long id;
/**
* 广场/门店id
*/
private Long mallId;
/**
* 日期
*/
private Date countDate;
/**
* 时间
*/
private Date countTime;
/**
* 小时
*/
private Integer hour;
/**
* 总人数
*/
private Integer totalPersonNum;
/**
* 店员人数
*/
private Integer staffNum;
/**
* 顾客人数
*/
private Integer customerNum;
/**
* 成人顾客人数
*/
private Integer customerAdultNum;
/**
* 儿童顾客人数
*/
private Integer customerChildNum;
/**
* 独自进店人数
*/
private Integer customerAlone;
/**
* 分组数
*/
private Integer customerGroup;
private Date createTime;
private Date modifyTime;
}
\ No newline at end of file \ No newline at end of file
package com.viontech.keliu.entity;
import lombok.Data;
import java.util.Date;
/**
* Created with IntelliJ IDEA.
*
* @author: zhuhai
* Date: 2023-12-23
* Time: 15:49
*/
@Data
public class DPersonReception {
private Long accountId;
private Long mallId;
private String personUnid;
private Date startTime;
private Date endTime;
private Long duration;
}
\ No newline at end of file \ No newline at end of file
package com.viontech.keliu.entity;
import cn.hutool.db.DaoTemplate;
import lombok.Data;
import java.util.Date;
import java.util.List;
/**
* Created with IntelliJ IDEA.
*
* @author: zhuhai
* Date: 2023-12-21
* Time: 16:28
*/
@Data
public class DPersonRecord {
private Long id;
private Long accountId;
private Long mallId;
private String personUnid;
private String groupUnid;
private Integer age;
private Integer gender;
private Integer personType;
private Date countDate;
/**
* 进店时间
*/
private Date arriveTime;
/**
* 离店时间
*/
private Date leaveTime;
/**
* 到访次数
*/
private Integer visitCount;
/**
* 停留时间
*/
private Long visitDuration;
/**
* 试乘次数
*/
private Integer engageCount = 0;
/**
* 试乘时间
*/
private Date engageTime;
/**
* 接待次数
*/
private Integer receptionCount = 0;
/**
* 接待时间
*/
private Date receptionTime;
/**
* 接待时长
*/
private Long receptionDuration;
/**
* 看车次数
*/
private Integer attentionCount = 0;
/**
* 看车时间
*/
private Date attentionTime;
/**
* 区域记录
*/
private List<DPersonTrackDetail> personTrackDetailList;
}
\ No newline at end of file \ No newline at end of file
package com.viontech.keliu.entity;
import lombok.Data;
import java.util.Date;
/**
* Created with IntelliJ IDEA.
*
* @author: zhuhai
* Date: 2023-12-21
* Time: 16:38
*/
@Data
public class DPersonTrackDetail {
private Long id;
private Long accountId;
private Long mallId;
private Long gateId;
private String personUnid;
/**
* 进入时间
*/
private Date arriveTime;
/**
* 离开时间
*/
private Date leaveTime;
/**
* 停留时间
*/
private Long visitDuration;
/**
* 是否试乘
*/
private Integer isEngage;
/**
* 分组id
*/
private String groupUnid;
/**
* 试乘时间
*/
private Date engageTime;
private Date countDate;
}
\ No newline at end of file \ No newline at end of file
package com.viontech.keliu.entity;
import lombok.Data;
import java.util.Date;
/**
* Created with IntelliJ IDEA.
*
* @author: zhuhai
* Date: 2022-11-02
* Time: 18:07
*/
@Data
public class Person {
private Long accountId;
private Long mallId;
private Long gateId;
private String personUnid;
private Integer personType;
private Date countTime;
private Date countDate;
private Integer mood;
private Integer direction;
private Integer age;
private Integer gender;
}
\ No newline at end of file \ No newline at end of file
package com.viontech.keliu.entity;
import lombok.Data;
/**
* Created with IntelliJ IDEA.
*
* @author: zhuhai
* Date: 2023-03-28
* Time: 11:25
*/
@Data
public class PersonGroupResult {
private int staffNum;
private int customerNum;
private int customerAdultNum;
private int customerChildNum;
private int customerAlone;
private int customerGroup;
}
\ No newline at end of file \ No newline at end of file
package com.viontech.keliu.entity;
import lombok.Data;
import java.util.Date;
import java.util.List;
/**
* Created with IntelliJ IDEA.
*
* @author: zhuhai
* Date: 2023-12-23
* Time: 13:20
*/
@Data
public class PersonInOutDetail {
private Long accountId;
private Long mallId;
private String personUnid;
private String groupUnid;
private Integer age;
private Integer gender;
/**
* 进店时间
*/
private Date arriveTime;
/**
* 离店时间
*/
private Date leaveTime;
/**
* 停留时长
*/
private Long visitDuration;
private String inOutUnid;
private Integer personType;
private Date countDate;
/**
* 每一次进出在店内的抓拍
*/
private List<Person> insidePersonList;
}
\ No newline at end of file \ No newline at end of file
package com.viontech.keliu.entity;
import lombok.Data;
/**
* Created with IntelliJ IDEA.
*
* @author: zhuhai
* Date: 2023-12-23
* Time: 14:32
*/
@Data
public class SConfigParam {
private Long mallId;
private String configKey;
private String configValue;
}
\ No newline at end of file \ No newline at end of file
package com.viontech.keliu.service;
import java.util.Date;
import java.util.List;
/**
* Created with IntelliJ IDEA.
*
* @author: zhuhai
* Date: 2022-11-02
* Time: 17:56
*/
public interface PersonGroupService {
public void personToGroup(List<Long> mallIdList, Date countDate);
}
\ No newline at end of file \ No newline at end of file
package com.viontech.keliu.service;
import java.util.Date;
/**
* Created with IntelliJ IDEA.
*
* @author: zhuhai
* Date: 2023-12-22
* Time: 16:54
*/
public interface PersonRecordService {
void handlePersonRecord(Long mallId, Date countDate);
}
package com.viontech.keliu.service;
import java.util.Date;
/**
* Created with IntelliJ IDEA.
*
* @author: zhuhai
* Date: 2023-12-21
* Time: 16:51
*/
public interface PersonTrackDetailService {
void handlePersonTrackDetail(Long mallId, Date countDate);
}
package com.viontech.keliu.service.impl;
import cn.hutool.core.date.DateUtil;
import com.viontech.keliu.dao.DMallPersonGroupDayCountDataDao;
import com.viontech.keliu.dao.DMallPersonGroupHourCountDataDao;
import com.viontech.keliu.dao.DataCountDao;
import com.viontech.keliu.entity.DMallPersonGroupDayCountData;
import com.viontech.keliu.entity.DMallPersonGroupHourCountData;
import com.viontech.keliu.entity.Person;
import com.viontech.keliu.entity.PersonGroupResult;
import com.viontech.keliu.service.PersonGroupService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;
/**
* Created with IntelliJ IDEA.
*
* @author: zhuhai
* Date: 2022-11-02
* Time: 17:57
*/
@Service
@Slf4j
public class PersonGroupServiceImpl implements PersonGroupService {
@Resource
private DataCountDao dataCountDao;
@Resource
private DMallPersonGroupDayCountDataDao dMallPersonGroupDayCountDataDao;
@Resource
private DMallPersonGroupHourCountDataDao dMallPersonGroupHourCountDataDao;
@Resource
private TaskExecutor taskExecutor;
@Override
public void personToGroup(List<Long> mallIdList, Date countDate) {
if (CollectionUtils.isEmpty(mallIdList)) {
return;
}
CountDownLatch countDownLatch = new CountDownLatch(mallIdList.size());
for (Long mallId : mallIdList) {
log.info("mallId:{},开始执行人员分组统计", mallId);
taskExecutor.execute(() -> {
try {
List<Person> personList = dataCountDao.getPersonByMallId(mallId, countDate);
//按天统计
personGroupDayStat(personList, mallId, countDate);
//按小时统计
Map<Date, List<Person>> hourPersonList = personList.stream().collect(Collectors.groupingBy((p) -> DateUtil.beginOfHour(p.getCountTime())));
for (Map.Entry<Date, List<Person>> entry : hourPersonList.entrySet()) {
personGroupHourStat(entry.getValue(), mallId, countDate, entry.getKey());
}
} catch (Exception e) {
log.error("mallId:{},人员分组异常", mallId, e);
} finally {
countDownLatch.countDown();
}
});
}
try {
countDownLatch.await();
} catch (InterruptedException e) {
log.error("线程等待异常", e);
}
}
/**
* 顾客组数小时级统计表
* @param personList
* @param mallId
* @param countDate
* @param countTime
*/
private void personGroupHourStat(List<Person> personList, Long mallId, Date countDate, Date countTime) {
PersonGroupResult personGroupResult = personGroupCompute(personList);
DMallPersonGroupHourCountData dMallPersonGroupHourCountData = new DMallPersonGroupHourCountData();
dMallPersonGroupHourCountData.setMallId(mallId);
dMallPersonGroupHourCountData.setCountDate(countDate);
dMallPersonGroupHourCountData.setCountTime(countTime);
dMallPersonGroupHourCountData.setHour(DateUtil.hour(countTime, true));
dMallPersonGroupHourCountData.setTotalPersonNum(personList.size());
dMallPersonGroupHourCountData.setStaffNum(personGroupResult.getStaffNum());
dMallPersonGroupHourCountData.setCustomerNum(personGroupResult.getCustomerNum());
dMallPersonGroupHourCountData.setCustomerAdultNum(personGroupResult.getCustomerAdultNum());
dMallPersonGroupHourCountData.setCustomerChildNum(personGroupResult.getCustomerChildNum());
dMallPersonGroupHourCountData.setCustomerAlone(personGroupResult.getCustomerAlone());
dMallPersonGroupHourCountData.setCustomerGroup(personGroupResult.getCustomerGroup());
//判断数据库中是否已经存在记录,如果不存在则插入记录,否则更新记录
List<DMallPersonGroupHourCountData> countDataList = dMallPersonGroupHourCountDataDao.selectByMallIdAndCountDate(mallId, countDate, countTime);
if (CollectionUtils.isEmpty(countDataList)) {
//插入记录
dMallPersonGroupHourCountDataDao.create(dMallPersonGroupHourCountData);
} else {
//更新记录
DMallPersonGroupHourCountData countData = countDataList.get(0);
dMallPersonGroupHourCountData.setId(countData.getId());
dMallPersonGroupHourCountDataDao.update(dMallPersonGroupHourCountData);
}
}
/**
* 顾客组数天级统计表
* @param personList
* @param mallId
* @param countDate
*/
private void personGroupDayStat(List<Person> personList, Long mallId, Date countDate) {
DMallPersonGroupDayCountData dMallPersonGroupDayCountData = new DMallPersonGroupDayCountData();
if (CollectionUtils.isEmpty(personList)) {
dMallPersonGroupDayCountData.setMallId(mallId);
dMallPersonGroupDayCountData.setCountDate(countDate);
dMallPersonGroupDayCountData.setTotalPersonNum(0);
dMallPersonGroupDayCountData.setStaffNum(0);
dMallPersonGroupDayCountData.setCustomerNum(0);
dMallPersonGroupDayCountData.setCustomerAdultNum(0);
dMallPersonGroupDayCountData.setCustomerChildNum(0);
dMallPersonGroupDayCountData.setCustomerAlone(0);
dMallPersonGroupDayCountData.setCustomerGroup(0);
} else {
PersonGroupResult personGroupResult = personGroupCompute(personList);
dMallPersonGroupDayCountData.setMallId(mallId);
dMallPersonGroupDayCountData.setCountDate(countDate);
dMallPersonGroupDayCountData.setTotalPersonNum(personList.size());
dMallPersonGroupDayCountData.setStaffNum(personGroupResult.getStaffNum());
dMallPersonGroupDayCountData.setCustomerNum(personGroupResult.getCustomerNum());
dMallPersonGroupDayCountData.setCustomerAdultNum(personGroupResult.getCustomerAdultNum());
dMallPersonGroupDayCountData.setCustomerChildNum(personGroupResult.getCustomerChildNum());
dMallPersonGroupDayCountData.setCustomerAlone(personGroupResult.getCustomerAlone());
dMallPersonGroupDayCountData.setCustomerGroup(personGroupResult.getCustomerGroup());
}
//判断数据库中是否已经存在记录,如果不存在则插入记录,否则更新记录
List<DMallPersonGroupDayCountData> countDataList = dMallPersonGroupDayCountDataDao.selectByMallIdAndCountDate(mallId, countDate);
if (CollectionUtils.isEmpty(countDataList)) {
//插入记录
dMallPersonGroupDayCountDataDao.create(dMallPersonGroupDayCountData);
} else {
//更新记录
DMallPersonGroupDayCountData countData = countDataList.get(0);
dMallPersonGroupDayCountData.setId(countData.getId());
dMallPersonGroupDayCountDataDao.update(dMallPersonGroupDayCountData);
}
}
/**
* 分组统计逻辑
* @param personList
* @return
*/
private PersonGroupResult personGroupCompute(List<Person> personList) {
int staffNum = (personList.stream().filter((t) -> t.getPersonType().equals(1)).collect(Collectors.toList())).size();
List<Person> customerList = (personList.stream().filter((t) -> t.getPersonType().equals(0)).collect(Collectors.toList())).stream().sorted(Comparator.comparing(Person::getCountTime)).collect(Collectors.toList());
int customerNum = customerList.size();
int customerAdultNum = 0;
int customerChildNum = 0;
for (Person person : customerList) {
Integer mood = person.getMood();
if (mood == null) {
continue;
}
if (mood.equals(108)) {
customerAdultNum += 1;
} else if (mood.equals(107)) {
customerChildNum += 1;
}
}
int customerAlone = 0;
int customerGroup = 0;
StringBuilder str = new StringBuilder();
for (int i = 0; i < customerList.size() - 1; ++i) {
Person pvo1 = customerList.get(i);
Person pvo2 = customerList.get(i + 1);
Long time1 = pvo1.getCountTime().getTime();
Long time2 = pvo2.getCountTime().getTime();
int seconds = (int) ((time2 - time1) / 1000L);
if (i == 0) {
str.append(pvo1.getMood());
}
if (seconds <= 6) {
str.append(",").append(pvo2.getMood());
} else {
str.append("#").append(pvo2.getMood());
}
}
String[] group = str.toString().split("#");
for (String s : group) {
String[] split = s.split(",");
//单独的加一
if (split.length == 1) {
customerAlone += 1;
} else {
//分组加一
customerGroup += 1;
}
}
PersonGroupResult result = new PersonGroupResult();
result.setStaffNum(staffNum);
result.setCustomerNum(customerNum);
result.setCustomerAdultNum(customerAdultNum);
result.setCustomerChildNum(customerChildNum);
result.setCustomerAlone(customerAlone);
result.setCustomerGroup(customerGroup);
return result;
}
}
\ No newline at end of file \ No newline at end of file
package com.viontech.keliu.service.impl;
import com.viontech.keliu.dao.DPersonTrackDetailDao;
import com.viontech.keliu.dao.FaceRecognitionDao;
import com.viontech.keliu.entity.DPersonTrackDetail;
import com.viontech.keliu.entity.Person;
import com.viontech.keliu.service.PersonTrackDetailService;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* Created with IntelliJ IDEA.
*
* @author: zhuhai
* Date: 2023-12-21
* Time: 16:53
*/
@Service
public class PersonTrackDetailServiceImpl implements PersonTrackDetailService {
@Resource
private FaceRecognitionDao faceRecognitionDao;
@Resource
private DPersonTrackDetailDao dPersonTrackDetailDao;
@Override
public void handlePersonTrackDetail(Long mallId, Date countDate) {
List<Person> personList = faceRecognitionDao.queryGateFaceRecognitionList(mallId, countDate);
if (CollectionUtils.isEmpty(personList)) {
return;
}
//按照gateId分组
Map<Long, List<Person>> gatePersonMap = personList.stream().collect(Collectors.groupingBy(Person::getGateId));
gatePersonMap.forEach((key, value) -> createPersonTrack(value));
}
/**
* 按照区域进行统计
* @param personList
*/
private void createPersonTrack(List<Person> personList) {
if (personList.size() < 2) {
return;
}
//按personUnid分组
Map<String, List<Person>> personUnidMap = personList.stream().collect(Collectors.groupingBy(Person::getPersonUnid));
personUnidMap.forEach((key, value) -> {
List<DPersonTrackDetail> personTrackDetailList = getPersonTrackDetail(value);
if (CollectionUtils.isNotEmpty(personTrackDetailList)) {
//保存进数据库
dPersonTrackDetailDao.createDPersonTrackDetailBatch(personTrackDetailList);
}
});
}
/**
* 按personUnid进行区域进出匹配
* @param personList
* @return
*/
private List<DPersonTrackDetail> getPersonTrackDetail(List<Person> personList) {
if (personList.size() < 2) {
return null;
}
List<DPersonTrackDetail> dPersonTrackDetailList = new ArrayList<>();
Person arrivePerson = null;
int isEngage = 0;
for (Person person : personList) {
//进
if (person.getDirection() == 1) {
arrivePerson = person;
continue;
}
//试乘
if (person.getDirection() == 6) {
isEngage = 1;
continue;
}
//进出匹配的
if (person.getDirection() == -1 && arrivePerson != null) {
DPersonTrackDetail personTrackDetail = new DPersonTrackDetail();
personTrackDetail.setAccountId(person.getAccountId());
personTrackDetail.setMallId(person.getMallId());
personTrackDetail.setGateId(person.getGateId());
personTrackDetail.setPersonUnid(person.getPersonUnid());
personTrackDetail.setArriveTime(arrivePerson.getCountTime());
personTrackDetail.setLeaveTime(person.getCountTime());
long milli = personTrackDetail.getLeaveTime().getTime() - personTrackDetail.getArriveTime().getTime();
personTrackDetail.setVisitDuration(milli);
personTrackDetail.setIsEngage(isEngage);
arrivePerson = null;
dPersonTrackDetailList.add(personTrackDetail);
}
isEngage = 0;
}
return dPersonTrackDetailList;
}
}
\ No newline at end of file \ No newline at end of file
package com.viontech.keliu.vo;
/**
* Created with IntelliJ IDEA.
*
* @author: zhuhai
* Date: 2022-10-31
* Time: 20:56
*/
public class MallVo {
private Integer id;
private String name;
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
\ No newline at end of file \ No newline at end of file
package com.viontech.keliu.vo;
import java.util.Date;
/**
* Created with IntelliJ IDEA.
*
* @author: zhuhai
* Date: 2022-10-31
* Time: 20:57
*/
public class PersonVo {
private Integer mall_id;
private String person_unid;
private Integer person_type;
private Date counttime;
private Integer mood;
public Integer getMall_id() {
return this.mall_id;
}
public void setMall_id(Integer mall_id) {
this.mall_id = mall_id;
}
public Integer getPerson_type() {
return this.person_type;
}
public String getPerson_unid() {
return this.person_unid;
}
public void setPerson_unid(String person_unid) {
this.person_unid = person_unid;
}
public void setPerson_type(Integer person_type) {
this.person_type = person_type;
}
public Date getCounttime() {
return this.counttime;
}
public void setCounttime(Date counttime) {
this.counttime = counttime;
}
public Integer getMood() {
return mood;
}
public void setMood(Integer mood) {
this.mood = mood;
}
}
\ No newline at end of file \ No newline at end of file
package com.viontech.keliu.vo;
/**
* Created with IntelliJ IDEA.
*
* @author: zhuhai
* Date: 2022-10-31
* Time: 20:57
*/
public class ResultVo {
/**
* 门店名称
*/
private String mall_name;
/**
* 总人数
*/
private String count_person;
/**
* 店员人数
*/
private String clerk_num;
/**
* 顾客人数
*/
private String customer_num;
/**
* 成人人数
*/
private String customer_adult;
/**
* 儿童人数
*/
private String customer_child;
/**
*独自进店顾客
*/
private String customer_alone;
/**
* 分组数(小于6s)
*/
private String customer_group;
public String getMall_name() {
return this.mall_name;
}
public void setMall_name(String mall_name) {
this.mall_name = mall_name;
}
public String getCount_person() {
return this.count_person;
}
public void setCount_person(String count_person) {
this.count_person = count_person;
}
public String getClerk_num() {
return this.clerk_num;
}
public void setClerk_num(String clerk_num) {
this.clerk_num = clerk_num;
}
public String getCustomer_num() {
return this.customer_num;
}
public void setCustomer_num(String customer_num) {
this.customer_num = customer_num;
}
public String getCustomer_adult() {
return customer_adult;
}
public void setCustomer_adult(String customer_adult) {
this.customer_adult = customer_adult;
}
public String getCustomer_child() {
return customer_child;
}
public void setCustomer_child(String customer_child) {
this.customer_child = customer_child;
}
public String getCustomer_alone() {
return customer_alone;
}
public void setCustomer_alone(String customer_alone) {
this.customer_alone = customer_alone;
}
public String getCustomer_group() {
return customer_group;
}
public void setCustomer_group(String customer_group) {
this.customer_group = customer_group;
}
}
\ No newline at end of file \ No newline at end of file
debug=false
server.max-http-header-size=102400
################################## DATABASE ########################################
# \u6570\u636E\u5E93Url \u6237\u540D \u5BC6\u7801 \u914D\u7F6E
spring.datasource.url=jdbc:postgresql://36.112.68.214:5432/VionCountStore
spring.datasource.username=postgres
spring.datasource.password=vion
spring.datasource.driver-class-name=org.postgresql.Driver
server.port=33333
debug=false
server.max-http-header-size=102400
################################## DATABASE ########################################
# \u6570\u636E\u5E93Url \u6237\u540D \u5BC6\u7801 \u914D\u7F6E
spring.datasource.url=jdbc:postgresql://117.133.143.116:5432/VionCountStore
spring.datasource.username=postgres
spring.datasource.password=vion
spring.datasource.driver-class-name=org.postgresql.Driver
server.port=18282
thread.core.pool.size=20
thread.max.pool.size=40
spring:
profiles:
active: pro
datasource:
driver-class-name: org.postgresql.Driver
aop:
proxy-target-class: true
messages:
encoding: UTF-8
basename: i18n/messages
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
<?xml version="1.0" encoding="UTF-8"?>
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
<!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true -->
<!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
<configuration scan="true" scanPeriod="10 seconds">
<!--<include resource="org/springframework/boot/logging/logback/base.xml" />-->
<contextName>logback</contextName>
<!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 -->
<property name="log.path" value="logs" />
<property name="pattern" value="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%thread] %logger{50} - %msg%n" />
<!--输出到控制台-->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>info</level>
</filter>
<encoder>
<Pattern>%highlight(%-5level) %yellow(%d{yyyy-MM-dd HH:mm:ss.SSS}) [%thread] %green(%logger{50}) - %msg%n</Pattern>
<!-- 设置字符集 -->
</encoder>
</appender>
<!--输出到文件-->
<!-- 时间滚动输出 level为 DEBUG 日志 -->
<appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/log_debug.log</file>
<!--日志文件输出格式-->
<encoder>
<Pattern>${pattern}</Pattern>
<charset>UTF-8</charset> <!-- 设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志归档 -->
<fileNamePattern>${log.path}/debug/debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录debug级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>debug</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 时间滚动输出 level为 INFO 日志 -->
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/log_info.log</file>
<!--日志文件输出格式-->
<encoder>
<Pattern>${pattern}</Pattern>
<charset>UTF-8</charset>
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 每天日志归档路径以及格式 -->
<fileNamePattern>${log.path}/info/info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录info级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>info</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 时间滚动输出 level为 WARN 日志 -->
<appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/log_warn.log</file>
<!--日志文件输出格式-->
<encoder>
<Pattern>${pattern}</Pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/warn/warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>5</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录warn级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>warn</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 时间滚动输出 level为 ERROR 日志 -->
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/log_error.log</file>
<!--日志文件输出格式-->
<encoder>
<Pattern>${pattern}</Pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/error/error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录ERROR级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!--
<logger>用来设置某一个包或者具体的某一个类的日志打印级别、
以及指定<appender>。<logger>仅有一个name属性,
一个可选的level和一个可选的addtivity属性。
name:用来指定受此logger约束的某一个包或者具体的某一个类。
level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
还有一个特俗值INHERITED或者同义词NULL,代表强制执行上级的级别。
如果未设置此属性,那么当前logger将会继承上级的级别。
addtivity:是否向上级logger传递打印信息。默认是true。
-->
<!--<logger name="org.springframework.web" level="info"/>-->
<!--<logger name="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor" level="INFO"/>-->
<!--
使用mybatis的时候,sql语句是debug下才会打印,而这里我们只配置了info,所以想要查看sql语句的话,有以下两种操作:
第一种把<root level="info">改成<root level="DEBUG">这样就会打印sql,不过这样日志那边会出现很多其他消息
第二种就是单独给dao下目录配置debug模式,代码如下,这样配置sql语句会打印,其他还是正常info级别:
-->
<!--
root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性
level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
不能设置为INHERITED或者同义词NULL。默认是DEBUG
可以包含零个或多个元素,标识这个appender将会添加到这个logger。
-->
<logger name="jdbc.sqlonly" level="off">
</logger>
<logger name="jdbc.audit" level="off">
</logger>
<logger name="jdbc.resultset" level="debug">
</logger>
<logger name="jdbc.connection" level="off">
</logger>
<logger name="jdbc.sqltiming" level="debug">
</logger>
<root level="DEBUG">
<appender-ref ref="CONSOLE" />
<appender-ref ref="DEBUG_FILE" />
<appender-ref ref="INFO_FILE" />
<appender-ref ref="WARN_FILE" />
<appender-ref ref="ERROR_FILE" />
</root>
<!--生产环境:输出到文件-->
<!--<springProfile name="pro">-->
<!--<root level="info">-->
<!--<appender-ref ref="CONSOLE" />-->
<!--<appender-ref ref="DEBUG_FILE" />-->
<!--<appender-ref ref="INFO_FILE" />-->
<!--<appender-ref ref="ERROR_FILE" />-->
<!--<appender-ref ref="WARN_FILE" />-->
<!--</root>-->
<!--</springProfile>-->
</configuration>
\ No newline at end of file \ No newline at end of file
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!