Commit d9635c08 by liangkaiping

copy

parent fd407364
# cloud-chat-practice
智能演练 智能演练
##Xservice与service区别
#### service 层调用repository层进行数据库查询.一个service对应一个repository
#### Xservice 层做业务逻辑处理,需要的数据从service获取.一个Xservice对应一个controller
<?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>
<artifactId>cloud-chat-practice</artifactId>
<groupId>com.yizhi</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>chat-practice-api</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.yizhi</groupId>
<artifactId>cloud-common-api</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.yizhi</groupId>
<artifactId>cloud-core</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.yizhi</groupId>
<artifactId>cloud-util</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
package com.yizhi.practice.application.enums;
public enum PracticeChatLogStatusEnum {
ING(40,"进行中"),
DONE(80,"正常结束"),
QUIT(90,"中途退出")
;
private Integer status;
private String desc;
PracticeChatLogStatusEnum(Integer status, String desc) {
this.status = status;
this.desc = desc;
}
public Integer getStatus() {
return status;
}
public String getDesc() {
return desc;
}
}
package com.yizhi.practice.application.enums;
/**
* 训练策略每轮对话过关条件开关 80:开启 10:关闭
*
*/
public enum PracticeDiaConditionEnum {
TRUE(80,"开启每轮对话过关限制条件"),
FALSE(10,"关闭每轮对话过关限制条件"),
;
private Integer status;
private String desc;
PracticeDiaConditionEnum(Integer status, String desc) {
this.status = status;
this.desc = desc;
}
public Integer getStatus() {
return status;
}
public String getDesc() {
return desc;
}
}
package com.yizhi.practice.application.enums;
public enum PracticeInternationEnum {
SCENE_CHAT_INCOMPLETE("practiceCode1","陪练下场景对话不完整")
;
private String code;
private String name;
PracticeInternationEnum(String code, String name){
this.name = name;
this.code = code;
}
public String getCode() {
return code;
}
public String getName() {
return name;
}
}
package com.yizhi.practice.application.enums;
public enum PracticeLevelMapEnum {
PRACTICE_LEVEL1("1010", "训练(初级)"),
PRACTICE_LEVEL2("1040", "训练(中级)"),
PRACTICE_LEVEL3("1080", "训练(高级)"),
EXAM("200","考核")
;
private String status;
private String desc;
PracticeLevelMapEnum(String status, String desc) {
this.status = status;
this.desc = desc;
}
public String getStatus() {
return status;
}
public String getDesc() {
return desc;
}
public static String getDescByStatus(String code) {
PracticeLevelMapEnum[] values = PracticeLevelMapEnum.values();
for(PracticeLevelMapEnum each : values) {
if(each.getStatus().equals(code)) {
return each.getDesc();
}
}
return "";
}
}
package com.yizhi.practice.application.enums;
/**
* 是否发放积分 80:发放 10:不发放
*
*/
public enum PracticeManyRoudChatEnum {
TRUE(80,"开启"),
FALSE(10,"关闭"),
;
private Integer status;
private String desc;
PracticeManyRoudChatEnum(Integer status, String desc) {
this.status = status;
this.desc = desc;
}
public Integer getStatus() {
return status;
}
public String getDesc() {
return desc;
}
}
package com.yizhi.practice.application.enums;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 陪练模式枚举
* 80:训练+考核 ,10:训练 20:考核
*/
public enum PracticeModelStatusEnum {
PRA_ASSESS(80, "训练+考核"),
PRACTICE(10, "训练"),
ASSESSMENT(20, "考核");
private Integer status;
private String desc;
PracticeModelStatusEnum(Integer status, String desc) {
this.status = status;
this.desc = desc;
}
/**
* 返回所有状态
*
* @return
*/
public static List<Integer> getAllStatus() {
return Arrays.stream(PracticeModelStatusEnum.values()).map(PracticeModelStatusEnum::getStatus).collect(Collectors.toList());
}
public static PracticeModelStatusEnum getByStatus(Integer status) {
Map<Integer,PracticeModelStatusEnum> map = Arrays.stream(PracticeModelStatusEnum.values()).collect(Collectors.toMap(PracticeModelStatusEnum::getStatus, a -> a,(k1, k2)-> k1));
return map.get(status);
}
public Integer getStatus() {
return status;
}
public String getDesc() {
return desc;
}
}
package com.yizhi.practice.application.enums;
/**
* 节点标识 10:机器人,20:学员 节点
*
*/
public enum PracticeNodeEnum {
ROBOT(10,"机器人节点"),
STUDENT(20,"学员节点"),
START(80,"开始节点")
;
private Integer status;
private String desc;
PracticeNodeEnum(Integer status, String desc) {
this.status = status;
this.desc = desc;
}
public Integer getStatus() {
return status;
}
public String getDesc() {
return desc;
}
}
package com.yizhi.practice.application.enums;
/**
* @Date 2020/11/18 2:09 下午
* @Author lvjianhui
**/
public enum PracticePassResultEnum {
PASS (80,"已通过"),
UN_PASS (10,"未通过"),
;
PracticePassResultEnum(Integer status, String msg) {
this.status = status;
this.msg = msg;
}
private Integer status;
private String msg;
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
package com.yizhi.practice.application.enums;
/**
* 是否开启多轮对话:80:开启 10:关闭
*
*/
public enum PracticePointGivenEnum {
TRUE(80,"开启"),
FALSE(10,"关闭"),
;
private Integer status;
private String desc;
PracticePointGivenEnum(Integer status, String desc) {
this.status = status;
this.desc = desc;
}
public Integer getStatus() {
return status;
}
public String getDesc() {
return desc;
}
}
package com.yizhi.practice.application.enums;
/**
* 考核策略是否允许重复提交; 80:允许重复提交 10:不允许重复提交
*
*/
public enum PracticeRepSubmitEnum {
TRUE(80,"允许重复提交"),
FALSE(10,"不允许重复提交"),
;
private Integer status;
private String desc;
PracticeRepSubmitEnum(Integer status, String desc) {
this.status = status;
this.desc = desc;
}
public Integer getStatus() {
return status;
}
public String getDesc() {
return desc;
}
}
package com.yizhi.practice.application.enums;
/**
* 未识别回复类型 80:默认回复,10:自定义回复
*
*/
public enum PracticeSimilaryFailedEnum {
TRUE(80,"默认回复"),
FALSE(10,"自定义回复"),
;
private Integer status;
private String desc;
PracticeSimilaryFailedEnum(Integer status, String desc) {
this.status = status;
this.desc = desc;
}
public Integer getStatus() {
return status;
}
public String getDesc() {
return desc;
}
}
package com.yizhi.practice.application.enums;
/**
* 是否跳过对话 80允许,10:不允许
*
*/
public enum PracticeSkipDialogueEnum {
SKIP_TRUE(80,"允许跳过对话"),
SKIP_FALSE(10,"不允许跳过对话"),
;
private Integer status;
private String desc;
PracticeSkipDialogueEnum(Integer status, String desc) {
this.status = status;
this.desc = desc;
}
public Integer getStatus() {
return status;
}
public String getDesc() {
return desc;
}
}
package com.yizhi.practice.application.enums;
public enum PracticeSkipEnum {
SKIP(10, "跳过"),
NOT_SKIP(80, "正常")
;
private Integer code;
private String desc;
private PracticeSkipEnum(Integer code, String desc) {
this.code = code;
this.desc = desc;
}
public Integer getCode() {
return code;
}
public String getDesc() {
return desc;
}
}
package com.yizhi.practice.application.enums;
/**
* 陪练状态
*/
public enum PracticeStatusEnum {
UP(80,"上架"),
DOWN(30,"下架"),
DRAFT(10,"草稿")
;
private Integer status;
private String desc;
PracticeStatusEnum(Integer status, String desc) {
this.status = status;
this.desc = desc;
}
public Integer getStatus() {
return status;
}
public String getDesc() {
return desc;
}
}
package com.yizhi.practice.application.enums;
public enum PracticeUseTypeEnum {
PRACTICE(10, "训练"),
EXAM(20, "考核");
private Integer code;
private String msg;
PracticeUseTypeEnum(Integer code, String msg){
this.code=code;
this.msg=msg;
}
public Integer getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
package com.yizhi.practice.application.enums;
/**
* 陪练可见范围
* 80:平台可见 40:指定用户可见
*/
public enum PracticeVisibleTypeEnum {
ALL(80,"平台可见"),
ORG(50,"部门用户可见"),
PART(40,"指定用户可见"),
;
private Integer status;
private String desc;
PracticeVisibleTypeEnum(Integer status, String desc) {
this.status = status;
this.desc = desc;
}
public Integer getStatus() {
return status;
}
public String getDesc() {
return desc;
}
}
package com.yizhi.practice.application.enums;
public enum PracticeVoiceTypeEnum {
MP3("mp3"), PCM("pcm"), WAV("wav");
private String type;
private PracticeVoiceTypeEnum(String type) {
this.type = type;
}
public String getType() {
return type;
}
}
package com.yizhi.practice.application.enums;
public enum PracticeXunFeiBusinessTypeEnum {
RECOGNIZE // 语音识别
, EVALUATE // 语音评测
, SYNTHESIS // 语音合成
}
package com.yizhi.practice.application.feign;
import com.yizhi.core.application.context.RequestContext;
import com.yizhi.util.application.domain.BizResponse;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
/**
* @Date 2020/11/19 2:00 下午
* @Author lvjianhui
**/
@FeignClient(value = "chat-practice",contextId = "MyPracticeStudentClient",path = "/student/practice")
public interface MyPracticeStudentClient {
@GetMapping("/running/count/get")
public BizResponse<Integer> getRuningPracticeCount(@RequestBody RequestContext requestContext);
@GetMapping("/user/auth")
public BizResponse<Boolean> getUserPracticeAuth(@RequestBody RequestContext requestContext
, @RequestParam("practiceId") Long practiceId);
}
package com.yizhi.practice.application.feign;
import com.yizhi.practice.application.pojo.vo.PracticeChatLogVo;
import com.yizhi.practice.application.pojo.vo.PracticeVisibleVo;
import com.yizhi.practice.application.pojo.vo.PracticeVo;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
@FeignClient(value = "chat-practice",contextId = "PracticeConfigClient",path = "/remote/manage/practice")
public interface PracticeConfigClient {
@GetMapping(path = "/range/list")
List<PracticeVo> selectRangeList(@RequestParam(name = "startDate",value="startDate",required=false)String startDate,
@RequestParam(name = "endDate",value="endDate",required=false)String endDate);
@GetMapping(path = "/visible/range/list")
List<PracticeVisibleVo> selectVisibleRangeList(@RequestParam(name = "startDate",value="startDate",required=false) String startDate,
@RequestParam(name = "endDate",value="endDate",required=false) String endDate);
/**
* 查询指定时间范围内更新的陪练记录
*/
@GetMapping(path = "/chat/range/list")
List<PracticeChatLogVo> selectChatLogRangeList(@RequestParam(name = "startDate",value="startDate",required=false) String startDate,
@RequestParam(name = "endDate",value="endDate",required=false) String endDate);
}
package com.yizhi.practice.application.feign;
import com.yizhi.practice.application.pojo.vo.PracticeVo;
import com.yizhi.util.application.domain.BizResponse;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(name = "chat-practice",contextId = "PracticeConfigStudentClient")
public interface PracticeConfigStudentClient {
@ApiOperation(value = "获取陪练")
@GetMapping("/student/practice/get")
public BizResponse<PracticeVo> getPractice(@ApiParam(value = "陪练的ID") @RequestParam("practiceId") Long practiceId);
}
package com.yizhi.practice.application.pojo.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
@Data
@ApiModel(value = "PracticeBaseInfoVo")
public class PracticeBaseInfoVo {
@ApiModelProperty(value = "陪练id")
private Long id;
@ApiModelProperty(value = "陪练名")
private String name;
@ApiModelProperty(value = "陪练模式",allowableValues = "80:训练+考核 ,10:训练 20:考核")
private Integer useType;
@ApiModelProperty(value = "训练开始时间 yyyy-MM-dd HH:mm")
private Date practiceStartAt;
@ApiModelProperty(value = "训练结束时间 yyyy-MM-dd HH:mm")
private Date practiceEndAt;
@ApiModelProperty(value = "考核开始时间 yyyy-MM-dd HH:mm")
private Date examStartAt;
@ApiModelProperty(value = "考核结束时间 yyyy-MM-dd HH:mm")
private Date examEndAt;
@ApiModelProperty(value = "陪练状态 80:上架 30:下架 10:草稿")
private Integer status;
@ApiModelProperty(value = "练习可见范围 80:平台可见 40:指定用户可见")
private Integer visibleType;
@ApiModelProperty(value = "陪练logoUrl")
private String logoUrl;
}
package com.yizhi.practice.application.pojo.vo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@Api(tags = "初始化草稿陪练")
public class PracticeBlankDraftVo {
@ApiModelProperty(value = "陪练id")
private Long id;
@ApiModelProperty(value = "陪练状态 80:上架 30:下架 10:草稿",allowableValues = "80,30,10")
private Integer status;
}
package com.yizhi.practice.application.pojo.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
* 场景对话结果记录
* </p>
*
* @author MybatisCodeGenerator123
* @since 2020-10-30
*/
@Data
public class PracticeChatLogVo implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
@ApiModelProperty(value = "陪练ID")
private Long practiceId;
@ApiModelProperty(value = "用户ID")
private Long accountId;
@ApiModelProperty(value = "用户名")
private String accountName;
@ApiModelProperty(value = "用户姓名")
private String accountFullName;
@ApiModelProperty(value = "10:训练 20:考核")
private Integer useType;
@ApiModelProperty(value = "部门名")
private String orgName;
@ApiModelProperty(value = "陪练级别 10:初级 40:中级 80:高级")
private Integer level;
@ApiModelProperty(value = "陪练状态 40:陪练中 80:陪练正常结束 90:陪练中途退出")
private Integer status;
@ApiModelProperty(value = "陪练开始时间")
private Date startAt;
@ApiModelProperty(value = "陪练结束时间")
private Date endAt;
@ApiModelProperty(value = "通过考核最低分")
private Integer passMinScore;
@ApiModelProperty(value = "是否发放积分 80 发放,10不发放")
private Integer givenPointType;
@ApiModelProperty(value = "得分")
private Integer averageScore;
@ApiModelProperty(value = "80:通过,10:未通过")
private Integer passResult;
@ApiModelProperty(value = "关键词得分")
private Integer keywordScore;
@ApiModelProperty(value = "关键词 完成度 单位%")
private Integer keywordRate;
@ApiModelProperty(value = "完整性得分")
private Integer completeScore;
@ApiModelProperty(value = "完整性 完成度 单位%")
private Integer completeRate;
@ApiModelProperty(value = "流畅性得分")
private Integer smoothScore;
@ApiModelProperty(value = "流畅性 完整度 单位%")
private Integer smoothRate;
@ApiModelProperty(value = "表达能力得分")
private Integer expressScore;
@ApiModelProperty(value = "表达能力 完成度 单位%")
private Integer expressRate;
@ApiModelProperty(value = "礼貌用语得分")
private Integer politeScore;
@ApiModelProperty(value = "礼貌用语 完成度 单位%")
private Integer politeRate;
@ApiModelProperty(value = "0: not deledted 1:deleted")
private Boolean deleted;
private Long orgId;
private Long siteId;
private Long companyId;
private Date createdAt;
private Date updatedAt;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getPracticeId() {
return practiceId;
}
public void setPracticeId(Long practiceId) {
this.practiceId = practiceId;
}
public Long getAccountId() {
return accountId;
}
public void setAccountId(Long accountId) {
this.accountId = accountId;
}
public String getAccountName() {
return accountName;
}
public void setAccountName(String accountName) {
this.accountName = accountName;
}
public String getAccountFullName() {
return accountFullName;
}
public void setAccountFullName(String accountFullName) {
this.accountFullName = accountFullName;
}
public Integer getUseType() {
return useType;
}
public void setUseType(Integer useType) {
this.useType = useType;
}
public String getOrgName() {
return orgName;
}
public void setOrgName(String orgName) {
this.orgName = orgName;
}
public Integer getLevel() {
return level;
}
public void setLevel(Integer level) {
this.level = level;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public Date getStartAt() {
return startAt;
}
public void setStartAt(Date startAt) {
this.startAt = startAt;
}
public Date getEndAt() {
return endAt;
}
public void setEndAt(Date endAt) {
this.endAt = endAt;
}
public Integer getPassMinScore() {
return passMinScore;
}
public void setPassMinScore(Integer passMinScore) {
this.passMinScore = passMinScore;
}
public Integer getGivenPointType() {
return givenPointType;
}
public void setGivenPointType(Integer givenPointType) {
this.givenPointType = givenPointType;
}
public Integer getAverageScore() {
return averageScore;
}
public void setAverageScore(Integer averageScore) {
this.averageScore = averageScore;
}
public Integer getPassResult() {
return passResult;
}
public void setPassResult(Integer passResult) {
this.passResult = passResult;
}
public Integer getKeywordScore() {
return keywordScore;
}
public void setKeywordScore(Integer keywordScore) {
this.keywordScore = keywordScore;
}
public Integer getKeywordRate() {
return keywordRate;
}
public void setKeywordRate(Integer keywordRate) {
this.keywordRate = keywordRate;
}
public Integer getCompleteScore() {
return completeScore;
}
public void setCompleteScore(Integer completeScore) {
this.completeScore = completeScore;
}
public Integer getCompleteRate() {
return completeRate;
}
public void setCompleteRate(Integer completeRate) {
this.completeRate = completeRate;
}
public Integer getSmoothScore() {
return smoothScore;
}
public void setSmoothScore(Integer smoothScore) {
this.smoothScore = smoothScore;
}
public Integer getSmoothRate() {
return smoothRate;
}
public void setSmoothRate(Integer smoothRate) {
this.smoothRate = smoothRate;
}
public Integer getExpressScore() {
return expressScore;
}
public void setExpressScore(Integer expressScore) {
this.expressScore = expressScore;
}
public Integer getExpressRate() {
return expressRate;
}
public void setExpressRate(Integer expressRate) {
this.expressRate = expressRate;
}
public Integer getPoliteScore() {
return politeScore;
}
public void setPoliteScore(Integer politeScore) {
this.politeScore = politeScore;
}
public Integer getPoliteRate() {
return politeRate;
}
public void setPoliteRate(Integer politeRate) {
this.politeRate = politeRate;
}
public Boolean getDeleted() {
return deleted;
}
public void setDeleted(Boolean deleted) {
this.deleted = deleted;
}
public Long getOrgId() {
return orgId;
}
public void setOrgId(Long orgId) {
this.orgId = orgId;
}
public Long getSiteId() {
return siteId;
}
public void setSiteId(Long siteId) {
this.siteId = siteId;
}
public Long getCompanyId() {
return companyId;
}
public void setCompanyId(Long companyId) {
this.companyId = companyId;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public Date getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
@Override
public String toString() {
return "PracticeChatLog{" +
", id=" + id +
", practiceId=" + practiceId +
", accountId=" + accountId +
", accountName=" + accountName +
", accountFullName=" + accountFullName +
", useType=" + useType +
", orgName=" + orgName +
", level=" + level +
", status=" + status +
", startAt=" + startAt +
", endAt=" + endAt +
", passMinScore=" + passMinScore +
", givenPointType=" + givenPointType +
", averageScore=" + averageScore +
", passResult=" + passResult +
", keywordScore=" + keywordScore +
", keywordRate=" + keywordRate +
", completeScore=" + completeScore +
", completeRate=" + completeRate +
", smoothScore=" + smoothScore +
", smoothRate=" + smoothRate +
", expressScore=" + expressScore +
", expressRate=" + expressRate +
", politeScore=" + politeScore +
", politeRate=" + politeRate +
", deleted=" + deleted +
", orgId=" + orgId +
", siteId=" + siteId +
", companyId=" + companyId +
", createdAt=" + createdAt +
", updatedAt=" + updatedAt +
"}";
}
}
package com.yizhi.practice.application.pojo.vo;
import lombok.Data;
@Data
public class PracticePointVo {
private Long id;
private Integer minScore;
private Integer maxScore;
private Integer point;
}
package com.yizhi.practice.application.pojo.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
*/
@Data
public class PracticeVisibleVo implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
@ApiModelProperty(value = "陪练ID")
private Long practiceId;
@ApiModelProperty(value = "可见站点Id")
private Long visibleSiteId;
@ApiModelProperty(value = "可见部门Id")
private Long visibleOrgId;
@ApiModelProperty(value = "可见部门名")
private String visibleOrgName;
@ApiModelProperty(value = "可见用户Id")
private Long visibleAccountId;
@ApiModelProperty(value = "可见用户工号")
private String visibleAccountWorkNum;
@ApiModelProperty(value = "用户名")
private String visibleAccountName;
@ApiModelProperty(value = "用户全名")
private String visibleAccountFullName;
@ApiModelProperty(value = "陪练可见范围 80:平台可见 50:部门可见 40:指定用户可见")
private Integer visibleType;
@ApiModelProperty(value = "公司Id")
private Long companyId;
@ApiModelProperty(value = "0:not deleted, 1:deleted")
private Boolean deleted;
private Date createdAt;
@ApiModelProperty(value = "创建管理员ID")
private Long createdUid;
private Date updatedAt;
@ApiModelProperty(value = "更新管理员ID")
private Long updatedUid;
}
package com.yizhi.practice.application.pojo.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
@Data
public class PracticeVo {
private Long id;
@ApiModelProperty(value = "陪练名")
private String name;
@ApiModelProperty(value = "陪练logoURL")
private String logoUrl;
@ApiModelProperty(value = "陪练描述")
private String description;
@ApiModelProperty(value = "80:训练+考核 ,10:训练 20:考核")
private Integer useType;
@ApiModelProperty(value = "训练开始时间")
private Date practiceStartAt;
@ApiModelProperty(value = "训练结束时间")
private Date practiceEndAt;
@ApiModelProperty(value = "考核开始时间")
private Date examStartAt;
@ApiModelProperty(value = "考核结束时间")
private Date examEndAt;
@ApiModelProperty(value = "允许最大考试;0:无限次;其他有限次;默认0")
private Integer maxExamCount;
@ApiModelProperty(value = "自定义关键词,逗号分隔,命中得分")
private String keyWord;
@ApiModelProperty(value = "机器人配置ID")
private Long robotId;
@ApiModelProperty(value = "机器人参数")
private String robotParams;
@ApiModelProperty(value = "机器人名字")
private String robotName;
@ApiModelProperty(value = "机器人头像URL null时走默认头像")
private String robotPicUrl;
@ApiModelProperty(value = "陪练状态 80:上架 30:下架 10:草稿")
private Integer status;
@ApiModelProperty(value = "练习可见范围 80:平台可见 40:指定用户可见")
private Integer visibleType;
@ApiModelProperty(value = "跳过对话类型 80允许,10:不允许")
private Integer skipType;
@ApiModelProperty(value = "80:本轮得分超过限制,则进入下轮;10:无论得分多少,直接进入下一轮")
private Integer startNextRoundType;
@ApiModelProperty(value = "超过该分数,进入下一轮对话")
private Integer startNextRoundScore;
@ApiModelProperty(value = "每轮最多失败次数,超过直接到下轮")
private Integer practiceFailedMaxCount;
@ApiModelProperty(value = "80:允许重复提交 10:不允许重复提交")
private Integer repeatPush;
@ApiModelProperty(value = "多轮对话:80:开启 10:关闭")
private Integer manyRoundChat;
@ApiModelProperty(value = "相似度")
private Integer similarityRate;
@ApiModelProperty(value = "考试失败最大次数,超过直接到下轮")
private Integer examFailedMaxCount;
@ApiModelProperty(value = "未识别回复类型 80:默认回复,10:自定义回复")
private Integer similarityFailedMsgType;
@ApiModelProperty(value = "自定义未识别回复,分号分隔。")
private String similarityFailedMsg;
@ApiModelProperty(value = "考试及格分")
private Integer examPassMinScore;
@ApiModelProperty(value = "是否发放积分 80:发放 10:不发放")
private Integer examGivenPointType;
@ApiModelProperty(value = "完整性")
private Integer scoreRuleComplete;
@ApiModelProperty(value = "完整性")
private Integer scoreRuleKeyword;
@ApiModelProperty(value = "流畅性")
private Integer scoreRuleSmooth;
@ApiModelProperty(value = "表达能力")
private Integer scoreRuleExpress;
@ApiModelProperty(value = "礼貌")
private Integer scoreRulePolite;
@ApiModelProperty(value = "0:未删除 1:已删除")
private Boolean deleted;
@ApiModelProperty(value = "部门ID")
private Long orgId;
@ApiModelProperty(value = "站点ID")
private Long siteId;
@ApiModelProperty(value = "公司ID")
private Long companyId;
@ApiModelProperty(value = "创建记录的管理员ID")
private Long createdUid;
@ApiModelProperty(value = "创建时间")
private Date createdAt;
@ApiModelProperty(value = "最后一次更新记录的管理员ID")
private Long updatedUid;
@ApiModelProperty(value = "更新时间")
private Date updatedAt;
}
package com.yizhi.practice.application.pojo.vo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* <p>
* 场景配置
* </p>
*
* @author MybatisCodeGenerator123
* @since 2020-10-21
*/
@Data
@Api(tags = "SceneVo")
public class SceneVo {
@ApiModelProperty(value = "场景id")
private Long id;
@ApiModelProperty(value = "陪练ID")
private Long practiceId;
@ApiModelProperty(value = "场景名")
private String name;
@ApiModelProperty(value = "场景描述")
private String description;
@ApiModelProperty(value = "场景排序")
private int sort;
}
package com.yizhi.practice.application.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 关键词请求体
*
*/
@Data
@ApiModel(value = "关键词")
public class
KeyWordsReq {
@ApiModelProperty(name = "key",value = "关键词")
private String key;
/**
* 关键词对应的扩展词
* 多个用分号;分割
*/
@ApiModelProperty(name = "value",value = "关键词对应扩展词")
private String value;
}
package com.yizhi.practice.application.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@Data
@ApiModel(value = "指定用户")
public class PracticeAccountReq {
@ApiModelProperty(value = "陪练表主键id")
private Long practiceId;
@ApiModelProperty(value = "用户或者部门信息")
private List<PracticeVisibleAccount> accountList;
}
package com.yizhi.practice.application.request;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@Data
@ApiModel(value = "陪练对话节点信息")
public class PracticeChatNodeReq {
private Long id;
@ApiModelProperty(name = "sceneNodeType",value = "节点标识 10:机器人,20:学员 节点,80:开始节点")
private Integer sceneNodeType;
@ApiModelProperty(name = "level",value = "层级;开始节点层级为0; 开始节点下所有机器人节点层级都为1,依次向下类推")
private Integer level;
@ApiModelProperty(name = "robotContent",value = "该轮 机器人话术")
private String robotContent;
@ApiModelProperty(name = "accountContent",value = "该轮学员标准话术文本")
private String accountContent;
@ApiModelProperty(value = "学员上传真人话术文件名")
private String accountContentFileName;
@ApiModelProperty(name = "accountRealVoiceUrl",value = "学员真人话术音频URL")
private String accountRealVoiceUrl;
@ApiModelProperty(value = "机器人话术音频URL")
private String robotContentVoiceUrl;
@ApiModelProperty(name = "keyWordList",value = "学员话术关键字 key为关键字,value为拓展词,多个拓展词用分号分割")
private List<KeyWordsReq> keyWordList;
@ApiModelProperty(name = "accountContentTabooWord",value = "禁忌词,多个用分号分割")
private String accountContentTabooWord;
@ApiModelProperty(value = "节点坐标;x轴坐标")
@JsonProperty(value = "xAxis")
private String xAxis;
@ApiModelProperty(value = "节点坐标;y轴坐标")
@JsonProperty(value = "yAxis")
private String yAxis;
@ApiModelProperty(name = "childNodes",value = "该对话节点下子节点列表")
private List<PracticeChatNodeReq> childNodes;
}
package com.yizhi.practice.application.request;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.yizhi.practice.application.pojo.vo.PracticePointVo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
import java.util.List;
@Data
@ApiModel(value = "陪练基本信息和策略信息")
public class PracticeConfigInfoReq {
@ApiModelProperty(value = "陪练id")
private Long id;
@ApiModelProperty(value = "陪练名")
private String name;
@ApiModelProperty(value = "陪练logoURL")
private String logoUrl;
@ApiModelProperty(value = "陪练描述")
private String description;
@ApiModelProperty(value = "陪练模式 80:训练+考核 ,10:训练 20:考核",allowableValues = "80,10,20")
private Integer useType;
@ApiModelProperty(value = "训练开始时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
private Date practiceStartAt;
@ApiModelProperty(value = "训练结束时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
private Date practiceEndAt;
@ApiModelProperty(value = "考核开始时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
private Date examStartAt;
@ApiModelProperty(value = "考核结束时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
private Date examEndAt;
@ApiModelProperty(value = "允许最大考试次数 0:无限次;其他有限次;默认0")
private Integer maxExamCount;
@ApiModelProperty(value = "自定义关键词,逗号分隔")
private String keyWord;
@ApiModelProperty(value = "机器人id")
private Long robotId;
@ApiModelProperty(value = "机器人参数")
private String robotParams;
@ApiModelProperty(value = "机器人称呼")
private String robotAliasName;
@ApiModelProperty(value = "机器人头像URL null时走默认头像")
private String robotPicUrl;
@ApiModelProperty(value = "陪练状态 80:上架 30:下架 10:草稿",allowableValues = "80,30,10",example = "10")
private Integer status;
@ApiModelProperty(value = "80:平台可见 40:指定用户可见",allowableValues = "80,40",example = "80")
private Integer visibleType;
@ApiModelProperty(value = "是否跳过对话 80允许,10:不允许",allowableValues = "80,10")
private Integer skipType;
@ApiModelProperty(value = "每轮对话过关条件 80:开启 10:关闭",allowableValues = "80,10")
private Integer startNextRoundType;
@ApiModelProperty(value = "过关分数")
private Integer startNextRoundScore;
@ApiModelProperty(value = "强制练习轮次")
private Integer practiceFailedMaxCount;
@ApiModelProperty(value = "考核策略是否允许重复提交; 80:允许重复提交 10:不允许重复提交",allowableValues = "80,10")
private Integer repeatPush;
@ApiModelProperty(value = "多轮对话:80:开启 10:关闭",allowableValues = "80,10")
private Integer manyRoundChat;
@ApiModelProperty(value = "相似度")
private Integer similarityRate;
@ApiModelProperty(value = "考核强制对话轮次")
private Integer examFailedMaxCount;
@ApiModelProperty(value = "未识别回复类型 80:默认回复,10:自定义回复",allowableValues = "80,10")
private Integer similarityFailedMsgType;
@ApiModelProperty(value = "自定义未识别回复,分号分隔。")
private String similarityFailedMsg;
@ApiModelProperty(value = "考试及格分")
private Integer examPassMinScore;
@ApiModelProperty(value = "是否发放积分 80:发放 10:不发放",allowableValues = "80,10")
private Integer examGivenPointType;
@ApiModelProperty(value = "积分策略")
private List<PracticePointVo> practicePointList;
@ApiModelProperty(value = "完整性")
private Integer scoreRuleComplete;
@ApiModelProperty(value = "关键词命中")
private Integer scoreRuleKeyword;
@ApiModelProperty(value = "流畅性")
private Integer scoreRuleSmooth;
@ApiModelProperty(value = "表达能力")
private Integer scoreRuleExpress;
@ApiModelProperty(value = "礼貌用语")
private Integer scoreRulePolite;
}
package com.yizhi.practice.application.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "智能陪练用户导入导出")
public class PracticeImportAccountReq {
@ApiModelProperty(name = "practiceId",value = "陪练id")
private Long practiceId;
@ApiModelProperty(value = "文件oss路径")
private String fileUrl;
}
package com.yizhi.practice.application.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "智能陪练")
public class PracticeReq {
@ApiModelProperty(name = "practiceId",value = "陪练id")
private Long practiceId;
}
package com.yizhi.practice.application.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
* 场景对话请求
*/
@Data
@ApiModel(value = "陪练场景对话请求体")
public class PracticeSceneDialogueReq {
@ApiModelProperty(name = "practiceId",value = "场景所属陪练id")
private Long practiceId;
@ApiModelProperty(name = "sceneId",value = "对话所属场景id")
private Long sceneId;
//节点列表
private List<PracticeChatNodeReq> chatNodes;
}
package com.yizhi.practice.application.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
@Data
@ApiModel("报表统计请求")
public class PracticeStatisticsReq {
@ApiModelProperty(name = "startDate",value = "开始时间")
private String startDate;
@ApiModelProperty(name = "endDate",value = "结束时间")
private String endDate;
@ApiModelProperty(name = "pageNo", value = "当前页码 默认1")
private Integer pageNo = 1;
@ApiModelProperty(name = "pageSize", value = "每页大小 默认10")
private Integer pageSize = 10;
@ApiModelProperty(name = "practiceId",value = "陪练id")
private Long practiceId;
@ApiModelProperty(name = "practiceName",value = "陪练名称")
private String practiceName;
@ApiModelProperty(name = "nameKwd",value = "用户名关键字")
private String nameKwd;
@ApiModelProperty(name = "orgKwd",value = "部门关键字")
private String orgKwd;
private Date startOfDate;
private Date endOfDate;
}
package com.yizhi.practice.application.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "智能陪练上架下架请求参数")
public class PracticeStatusReq {
@ApiModelProperty(value = "陪练id")
private Long practiceId;
@ApiModelProperty(value = "陪练状态;80:上架 30:下架",allowableValues = "80,30")
private Integer status;
}
package com.yizhi.practice.application.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "可用用户、部门范围")
public class PracticeVisibleAccount {
@ApiModelProperty(value = "用户或者部门id")
private Long visibleId;
@ApiModelProperty(value = "可见范围类型; 50:部门可见 40:用户可见")
private Integer visibleType;
@ApiModelProperty(value = "用户名或部门名")
private String name;
@ApiModelProperty(value = "用户全名;可见范围类型visibleType为用户可见时填写")
private String fullName;
@ApiModelProperty(value = "用户工号;可见范围类型visibleType为用户可见时填写")
private String workNum;
}
package com.yizhi.practice.application.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
* 查询陪练列表请求体
*/
@Data
@ApiModel(value = "查询陪练列表请求体")
public class PracticesGetReq {
@ApiModelProperty(name = "name",value = "陪练名称或者关键字")
private String name;
@ApiModelProperty(name = "status",value = "陪练状态 80:上架 30:下架 10:草稿",allowableValues = "80,30,10")
private Integer status;
@ApiModelProperty(name = "models",value = "陪练模式 80:训练+考核 ,10:训练 20:考核")
private List<Integer> models;
@ApiModelProperty(name = "pageNo", value = "当前页码 默认1")
private Integer pageNo = 1;
@ApiModelProperty(name = "pageSize", value = "每页大小 默认10")
private Integer pageSize = 10;
/**
* 用户以及用户管理的用户ids
* 用于根据权限查询陪练列表
* */
private List<Long> ids;
private Long companyId;
private Long siteId;
}
package com.yizhi.practice.application.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "智能演练场景对话文件导入")
public class SceneChatImportReq {
@ApiModelProperty(value = "文件名")
private String fileName;
@ApiModelProperty(value = "文件url")
private String fileUrl;
@ApiModelProperty(value = "对话所属陪练id")
private Long practiceId;
@ApiModelProperty(value = "对话所属场景id")
private Long sceneId;
}
package com.yizhi.practice.application.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "场景")
public class SceneChatReq {
@ApiModelProperty(name = "sceneId",value = "陪练场景id;修改时必传")
private Long sceneId;
}
package com.yizhi.practice.application.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "场景请求")
public class SceneReq {
@ApiModelProperty(name = "practiceId",value = "陪练id")
private Long practiceId;
@ApiModelProperty(name = "sceneId",value = "陪练场景id,修改时必传")
private Long sceneId;
@ApiModelProperty(name = "sceneName",value = "陪练场景名称,修改时必传")
private String sceneName;
@ApiModelProperty(name = "desc",value = "陪练场景描述")
private String desc;
@ApiModelProperty(name = "sort",value = "场景排序序号")
private int sort;
}
<?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>
<artifactId>cloud-chat-practice</artifactId>
<groupId>com.yizhi</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<packaging>jar</packaging>
<modelVersion>4.0.0</modelVersion>
<artifactId>chat-practice-service</artifactId>
<properties>
<kotlin.version>1.4.10</kotlin.version>
</properties>
<dependencies>
<dependency>
<groupId>ws.schild</groupId>
<artifactId>jave-core</artifactId>
<version>2.4.4</version>
</dependency>
<dependency>
<groupId>ws.schild</groupId>
<artifactId>jave-native-osx64</artifactId>
<version>2.4.4</version>
</dependency>
<dependency>
<groupId>ws.schild</groupId>
<artifactId>jave-native-linux64</artifactId>
<version>2.4.4</version>
</dependency>
<dependency>
<groupId>ws.schild</groupId>
<artifactId>jave-native-win64</artifactId>
<version>2.4.4</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>com.jave</groupId>-->
<!-- <artifactId>jave</artifactId>-->
<!-- <version>1.0.2</version>-->
<!-- </dependency>-->
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.13.1</version>
</dependency>
<dependency>
<groupId>com.squareup.okio</groupId>
<artifactId>okio</artifactId>
<version>1.15.0</version>
</dependency>
<!-- 百度 自然语言处理SDK -->
<dependency>
<groupId>com.baidu.aip</groupId>
<artifactId>java-sdk</artifactId>
<version>4.15.1</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.0</version>
</dependency>
<!-- JPA + QueryDsl-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.yizhi</groupId>
<artifactId>cloud-orm</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.yizhi</groupId>
<artifactId>cloud-core</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.yizhi</groupId>
<artifactId>cloud-util</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.yizhi</groupId>
<artifactId>chat-practice-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.yizhi</groupId>
<artifactId>cloud-system-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.yizhi</groupId>
<artifactId>cloud-point-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.yizhi</groupId>
<artifactId>cloud-statistics-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.yizhi</groupId>
<artifactId>cloud-wechat-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<!-- <build>-->
<!-- <plugins>-->
<!-- <plugin>-->
<!-- <groupId>com.mysema.maven</groupId>-->
<!-- <artifactId>apt-maven-plugin</artifactId>-->
<!-- <version>1.1.3</version>-->
<!-- <executions>-->
<!-- <execution>-->
<!-- &lt;!&ndash; <phase>generate-sources</phase>&ndash;&gt;-->
<!-- <goals>-->
<!-- <goal>process</goal>-->
<!-- </goals>-->
<!-- <configuration>-->
<!-- <outputDirectory>src/main/java/com/yizhi/practice/application/pojo/domain</outputDirectory>-->
<!-- <processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>-->
<!-- </configuration>-->
<!-- </execution>-->
<!-- </executions>-->
<!-- </plugin>-->
<!-- </plugins>-->
<!-- </build>-->
</project>
package com.yizhi.practice.application;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.ComponentScan;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* @Date 2020/10/21 9:58 上午
* @Author lvjianhui
**/
@SpringBootApplication
@EnableDiscoveryClient
@EnableSwagger2
@EnableCaching
@EnableFeignClients(basePackages = {"com.yizhi"})
@ComponentScan(basePackages = {"com.yizhi"})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
package com.yizhi.practice.application.aop;
import com.google.gson.Gson;
import com.yizhi.core.application.context.ContextHolder;
import com.yizhi.core.application.context.RequestContext;
import com.yizhi.util.application.domain.BizResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.formula.functions.T;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
/**
* 智能陪练aop
*/
@Component
@Aspect
@Slf4j
public class PracticeAop {
/**
* 定义切入点,切入点为com.yizhi.practice.application.controller包下所有controller中的所有函数
*通过@Pointcut注解声明频繁使用的切点表达式
*/
@Pointcut("execution(public * com.yizhi.practice.application.controller.manage.*.*(..)))")
public void webLogAspect(){
}
/**
* 方法执行前后打印日志
*/
@Around("webLogAspect()")
public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
RequestContext context = ContextHolder.get();
Long accountId = context.getAccountId();
Long siteId = context.getSiteId();
String siteCode = context.getSiteCode();
Long orgId = context.getOrgId();
String accountName = context.getAccountName();
Gson gson = new Gson();
//打印请求信息
log.info("===START=====Request AccountId = {} ,AccountName = {},SiteId = {} ,SiteCode = {},OrgId = {}; " +
"URL : {}, Request Class-Method: [{}-{}] " +
" ,Request Args : {} ======\r\n"
,accountId,accountName,siteId,siteCode,orgId
,request.getRequestURL().toString(),proceedingJoinPoint.getTarget().getClass().getName(),proceedingJoinPoint.getSignature().getName()
,gson.toJson(proceedingJoinPoint.getArgs()));
BizResponse<T> result = (BizResponse<T>) proceedingJoinPoint.proceed();
// 打印出参
log.info("Response Args : {}", gson.toJson(result));
log.info("===END=====Request AccountId = {} ,AccountName = {},SiteId = {} ,SiteCode = {},OrgId = {}; " +
"URL : {}, Request Class-Method: [{}-{}] " +
" ,Response : {} ======\r\n"
,accountId,accountName,siteId,siteCode,orgId
,request.getRequestURL().toString(),proceedingJoinPoint.getTarget().getClass().getName(),proceedingJoinPoint.getSignature().getName()
,gson.toJson(result.getData()));
return result;
}
}
package com.yizhi.practice.application.config
import org.apache.commons.io.FileUtils
import org.apache.commons.lang.math.RandomUtils
import org.slf4j.LoggerFactory
import ws.schild.jave.AudioAttributes
import ws.schild.jave.Encoder
import ws.schild.jave.EncodingAttributes
import ws.schild.jave.MultimediaObject
import java.io.File
import java.net.URL
object AudioUtils {
private val logger = LoggerFactory.getLogger(javaClass)
val dir = "tmp/audio/"
init {
val dirFile = File(dir)
if (!dirFile.exists()) {
dirFile.mkdirs()
}
}
private fun wavToMp3(sourceFile: File): File? {
val targetFileName = System.currentTimeMillis().toString() + RandomUtils.nextInt(100000).toString()
val target = File("$dir$targetFileName.mp3")
val audio = AudioAttributes()
audio.setCodec("libmp3lame")
audio.setBitRate(16000)
audio.setChannels(1)
audio.setSamplingRate(16000)
val attrs = EncodingAttributes()
attrs.setFormat("mp3")
attrs.setAudioAttributes(audio)
val encoder = Encoder()
val multimediaObject = MultimediaObject(sourceFile)
encoder.encode(multimediaObject, target, attrs)
return target
}
private fun wavToPcm(sourceFile: File): File? {
val targetFileName = System.currentTimeMillis().toString() + RandomUtils.nextInt(100000).toString()
val target = File("$dir$targetFileName.pcm")
val audio = AudioAttributes()
audio.setCodec("pcm_s16le")
audio.setBitRate(16)
audio.setChannels(1)
audio.setSamplingRate(16000)
val attrs = EncodingAttributes()
attrs.setFormat("s16le")
attrs.setAudioAttributes(audio)
val encoder = Encoder()
val multimediaObject = MultimediaObject(sourceFile)
encoder.encode(multimediaObject, target, attrs)
return target
}
fun wavToPcm(fileUrl: String):File? {
val type = fileUrl.split(".").last()
val httpurl = URL(fileUrl)
// 生成随机文件名
val fileName = System.currentTimeMillis().toString() + RandomUtils.nextInt(100000).toString() + "." + type
val file = File(dir + fileName)
var mp3File: File? = null
try {
FileUtils.copyURLToFile(httpurl, file)
mp3File = wavToPcm(file)!!
return mp3File
} catch (e: Exception) {
logger.error("拷贝文件或转MPCM出错。URL:$fileUrl")
e.printStackTrace()
file.deleteOnExit()
} finally {
file.deleteOnExit()
}
return null
}
fun wavToMp3(fileUrl: String): File? {
val type = fileUrl.split(".").last()
val httpurl = URL(fileUrl)
// 生成随机文件名
val fileName = System.currentTimeMillis().toString() + RandomUtils.nextInt(100000).toString() + "." + type
println("fileName-->>>"+fileName)
val file = File(dir + fileName)
var mp3File: File? = null
try {
FileUtils.copyURLToFile(httpurl, file)
mp3File = wavToMp3(file)!!
return mp3File
} catch (e: Exception) {
logger.error("拷贝文件或转MP3出错。URL:$fileUrl")
e.printStackTrace()
//file.deleteOnExit()
} finally {
//file.deleteOnExit()
}
return null
}
/**
* 获取音频文件时长
*/
fun getAudioDuration(file: File): Long {
val multimediaObject = MultimediaObject(file)
return multimediaObject.info.duration
}
/**
* 获取网络音频资源时长
*/
fun getAudioDuration(fileUrl: String): Long {
val type = fileUrl.split(".").last()
val httpurl = URL(fileUrl)
// 生成随机文件名
val fileName = System.currentTimeMillis().toString() + RandomUtils.nextInt(100000).toString() + "." + type
var file: File? = File(dir + fileName)
var duration = 0L;
try {
FileUtils.copyURLToFile(httpurl, file)
duration = getAudioDuration(file!!)
file.deleteOnExit()
return duration
} catch (e: Exception) {
e.printStackTrace()
logger.error("获取音频时长异常。URL:$fileUrl")
file!!.deleteOnExit()
} finally {
// 删除生成的文件
file!!.deleteOnExit()
}
return duration
}
}
\ No newline at end of file
package com.yizhi.practice.application.config
/**
* @Date 2020/10/26 4:21 下午
* @Author lvjianhui
**/
enum class PracticeLevelEnum(val level:Int,val msg:String) {
PRIMARY_LEVEL (10,"初级"),
INTERMEDIATE_LEVEL (40,"中级"),
SENIOR_LEVEL (80,"高级");
companion object {
val map = values().associateBy { it.level }
fun getAlllevel() = map.keys
}
}
package com.yizhi.practice.application.config
/**
* @Date 2020/10/26 2:04 下午
* @Author lvjianhui
**/
enum class PracticeRunningStatusEnum(val status:Int,val msg:String) {
NOT_STARTED (10,"未开始"),
RUNNING (40,"进行中"),
ENDED (80,"已结束"),
ALL (90,"所有状态");
companion object {
val map = values().associateBy { it.status }
fun getAllStatus() = map.keys
fun getEnumByState(status: Int) :PracticeRunningStatusEnum {
return map[status]!!
}
}
}
\ No newline at end of file
package com.yizhi.practice.application.config;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ThreadPoolConfig {
@Value("${practice.thread.pool.corePoolSize}")
private Integer corePoolSize;
@Value("${practice.thread.pool.maxPoolSize}")
private Integer maxPoolSize;
@Value("${practice.thread.pool.keepAliveTime}")
private Long keepAliveTime;
@Value("${practice.thread.pool.queueSize}")
private Integer queueSize;
@Bean(value="practiceThreadPool")
public ExecutorService practiceThreadPool() {
return new ThreadPoolExecutor(corePoolSize, maxPoolSize, keepAliveTime, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(queueSize), new ThreadPoolExecutor.AbortPolicy());
}
}
package com.yizhi.practice.application.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.async.DeferredResult;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* @Author: shengchenglong
* @Date: 2018/3/6 14:30
*/
@Configuration
@EnableSwagger2
public class WebMvcConfigure extends WebMvcConfigurerAdapter {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.groupName("未木云")
.apiInfo(new ApiInfoBuilder()
.title("智能陪练接口")
.version("1.0")
.build())
.select()
.apis(RequestHandlerSelectors.basePackage("com.yizhi"))
.paths(PathSelectors.any())
.build();
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("docs.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}
package com.yizhi.practice.application.constants;
/**
* 常量表
*/
public class PracticeConstant {
public static final String BUSINESS_TYPE = "PRACTICE";
public static final String SUB_BUSINESS_TYPE = "MANAGECHAT";
public static final String SUB_BUSINESS_TYPE_EXPORT = "EXPORT";
public static final String KEY_WORD_SPERATOR_EN = ";";
public static final String KEY_WORD_SPERATOR_CN = ";";
/**
* 导入对话开始节点默认横坐标(X坐标)值
*/
public static final int CHAT_DEFAULT_XAXIS = 50;
/**
* 导入对话开始节点默认纵坐标(Y坐标)值
*/
public static final int CHAT_DEFAULT_YAXIS = 50;
/**
* 导入对话,默认递增纵坐标(Y坐标)值步长
*/
public static final int YAXIS_STEP_LEN = 100;
/**
* 智能陪练陪练策略未识别回复语句
*/
public static final String EXAM_FAIL_MESSAGE = "我无法理解您的意图,请重新回复";
/**
* 智能陪练默认logo图片地址
*/
public static final String PRACTICE_DEFAULT_LOGO_URL = "https://cloud-wmy.oss-cn-shanghai.aliyuncs.com/practice/logo/practice_logo.png";
}
package com.yizhi.practice.application.constants;
/**
* @Date 2020/11/13 3:47 下午
* @Author lvjianhui
**/
public class PracticePointConstant {
public static final String POINT_EVENT_NAME = "practiceChat";
public static final String POINT_ACTIVITY_TYPE = "陪练考核通过";
public static final String POINT_ACTIVITY_SOURCE = "陪练";
}
package com.yizhi.practice.application.controller.manage;
import com.yizhi.practice.application.pojo.vo.PracticeChatLogListHeaderVo;
import com.yizhi.practice.application.pojo.vo.PracticeChatLogListParamVo;
import com.yizhi.practice.application.pojo.vo.PracticeChatLogListVo;
import com.yizhi.practice.application.xservice.PracticeChatLogXService;
import com.yizhi.util.application.domain.BizResponse;
import com.yizhi.util.application.page.PageInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@Api(tags = "智能演练-陪练记录")
@RequestMapping(path = "/manage/practice/log")
@RestController
public class PracticeChatLogController {
@Autowired
private PracticeChatLogXService xservice;
@ApiOperation(value = "陪练记录-列表-头部基本信息")
@GetMapping("/base/info/get")
public BizResponse<PracticeChatLogListHeaderVo> listHeaderInfo(@ApiParam(value="陪练的ID") @RequestParam("practiceId")Long practiceId){
return BizResponse.ok(xservice.baseInfo(practiceId));
}
@ApiOperation(value = "陪练记录-列表-列表信息")
@PostMapping("/list")
public BizResponse<PageInfo<PracticeChatLogListVo>> list(@ApiParam(name="传入参数") @RequestBody PracticeChatLogListParamVo param){
return BizResponse.ok(xservice.list(param));
}
@ApiOperation("陪练记录-导出陪练记录")
@PostMapping("/download")
public BizResponse<String> export(@ApiParam(name="传入参数") @RequestBody PracticeChatLogListParamVo param) {
return BizResponse.ok(xservice.export(param));
}
}
package com.yizhi.practice.application.controller.manage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.yizhi.core.application.context.ContextHolder;
import com.yizhi.core.application.context.RequestContext;
import com.yizhi.practice.application.pojo.vo.PracticeChatLogBaseInfoVo;
import com.yizhi.practice.application.pojo.vo.PracticeChatLogDetailParamVo;
import com.yizhi.practice.application.pojo.vo.PracticeChatRoundLogDetailVo;
import com.yizhi.practice.application.service.IPracticeChatLogService;
import com.yizhi.practice.application.xservice.PracticeChatRoundLogXService;
import com.yizhi.util.application.domain.BizResponse;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Api(tags = "智能演练-陪练记录-陪练详情")
@RequestMapping(path = "/manage/practice/log/detail")
@RestController
public class PracticeChatRoundLogController {
@Autowired
private PracticeChatRoundLogXService roundXservice;
@Autowired
private IPracticeChatLogService chatservice;
@ApiOperation(value = "本题分析")
@GetMapping("/analysis/get")
public BizResponse<PracticeChatRoundLogDetailVo> analysis(@ApiParam(value="某句对话的ID") @RequestParam("roundId")Long roundId){
return BizResponse.ok(roundXservice.analysis(roundId));
}
@ApiOperation(value = "陪练详情(包含学员信息,总得分信息,场景对话及得分)")
@GetMapping("/get")
public BizResponse<PracticeChatLogBaseInfoVo> baseInfo(@ApiParam(value="陪练记录的ID") @RequestParam("practiceLogId") Long practiceLogId){
return BizResponse.ok(roundXservice.getLogByPracticeChatId(practiceLogId));
}
@ApiOperation(value = "上一份")
@PostMapping("/previous/get")
public BizResponse<PracticeChatLogBaseInfoVo> previous(@RequestBody PracticeChatLogDetailParamVo param){
RequestContext requestContext = ContextHolder.get();
Long previousId = chatservice.previous(param, requestContext);
if(null == previousId) {
log.warn("Previous practice log not exist!");
return BizResponse.ok();
}
return BizResponse.ok(roundXservice.getLogByPracticeChatId(previousId));
}
@ApiOperation(value = "下一份")
@PostMapping("/next/get")
public BizResponse<PracticeChatLogBaseInfoVo> next(@RequestBody PracticeChatLogDetailParamVo param){
RequestContext requestContext = ContextHolder.get();
Long nextId = chatservice.next(param, requestContext);
if(null == nextId) {
log.warn("Next practice log not exist!");
return BizResponse.ok();
}
return BizResponse.ok(roundXservice.getLogByPracticeChatId(nextId));
}
}
package com.yizhi.practice.application.controller.manage;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.yizhi.core.application.context.ContextHolder;
import com.yizhi.core.application.context.RequestContext;
import com.yizhi.practice.application.pojo.vo.*;
import com.yizhi.practice.application.request.*;
import com.yizhi.practice.application.xservice.PracticeXservice;
import com.yizhi.util.application.domain.BizResponse;
import com.yizhi.util.application.page.PageInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@Api(tags = "智能演练")
@RequestMapping(path = "/manage/practice")
@RestController
public class PracticeController {
@Autowired
PracticeXservice practiceXservice;
/**
* 新增陪练 初始化空白陪练
* @return 陪练唯一id
*/
@ApiOperation(value = "初始化空白陪练")
@PostMapping(path = "/init/blank/draft/save/")
public BizResponse<PracticeBlankDraftVo> initBlankDraftPractice(){
PracticeBlankDraftVo baseInfoVo = practiceXservice.initBlankDraftPractice();
return BizResponse.ok(baseInfoVo);
}
/**
* 保存陪练基本信息
*/
@ApiOperation(value = "保存陪练基本信息")
@PostMapping(path = "/base/info/save")
public BizResponse savePracticeConfigInfo(@RequestBody PracticeConfigInfoReq practiceConfigInfoReq){
return practiceXservice.savePracticeConfInfo(practiceConfigInfoReq);
}
/**
* 保存陪练策略配置
*/
@ApiOperation(value = "保存陪练策略信息")
@PostMapping(path = "/strategy/info/save")
public BizResponse savePracticeStrategyInfo(@RequestBody PracticeConfigInfoReq practiceConfigInfoReq){
return practiceXservice.savePracticeStrategyInfo(practiceConfigInfoReq);
}
/**
* 保存陪练 对话
*/
@ApiOperation(value = "保存陪练对话信息")
@PostMapping(path = "/dialogue/save")
public BizResponse savePracticeDialogue(@RequestBody List<PracticeSceneDialogueReq> sceneNodeList){
if (null == sceneNodeList || sceneNodeList.size() == 0){
return BizResponse.fail("陪练对话参数为空");
}
return practiceXservice.savePracticeDialogue(sceneNodeList);
}
/**
* 保存智能陪练指定用户
*/
@ApiOperation(value = "保存智能陪练指定用户")
@PostMapping(path = "/account/save")
public BizResponse addPracticeAccount(@RequestBody PracticeAccountReq practiceAccountReq){
return practiceXservice.addPracticeAccount(practiceAccountReq);
}
/**
* 智能陪练上架、下架
*/
@ApiOperation(value = "智能陪练上架、下架")
@PostMapping(path = "/status/update")
public BizResponse setPracticeStatus(@RequestBody PracticeStatusReq practiceStatusReq) throws Exception {
Long practiceId = practiceStatusReq.getPracticeId();
Integer status = practiceStatusReq.getStatus();
if (null == practiceId || null == status){
log.error("上架下架陪练失败,参数包含空值 practiceId = {},status ={}",practiceId,status);
return BizResponse.fail("操作失败");
}
BizResponse bizResponse = practiceXservice.updatePracticeStatus(practiceId, status);
return bizResponse;
}
/**
* 复制智能陪练
* @return 返回复制成功的新的陪练的ID
* @throws Exception
*/
@ApiOperation(value = "复制智能陪练")
@PostMapping(path = "/copy/save")
public BizResponse<Long> copyPractice(@RequestBody PracticeReq practiceReq) throws Exception{
Long practiceId = practiceReq.getPracticeId();
return BizResponse.ok(practiceXservice.copyPractice(practiceId));
}
/**
* 导入陪练对话
* @param sceneChatImportReq 导入文件信息
*/
@ApiOperation(value = "导入陪练对话")
@PostMapping(value = "/import/chat/update")
public BizResponse<String> importScore(@RequestBody SceneChatImportReq sceneChatImportReq) throws Exception {
String fileName = sceneChatImportReq.getFileName();
String fileUrl = sceneChatImportReq.getFileUrl();
Long practiceId = sceneChatImportReq.getPracticeId();
RequestContext context = ContextHolder.get();
Long sceneId = sceneChatImportReq.getSceneId();
if (StringUtils.isEmpty(fileUrl) || null == practiceId || null == sceneId || (!fileUrl.endsWith(".xlsx") && !fileUrl.endsWith(".xls"))){
log.error("智能陪练导入对话失败;文件名不符合要求或必要参数为空。accountId = {} ,入参: {}",context.getAccountId(),JSONObject.toJSONString(sceneChatImportReq));
return BizResponse.fail("导入陪练对话失败");
}
return practiceXservice.importPracticeChat(sceneChatImportReq);
}
/**
* 清空陪练下场景对话
*/
@ApiOperation(value = "清空场景对话")
@PostMapping(path = "/clear/scene/chat/update")
public BizResponse clearScene(@RequestBody SceneChatReq chatReq){
Long sceneId = chatReq.getSceneId();
RequestContext context = ContextHolder.get();
if (null == sceneId){
log.error("清空场景对话失败! 场景id为空;accountId = {}",context.getAccountId());
return BizResponse.fail("清空场景对话失败");
}
return practiceXservice.clearSceneChat(sceneId);
}
/**
* 删除陪练
*/
@ApiOperation(value = "删除陪练")
@PostMapping(path = "/delete")
public BizResponse deletePractice(@RequestBody PracticeReq practiceReq ){
RequestContext context = ContextHolder.get();
Long practiceId = practiceReq.getPracticeId();
if (null == practiceId){
log.error("[PracticeController:deletePractice]删除陪练失败! practiceId为空;accountId = {}",context.getAccountId());
return BizResponse.fail("删除陪练失败");
}
return practiceXservice.delete(practiceId);
}
/**
* 导入可见范围
* 导入用户
*/
@ApiOperation(value = "导入可见范围")
@PostMapping(path = "/import/account/update")
public BizResponse importPracticeUsers(@RequestBody PracticeImportAccountReq importAccountReq){
return practiceXservice.importAccount(importAccountReq);
}
/**
* 导出可见范围
* 导出用户
*/
@ApiOperation(value = "导出可见范围")
@GetMapping(path = "/export/account/update")
public BizResponse exportPracticeUsers(@RequestParam("practiceId") Long practiceId){
RequestContext context = ContextHolder.get();
if (null == practiceId){
log.error("导出可见范围失败! 传入practiceId 为空;accountId = {}",context.getAccountId());
return BizResponse.fail("导出可见范围失败");
}
return practiceXservice.exportAccount(practiceId);
}
/**
* 设置对话‘下一步’校验场景和对话
*/
@ApiOperation(value = "校验陪练场景和对话是否完整")
@GetMapping(path = "/scene/check")
public BizResponse checkSceneAndChat(@RequestParam("practiceId") Long practiceId){
return practiceXservice.checkPracticeSceneValid(practiceId);
}
/**
* 查询机器人
*/
@ApiOperation(value = "查询机器人信息")
@GetMapping(path = "/robot/list")
public BizResponse<List<RobotVo>> getRobotList(){
List<RobotVo> list = practiceXservice.getRobotList();
return BizResponse.ok(list);
}
/**
* 分页查询陪练列表
*/
@ApiOperation(value = "分页查询陪练列表" )
@PostMapping(path = "/practices/list")
public BizResponse<PageInfo<PracticeBaseInfoVo>> selectPractices(@RequestBody PracticesGetReq practicesGetReq){
BizResponse<PageInfo<PracticeBaseInfoVo>> response = practiceXservice.getPracticeList(practicesGetReq);
return response;
}
/**
* 查询陪练基本信息和策略信息
*/
@ApiOperation(value = "查询陪练基本信息和策略信息")
@GetMapping(path = "/baseInfo/list")
public BizResponse<PracticeConfigInfoVo> selectPracticeBaseInfo(@RequestParam(value = "practiceId") Long practiceId){
PracticeConfigInfoVo configInfoVo = practiceXservice.getPracticeConfigInfo(practiceId);
if (null != configInfoVo){
return BizResponse.ok(configInfoVo);
}
return BizResponse.fail("查询陪练基本信息失败");
}
/**
* 查询陪练指定用户信息
*/
@ApiOperation(value = "查询陪练指定用户信息")
@GetMapping(path = "/account/list")
public BizResponse<PracticeVisibleAccountVo> selectPracticeAccountInfo(@RequestParam(value = "practiceId") Long practiceId){
RequestContext context = ContextHolder.get();
if (null == practiceId){
log.error("查询陪练指定用户信息失败;practiceId 为空; accountId = {}",context.getAccountId());
return BizResponse.fail("查询陪练指定用户信息失败");
}
PracticeVisibleAccountVo visibleAccountVo = practiceXservice.getPracticeVisibleList(practiceId);
return BizResponse.ok(visibleAccountVo);
}
/**
* 查询陪练场景对话
*/
@ApiOperation(value = "查询场景对话")
@GetMapping(path = "/scene/chat/list")
public BizResponse<List<PracticeSceneDialogueVo>> selectPracticeSceneChatList(@RequestParam(value = "practiceId") Long practiceId,@RequestParam(value = "sceneId") Long sceneId){
if (null == practiceId || null == sceneId){
log.error("查询场景失败;参数都为空");
return BizResponse.fail("查询场景失败");
}
List<PracticeSceneDialogueVo> vo = new ArrayList<>();
try {
vo = practiceXservice.getPracticeSceneChatList(practiceId,sceneId);
} catch (JsonProcessingException e) {
log.error("查询场景对话 .",e);
return BizResponse.fail("查询场景对话失败");
}
return BizResponse.ok(vo);
}
}
package com.yizhi.practice.application.controller.manage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.baomidou.mybatisplus.plugins.Page;
import com.yizhi.core.application.context.ContextHolder;
import com.yizhi.practice.application.util.NumberUtil;
import com.yizhi.statistics.application.feign.StatisticsPracticeByUserClient;
import com.yizhi.statistics.application.request.practice.PracticeReportByUserDetailReq;
import com.yizhi.statistics.application.request.practice.PracticeReportByUserReq;
import com.yizhi.statistics.application.vo.practice.PracticeReportByUserDetailVo;
import com.yizhi.statistics.application.vo.practice.PracticeReportByUserListVo;
import com.yizhi.util.application.domain.BizResponse;
import com.yizhi.util.application.page.PageInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
@Api(tags = "智能演练-报表-按用户统计")
@RequestMapping(path = "/manage/practice/report/user")
@RestController
@Slf4j
public class PracticeReportByUserController {
@Autowired
private StatisticsPracticeByUserClient statisticsClient;
@ApiOperation(value = "列表")
@PostMapping("/list/get")
public BizResponse<PageInfo<PracticeReportByUserListVo>> list(@RequestBody PracticeReportByUserReq param){
param.setContext(ContextHolder.get());
Page<PracticeReportByUserListVo> result = statisticsClient.list(param);
PageInfo<PracticeReportByUserListVo> page = new PageInfo<PracticeReportByUserListVo>();
page.setPageNo(param.getPageNo());
page.setPageSize(param.getPageSize());
page.setPageTotal(NumberUtil.getPageCount((long) result.getTotal(), param.getPageSize()));
page.setPageRecords(result.getTotal());
page.setRecords(result.getRecords());
log.info("Practice report by user - list page - size : {}.", result.getTotal());
return BizResponse.ok(page);
}
@ApiOperation(value = "列表-下载")
@PostMapping("/list/download")
public BizResponse<String> listDownload(@RequestBody PracticeReportByUserReq param){
param.setContext(ContextHolder.get());
return BizResponse.ok(statisticsClient.listDownload(param));
}
@ApiOperation(value = "详情")
@PostMapping("/detail/get")
public BizResponse<PageInfo<PracticeReportByUserDetailVo>> detail(@RequestBody PracticeReportByUserDetailReq param){
param.setContext(ContextHolder.get());
Page<PracticeReportByUserDetailVo> result = statisticsClient.detail(param);
PageInfo<PracticeReportByUserDetailVo> page = new PageInfo<PracticeReportByUserDetailVo>();
page.setPageNo(param.getPageNo());
page.setPageSize(param.getPageSize());
page.setPageTotal(NumberUtil.getPageCount((long) result.getTotal(), param.getPageSize()));
page.setPageRecords(result.getTotal());
page.setRecords(result.getRecords());
log.info("Practice report by user - detail page - size : {}.", result.getTotal());
return BizResponse.ok(page);
}
@ApiOperation(value = "详情-下载")
@PostMapping("/detail/download")
public BizResponse<String> detailDownload(@RequestBody PracticeReportByUserDetailReq param){
param.setContext(ContextHolder.get());
return BizResponse.ok(statisticsClient.detailDownload(param));
}
}
package com.yizhi.practice.application.controller.manage;
import com.alibaba.fastjson.JSONObject;
import com.yizhi.core.application.context.ContextHolder;
import com.yizhi.core.application.context.RequestContext;
import com.yizhi.core.application.enums.InternationalEnums;
import com.yizhi.core.application.exception.BizException;
import com.yizhi.practice.application.pojo.vo.SceneVo;
import com.yizhi.practice.application.request.SceneChatReq;
import com.yizhi.practice.application.request.SceneReq;
import com.yizhi.practice.application.xservice.PracticeXSceneservice;
import com.yizhi.util.application.domain.BizResponse;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Slf4j
@Api(tags = "智能演练-场景")
@RequestMapping(path = "/manage/scene")
@RestController(value = "ManagePracticeSceneController")
public class PracticeSceneController {
private static Logger logger = LoggerFactory.getLogger(PracticeSceneController.class);
@Autowired
PracticeXSceneservice xSceneservice;
/**
* 新增场景
*/
@ApiOperation(value = "新增陪练场景")
@PostMapping(path = "/save")
public BizResponse<SceneVo> addScene(@RequestBody SceneReq sceneReq){
if (null == sceneReq.getPracticeId()){
logger.error("新增陪练场景,陪练id为空! 请求入参: {}", JSONObject.toJSONString(sceneReq));
throw new BizException(InternationalEnums.MATERIALCONTROLLER1);
}
return xSceneservice.save(sceneReq);
}
/**
* 修改场景
*/
@ApiOperation(value = "修改场景")
@PostMapping(path = "/update")
public BizResponse<SceneVo> updateScene(@RequestBody SceneReq sceneReq){
if (null == sceneReq.getPracticeId()){
logger.error("修改陪练场景,陪练id为空! 请求入参: {}", JSONObject.toJSONString(sceneReq));
throw new BizException(InternationalEnums.MATERIALCONTROLLER1);
}
return xSceneservice.save(sceneReq);
}
/**
* 修改场景排序
*/
@ApiOperation(value = "修改场景排序")
@PostMapping(path = "/sort/update")
public BizResponse updateSceneSort(@RequestBody List<SceneReq> sceneReqList){
if (null == sceneReqList || sceneReqList.size() == 0){
logger.error("修改场景排序失败,入参为空!");
throw new BizException(InternationalEnums.MATERIALCONTROLLER1);
}
return xSceneservice.updateSceneSort(sceneReqList);
}
/**
* 删除场景
*/
@ApiOperation(value = "删除场景")
@PostMapping(path = "/delete")
public BizResponse deleteScene(@RequestBody SceneChatReq sceneReq){
//删除场景
RequestContext context = ContextHolder.get();
Long sceneId = sceneReq.getSceneId();
if (null == sceneId){
log.error("[PracticeSceneController:deleteScene]删除场景失败。sceneId is null. accountId = {}",context.getAccountId());
throw new BizException(InternationalEnums.CLASSIFYCONTROLLER4);
}
return xSceneservice.deleteScene(sceneId);
}
/**
* 查询场景
*/
@ApiOperation(value = "查询场景详情")
@GetMapping(path = "/one/get")
public BizResponse<SceneVo> selectScene(@RequestParam(name = "sceneId") Long sceneId){
SceneVo sceneVo = xSceneservice.selectScene(sceneId);
return BizResponse.ok(sceneVo);
}
/**
* 查询场景列表
*/
@ApiOperation(value = "查询场景列表")
@GetMapping(path = "/list")
public BizResponse<List<SceneVo>> selectSceneList(@RequestParam(name = "practiceId") Long practiceId){
RequestContext context = ContextHolder.get();
if (null == practiceId){
log.error("查询场景列表失败.传入practiceId 为空;accountId = {}",context.getAccountId());
return BizResponse.fail("查询场景列表失败");
}
List<SceneVo> list = xSceneservice.selectSceneList(practiceId);
return BizResponse.ok(list);
}
}
package com.yizhi.practice.application.controller.manage;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.plugins.Page;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.yizhi.core.application.context.ContextHolder;
import com.yizhi.core.application.enums.InternationalEnums;
import com.yizhi.core.application.exception.BizException;
import com.yizhi.practice.application.request.PracticeStatisticsReq;
import com.yizhi.statistics.application.feign.StatisticsPracticeClient;
import com.yizhi.statistics.application.request.practice.PracticeStatByPracticeIdReq;
import com.yizhi.statistics.application.request.practice.PracticeStatByPracticeReq;
import com.yizhi.statistics.application.vo.practice.PracticeStatByPracticeVo;
import com.yizhi.statistics.application.vo.practice.PracticeStatViewByIdVo;
import com.yizhi.util.application.domain.BizResponse;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
@Slf4j
@Api(tags = "智能陪练统计")
@RequestMapping("/manage/practice/report")
@RestController
public class PracticeStatisticsController {
private static Logger logger = LoggerFactory.getLogger(PracticeStatisticsController.class);
private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
@Autowired
StatisticsPracticeClient practiceClient;
@PostMapping("/group/list")
@ApiOperation(value = "智能陪练统计-按陪练统计")
public BizResponse<Page<PracticeStatByPracticeVo>> practiceGroup(@RequestBody PracticeStatisticsReq req) throws JsonProcessingException, ParseException {
PracticeStatByPracticeReq practiceReq = new PracticeStatByPracticeReq();
checkAndSetTime(req);
practiceReq.setStartDate(req.getStartOfDate());
practiceReq.setEndDate(req.getEndOfDate());
practiceReq.setName(req.getPracticeName());
practiceReq.setPageNo(req.getPageNo());
practiceReq.setPageSize(req.getPageSize());
practiceReq.setContext(ContextHolder.get());
return BizResponse.ok(practiceClient.practiceGroup(practiceReq));
}
@PostMapping("/group/list/download")
@ApiOperation(value = "智能陪练统计-按陪练统计-按陪练统计下载")
public BizResponse practiceGroupDownload(@RequestBody PracticeStatisticsReq req) throws ParseException {
checkAndSetTime(req);
PracticeStatByPracticeReq practiceReq = new PracticeStatByPracticeReq();
practiceReq.setPageSize(req.getPageSize());
practiceReq.setPageNo(req.getPageNo());
practiceReq.setName(req.getPracticeName());
practiceReq.setStartDate(req.getStartOfDate());
practiceReq.setEndDate(req.getEndOfDate());
practiceReq.setContext(ContextHolder.get());
return BizResponse.ok(practiceClient.practiceGroupDownload(practiceReq));
}
@PostMapping("/group/view/list")
@ApiOperation(value = "智能陪练统计-按陪练统计-学员陪练结果列表")
public BizResponse<Page<PracticeStatViewByIdVo>> practiceGroupView(@RequestBody PracticeStatisticsReq req) throws ParseException {
checkAndSetTime(req);
Long practiceId = req.getPracticeId();
if (null == practiceId){
logger.error("智能陪练学员训练详情列表陪练id为空!");
return BizResponse.fail(InternationalEnums.DROOLSMANAGERCONTROLLER1.getCode(),InternationalEnums.DROOLSMANAGERCONTROLLER1.getName());
}
PracticeStatByPracticeIdReq practiceViewReq = new PracticeStatByPracticeIdReq();
practiceViewReq.setPageSize(req.getPageSize());
practiceViewReq.setPageNo(req.getPageNo());
practiceViewReq.setPracticeId(req.getPracticeId());
practiceViewReq.setPracticeName(req.getPracticeName());
practiceViewReq.setStartDate(req.getStartOfDate());
practiceViewReq.setEndDate(req.getEndOfDate());
practiceViewReq.setNameKwd(req.getNameKwd());
practiceViewReq.setOrgKwd(req.getOrgKwd());
practiceViewReq.setContext(ContextHolder.get());
return BizResponse.ok(practiceClient.practiceGroupView(practiceViewReq));
}
@PostMapping("/group/view/list/download")
@ApiOperation(value = "智能陪练统计-按陪练统计-详情-下载结果数据")
public BizResponse PagepracticeGroupViewDownload(@RequestBody PracticeStatisticsReq req) throws ParseException {
checkAndSetTime(req);
Long practiceId = req.getPracticeId();
if (null == practiceId){
logger.error("智能陪练统计-按陪练统计-详情-下载结果数据,陪练id为空!");
return BizResponse.fail(InternationalEnums.DROOLSMANAGERCONTROLLER1.getCode(),InternationalEnums.DROOLSMANAGERCONTROLLER1.getName());
}
PracticeStatByPracticeIdReq practiceViewReq = new PracticeStatByPracticeIdReq();
practiceViewReq.setPageSize(req.getPageSize());
practiceViewReq.setPageNo(req.getPageNo());
practiceViewReq.setPracticeId(req.getPracticeId());
practiceViewReq.setPracticeName(req.getPracticeName());
practiceViewReq.setStartDate(req.getStartOfDate());
practiceViewReq.setEndDate(req.getEndOfDate());
practiceViewReq.setNameKwd(req.getNameKwd());
practiceViewReq.setOrgKwd(req.getOrgKwd());
practiceViewReq.setContext(ContextHolder.get());
return BizResponse.ok(practiceClient.practiceGroupViewDownload(practiceViewReq));
}
@PostMapping("/group/view/list/detail/download")
@ApiOperation(value = "智能陪练统计-按陪练统计-详情-下载陪练明细")
public BizResponse practiceGroupViewDetailDownload(@RequestBody PracticeStatisticsReq req) throws ParseException {
checkAndSetTime(req);
Long practiceId = req.getPracticeId();
if (null == practiceId){
logger.error("智能陪练统计-按陪练统计-详情-下载陪练明细,陪练id为空!");
return BizResponse.fail(InternationalEnums.DROOLSMANAGERCONTROLLER1.getCode(),InternationalEnums.DROOLSMANAGERCONTROLLER1.getName());
}
PracticeStatByPracticeIdReq practiceViewReq = new PracticeStatByPracticeIdReq();
practiceViewReq.setPageSize(req.getPageSize());
practiceViewReq.setPageNo(req.getPageNo());
practiceViewReq.setPracticeId(req.getPracticeId());
practiceViewReq.setPracticeName(req.getPracticeName());
practiceViewReq.setStartDate(req.getStartOfDate());
practiceViewReq.setEndDate(req.getEndOfDate());
practiceViewReq.setNameKwd(req.getNameKwd());
practiceViewReq.setOrgKwd(req.getOrgKwd());
practiceViewReq.setContext(ContextHolder.get());
return BizResponse.ok(practiceClient.practiceGroupViewDetailDownload(practiceViewReq));
}
//时间转换
private PracticeStatisticsReq checkAndSetTime(PracticeStatisticsReq req) throws ParseException {
String startDate = req.getStartDate();
String endDate = req.getEndDate();
if (StringUtils.isEmpty(startDate) || StringUtils.isEmpty(endDate)){
logger.error("智能陪练统计-按陪练统计时间段包含空值");
throw new BizException(InternationalEnums.OFFLINECOURSEREPORTCONTROLLER);
}
Date startOfDate = DateUtil.beginOfDay(format.parse(startDate));
Date endOfDate = DateUtil.endOfDay(format.parse(endDate));
req.setStartOfDate(startOfDate);
req.setEndOfDate(endOfDate);
return req;
}
}
package com.yizhi.practice.application.controller.manage.export;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.yizhi.core.application.context.TaskContext;
import com.yizhi.core.application.file.task.AbstractDefaultTask;
import com.yizhi.practice.application.constants.PracticeConstant;
import com.yizhi.practice.application.pojo.po.PracticeChatLogExportPo;
import com.yizhi.practice.application.pojo.vo.PracticeChatLogListVo;
import com.yizhi.practice.application.third.aliyun.AliyunUtil;
import com.yizhi.practice.application.third.util.OssFileUtil;
@Component
public class PracticeChatLogExport extends AbstractDefaultTask<String, PracticeChatLogExportPo> {
private static final Logger LOGGER = LoggerFactory.getLogger(PracticeChatLogExport.class);
@Autowired
private AliyunUtil aliyunUtil;
@Override
protected String execute(PracticeChatLogExportPo exportParam) {
String resultUrl = null;
TaskContext taskContext = new TaskContext(exportParam.getTaskId(), exportParam.getSerialNo(), exportParam.getTaskName(),
exportParam.getAccountId(), new Date(), exportParam.getSiteId(), exportParam.getCompanyId());
working(taskContext);
InputStream ins = null;
try(Workbook wb = createExcel(exportParam.getDatas());
ByteArrayOutputStream bos = new ByteArrayOutputStream()){
wb.write(bos);
ins = new ByteArrayInputStream(bos.toByteArray());
resultUrl = aliyunUtil.uploadByStream(OssFileUtil.getManageStandardFileUri(exportParam.getCompanyId(), exportParam.getSiteId()
, PracticeConstant.BUSINESS_TYPE
, PracticeConstant.SUB_BUSINESS_TYPE_EXPORT
, exportParam.getAccountId()
, ".xlsx"), ins);
success(taskContext, "成功", resultUrl);
} catch (IOException e) {
fail(taskContext, "导出陪练记录过程中发生错误");
LOGGER.error("Error occurred : ", e);
} finally {
if(null != ins) {
try {
ins.close();
} catch (IOException e) {
LOGGER.error("Error occurred : ", e);
}
}
}
return resultUrl;
}
private Workbook createExcel(List<PracticeChatLogListVo> datas) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
XSSFWorkbook wb = new XSSFWorkbook();
//创建报表页
XSSFSheet sheet = wb.createSheet("陪练记录");
int rowCount=0;
XSSFRow row = sheet.createRow(rowCount);
rowCount++;
String[] headers = new String[] {"用户名","姓名","部门","陪练模式","完成时间","总得分"};
for(int i = 0 ; i < headers.length; i++) {
row.createCell(i).setCellValue(headers[i]);
}
if(null != datas && datas.size()>0){
for(PracticeChatLogListVo data : datas) {
XSSFRow dataRow = sheet.createRow(rowCount++);
int cellCount = 0;
dataRow.createCell(cellCount++).setCellValue(data.getAccountName());
dataRow.createCell(cellCount++).setCellValue(data.getAccountFullName());
dataRow.createCell(cellCount++).setCellValue(data.getOrgName());
dataRow.createCell(cellCount++).setCellValue(data.getMode());
dataRow.createCell(cellCount++).setCellValue(sdf.format(data.getEndAt()));
dataRow.createCell(cellCount++).setCellValue(data.getTotalScore());
}
}
return wb;
}
}
package com.yizhi.practice.application.controller.manage.statistics;
import com.baomidou.mybatisplus.plugins.Page;
import com.yizhi.core.application.context.ContextHolder;
import com.yizhi.statistics.application.feign.StatisticsPracticeByOrgClient;
import com.yizhi.statistics.application.request.practice.PracticeByOrgPageReq;
import com.yizhi.statistics.application.request.practice.PracticeReportByUserReq;
import com.yizhi.statistics.application.vo.practice.PracticeReportByUserListVo;
import com.yizhi.statistics.application.vo.practice.PracticeStatByOrgVo;
import com.yizhi.util.application.domain.BizResponse;
import com.yizhi.util.application.page.PageInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Date 2020/11/18 3:17 下午
* @Author lvjianhui
**/
@Api(tags = "智能演练-按部门统计")
@RequestMapping(path = "/manage/statistic/practice/report/org")
@RestController
public class PracticeGroupByOrgController {
@Autowired
private StatisticsPracticeByOrgClient statisticsPracticeByOrgClient;
@PostMapping("/page")
@ApiOperation("按部门统计查询")
public BizResponse<PageInfo<PracticeStatByOrgVo>> getPageByOrg(@RequestBody PracticeByOrgPageReq po) {
po.setRequestContext(ContextHolder.get());
PageInfo<PracticeStatByOrgVo> page = statisticsPracticeByOrgClient.groupByOrgPage(po);
return BizResponse.ok(page);
}
@PostMapping("/detail/page")
@ApiOperation("按部门统计查询")
public BizResponse<PageInfo<PracticeReportByUserListVo>> getPageByOrgDetail(@RequestBody PracticeReportByUserReq po) {
po.setContext(ContextHolder.get());
Page<PracticeReportByUserListVo> page = statisticsPracticeByOrgClient.getDetailByOrgIdPage(po);
PageInfo<PracticeReportByUserListVo> vo = new PageInfo();
vo.setRecords(page.getRecords());
vo.setPageTotal(page.getTotal());
vo.setPageNo(page.getOffset());
vo.setPageSize(page.getSize());
vo.setPageRecords(page.getTotal());
return BizResponse.ok(vo);
}
@PostMapping("/page/export")
@ApiOperation("按部门统计导出")
public BizResponse<String> exportByOrg(@RequestBody PracticeByOrgPageReq po) {
po.setRequestContext(ContextHolder.get());
String taskCode = statisticsPracticeByOrgClient.groupByOrgExport(po);
return BizResponse.ok(taskCode);
}
@PostMapping("/detail/export")
@ApiOperation("按部门+用户统计导出")
public BizResponse<String> exportByOrgDedaill(@RequestBody PracticeReportByUserReq po) {
po.setContext(ContextHolder.get());
String taskCode = statisticsPracticeByOrgClient.getDetailByOrgIdPageExport(po);
return BizResponse.ok(taskCode);
}
@PostMapping("/user/detail/export")
@ApiOperation("按部门+用户-明细统计导出")
public BizResponse<String> exportByOrgUserDetail(@RequestBody PracticeReportByUserReq po) {
po.setContext(ContextHolder.get());
String taskCode = statisticsPracticeByOrgClient.getUserDetailByOrgIdPageExport(po);
return BizResponse.ok(taskCode);
}
}
package com.yizhi.practice.application.controller.remote;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.yizhi.practice.application.pojo.vo.PracticeChatLogVo;
import com.yizhi.practice.application.pojo.vo.PracticeVisibleVo;
import com.yizhi.practice.application.pojo.vo.PracticeVo;
import com.yizhi.practice.application.xservice.PracticeChatLogXService;
import com.yizhi.practice.application.xservice.PracticeXservice;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
@Api(tags = "智能演练remote api")
@RestController
@Slf4j
public class PracticeControllerApi {
@Autowired
PracticeXservice practiceXservice;
@Autowired
private PracticeChatLogXService xservice;
private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
private Date getStartDate(String startDate) throws ParseException {
log.info("Incoming param start date string:{}", startDate);
SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
Date start = null;
if(StringUtils.isEmpty(startDate)) {
Date previousDay = com.yizhi.util.application.date.DateUtil.add(new Date(), Calendar.DAY_OF_MONTH, -1);
start = cn.hutool.core.date.DateUtil.beginOfDay(previousDay);
}else {
start = sdf.parse(startDate);
}
return start;
}
private Date getEndDate(String endDate) throws ParseException {
log.info("Incoming param end date string:{}", endDate);
SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
Date end = null;
if(StringUtils.isEmpty(endDate)) {
Date previousDay = com.yizhi.util.application.date.DateUtil.add(new Date(), Calendar.DAY_OF_MONTH, -1);
end = cn.hutool.core.date.DateUtil.endOfDay(previousDay);
}else {
end = sdf.parse(endDate);
}
return end;
}
/**
* 查询指定时间范围内更新的陪练
*/
@ApiOperation(value = "查询指定时间范围内更新的陪练")
@GetMapping(path = "/remote/manage/practice/range/list")
public List<PracticeVo> selectRangeList(@RequestParam(name = "startDate",value="startDate",required=false)String startDate,
@RequestParam(name = "endDate",value="endDate",required=false)String endDate) {
List<PracticeVo> practiceVos = null;
try {
practiceVos = practiceXservice.selectRangeList(getStartDate(startDate), getEndDate(endDate));
} catch (ParseException e) {
log.error("Parse error", e);
}
return practiceVos;
}
/**
* 查询指定时间范围内更新的陪练可见范围
*/
@ApiOperation(value = "查询指定时间范围内更新的陪练可见范围")
@GetMapping(path = "/remote/manage/practice/visible/range/list")
public List<PracticeVisibleVo> selectVisibleRangeList(@RequestParam(name = "startDate",value="startDate",required=false) String startDate,
@RequestParam(name = "endDate",value="endDate",required=false) String endDate) {
List<PracticeVisibleVo> visibleVos= null;
try {
visibleVos = practiceXservice.selectVisibleRangeList(getStartDate(startDate), getEndDate(endDate));
} catch (ParseException e) {
log.error("Parse error", e);
}
return visibleVos;
}
/**
* 查询指定时间范围内更新的陪练记录
*/
@ApiOperation(value = "查询指定时间范围内更新的陪练记录")
@GetMapping(path = "/remote/manage/practice/chat/range/list")
public List<PracticeChatLogVo> selectChatLogRangeList(@RequestParam(name = "startDate",value="startDate",required=false) String startDate,
@RequestParam(name = "endDate",value="endDate",required=false) String endDate) {
List<PracticeChatLogVo> visibleVos= null;
try {
visibleVos = xservice.selectChatLogRangeList(getStartDate(startDate), getEndDate(endDate));
} catch (ParseException e) {
log.error("Parse error", e);
}
return visibleVos;
}
}
package com.yizhi.practice.application.controller.student;
import com.yizhi.core.application.enums.InternationalEnums;
import com.yizhi.practice.application.pojo.domain.PracticeConfig;
import com.yizhi.practice.application.pojo.vo.PracticeVo;
import com.yizhi.practice.application.repository.PracticeConfigRepository;
import com.yizhi.util.application.domain.BizResponse;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@Api(tags = "智能演练-学员端-陪练")
@RequestMapping(path = "/student/practice")
@RestController
public class PracticeConfigStudentController {
@Autowired
private PracticeConfigRepository configRepository;
@ApiOperation(value = "获取陪练")
@GetMapping("/get")
public BizResponse<PracticeVo> getPractice(@ApiParam(value="陪练的ID") @RequestParam("practiceId") Long practiceId){
if (null == practiceId){
return BizResponse.fail(InternationalEnums.DROOLSMANAGERCONTROLLER1.getCode());
}
PracticeVo practiceVo = new PracticeVo();
PracticeConfig practiceConfig = configRepository.findById(practiceId).get();
if (null != practiceConfig){
BeanUtils.copyProperties(practiceConfig,practiceVo);
}
return BizResponse.ok(practiceVo);
}
}
package com.yizhi.practice.application.controller.student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.yizhi.practice.application.pojo.vo.PracticeChatLogBaseInfoVo;
import com.yizhi.practice.application.pojo.vo.PracticeChatLogListParamVo;
import com.yizhi.practice.application.pojo.vo.PracticeChatRoundLogDetailVo;
import com.yizhi.practice.application.pojo.vo.StudentPracticeLogVo;
import com.yizhi.practice.application.xservice.PracticeChatLogXService;
import com.yizhi.practice.application.xservice.PracticeChatRoundLogXService;
import com.yizhi.util.application.domain.BizResponse;
import com.yizhi.util.application.page.PageInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
@Api(tags = "智能演练-学员端-陪练记录")
@RequestMapping(path = "/student/practice/log")
@RestController
public class PracticeLogStudentController {
@Autowired
private PracticeChatLogXService xservice;
@Autowired
private PracticeChatRoundLogXService roundXservice;
@ApiOperation(value = "学员端-陪练记录-列表")
@PostMapping("/list")
public BizResponse<PageInfo<StudentPracticeLogVo>> list(@RequestBody PracticeChatLogListParamVo param){
return BizResponse.ok(xservice.studentList(param));
}
@ApiOperation(value = "答案解析")
@GetMapping("/analysis/get")
public BizResponse<PracticeChatRoundLogDetailVo> analysis(@ApiParam(value="某句对话的ID") @RequestParam("roundId")Long roundId){
return BizResponse.ok(roundXservice.analysis(roundId));
}
@ApiOperation(value = "陪练分析")
@GetMapping("/get")
public BizResponse<PracticeChatLogBaseInfoVo> baseInfo(@ApiParam(value="陪练记录的ID") @RequestParam("practiceLogId") Long practiceLogId){
return BizResponse.ok(roundXservice.getLogByPracticeChatId(practiceLogId));
}
}
package com.yizhi.practice.application.controller.student
import com.yizhi.core.application.context.ContextHolder
import com.yizhi.practice.application.pojo.po.AnalyzeStudentVoicePo
import com.yizhi.practice.application.pojo.po.StartPracticePO
import com.yizhi.practice.application.pojo.vo.*
import com.yizhi.practice.application.xservice.PracticeStuChatXService
import com.yizhi.util.application.domain.BizResponse
import io.swagger.annotations.Api
import io.swagger.annotations.ApiOperation
import io.swagger.annotations.ApiParam
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.web.bind.annotation.*
/**
* @Date 2020/10/26 3:54 下午
* @Author lvjianhui
**/
@Api(tags = ["开始陪练"])
@RestController
@RequestMapping(path = ["/student/chat"])
class PracticeStuSceneController {
@Autowired
lateinit var practiceStuChatXService: PracticeStuChatXService
@PostMapping("/start/practice/save")
@ApiOperation("陪练开始,新增一条陪练记录")
fun startPractice(@RequestBody startPracticePO: StartPracticePO): BizResponse<StuPracticeLogVo> {
startPracticePO.requestContext = ContextHolder.get()
val vo = practiceStuChatXService.startPractice(startPracticePO)
return BizResponse.ok(vo)
}
@GetMapping("/scene/list")
@ApiOperation("获取所有场景")
fun getAllScene(
@ApiParam("陪练ID")
@RequestParam("practiceId") practiceId: Long): BizResponse<List<SceneChatVO>> {
val list = practiceStuChatXService.getAllScene(practiceId)
return BizResponse.ok(list)
}
@GetMapping("/scene/first/list")
@ApiOperation("按顺序开始场景,返回机器人话术")
fun startChatByScene(
@ApiParam("场景ID")
@RequestParam("sceneId") sceneId: Long,
@ApiParam("陪练模式 模式 10:训练 20:考核", allowableValues = "10,20")
@RequestParam("useType") useType: Int,
@ApiParam("陪练ID")
@RequestParam("practiceId") practiceId: Long
): BizResponse<List<ChatContextVo>> {
val list = practiceStuChatXService.getRobotFirstChat(practiceId, sceneId, useType)
return BizResponse.ok(list)
}
@GetMapping("/context/student/list")
@ApiOperation("根据机器人话术,查询学员话术")
fun getStudentChatByRobot(
@ApiParam("场景ID")
@RequestParam("sceneId") sceneId: Long,
@ApiParam("陪练模式 模式 10:训练 20:考核", allowableValues = "10,20")
@RequestParam("useType") useType: Int,
@ApiParam("陪练ID")
@RequestParam("practiceId") practiceId: Long,
@ApiParam("机器人话术Id")
@RequestParam robotChatId: Long,
@ApiParam("陪练记录Id")
@RequestParam practiceLogId: Long
): BizResponse<List<StudentChatContextVo>> {
val list = practiceStuChatXService.getStudentContent(sceneId, useType, practiceId,practiceLogId, robotChatId)
return BizResponse.ok(list)
}
@PostMapping("/analyze/voice/save")
@ApiOperation("用户上传录音,返回结果")
fun analyzeStudentVoice(@RequestBody po: AnalyzeStudentVoicePo): BizResponse<ChatResultVo> {
po.requestContext = ContextHolder.get()
val vo = practiceStuChatXService.analyzeStudentVoice(po)
return BizResponse.ok(vo)
}
@GetMapping("/chat/log/delete")
fun deletedAccountUploadId(@RequestParam("accountUploadId") accountUploadId:Long):BizResponse<String> {
practiceStuChatXService.deletedAccountUploadId(accountUploadId,ContextHolder.get())
return BizResponse.ok()
}
@GetMapping("/robot/context/get")
@ApiOperation("根据学员话术返回机器人话术")
fun getRobotContext(@ApiParam("场景ID")
@RequestParam("sceneId") sceneId: Long,
@ApiParam("陪练模式 模式 10:训练 20:考核", allowableValues = "10,20")
@RequestParam("useType") useType: Int,
@ApiParam("陪练ID")
@RequestParam("practiceId") practiceId: Long,
@ApiParam("学员话术Id")
@RequestParam chatRoundConfigId: Long): BizResponse<List<ChatContextVo>> {
val vo = practiceStuChatXService.getRobotLevelChat(practiceId, sceneId, chatRoundConfigId, useType)
return BizResponse.ok(vo)
}
@GetMapping("/end/save")
fun endAccountPractice(@ApiParam("陪练模式 模式 10:训练 20:考核", allowableValues = "10,20")
@RequestParam("useType") useType: Int,
@ApiParam("陪练ID")
@RequestParam("practiceId") practiceId: Long,
@ApiParam("陪练记录ID")
@RequestParam("practiceLogId") practiceLogId: Long,
@ApiParam("异常退出 传true")
@RequestParam("errorEnd", defaultValue = "false") errorEnd: Boolean
): BizResponse<PracticeEndResultVo> {
val vo = practiceStuChatXService.endPractice(practiceId, practiceLogId, useType, ContextHolder.get(), errorEnd)
return BizResponse.ok(vo)
}
@GetMapping("/score/get")
fun getResultByLogResult(@ApiParam("陪练记录ID")
@RequestParam("practiceLogId") practiceLogId: Long):BizResponse<PracticeEndResultVo> {
val vo = practiceStuChatXService.getLogResult(practiceLogId,ContextHolder.get().accountId)
return BizResponse.ok(vo)
}
}
\ No newline at end of file
package com.yizhi.practice.application.controller.student
import com.yizhi.core.application.context.ContextHolder
import com.yizhi.core.application.context.RequestContext
import com.yizhi.practice.application.feign.MyPracticeStudentClient
import com.yizhi.practice.application.pojo.vo.PracticeConfigVo
import com.yizhi.practice.application.pojo.vo.PracticeJoinedVo
import com.yizhi.practice.application.xservice.PracticeStudentXSerice
import com.yizhi.util.application.domain.BizResponse
import com.yizhi.util.application.page.PageInfo
import io.swagger.annotations.Api
import io.swagger.annotations.ApiOperation
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.web.bind.annotation.*
@RestController
@Api(tags = ["学员陪练"])
@RequestMapping(path = ["/student/practice"])
class PracticeStudentController : MyPracticeStudentClient {
@Autowired
lateinit var practiceStudentXSerice: PracticeStudentXSerice
// @ApiOperation("获取用户进行中的配练数")
@GetMapping("/running/count/get")
override fun getRuningPracticeCount(@RequestBody requestContext: RequestContext): BizResponse<Int> {
val count = practiceStudentXSerice.getRunningCount(
requestContext.accountId,
requestContext.orgId,
requestContext.siteId,
requestContext.companyId
)
return BizResponse.ok(count)
}
@ApiOperation(value = "校验用户是否有陪练可见权限")
@GetMapping("/user/auth")
override fun getUserPracticeAuth(@RequestBody requestContext: RequestContext
,@RequestParam("practiceId") practiceId: Long): BizResponse<Boolean> {
return practiceStudentXSerice.getUserPracticeAuth(requestContext,practiceId);
}
@GetMapping("/list/tab/index/get")
@ApiOperation("获取前端走哪个tab 0:未开始 1:进行中 2:已完成")
fun getAccountTab():BizResponse<Int> {
val requestContext = ContextHolder.get()
val index = practiceStudentXSerice.getTabIndex(requestContext)
return BizResponse.ok(index)
}
@GetMapping("/by/state/list")
@ApiOperation("根据状态获取陪练列表 40:进行中 10:未开始 80:已结束")
fun getRunningPracticeList(@RequestParam(defaultValue = "1") pageIndex: Int,
@RequestParam(defaultValue = "10") pageSize: Int,
@RequestParam(defaultValue = "40") state: Int): BizResponse<PageInfo<PracticeConfigVo>> {
val requestContext = ContextHolder.get()
val page = practiceStudentXSerice.getRunningList(
requestContext.accountId,
requestContext.orgId,
requestContext.siteId,
requestContext.companyId,
state,
pageIndex,
pageSize
)
return BizResponse.ok(page)
}
@GetMapping("/msg/by/id/list")
@ApiOperation("获取配练时间及次数信息")
fun getStartMsgById(
@RequestParam(name = "practiceId") practiceId: Long): BizResponse<PracticeConfigVo> {
val requestContext = ContextHolder.get()
val vo: PracticeConfigVo = practiceStudentXSerice.getPracticeInfo(
practiceId,
requestContext.accountId,
requestContext.orgId,
requestContext.siteId,
requestContext.companyId
)
return BizResponse.ok(vo)
}
@GetMapping("/joined/count")
fun getPracticeJoinEd(@RequestParam practiceId: Long):BizResponse<PracticeJoinedVo> {
val vo = practiceStudentXSerice.getPracticeJoined(practiceId, ContextHolder.get())
return BizResponse.ok(vo)
}
}
\ No newline at end of file
package com.yizhi.practice.application.excel;
import com.alibaba.fastjson.JSONObject;
import com.yizhi.core.application.context.RequestContext;
import com.yizhi.core.application.file.task.AbstractDefaultTask;
import com.yizhi.practice.application.enums.PracticeVisibleTypeEnum;
import com.yizhi.practice.application.pojo.domain.PracticeConfig;
import com.yizhi.practice.application.pojo.domain.PracticeVisible;
import com.yizhi.practice.application.repository.PracticeConfigRepository;
import com.yizhi.practice.application.repository.PracticeVisibleRepository;
import com.yizhi.system.application.model.AccountRangeExportParam;
import com.yizhi.system.application.system.remote.AccountRangeClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
@Component
public class PracticeAccountExport extends AbstractDefaultTask<String, PracticeAccountExportParam> {
private static final Logger logger = LoggerFactory.getLogger(PracticeAccountExport.class);
@Autowired
private AccountRangeClient accountRangeClient;
@Autowired
private PracticeVisibleRepository visibleRepository;
@Autowired
private PracticeConfigRepository practiceConfigRepository;
@Override
public String execute(PracticeAccountExportParam accountExportParam) {
RequestContext context = accountExportParam.getContext();
Long practiceId = accountExportParam.getPracticeId();
try {
AccountRangeExportParam accountRangeImportParam=new AccountRangeExportParam();
accountRangeImportParam.setContext(context);
PracticeConfig practice = practiceConfigRepository.findById(practiceId).get();
Integer practiceVisibleType = practice.getVisibleType();
List<Long> accountIds = new ArrayList<>();
List<Long> orgIds = new ArrayList<>();
if (PracticeVisibleTypeEnum.ALL.getStatus().equals(practiceVisibleType)){
return "";
}else if (PracticeVisibleTypeEnum.PART.getStatus().equals(practiceVisibleType)){
//指定用户可见
List<PracticeVisible> practiceVisibleList = visibleRepository.findByPracticeId(practiceId);
taskDetail(accountExportParam.getTaskId(),"智能陪练导出用户可见范围:查询可见范围成功;practiceId="+practiceId);
if (null != practiceVisibleList && practiceVisibleList.size() > 0){
for (PracticeVisible practiceVisible : practiceVisibleList) {
Integer visibleType = practiceVisible.getVisibleType();
if (PracticeVisibleTypeEnum.PART.getStatus().equals(visibleType)){
accountIds.add(practiceVisible.getVisibleAccountId());
}
else if (PracticeVisibleTypeEnum.ORG.getStatus().equals(visibleType)){
orgIds.add(practiceVisible.getVisibleOrgId());
}
}
accountRangeImportParam.setAccountIds(accountIds);
accountRangeImportParam.setOrgIds(orgIds);
taskDetail(accountExportParam.getTaskId(),"智能陪练导出用户可见范围:获取到可见范围accountIdsSize="+accountIds.size()+",orgIdsSize="+orgIds.size());
}
}
accountRangeImportParam.setBizName(practice.getName());
logger.info("智能陪练-[PracticeAccountExport:execute]导出可见范围参数: {}", JSONObject.toJSONString(accountRangeImportParam));
taskDetail(accountExportParam.getTaskId(),"智能陪练导出用户可见范围:调用system导出可见范围入参="+JSONObject.toJSONString(accountRangeImportParam));
String serialNo=accountRangeClient.doExport(accountRangeImportParam);
logger.info("智能陪练-[PracticeAccountExport:execute]导出可见范围返回结果: {}",serialNo);
return serialNo;
}catch (Exception e){
logger.error("智能陪练可见范围导出异常;",e);
}
return null;
}
}
package com.yizhi.practice.application.excel;
import com.yizhi.core.application.context.RequestContext;
import com.yizhi.core.application.context.TaskContext;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class PracticeAccountExportParam {
@ApiModelProperty(value = "RequestContext")
private RequestContext context;
@ApiModelProperty(value = "陪练id")
private Long practiceId;
@ApiModelProperty(value = "任务id")
private Long taskId;
@ApiModelProperty(value = "序列号")
private String serialNo;
@ApiModelProperty(value = "任务名")
private String taskName;
private TaskContext taskContext;
}
package com.yizhi.practice.application.excel;
import com.alibaba.fastjson.JSONObject;
import com.yizhi.application.orm.id.IdGenerator;
import com.yizhi.core.application.context.ContextHolder;
import com.yizhi.core.application.context.RequestContext;
import com.yizhi.core.application.context.TaskContext;
import com.yizhi.core.application.event.LogEvent;
import com.yizhi.core.application.file.task.AbstractDefaultTask;
import com.yizhi.core.application.log.LogEventPublisher;
import com.yizhi.core.application.log.TaskLogDetailEvent;
import com.yizhi.core.application.log.TaskLogEvent;
import com.yizhi.practice.application.enums.PracticeVisibleTypeEnum;
import com.yizhi.practice.application.request.PracticeAccountReq;
import com.yizhi.practice.application.request.PracticeVisibleAccount;
import com.yizhi.practice.application.xservice.PracticeXservice;
import com.yizhi.system.application.model.AccountRangeImportModel;
import com.yizhi.system.application.model.AccountRangeImportParam;
import com.yizhi.system.application.system.remote.AccountClient;
import com.yizhi.system.application.system.remote.AccountRangeClient;
import com.yizhi.system.application.vo.AccountVO;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Component
public class PracticeAccountImport extends AbstractDefaultTask<String, PracticeAccountImportParam> {
private static final Logger logger = LoggerFactory.getLogger(PracticeAccountImport.class);
@Autowired
private AccountRangeClient accountRangeClient;
@Autowired
IdGenerator idGenerator;
@Autowired
AccountClient accountClient;
@Autowired
PracticeXservice practiceXservice;
@Autowired
LogEventPublisher publisher;
@Override
protected String execute(PracticeAccountImportParam accountImportParam) {
String ossUrl = accountImportParam.getFileUrl();
RequestContext context = accountImportParam.getContext();
ContextHolder.set(context);
Long accountId = context.getAccountId();
TaskContext taskContext = new TaskContext(accountImportParam.getTaskId(), accountImportParam.getSerialNo()
, accountImportParam.getTaskName(), accountId, new Date(), context.getSiteId(), context.getCompanyId());
working(taskContext);
AccountRangeImportParam param = new AccountRangeImportParam();
param.setType(AccountRangeImportParam.Type.PRACTICE);
param.setOssUrl(ossUrl);
param.setRequestContext(context);
List<AccountRangeImportModel.SuccessAccount> successList = new ArrayList<>();
List<AccountRangeImportModel.ErrorAccount> errorList = new ArrayList<>();
//进行入库
try {
logger.info("智能演练导入用户可见范围:[AccountRangeClient.doImport]入参: {}",JSONObject.toJSONString(param));
AccountRangeImportModel accountRangeImportModel = accountRangeClient.doImport(param);
if (null == accountRangeImportModel) {
logger.error("智能演练导入用户可见范围:[AccountRangeClient.doImport]出参is null");
logEventPublish(taskContext,successList,errorList,null);
return null;
}
if (null != accountRangeImportModel) {
logger.info("智能演练导入用户可见范围,[AccountRangeClient.doImport]出参: {}", JSONObject.toJSONString(accountRangeImportModel));
successList = accountRangeImportModel.getSuccessList();
errorList = accountRangeImportModel.getErrorList();
}
PracticeAccountReq practiceAccountReq = new PracticeAccountReq();
practiceAccountReq.setPracticeId(accountImportParam.getPracticeId());
List<PracticeVisibleAccount> accountList = new ArrayList<>();
for (AccountRangeImportModel.SuccessAccount successAccount : successList) {
PracticeVisibleAccount visibleAccount = new PracticeVisibleAccount();
Long id = successAccount.getId();
AccountVO accountVO = accountClient.findById(id);
visibleAccount.setName(accountVO.getName());
visibleAccount.setFullName(accountVO.getFullName());
visibleAccount.setWorkNum(accountVO.getWorkNum());
visibleAccount.setVisibleId(id);
visibleAccount.setVisibleType(PracticeVisibleTypeEnum.PART.getStatus());
accountList.add(visibleAccount);
}
practiceAccountReq.setAccountList(accountList);
practiceXservice.addPracticeAccount(practiceAccountReq);
logEventPublish(taskContext,successList,errorList,null);
} catch (Exception e) {
fail(taskContext, "智能陪练可见范围异步导入过程中出现错误");
logger.error("智能陪练可见范围异步导入过程中出现错误.", e);
}
return "ok";
}
public void logEventPublish(TaskContext taskContext, List<AccountRangeImportModel.SuccessAccount> successList,
List<AccountRangeImportModel.ErrorAccount> errorList, String url) {
TaskLogEvent taskLogEvent = TaskLogEvent.success(taskContext, "成功导入" + successList.size() + "条," + "导入失败" + errorList.size() + "条", url);
LogEvent<TaskLogEvent> event = new LogEvent("taskLog", taskLogEvent);
this.publisher.publish(event);
if (CollectionUtils.isNotEmpty(errorList)) {
List<TaskLogDetailEvent> details = new ArrayList(errorList.size());
Long taskId = taskContext.getTaskId();
for (AccountRangeImportModel.ErrorAccount a : errorList) {
details.add(new TaskLogDetailEvent(taskId, "第"+a.getLine()+"行,"+a.getErrMsg()));
}
LogEvent<List<TaskLogDetailEvent>> eventDetails = new LogEvent("batchTaskDetailLog", details);
this.publisher.publish(eventDetails);
}
}
}
package com.yizhi.practice.application.excel;
import com.yizhi.core.application.context.RequestContext;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class PracticeAccountImportParam {
@ApiModelProperty(value = "文件路径")
private String fileUrl;
@ApiModelProperty(value = "RequestContext")
private RequestContext context;
@ApiModelProperty(value = "陪练id")
private Long practiceId;
@ApiModelProperty(value = "任务id")
private Long taskId;
@ApiModelProperty(value = "序列号")
private String serialNo;
@ApiModelProperty(value = "任务名")
private String taskName;
}
package com.yizhi.practice.application.excel;
import com.alibaba.fastjson.JSONObject;
import com.yizhi.core.application.file.domain.Template;
import com.yizhi.core.application.file.util.ProxyCreateUtil;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.Proxy;
import java.net.URL;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
/**
* excel 导入 包含合并单元格
*/
@Component
public class PracticeExcelImporter {
private static Integer httpProxyPort;
private static String httpProxyUrl;
private static final Logger logger = LoggerFactory.getLogger(PracticeExcelImporter.class);
public List<List<String>> parse(String fileUrl,Template template) {
//
InputStream inputStream = this.read(fileUrl);
int columnCount = template.getColumns().size();
Workbook book = null;
try {
book = WorkbookFactory.create(inputStream);
} catch (Exception e) {
logger.error("[PracticeExcelImporter : parse] excel文件读取发生错误",e);
throw new RuntimeException("excel文件读取发生错误");
}
List<List<String>> lines = new ArrayList<>();
Sheet sheet = book.getSheetAt(0);
for (int i = template.getStartLine() - 1; i <= sheet.getLastRowNum(); i++) {
List<String> rowValues = new ArrayList<>();
Row row ;
for (int j = 0; j < columnCount; j++) {
String cellValue = "";
boolean mergedRegion = isMergedRegion(sheet, i, j);
if (mergedRegion){
//合并单元格方式获取整行数据
cellValue = getMergedRegionValue(sheet, i, j);
}else {
row = sheet.getRow(i);
Cell cell = row.getCell(j);
if (null != cell){
cellValue = getCellValue(cell);
}
}
rowValues.add(cellValue);
}
lines.add(rowValues);
}
logger.info("导入场景对话数据解析: {}",JSONObject.toJSONString(lines));
return lines;
}
private InputStream read(String fileUrl) {
HttpURLConnection conn = null;
try {
URL url = new URL(fileUrl);
Proxy proxy = ProxyCreateUtil.createUrlProxy(httpProxyUrl, httpProxyPort);
if (proxy != null) {
conn = (HttpURLConnection)url.openConnection(proxy);
} else {
conn = (HttpURLConnection)url.openConnection();
}
conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
InputStream inputStream = conn.getInputStream();
return inputStream;
} catch (Exception var7) {
logger.error("文件解析失败", var7);
}
return null;
}
/**
* 判断指定的单元格是否是合并单元格
* @param sheet
* @param row 行下标
* @param column 列下标
* @return
*/
private boolean isMergedRegion(Sheet sheet,int row ,int column) {
int sheetMergeCount = sheet.getNumMergedRegions();
for (int i = 0; i < sheetMergeCount; i++) {
CellRangeAddress range = sheet.getMergedRegion(i);
int firstColumn = range.getFirstColumn();
int lastColumn = range.getLastColumn();
int firstRow = range.getFirstRow();
int lastRow = range.getLastRow();
if(row >= firstRow && row <= lastRow){
if(column >= firstColumn && column <= lastColumn){
return true;
}
}
}
return false;
}
/**
* 获取合并单元格的值
*/
public String getMergedRegionValue(Sheet sheet ,int row , int column){
int sheetMergeCount = sheet.getNumMergedRegions();
for(int i = 0 ; i < sheetMergeCount ; i++){
CellRangeAddress ca = sheet.getMergedRegion(i);
int firstColumn = ca.getFirstColumn();
int lastColumn = ca.getLastColumn();
int firstRow = ca.getFirstRow();
int lastRow = ca.getLastRow();
if(row >= firstRow && row <= lastRow){
if(column >= firstColumn && column <= lastColumn){
Row fRow = sheet.getRow(firstRow);
Cell fCell = fRow.getCell(firstColumn);
return getCellValue(fCell) ;
}
}
}
return null ;
}
/**
* 获取单元格的值
*/
public String getCellValue(Cell cell){
CellType cellType = cell.getCellTypeEnum();
String cellValue;
switch (cellType){
case STRING:
cellValue = cell.getStringCellValue();
break;
case BOOLEAN:
cellValue = String.valueOf(cell.getBooleanCellValue());
break;
case FORMULA:
cellValue = String.valueOf(cell.getCellFormula());
break;
case NUMERIC:
cellValue = getDataCellValue(cell);
break;
case ERROR:
cellValue = "非法字符";
break;
default:
cellValue = "";
}
return cellValue;
}
/**获取数值类型单元格的值*/
private String getDataCellValue(Cell cell){
String cellStr = "";
String formatType = cell.getCellStyle().getDataFormatString();
if (formatType.indexOf("%") != -1) {// 判断如果含百分号,则认为百分数类型
int baifenshuxiaoshuwei = 0;
if(formatType.indexOf(".")!=-1) { // 判断包含小数点
baifenshuxiaoshuwei = formatType.substring(formatType.indexOf("."), formatType.indexOf("%")).length()-1; // 获取小数位数
cellStr = "#.";
for(int weishu=0;weishu<baifenshuxiaoshuwei;weishu++) {
cellStr += "0";
}
cellStr = new DecimalFormat(cellStr).format(cell.getNumericCellValue()*100) + "%"; // 保留对应位数百分号
if(cellStr.startsWith(".")) {// 如果以.开头的,前面加0拼接;
cellStr = "0" + cellStr;
}
}else {
// 不含小数点,直接四舍五入整数;
cellStr = Math.round(cell.getNumericCellValue()*100)+"%";
}
}else {
cell.setCellType(CellType.STRING);
cellStr = cell.getStringCellValue();
}
return cellStr;
}
/*public static void main(String[] args) throws FileNotFoundException {
PracticeExcelImporter importer = new PracticeExcelImporter();
Template template = new Template();
List<TemplateColumn> columns = new ArrayList<>();
columns.add(new TemplateColumn("order","序列号",1));
columns.add(new TemplateColumn("robotNode","机器人节点话术(必填)",2));
columns.add(new TemplateColumn("studentNode","学员节点话术(必填)",3));
columns.add(new TemplateColumn("keyword","关键词(必填)",4));
columns.add(new TemplateColumn("extendWord","扩展词(非必填)",5));
columns.add(new TemplateColumn("tabooWord","禁忌词",6));
template.setColumns(columns);
RequestContext context = new RequestContext();
context.setAccountId(1314L);
context.setSiteId(1314L);
context.setCompanyId(1314L);
context.setSiteCode("shyz");
context.setOrgId(1314L);
String fileUrl = "D:\\bugdoc\\岗前培训对话脚本导入已审核1105\\促成对话导入脚本.xlsx";
InputStream inputStream = new FileInputStream(fileUrl);
int columnCount = template.getColumns().size();
Workbook book = null;
try {
book = WorkbookFactory.create(inputStream);
} catch (Exception e) {
logger.error("[PracticeExcelImporter : parse] excel文件读取发生错误",e);
throw new RuntimeException("excel文件读取发生错误");
}
List<List<String>> lines = new ArrayList<>();
Sheet sheet = book.getSheetAt(0);
for (int i = template.getStartLine() - 1; i <= sheet.getLastRowNum(); i++) {
List<String> rowValues = new ArrayList<>();
Row row ;
for (int j = 0; j < columnCount; j++) {
String cellValue = "";
boolean mergedRegion = importer.isMergedRegion(sheet, i, j);
if (mergedRegion){
//合并单元格方式获取整行数据
cellValue = importer.getMergedRegionValue(sheet, i, j);
}else {
row = sheet.getRow(i);
Cell cell = row.getCell(j);
if (null != cell){
cellValue = importer.getCellValue(cell);
}
}
rowValues.add(cellValue);
}
lines.add(rowValues);
}
logger.info("导入场景对话数据解析: {}",JSONObject.toJSONString(lines));
}*/
}
package com.yizhi.practice.application.excel;
import com.yizhi.core.application.file.imp.ImportCallBack;
import com.yizhi.core.application.task.TaskHandler;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 导入智能陪练场景对话callback
*/
@Component
public class PracticeImportSceneChatCallBack implements ImportCallBack {
@Override
public Boolean exec(TaskHandler taskHandler, List dataObjs) {
// TODO: 2020/11/2 导入对话
System.out.println(dataObjs);
return null;
}
}
package com.yizhi.practice.application.excel;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
@Data
@ApiModel(value = "场景对话导入模板")
public class PracticeSceneChatImport implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "对话序列号")
private String order;
@ApiModelProperty(value = "机器人节点话术(必填)")
private String robotNode;
@ApiModelProperty(value = "学员节点话术(必填)")
private String studentNode;
@ApiModelProperty(value = "关键词(必填)")
private List<String> keyword;
@ApiModelProperty(value = "扩展词(非必填)")
private List<String> extendWord;
@ApiModelProperty(value = "禁忌词;多个用分号分隔(非必填)")
private String tabooWord;
}
package com.yizhi.practice.application.exception
import com.yizhi.core.application.exception.BizException
import com.yizhi.practice.application.exception.RequestParameter.ERROR_CODE
import com.yizhi.practice.application.exception.RequestParameter.EXCEPTION
import com.yizhi.util.application.domain.BizResponse
import com.yizhi.util.application.enums.i18n.Constants
import org.slf4j.LoggerFactory
import org.springframework.messaging.handler.annotation.support.MethodArgumentNotValidException
import org.springframework.validation.BeanPropertyBindingResult
import org.springframework.web.HttpRequestMethodNotSupportedException
import org.springframework.web.bind.annotation.ControllerAdvice
import org.springframework.web.bind.annotation.ExceptionHandler
import org.springframework.web.bind.annotation.ResponseBody
import javax.servlet.http.HttpServletRequest
/**
* @Author: Lvjh
* @Date 2020/02/19 18:32
*/
@ControllerAdvice
open class ApiResponseHandler {
private val logger = LoggerFactory.getLogger(javaClass)
@ExceptionHandler(HttpRequestMethodNotSupportedException::class)
@ResponseBody
fun requestMethodNotSupportException(e: HttpRequestMethodNotSupportedException, request: HttpServletRequest): BizResponse<Any> {
logger.error(" requestMethodNotSupportException uri[${request.requestURI}]", e)
return BizResponse.fail(Constants.MSG_BIZ_FAIL.code.toString(), Constants.MSG_BIZ_FAIL.name)
}
@ExceptionHandler(MethodArgumentNotValidException::class)
@ResponseBody
fun parameterInvalidException(e: MethodArgumentNotValidException, request: HttpServletRequest): BizResponse<Any> {
logger.error(" parameterInvalidException uri[${request.requestURI}]", e)
var msg = Constants.MSG_BIZ_FAIL.name
try {
val propertyBindResult: BeanPropertyBindingResult = e.bindingResult as BeanPropertyBindingResult
if (propertyBindResult.hasErrors()) {
val sbf = StringBuffer()
propertyBindResult.allErrors.forEach {
sbf.append(it.defaultMessage).append(";")
}
msg = sbf.toString()
}
return BizResponse.fail(Constants.MSG_BIZ_FAIL.code.toString(), msg)
} catch (e: Exception) {
logger.error(" parameterInvalidException url[${request.requestURL}]", e)
e.printStackTrace()
return BizResponse.fail(Constants.MSG_BIZ_FAIL.code.toString(), Constants.MSG_BIZ_FAIL.name)
}
}
@ExceptionHandler(Exception::class)
@ResponseBody
fun sysException(e: Exception, request: HttpServletRequest): BizResponse<Any> {
request.setAttribute(EXCEPTION, getStackTrace(e))
request.setAttribute(ERROR_CODE, Constants.MSG_BIZ_FAIL.code.toString())
val clientIp = request.getHeader("X-Real-IP")
logger.error("Exception requestUrl[${request.requestURI},clientIp:$clientIp] ", e)
e.printStackTrace()
return BizResponse.fail(Constants.MSG_BIZ_FAIL.code.toString(), Constants.MSG_BIZ_FAIL.name)
}
@ExceptionHandler(BizException::class)
@ResponseBody
fun bizException(e: BizException, request: HttpServletRequest): BizResponse<Any> {
request.setAttribute(ERROR_CODE, e.code)
request.setAttribute(EXCEPTION, getStackTrace(e))
logger.error("BizException requestUrl[${request.requestURL}] ${e.code}:${e.msg}")
return BizResponse.fail(e.code, e.msg)
}
private fun getStackTrace(e: Exception): String {
val stringBuffer = StringBuffer(e.toString() + "\n")
val messages = e.stackTrace
messages.forEach {
stringBuffer.append("\t $it \n")
}
return stringBuffer.toString()
}
}
\ No newline at end of file
//package com.yizhi.practice.application.exception;
//
//import com.yizhi.core.application.enums.InternationalEnums;
//import lombok.Data;
//import org.apache.poi.ss.formula.functions.T;
//
///**
// * 陪练业务异常类
// */
//@Data
//public class PracBusinessException extends RuntimeException{
//
// private String errCode;
// private String errMsg;
// private InternationalEnums enums;
// private T data;
//
// /**
// * Constructs a new runtime exception with {@code null} as its
// * detail message. The cause is not initialized, and may subsequently be
// * initialized by a call to {@link #initCause}.
// */
// public PracBusinessException() {
// }
//
// /**
// * Constructs a new runtime exception with the specified detail message.
// * The cause is not initialized, and may subsequently be initialized by a
// * call to {@link #initCause}.
// *
// */
// public PracBusinessException(String errCode, String errMsg) {
// this.errCode = errCode;
// this.errMsg = errMsg;
// }
//
//
// /**
// * Constructs a new runtime exception with {@code null} as its
// * detail message. The cause is not initialized, and may subsequently be
// * initialized by a call to {@link #initCause}.
// */
// public PracBusinessException(InternationalEnums enums) {
// this.errCode = enums.getCode();
// this.errMsg = enums.getName();
// }
//
// /**
// * Constructs a new runtime exception with {@code null} as its
// * detail message. The cause is not initialized, and may subsequently be
// * initialized by a call to {@link #initCause}.
// */
// public PracBusinessException(InternationalEnums enums, T data) {
// this.errCode = enums.getCode();
// this.errMsg = enums.getName();
// this.data = data;
// }
//
// /**
// * Constructs a new runtime exception with {@code null} as its
// * detail message. The cause is not initialized, and may subsequently be
// * initialized by a call to {@link #initCause}.
// */
// public PracBusinessException(String errCode, String errMsg, T data) {
// this.errCode = errCode;
// this.errMsg = errMsg;
// this.data = data;
// }
//}
package com.yizhi.practice.application.exception
/**
* @Author: Lvjh
* @Date 2020/02/19 18:32
*/
object RequestParameter {
const val CUSTOMER_MOBILE = "customer_mobile"
const val CUSTOMER_ID = "customer_id"
const val REQUEST_UUID = "request_uuid"
const val VERSION = "version"
const val PLATFORM = "channel_code"
const val DEVICE_UUID = "device_uuid"
const val TIMESTAMP = "timestamp"
const val EXCEPTION = "exception"
const val ERROR_CODE = "error_code"
const val TIME_ZONE = "user_timezone"
}
\ No newline at end of file
package com.yizhi.practice.application.mapper;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.yizhi.practice.application.pojo.domain.PracticeChatRoundLog;
import com.yizhi.practice.application.pojo.dto.PracticeLogScoreDto;
import org.apache.ibatis.annotations.Param;
/**
* @Date 2020/11/24 7:11 下午
* @Author lvjianhui
**/
public interface PracticeChatRoundLogMapper extends BaseMapper<PracticeChatRoundLog> {
public PracticeLogScoreDto getScoreByAccount(@Param(value = "practiceChatId") Long practiceChatId,
@Param(value = "accountId") Long accountId,
@Param(value = "orgId") Long orgId,
@Param(value = "siteId") Long siteId,
@Param(value = "companyId") Long companyId);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yizhi.practice.application.mapper.PracticeChatRoundLogMapper">
<select id="getScoreByAccount" resultType="com.yizhi.practice.application.pojo.dto.PracticeLogScoreDto">
<!-- 每轮多次提及的取最后一次提交计算得分。
如果该轮最后为跳过,则该轮所有提交不进行得分计算-->
select
avg(a.average_score) as averageScore,
avg(a.keyword_score) as keywordScore,
avg(a.complete_score) as complateScore,
avg(a.smooth_score) as fluencyScore,
avg(a.polite_score) as politeScore,
avg(a.express_score) as expressScore
from practice_chat_round_log a inner join (
select
max(created_at) as created_at,
min(round_skip_type) as minskipType
from practice_chat_round_log
where
practice_chat_id = #{practiceChatId}
and account_id = #{accountId}
and company_id = #{companyId}
and site_id = #{siteId}
and org_id = #{orgId}
and round_skip_type is not null
and deleted = 0
group by round_level
) b
on a.created_at = b.created_at
where a.practice_chat_id = #{practiceChatId}
and a.round_skip_type = 80
and a.account_id = #{accountId}
and a.company_id = #{companyId}
and a.site_id = #{siteId}
and a.org_id = #{orgId}
and a.deleted = 0
and b.minSkipType = 80
order by a.scene_id,a.round_level
</select>
</mapper>
\ No newline at end of file
package com.yizhi.practice.application.pojo.domain;
import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.annotations.TableName;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import javax.persistence.Entity;
import javax.persistence.Id;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
* 场景对话结果记录
* </p>
*
* @author MybatisCodeGenerator123
* @since 2020-10-30
*/
@DynamicUpdate
@DynamicInsert
@Api(tags = "PracticeChatLog", description = "场景对话结果记录")
@TableName("practice_chat_log")
@Entity
public class PracticeChatLog implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private Long id;
@ApiModelProperty(value = "陪练ID")
@TableField("practice_id")
private Long practiceId;
@ApiModelProperty(value = "用户ID")
@TableField("account_id")
private Long accountId;
@ApiModelProperty(value = "用户名")
@TableField("account_name")
private String accountName;
@ApiModelProperty(value = "用户姓名")
@TableField("account_full_name")
private String accountFullName;
@ApiModelProperty(value = "10:训练 20:考核")
@TableField("use_type")
private Integer useType;
@ApiModelProperty(value = "部门名")
@TableField("org_name")
private String orgName;
@ApiModelProperty(value = "陪练级别 10:初级 40:中级 80:高级")
private Integer level;
@ApiModelProperty(value = "陪练状态 40:陪练中 80:陪练正常结束 90:陪练中途退出")
private Integer status;
@ApiModelProperty(value = "陪练开始时间")
@TableField("start_at")
private Date startAt;
@ApiModelProperty(value = "陪练结束时间")
@TableField("end_at")
private Date endAt;
@ApiModelProperty(value = "通过考核最低分")
@TableField("pass_min_score")
private Integer passMinScore;
@ApiModelProperty(value = "是否发放积分 80 发放,10不发放")
@TableField("given_point_type")
private Integer givenPointType;
@ApiModelProperty(value = "发放积分数量")
@TableField("given_point_count")
private Integer givenPointCount;
@ApiModelProperty(value = "得分")
@TableField("average_score")
private Integer averageScore;
@ApiModelProperty(value = "80:通过,10:未通过")
@TableField("pass_result")
private Integer passResult;
@ApiModelProperty(value = "关键词得分")
@TableField("keyword_score")
private Integer keywordScore;
@ApiModelProperty(value = "关键词 完成度 单位%")
@TableField("keyword_rate")
private Integer keywordRate;
@ApiModelProperty(value = "完整性得分")
@TableField("complete_score")
private Integer completeScore;
@ApiModelProperty(value = "完整性 完成度 单位%")
@TableField("complete_rate")
private Integer completeRate;
@ApiModelProperty(value = "流畅性得分")
@TableField("smooth_score")
private Integer smoothScore;
@ApiModelProperty(value = "流畅性 完整度 单位%")
@TableField("smooth_rate")
private Integer smoothRate;
@ApiModelProperty(value = "表达能力得分")
@TableField("express_score")
private Integer expressScore;
@ApiModelProperty(value = "表达能力 完成度 单位%")
@TableField("express_rate")
private Integer expressRate;
@ApiModelProperty(value = "礼貌用语得分")
@TableField("polite_score")
private Integer politeScore;
@ApiModelProperty(value = "礼貌用语 完成度 单位%")
@TableField("polite_rate")
private Integer politeRate;
@ApiModelProperty(value = "0: not deledted 1:deleted")
private Boolean deleted;
@TableField("org_id")
private Long orgId;
@TableField("site_id")
private Long siteId;
@TableField("company_id")
private Long companyId;
@TableField("created_at")
private Date createdAt;
@TableField("updated_at")
private Date updatedAt;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getPracticeId() {
return practiceId;
}
public void setPracticeId(Long practiceId) {
this.practiceId = practiceId;
}
public Long getAccountId() {
return accountId;
}
public void setAccountId(Long accountId) {
this.accountId = accountId;
}
public String getAccountName() {
return accountName;
}
public void setAccountName(String accountName) {
this.accountName = accountName;
}
public String getAccountFullName() {
return accountFullName;
}
public void setAccountFullName(String accountFullName) {
this.accountFullName = accountFullName;
}
public Integer getUseType() {
return useType;
}
public void setUseType(Integer useType) {
this.useType = useType;
}
public String getOrgName() {
return orgName;
}
public void setOrgName(String orgName) {
this.orgName = orgName;
}
public Integer getLevel() {
return level;
}
public void setLevel(Integer level) {
this.level = level;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public Date getStartAt() {
return startAt;
}
public void setStartAt(Date startAt) {
this.startAt = startAt;
}
public Date getEndAt() {
return endAt;
}
public void setEndAt(Date endAt) {
this.endAt = endAt;
}
public Integer getPassMinScore() {
return passMinScore;
}
public void setPassMinScore(Integer passMinScore) {
this.passMinScore = passMinScore;
}
public Integer getGivenPointType() {
return givenPointType;
}
public void setGivenPointType(Integer givenPointType) {
this.givenPointType = givenPointType;
}
public Integer getAverageScore() {
return averageScore;
}
public void setAverageScore(Integer averageScore) {
this.averageScore = averageScore;
}
public Integer getPassResult() {
return passResult;
}
public void setPassResult(Integer passResult) {
this.passResult = passResult;
}
public Integer getKeywordScore() {
return keywordScore;
}
public void setKeywordScore(Integer keywordScore) {
this.keywordScore = keywordScore;
}
public Integer getKeywordRate() {
return keywordRate;
}
public void setKeywordRate(Integer keywordRate) {
this.keywordRate = keywordRate;
}
public Integer getCompleteScore() {
return completeScore;
}
public void setCompleteScore(Integer completeScore) {
this.completeScore = completeScore;
}
public Integer getCompleteRate() {
return completeRate;
}
public void setCompleteRate(Integer completeRate) {
this.completeRate = completeRate;
}
public Integer getSmoothScore() {
return smoothScore;
}
public void setSmoothScore(Integer smoothScore) {
this.smoothScore = smoothScore;
}
public Integer getSmoothRate() {
return smoothRate;
}
public void setSmoothRate(Integer smoothRate) {
this.smoothRate = smoothRate;
}
public Integer getExpressScore() {
return expressScore;
}
public void setExpressScore(Integer expressScore) {
this.expressScore = expressScore;
}
public Integer getExpressRate() {
return expressRate;
}
public void setExpressRate(Integer expressRate) {
this.expressRate = expressRate;
}
public Integer getPoliteScore() {
return politeScore;
}
public void setPoliteScore(Integer politeScore) {
this.politeScore = politeScore;
}
public Integer getPoliteRate() {
return politeRate;
}
public void setPoliteRate(Integer politeRate) {
this.politeRate = politeRate;
}
public Boolean getDeleted() {
return deleted;
}
public void setDeleted(Boolean deleted) {
this.deleted = deleted;
}
public Long getOrgId() {
return orgId;
}
public void setOrgId(Long orgId) {
this.orgId = orgId;
}
public Long getSiteId() {
return siteId;
}
public void setSiteId(Long siteId) {
this.siteId = siteId;
}
public Long getCompanyId() {
return companyId;
}
public void setCompanyId(Long companyId) {
this.companyId = companyId;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public Date getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
public Integer getGivenPointCount() {
return givenPointCount;
}
public void setGivenPointCount(Integer givenPointCount) {
this.givenPointCount = givenPointCount;
}
@Override
public String toString() {
return "PracticeChatLog{" +
", id=" + id +
", practiceId=" + practiceId +
", accountId=" + accountId +
", accountName=" + accountName +
", accountFullName=" + accountFullName +
", useType=" + useType +
", orgName=" + orgName +
", level=" + level +
", status=" + status +
", startAt=" + startAt +
", endAt=" + endAt +
", passMinScore=" + passMinScore +
", givenPointType=" + givenPointType +
", averageScore=" + averageScore +
", passResult=" + passResult +
", keywordScore=" + keywordScore +
", keywordRate=" + keywordRate +
", completeScore=" + completeScore +
", completeRate=" + completeRate +
", smoothScore=" + smoothScore +
", smoothRate=" + smoothRate +
", expressScore=" + expressScore +
", expressRate=" + expressRate +
", politeScore=" + politeScore +
", politeRate=" + politeRate +
", deleted=" + deleted +
", orgId=" + orgId +
", siteId=" + siteId +
", companyId=" + companyId +
", createdAt=" + createdAt +
", updatedAt=" + updatedAt +
"}";
}
}
package com.yizhi.practice.application.pojo.domain;
import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.annotations.TableName;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import javax.persistence.Entity;
import javax.persistence.Id;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
* 场景中每轮对话记录
* </p>
*
* @author MybatisCodeGenerator123
* @since 2020-11-09
*/
@DynamicUpdate
@DynamicInsert
@Api(tags = "PracticeChatRoundLog", description = "场景中每轮对话记录")
@TableName("practice_chat_round_log")
@Entity
public class PracticeChatRoundLog implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private Long id;
@ApiModelProperty(value = "陪练ID")
@TableField("practice_id")
private Long practiceId;
@ApiModelProperty(value = "场景ID")
@TableField("scene_id")
private Long sceneId;
@ApiModelProperty(value = "场景标准话术ID")
@TableField("scene_chat_id")
private Long sceneChatId;
@ApiModelProperty(value = "陪练记录ID")
@TableField("practice_chat_id")
private Long practiceChatId;
@ApiModelProperty(value = "学员ID")
@TableField("account_id")
private Long accountId;
@ApiModelProperty(value = "学员名")
@TableField("account_name")
private String accountName;
@ApiModelProperty(value = "学员姓名")
@TableField("account_full_name")
private String accountFullName;
@ApiModelProperty(value = "部门名")
@TableField("org_name")
private String orgName;
@ApiModelProperty(value = "机器人话术")
@TableField("robot_content")
private String robotContent;
@ApiModelProperty(value = "机器人话术语音URL")
@TableField("robot_content_voice_url")
private String robotContentVoiceUrl;
@ApiModelProperty(value = "机器人话术时长")
@TableField("robot_content_voice_duration")
private Long robotContentVoiceDuration;
@ApiModelProperty(value = "学员话术")
@TableField("account_content")
private String accountContent;
@ApiModelProperty(value = "学员命中关键词数组")
@TableField("account_hit_keyword")
private String accountHitKeyword;
@ApiModelProperty(value = "学员命中命中禁忌词")
@TableField("account_hit_taboo_word")
private String accountHitTabooWord;
@ApiModelProperty(value = "学员话术URL")
@TableField("account_content_voice_url")
private String accountContentVoiceUrl;
@ApiModelProperty(value = "学员话术时长")
@TableField("account_content_voice_duration")
private Long accountContentVoiceDuration;
@ApiModelProperty(value = "本轮对话层级 ")
@TableField("round_level")
private Integer roundLevel;
@ApiModelProperty(value = "本轮对话过关方式 80:正常通过。10:跳过")
@TableField("round_skip_type")
private Integer roundSkipType;
@ApiModelProperty(value = "考核本轮过关最低相似度")
@TableField("pass_similarity_rate")
private Integer passSimilarityRate;
@ApiModelProperty(value = "相似度得分 第三方返回的相似度")
@TableField("similarity_score")
private Integer similarityScore;
@ApiModelProperty(value = "陪练过关最低分")
@TableField("pass_min_score")
private Integer passMinScore;
@ApiModelProperty(value = "本轮平均得分")
@TableField("average_score")
private Integer averageScore;
@ApiModelProperty(value = "关键词得分")
@TableField("keyword_score")
private Integer keywordScore;
@ApiModelProperty(value = "完整性得分")
@TableField("complete_score")
private Integer completeScore;
@ApiModelProperty(value = "流畅度得分")
@TableField("smooth_score")
private Integer smoothScore;
@ApiModelProperty(value = "表达能力得分")
@TableField("express_score")
private Integer expressScore;
@ApiModelProperty(value = "礼貌性得分")
@TableField("polite_score")
private Integer politeScore;
@ApiModelProperty(value = "0:not del 1:del")
private Boolean deleted;
@ApiModelProperty(value = "部门ID")
@TableField("org_id")
private Long orgId;
@ApiModelProperty(value = "站点ID")
@TableField("site_Id")
private Long siteId;
@ApiModelProperty(value = "公司ID")
@TableField("company_id")
private Long companyId;
@TableField("created_at")
private Date createdAt;
public String getAccountHitTabooWord() {
return accountHitTabooWord;
}
public void setAccountHitTabooWord(String accountHitTabooWord) {
this.accountHitTabooWord = accountHitTabooWord;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getPracticeId() {
return practiceId;
}
public void setPracticeId(Long practiceId) {
this.practiceId = practiceId;
}
public Long getSceneId() {
return sceneId;
}
public void setSceneId(Long sceneId) {
this.sceneId = sceneId;
}
public Long getSceneChatId() {
return sceneChatId;
}
public void setSceneChatId(Long sceneChatId) {
this.sceneChatId = sceneChatId;
}
public Long getPracticeChatId() {
return practiceChatId;
}
public void setPracticeChatId(Long practiceChatId) {
this.practiceChatId = practiceChatId;
}
public Long getAccountId() {
return accountId;
}
public void setAccountId(Long accountId) {
this.accountId = accountId;
}
public String getAccountName() {
return accountName;
}
public void setAccountName(String accountName) {
this.accountName = accountName;
}
public String getAccountFullName() {
return accountFullName;
}
public void setAccountFullName(String accountFullName) {
this.accountFullName = accountFullName;
}
public String getOrgName() {
return orgName;
}
public void setOrgName(String orgName) {
this.orgName = orgName;
}
public String getRobotContent() {
return robotContent;
}
public void setRobotContent(String robotContent) {
this.robotContent = robotContent;
}
public String getRobotContentVoiceUrl() {
return robotContentVoiceUrl;
}
public void setRobotContentVoiceUrl(String robotContentVoiceUrl) {
this.robotContentVoiceUrl = robotContentVoiceUrl;
}
public Long getRobotContentVoiceDuration() {
return robotContentVoiceDuration;
}
public void setRobotContentVoiceDuration(Long robotContentVoiceDuration) {
this.robotContentVoiceDuration = robotContentVoiceDuration;
}
public String getAccountContent() {
return accountContent;
}
public void setAccountContent(String accountContent) {
this.accountContent = accountContent;
}
public String getAccountHitKeyword() {
return accountHitKeyword;
}
public void setAccountHitKeyword(String accountHitKeyword) {
this.accountHitKeyword = accountHitKeyword;
}
public String getAccountContentVoiceUrl() {
return accountContentVoiceUrl;
}
public void setAccountContentVoiceUrl(String accountContentVoiceUrl) {
this.accountContentVoiceUrl = accountContentVoiceUrl;
}
public Long getAccountContentVoiceDuration() {
return accountContentVoiceDuration;
}
public void setAccountContentVoiceDuration(Long accountContentVoiceDuration) {
this.accountContentVoiceDuration = accountContentVoiceDuration;
}
public Integer getRoundLevel() {
return roundLevel;
}
public void setRoundLevel(Integer roundLevel) {
this.roundLevel = roundLevel;
}
public Integer getRoundSkipType() {
return roundSkipType;
}
public void setRoundSkipType(Integer roundSkipType) {
this.roundSkipType = roundSkipType;
}
public Integer getPassSimilarityRate() {
return passSimilarityRate;
}
public void setPassSimilarityRate(Integer passSimilarityRate) {
this.passSimilarityRate = passSimilarityRate;
}
public Integer getSimilarityScore() {
return similarityScore;
}
public void setSimilarityScore(Integer similarityScore) {
this.similarityScore = similarityScore;
}
public Integer getPassMinScore() {
return passMinScore;
}
public void setPassMinScore(Integer passMinScore) {
this.passMinScore = passMinScore;
}
public Integer getAverageScore() {
return averageScore;
}
public void setAverageScore(Integer averageScore) {
this.averageScore = averageScore;
}
public Integer getKeywordScore() {
return keywordScore;
}
public void setKeywordScore(Integer keywordScore) {
this.keywordScore = keywordScore;
}
public Integer getCompleteScore() {
return completeScore;
}
public void setCompleteScore(Integer completeScore) {
this.completeScore = completeScore;
}
public Integer getSmoothScore() {
return smoothScore;
}
public void setSmoothScore(Integer smoothScore) {
this.smoothScore = smoothScore;
}
public Integer getExpressScore() {
return expressScore;
}
public void setExpressScore(Integer expressScore) {
this.expressScore = expressScore;
}
public Integer getPoliteScore() {
return politeScore;
}
public void setPoliteScore(Integer politeScore) {
this.politeScore = politeScore;
}
public Boolean getDeleted() {
return deleted;
}
public void setDeleted(Boolean deleted) {
this.deleted = deleted;
}
public Long getOrgId() {
return orgId;
}
public void setOrgId(Long orgId) {
this.orgId = orgId;
}
public Long getSiteId() {
return siteId;
}
public void setSiteId(Long siteId) {
this.siteId = siteId;
}
public Long getCompanyId() {
return companyId;
}
public void setCompanyId(Long companyId) {
this.companyId = companyId;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
@Override
public String toString() {
return "PracticeChatRoundLog{" +
", id=" + id +
", practiceId=" + practiceId +
", sceneId=" + sceneId +
", sceneChatId=" + sceneChatId +
", practiceChatId=" + practiceChatId +
", accountId=" + accountId +
", accountName=" + accountName +
", accountFullName=" + accountFullName +
", orgName=" + orgName +
", robotContent=" + robotContent +
", robotContentVoiceUrl=" + robotContentVoiceUrl +
", robotContentVoiceDuration=" + robotContentVoiceDuration +
", accountContent=" + accountContent +
", accountHitKeyword=" + accountHitKeyword +
", accountContentVoiceUrl=" + accountContentVoiceUrl +
", accountContentVoiceDuration=" + accountContentVoiceDuration +
", roundLevel=" + roundLevel +
", roundSkipType=" + roundSkipType +
", passSimilarityRate=" + passSimilarityRate +
", similarityScore=" + similarityScore +
", passMinScore=" + passMinScore +
", averageScore=" + averageScore +
", keywordScore=" + keywordScore +
", completeScore=" + completeScore +
", smoothScore=" + smoothScore +
", expressScore=" + expressScore +
", politeScore=" + politeScore +
", deleted=" + deleted +
", orgId=" + orgId +
", siteId=" + siteId +
", companyId=" + companyId +
", createdAt=" + createdAt +
"}";
}
}
package com.yizhi.practice.application.pojo.domain;
import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.annotations.TableName;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import javax.persistence.Entity;
import javax.persistence.Id;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
* 陪练配置
* </p>
*
* @author MybatisCodeGenerator123
* @since 2020-10-30
*/
@DynamicUpdate
@DynamicInsert
@Api(tags = "PracticeConfig", description = "陪练配置")
@TableName("practice_config")
@Entity
public class PracticeConfig implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private Long id;
@ApiModelProperty(value = "陪练名")
private String name;
@ApiModelProperty(value = "陪练logoURL")
@TableField("logo_url")
private String logoUrl;
@ApiModelProperty(value = "陪练描述")
private String description;
@ApiModelProperty(value = "80:训练+考核 ,10:训练 20:考核")
@TableField("use_type")
private Integer useType;
@ApiModelProperty(value = "训练开始时间")
@TableField("practice_start_at")
private Date practiceStartAt;
@ApiModelProperty(value = "训练结束时间")
@TableField("practice_end_at")
private Date practiceEndAt;
@ApiModelProperty(value = "考核开始时间")
@TableField("exam_start_at")
private Date examStartAt;
@ApiModelProperty(value = "考核结束时间")
@TableField("exam_end_at")
private Date examEndAt;
@ApiModelProperty(value = "允许最大考试;0:无限次;其他有限次;默认0")
@TableField("max_exam_count")
private Integer maxExamCount;
@ApiModelProperty(value = "自定义关键词,逗号分隔,命中得分")
@TableField("key_word")
private String keyWord;
@ApiModelProperty(value = "机器人配置ID")
@TableField("robot_id")
private Long robotId;
@ApiModelProperty(value = "机器人参数")
@TableField("robot_params")
private String robotParams;
@ApiModelProperty(value = "机器人名字")
@TableField("robot_name")
private String robotName;
@ApiModelProperty(value = "机器人头像URL null时走默认头像")
@TableField("robot_pic_url")
private String robotPicUrl;
@ApiModelProperty(value = "陪练状态 80:上架 30:下架 10:草稿")
private Integer status;
@ApiModelProperty(value = "练习可见范围 80:平台可见 40:指定用户可见")
@TableField("visible_type")
private Integer visibleType;
@ApiModelProperty(value = "跳过对话类型 80允许,10:不允许")
@TableField("skip_type")
private Integer skipType;
@ApiModelProperty(value = "80:本轮得分超过限制,则进入下轮;10:无论得分多少,直接进入下一轮")
@TableField("start_next_round_type")
private Integer startNextRoundType;
@ApiModelProperty(value = "超过该分数,进入下一轮对话")
@TableField("start_next_round_score")
private Integer startNextRoundScore;
@ApiModelProperty(value = "每轮最多失败次数,超过直接到下轮")
@TableField("practice_failed_max_count")
private Integer practiceFailedMaxCount;
@ApiModelProperty(value = "80:允许重复提交 10:不允许重复提交")
@TableField("repeat_push")
private Integer repeatPush;
@ApiModelProperty(value = "多轮对话:80:开启 10:关闭")
@TableField("many_round_chat")
private Integer manyRoundChat;
@ApiModelProperty(value = "相似度")
@TableField("similarity_rate")
private Integer similarityRate;
@ApiModelProperty(value = "考试失败最大次数,超过直接到下轮")
@TableField("exam_failed_max_count")
private Integer examFailedMaxCount;
@ApiModelProperty(value = "未识别回复类型 80:默认回复,10:自定义回复")
@TableField("similarity_failed_msg_type")
private Integer similarityFailedMsgType;
@ApiModelProperty(value = "自定义未识别回复,分号分隔。")
@TableField("similarity_failed_msg")
private String similarityFailedMsg;
@ApiModelProperty(value = "考试及格分")
@TableField("exam_pass_min_score")
private Integer examPassMinScore;
@ApiModelProperty(value = "是否发放积分 80:发放 10:不发放")
@TableField("exam_given_point_type")
private Integer examGivenPointType;
@ApiModelProperty(value = "完整性")
@TableField("score_rule_complete")
private Integer scoreRuleComplete;
@ApiModelProperty(value = "完整性")
@TableField("score_rule_keyword")
private Integer scoreRuleKeyword;
@ApiModelProperty(value = "流畅性")
@TableField("score_rule_smooth")
private Integer scoreRuleSmooth;
@ApiModelProperty(value = "表达能力")
@TableField("score_rule_express")
private Integer scoreRuleExpress;
@ApiModelProperty(value = "礼貌")
@TableField("score_rule_polite")
private Integer scoreRulePolite;
@ApiModelProperty(value = "0:未删除 1:已删除")
private Boolean deleted;
@ApiModelProperty(value = "部门ID")
@TableField("org_id")
private Long orgId;
@ApiModelProperty(value = "站点ID")
@TableField("site_id")
private Long siteId;
@ApiModelProperty(value = "公司ID")
@TableField("company_id")
private Long companyId;
@ApiModelProperty(value = "创建记录的管理员ID")
@TableField("created_uid")
private Long createdUid;
@ApiModelProperty(value = "创建时间")
@TableField("created_at")
private Date createdAt;
@ApiModelProperty(value = "最后一次更新记录的管理员ID")
@TableField("updated_uid")
private Long updatedUid;
@ApiModelProperty(value = "更新时间")
@TableField("updated_at")
private Date updatedAt;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLogoUrl() {
return logoUrl;
}
public void setLogoUrl(String logoUrl) {
this.logoUrl = logoUrl;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Integer getUseType() {
return useType;
}
public void setUseType(Integer useType) {
this.useType = useType;
}
public Date getPracticeStartAt() {
return practiceStartAt;
}
public void setPracticeStartAt(Date practiceStartAt) {
this.practiceStartAt = practiceStartAt;
}
public Date getPracticeEndAt() {
return practiceEndAt;
}
public void setPracticeEndAt(Date practiceEndAt) {
this.practiceEndAt = practiceEndAt;
}
public Date getExamStartAt() {
return examStartAt;
}
public void setExamStartAt(Date examStartAt) {
this.examStartAt = examStartAt;
}
public Date getExamEndAt() {
return examEndAt;
}
public void setExamEndAt(Date examEndAt) {
this.examEndAt = examEndAt;
}
public Integer getMaxExamCount() {
return maxExamCount;
}
public void setMaxExamCount(Integer maxExamCount) {
this.maxExamCount = maxExamCount;
}
public String getKeyWord() {
return keyWord;
}
public void setKeyWord(String keyWord) {
this.keyWord = keyWord;
}
public Long getRobotId() {
return robotId;
}
public void setRobotId(Long robotId) {
this.robotId = robotId;
}
public String getRobotParams() {
return robotParams;
}
public void setRobotParams(String robotParams) {
this.robotParams = robotParams;
}
public String getRobotName() {
return robotName;
}
public void setRobotName(String robotName) {
this.robotName = robotName;
}
public String getRobotPicUrl() {
return robotPicUrl;
}
public void setRobotPicUrl(String robotPicUrl) {
this.robotPicUrl = robotPicUrl;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public Integer getVisibleType() {
return visibleType;
}
public void setVisibleType(Integer visibleType) {
this.visibleType = visibleType;
}
public Integer getSkipType() {
return skipType;
}
public void setSkipType(Integer skipType) {
this.skipType = skipType;
}
public Integer getStartNextRoundType() {
return startNextRoundType;
}
public void setStartNextRoundType(Integer startNextRoundType) {
this.startNextRoundType = startNextRoundType;
}
public Integer getStartNextRoundScore() {
return startNextRoundScore;
}
public void setStartNextRoundScore(Integer startNextRoundScore) {
this.startNextRoundScore = startNextRoundScore;
}
public Integer getPracticeFailedMaxCount() {
return practiceFailedMaxCount;
}
public void setPracticeFailedMaxCount(Integer practiceFailedMaxCount) {
this.practiceFailedMaxCount = practiceFailedMaxCount;
}
public Integer getRepeatPush() {
return repeatPush;
}
public void setRepeatPush(Integer repeatPush) {
this.repeatPush = repeatPush;
}
public Integer getManyRoundChat() {
return manyRoundChat;
}
public void setManyRoundChat(Integer manyRoundChat) {
this.manyRoundChat = manyRoundChat;
}
public Integer getSimilarityRate() {
return similarityRate;
}
public void setSimilarityRate(Integer similarityRate) {
this.similarityRate = similarityRate;
}
public Integer getExamFailedMaxCount() {
return examFailedMaxCount;
}
public void setExamFailedMaxCount(Integer examFailedMaxCount) {
this.examFailedMaxCount = examFailedMaxCount;
}
public Integer getSimilarityFailedMsgType() {
return similarityFailedMsgType;
}
public void setSimilarityFailedMsgType(Integer similarityFailedMsgType) {
this.similarityFailedMsgType = similarityFailedMsgType;
}
public String getSimilarityFailedMsg() {
return similarityFailedMsg;
}
public void setSimilarityFailedMsg(String similarityFailedMsg) {
this.similarityFailedMsg = similarityFailedMsg;
}
public Integer getExamPassMinScore() {
return examPassMinScore;
}
public void setExamPassMinScore(Integer examPassMinScore) {
this.examPassMinScore = examPassMinScore;
}
public Integer getExamGivenPointType() {
return examGivenPointType;
}
public void setExamGivenPointType(Integer examGivenPointType) {
this.examGivenPointType = examGivenPointType;
}
public Integer getScoreRuleComplete() {
return scoreRuleComplete;
}
public void setScoreRuleComplete(Integer scoreRuleComplete) {
this.scoreRuleComplete = scoreRuleComplete;
}
public Integer getScoreRuleKeyword() {
return scoreRuleKeyword;
}
public void setScoreRuleKeyword(Integer scoreRuleKeyword) {
this.scoreRuleKeyword = scoreRuleKeyword;
}
public Integer getScoreRuleSmooth() {
return scoreRuleSmooth;
}
public void setScoreRuleSmooth(Integer scoreRuleSmooth) {
this.scoreRuleSmooth = scoreRuleSmooth;
}
public Integer getScoreRuleExpress() {
return scoreRuleExpress;
}
public void setScoreRuleExpress(Integer scoreRuleExpress) {
this.scoreRuleExpress = scoreRuleExpress;
}
public Integer getScoreRulePolite() {
return scoreRulePolite;
}
public void setScoreRulePolite(Integer scoreRulePolite) {
this.scoreRulePolite = scoreRulePolite;
}
public Boolean getDeleted() {
return deleted;
}
public void setDeleted(Boolean deleted) {
this.deleted = deleted;
}
public Long getOrgId() {
return orgId;
}
public void setOrgId(Long orgId) {
this.orgId = orgId;
}
public Long getSiteId() {
return siteId;
}
public void setSiteId(Long siteId) {
this.siteId = siteId;
}
public Long getCompanyId() {
return companyId;
}
public void setCompanyId(Long companyId) {
this.companyId = companyId;
}
public Long getCreatedUid() {
return createdUid;
}
public void setCreatedUid(Long createdUid) {
this.createdUid = createdUid;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public Long getUpdatedUid() {
return updatedUid;
}
public void setUpdatedUid(Long updatedUid) {
this.updatedUid = updatedUid;
}
public Date getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
@Override
public String toString() {
return "PracticeConfig{" +
", id=" + id +
", name=" + name +
", logoUrl=" + logoUrl +
", description=" + description +
", useType=" + useType +
", practiceStartAt=" + practiceStartAt +
", practiceEndAt=" + practiceEndAt +
", examStartAt=" + examStartAt +
", examEndAt=" + examEndAt +
", maxExamCount=" + maxExamCount +
", keyWord=" + keyWord +
", robotId=" + robotId +
", robotParams=" + robotParams +
", robotName=" + robotName +
", robotPicUrl=" + robotPicUrl +
", status=" + status +
", visibleType=" + visibleType +
", skipType=" + skipType +
", startNextRoundType=" + startNextRoundType +
", startNextRoundScore=" + startNextRoundScore +
", practiceFailedMaxCount=" + practiceFailedMaxCount +
", repeatPush=" + repeatPush +
", manyRoundChat=" + manyRoundChat +
", similarityRate=" + similarityRate +
", examFailedMaxCount=" + examFailedMaxCount +
", similarityFailedMsgType=" + similarityFailedMsgType +
", similarityFailedMsg=" + similarityFailedMsg +
", examPassMinScore=" + examPassMinScore +
", examGivenPointType=" + examGivenPointType +
", scoreRuleComplete=" + scoreRuleComplete +
", scoreRuleKeyword=" + scoreRuleKeyword +
", scoreRuleSmooth=" + scoreRuleSmooth +
", scoreRuleExpress=" + scoreRuleExpress +
", scoreRulePolite=" + scoreRulePolite +
", deleted=" + deleted +
", orgId=" + orgId +
", siteId=" + siteId +
", companyId=" + companyId +
", createdUid=" + createdUid +
", createdAt=" + createdAt +
", updatedUid=" + updatedUid +
", updatedAt=" + updatedAt +
"}";
}
}
package com.yizhi.practice.application.pojo.domain;
import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.annotations.TableName;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import javax.persistence.Entity;
import javax.persistence.Id;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
* 陪练积分发放记录
* </p>
*
* @author MybatisCodeGenerator123
* @since 2020-10-29
*/
@DynamicUpdate
@DynamicInsert
@Api(tags = "PracticePointGivenLog", description = "陪练积分发放记录")
@TableName("practice_point_given_log")
@Entity
public class PracticePointGivenLog implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private Long id;
@ApiModelProperty(value = "用户ID")
@TableField("account_id")
private Long accountId;
@ApiModelProperty(value = "陪练Id")
@TableField("practice_id")
private Long practiceId;
@ApiModelProperty(value = "陪练得分")
@TableField("practice_score")
private Integer practiceScore;
@ApiModelProperty(value = "陪练考核通过时间")
@TableField("practice_pass_time")
private Date practicePassTime;
@ApiModelProperty(value = "陪练积分规则id")
@TableField("point_rule_id")
private Long pointRuleId;
@ApiModelProperty(value = "赠送积分数量")
private Integer point;
@ApiModelProperty(value = "0:not del 1:del")
private Boolean deleted;
@TableField("org_id")
private Long orgId;
@TableField("site_id")
private Long siteId;
@TableField("company_id")
private Long companyId;
@ApiModelProperty(value = "创建时间")
@TableField("created_at")
private Date createdAt;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getAccountId() {
return accountId;
}
public void setAccountId(Long accountId) {
this.accountId = accountId;
}
public Long getPracticeId() {
return practiceId;
}
public void setPracticeId(Long practiceId) {
this.practiceId = practiceId;
}
public Integer getPracticeScore() {
return practiceScore;
}
public void setPracticeScore(Integer practiceScore) {
this.practiceScore = practiceScore;
}
public Date getPracticePassTime() {
return practicePassTime;
}
public void setPracticePassTime(Date practicePassTime) {
this.practicePassTime = practicePassTime;
}
public Long getPointRuleId() {
return pointRuleId;
}
public void setPointRuleId(Long pointRuleId) {
this.pointRuleId = pointRuleId;
}
public Integer getPoint() {
return point;
}
public void setPoint(Integer point) {
this.point = point;
}
public Boolean getDeleted() {
return deleted;
}
public void setDeleted(Boolean deleted) {
this.deleted = deleted;
}
public Long getOrgId() {
return orgId;
}
public void setOrgId(Long orgId) {
this.orgId = orgId;
}
public Long getSiteId() {
return siteId;
}
public void setSiteId(Long siteId) {
this.siteId = siteId;
}
public Long getCompanyId() {
return companyId;
}
public void setCompanyId(Long companyId) {
this.companyId = companyId;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
@Override
public String toString() {
return "PracticePointGivenLog{" +
", id=" + id +
", accountId=" + accountId +
", practiceId=" + practiceId +
", practiceScore=" + practiceScore +
", practicePassTime=" + practicePassTime +
", pointRuleId=" + pointRuleId +
", point=" + point +
", deleted=" + deleted +
", orgId=" + orgId +
", siteId=" + siteId +
", companyId=" + companyId +
", createdAt=" + createdAt +
"}";
}
}
package com.yizhi.practice.application.pojo.domain;
import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.annotations.TableName;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import javax.persistence.Entity;
import javax.persistence.Id;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
* 陪练积分发放规则
* </p>
*
* @author MybatisCodeGenerator123
* @since 2020-10-29
*/
@DynamicUpdate
@DynamicInsert
@Api(tags = "PracticePointRuleConfig", description = "陪练积分发放规则")
@TableName("practice_point_rule_config")
@Entity
public class PracticePointRuleConfig implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private Long id;
@ApiModelProperty(value = "练习Id")
@TableField("practice_id")
private Long practiceId;
@ApiModelProperty(value = "获得积分允许最小得分")
@TableField("min_score")
private Integer minScore;
@ApiModelProperty(value = "获得积分允许最大得分")
@TableField("max_score")
private Integer maxScore;
@ApiModelProperty(value = "发放积分数量")
private Integer point;
@ApiModelProperty(value = "0:not del 1:del")
private Boolean deleted;
@TableField("org_id")
private Long orgId;
@TableField("site_id")
private Long siteId;
@TableField("company_id")
private Long companyId;
@TableField("created_at")
private Date createdAt;
@TableField("updated_at")
private Date updatedAt;
@ApiModelProperty(value = "创建管理员ID")
@TableField("created_uid")
private Long createdUid;
@ApiModelProperty(value = "最后一次修改人员ID")
@TableField("updated_uid")
private Long updatedUid;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getPracticeId() {
return practiceId;
}
public void setPracticeId(Long practiceId) {
this.practiceId = practiceId;
}
public Integer getMinScore() {
return minScore;
}
public void setMinScore(Integer minScore) {
this.minScore = minScore;
}
public Integer getMaxScore() {
return maxScore;
}
public void setMaxScore(Integer maxScore) {
this.maxScore = maxScore;
}
public Integer getPoint() {
return point;
}
public void setPoint(Integer point) {
this.point = point;
}
public Boolean getDeleted() {
return deleted;
}
public void setDeleted(Boolean deleted) {
this.deleted = deleted;
}
public Long getOrgId() {
return orgId;
}
public void setOrgId(Long orgId) {
this.orgId = orgId;
}
public Long getSiteId() {
return siteId;
}
public void setSiteId(Long siteId) {
this.siteId = siteId;
}
public Long getCompanyId() {
return companyId;
}
public void setCompanyId(Long companyId) {
this.companyId = companyId;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public Date getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
public Long getCreatedUid() {
return createdUid;
}
public void setCreatedUid(Long createdUid) {
this.createdUid = createdUid;
}
public Long getUpdatedUid() {
return updatedUid;
}
public void setUpdatedUid(Long updatedUid) {
this.updatedUid = updatedUid;
}
@Override
public String toString() {
return "PracticePointRuleConfig{" +
", id=" + id +
", practiceId=" + practiceId +
", minScore=" + minScore +
", maxScore=" + maxScore +
", point=" + point +
", deleted=" + deleted +
", orgId=" + orgId +
", siteId=" + siteId +
", companyId=" + companyId +
", createdAt=" + createdAt +
", updatedAt=" + updatedAt +
", createdUid=" + createdUid +
", updatedUid=" + updatedUid +
"}";
}
}
package com.yizhi.practice.application.pojo.domain;
import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableName;
import com.baomidou.mybatisplus.enums.IdType;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import javax.persistence.Entity;
import javax.persistence.Id;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
*
* </p>
*
* @author MybatisCodeGenerator123
* @since 2020-10-29
*/
@DynamicUpdate
@DynamicInsert
@Api(tags = "PracticeVisible", description = "")
@TableName("practice_visible")
@Entity
public class PracticeVisible implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@TableId(value="id", type= IdType.AUTO)
private Long id;
@ApiModelProperty(value = "陪练ID")
@TableField("practice_id")
private Long practiceId;
@ApiModelProperty(value = "可见站点Id")
@TableField("visible_site_id")
private Long visibleSiteId;
@ApiModelProperty(value = "可见部门Id")
@TableField("visible_org_id")
private Long visibleOrgId;
@ApiModelProperty(value = "可见部门名")
@TableField("visible_org_name")
private String visibleOrgName;
@ApiModelProperty(value = "可见用户Id")
@TableField("visible_account_id")
private Long visibleAccountId;
@ApiModelProperty(value = "可见用户工号")
@TableField("visible_account_work_num")
private String visibleAccountWorkNum;
@ApiModelProperty(value = "用户名")
@TableField("visible_account_name")
private String visibleAccountName;
@ApiModelProperty(value = "用户全名")
@TableField("visible_account_full_name")
private String visibleAccountFullName;
@ApiModelProperty(value = "陪练可见范围 80:平台可见 50:部门可见 40:指定用户可见")
@TableField("visible_type")
private Integer visibleType;
@ApiModelProperty(value = "公司Id")
@TableField("company_id")
private Long companyId;
@ApiModelProperty(value = "0:not deleted, 1:deleted")
private Boolean deleted;
@TableField("created_at")
private Date createdAt;
@ApiModelProperty(value = "创建管理员ID")
@TableField("created_uid")
private Long createdUid;
@TableField("updated_at")
private Date updatedAt;
@ApiModelProperty(value = "更新管理员ID")
@TableField("updated_uid")
private Long updatedUid;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getPracticeId() {
return practiceId;
}
public void setPracticeId(Long practiceId) {
this.practiceId = practiceId;
}
public Long getVisibleSiteId() {
return visibleSiteId;
}
public void setVisibleSiteId(Long visibleSiteId) {
this.visibleSiteId = visibleSiteId;
}
public Long getVisibleOrgId() {
return visibleOrgId;
}
public void setVisibleOrgId(Long visibleOrgId) {
this.visibleOrgId = visibleOrgId;
}
public String getVisibleOrgName() {
return visibleOrgName;
}
public void setVisibleOrgName(String visibleOrgName) {
this.visibleOrgName = visibleOrgName;
}
public Long getVisibleAccountId() {
return visibleAccountId;
}
public void setVisibleAccountId(Long visibleAccountId) {
this.visibleAccountId = visibleAccountId;
}
public String getVisibleAccountWorkNum() {
return visibleAccountWorkNum;
}
public void setVisibleAccountWorkNum(String visibleAccountWorkNum) {
this.visibleAccountWorkNum = visibleAccountWorkNum;
}
public String getVisibleAccountName() {
return visibleAccountName;
}
public void setVisibleAccountName(String visibleAccountName) {
this.visibleAccountName = visibleAccountName;
}
public String getVisibleAccountFullName() {
return visibleAccountFullName;
}
public void setVisibleAccountFullName(String visibleAccountFullName) {
this.visibleAccountFullName = visibleAccountFullName;
}
public Integer getVisibleType() {
return visibleType;
}
public void setVisibleType(Integer visibleType) {
this.visibleType = visibleType;
}
public Long getCompanyId() {
return companyId;
}
public void setCompanyId(Long companyId) {
this.companyId = companyId;
}
public Boolean getDeleted() {
return deleted;
}
public void setDeleted(Boolean deleted) {
this.deleted = deleted;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public Long getCreatedUid() {
return createdUid;
}
public void setCreatedUid(Long createdUid) {
this.createdUid = createdUid;
}
public Date getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
public Long getUpdatedUid() {
return updatedUid;
}
public void setUpdatedUid(Long updatedUid) {
this.updatedUid = updatedUid;
}
@Override
public String toString() {
return "PracticeVisible{" +
", id=" + id +
", practiceId=" + practiceId +
", visibleSiteId=" + visibleSiteId +
", visibleOrgId=" + visibleOrgId +
", visibleOrgName=" + visibleOrgName +
", visibleAccountId=" + visibleAccountId +
", visibleAccountWorkNum=" + visibleAccountWorkNum +
", visibleAccountName=" + visibleAccountName +
", visibleAccountFullName=" + visibleAccountFullName +
", visibleType=" + visibleType +
", companyId=" + companyId +
", deleted=" + deleted +
", createdAt=" + createdAt +
", createdUid=" + createdUid +
", updatedAt=" + updatedAt +
", updatedUid=" + updatedUid +
"}";
}
}
package com.yizhi.practice.application.pojo.domain;
import com.querydsl.core.types.Path;
import com.querydsl.core.types.PathMetadata;
import com.querydsl.core.types.dsl.*;
import javax.annotation.Generated;
import static com.querydsl.core.types.PathMetadataFactory.forVariable;
/**
* QPracticeChatLog is a Querydsl query type for PracticeChatLog
*/
@Generated("com.querydsl.codegen.EntitySerializer")
public class QPracticeChatLog extends EntityPathBase<PracticeChatLog> {
private static final long serialVersionUID = -93214000L;
public static final QPracticeChatLog practiceChatLog = new QPracticeChatLog("practiceChatLog");
public final StringPath accountFullName = createString("accountFullName");
public final NumberPath<Long> accountId = createNumber("accountId", Long.class);
public final StringPath accountName = createString("accountName");
public final NumberPath<Integer> averageScore = createNumber("averageScore", Integer.class);
public final NumberPath<Long> companyId = createNumber("companyId", Long.class);
public final NumberPath<Integer> completeRate = createNumber("completeRate", Integer.class);
public final NumberPath<Integer> completeScore = createNumber("completeScore", Integer.class);
public final DateTimePath<java.util.Date> createdAt = createDateTime("createdAt", java.util.Date.class);
public final BooleanPath deleted = createBoolean("deleted");
public final DateTimePath<java.util.Date> endAt = createDateTime("endAt", java.util.Date.class);
public final NumberPath<Integer> expressRate = createNumber("expressRate", Integer.class);
public final NumberPath<Integer> expressScore = createNumber("expressScore", Integer.class);
public final NumberPath<Integer> givenPointType = createNumber("givenPointType", Integer.class);
public final NumberPath<Integer> givenPointCount = createNumber("givenPointCount", Integer.class);
public final NumberPath<Long> id = createNumber("id", Long.class);
public final NumberPath<Integer> keywordRate = createNumber("keywordRate", Integer.class);
public final NumberPath<Integer> keywordScore = createNumber("keywordScore", Integer.class);
public final NumberPath<Integer> level = createNumber("level", Integer.class);
public final NumberPath<Long> orgId = createNumber("orgId", Long.class);
public final StringPath orgName = createString("orgName");
public final NumberPath<Integer> passMinScore = createNumber("passMinScore", Integer.class);
public final NumberPath<Integer> passResult = createNumber("passResult", Integer.class);
public final NumberPath<Integer> politeRate = createNumber("politeRate", Integer.class);
public final NumberPath<Integer> politeScore = createNumber("politeScore", Integer.class);
public final NumberPath<Long> practiceId = createNumber("practiceId", Long.class);
public final NumberPath<Long> siteId = createNumber("siteId", Long.class);
public final NumberPath<Integer> smoothRate = createNumber("smoothRate", Integer.class);
public final NumberPath<Integer> smoothScore = createNumber("smoothScore", Integer.class);
public final DateTimePath<java.util.Date> startAt = createDateTime("startAt", java.util.Date.class);
public final NumberPath<Integer> status = createNumber("status", Integer.class);
public final DateTimePath<java.util.Date> updatedAt = createDateTime("updatedAt", java.util.Date.class);
public final NumberPath<Integer> useType = createNumber("useType", Integer.class);
public QPracticeChatLog(String variable) {
super(PracticeChatLog.class, forVariable(variable));
}
public QPracticeChatLog(Path<? extends PracticeChatLog> path) {
super(path.getType(), path.getMetadata());
}
public QPracticeChatLog(PathMetadata metadata) {
super(PracticeChatLog.class, metadata);
}
}
package com.yizhi.practice.application.pojo.domain;
import static com.querydsl.core.types.PathMetadataFactory.*;
import com.querydsl.core.types.dsl.*;
import com.querydsl.core.types.PathMetadata;
import javax.annotation.Generated;
import com.querydsl.core.types.Path;
/**
* QPracticeChatRoundLog is a Querydsl query type for PracticeChatRoundLog
*/
@Generated("com.querydsl.codegen.EntitySerializer")
public class QPracticeChatRoundLog extends EntityPathBase<PracticeChatRoundLog> {
private static final long serialVersionUID = -329238838L;
public static final QPracticeChatRoundLog practiceChatRoundLog = new QPracticeChatRoundLog("practiceChatRoundLog");
public final StringPath accountContent = createString("accountContent");
public final NumberPath<Long> accountContentVoiceDuration = createNumber("accountContentVoiceDuration", Long.class);
public final StringPath accountContentVoiceUrl = createString("accountContentVoiceUrl");
public final StringPath accountFullName = createString("accountFullName");
public final StringPath accountHitKeyword = createString("accountHitKeyword");
public final StringPath accountHitTabooWord = createString("accountHitTabooWord");
public final NumberPath<Long> accountId = createNumber("accountId", Long.class);
public final StringPath accountName = createString("accountName");
public final NumberPath<Integer> averageScore = createNumber("averageScore", Integer.class);
public final NumberPath<Long> companyId = createNumber("companyId", Long.class);
public final NumberPath<Integer> completeScore = createNumber("completeScore", Integer.class);
public final DateTimePath<java.util.Date> createdAt = createDateTime("createdAt", java.util.Date.class);
public final BooleanPath deleted = createBoolean("deleted");
public final NumberPath<Integer> expressScore = createNumber("expressScore", Integer.class);
public final NumberPath<Long> id = createNumber("id", Long.class);
public final NumberPath<Integer> keywordScore = createNumber("keywordScore", Integer.class);
public final NumberPath<Long> orgId = createNumber("orgId", Long.class);
public final StringPath orgName = createString("orgName");
public final NumberPath<Integer> passMinScore = createNumber("passMinScore", Integer.class);
public final NumberPath<Integer> passSimilarityRate = createNumber("passSimilarityRate", Integer.class);
public final NumberPath<Integer> politeScore = createNumber("politeScore", Integer.class);
public final NumberPath<Long> practiceChatId = createNumber("practiceChatId", Long.class);
public final NumberPath<Long> practiceId = createNumber("practiceId", Long.class);
public final StringPath robotContent = createString("robotContent");
public final NumberPath<Long> robotContentVoiceDuration = createNumber("robotContentVoiceDuration", Long.class);
public final StringPath robotContentVoiceUrl = createString("robotContentVoiceUrl");
public final NumberPath<Integer> roundLevel = createNumber("roundLevel", Integer.class);
public final NumberPath<Integer> roundSkipType = createNumber("roundSkipType", Integer.class);
public final NumberPath<Long> sceneChatId = createNumber("sceneChatId", Long.class);
public final NumberPath<Long> sceneId = createNumber("sceneId", Long.class);
public final NumberPath<Integer> similarityScore = createNumber("similarityScore", Integer.class);
public final NumberPath<Long> siteId = createNumber("siteId", Long.class);
public final NumberPath<Integer> smoothScore = createNumber("smoothScore", Integer.class);
public QPracticeChatRoundLog(String variable) {
super(PracticeChatRoundLog.class, forVariable(variable));
}
public QPracticeChatRoundLog(Path<? extends PracticeChatRoundLog> path) {
super(path.getType(), path.getMetadata());
}
public QPracticeChatRoundLog(PathMetadata metadata) {
super(PracticeChatRoundLog.class, metadata);
}
}
package com.yizhi.practice.application.pojo.domain;
import com.querydsl.core.types.Path;
import com.querydsl.core.types.PathMetadata;
import com.querydsl.core.types.dsl.*;
import javax.annotation.Generated;
import static com.querydsl.core.types.PathMetadataFactory.forVariable;
/**
* QPracticeConfig is a Querydsl query type for PracticeConfig
*/
@Generated("com.querydsl.codegen.EntitySerializer")
public class QPracticeConfig extends EntityPathBase<PracticeConfig> {
private static final long serialVersionUID = 1666400446L;
public static final QPracticeConfig practiceConfig = new QPracticeConfig("practiceConfig");
public final NumberPath<Long> companyId = createNumber("companyId", Long.class);
public final DateTimePath<java.util.Date> createdAt = createDateTime("createdAt", java.util.Date.class);
public final NumberPath<Long> createdUid = createNumber("createdUid", Long.class);
public final BooleanPath deleted = createBoolean("deleted");
public final StringPath description = createString("description");
public final DateTimePath<java.util.Date> examEndAt = createDateTime("examEndAt", java.util.Date.class);
public final NumberPath<Integer> examFailedMaxCount = createNumber("examFailedMaxCount", Integer.class);
public final NumberPath<Integer> examGivenPointType = createNumber("examGivenPointType", Integer.class);
public final NumberPath<Integer> examPassMinScore = createNumber("examPassMinScore", Integer.class);
public final DateTimePath<java.util.Date> examStartAt = createDateTime("examStartAt", java.util.Date.class);
public final NumberPath<Long> id = createNumber("id", Long.class);
public final StringPath keyWord = createString("keyWord");
public final StringPath logoUrl = createString("logoUrl");
public final NumberPath<Integer> manyRoundChat = createNumber("manyRoundChat", Integer.class);
public final NumberPath<Integer> maxExamCount = createNumber("maxExamCount", Integer.class);
public final StringPath name = createString("name");
public final NumberPath<Long> orgId = createNumber("orgId", Long.class);
public final DateTimePath<java.util.Date> practiceEndAt = createDateTime("practiceEndAt", java.util.Date.class);
public final NumberPath<Integer> practiceFailedMaxCount = createNumber("practiceFailedMaxCount", Integer.class);
public final DateTimePath<java.util.Date> practiceStartAt = createDateTime("practiceStartAt", java.util.Date.class);
public final NumberPath<Integer> repeatPush = createNumber("repeatPush", Integer.class);
public final NumberPath<Long> robotId = createNumber("robotId", Long.class);
public final StringPath robotName = createString("robotName");
public final StringPath robotParams = createString("robotParams");
public final StringPath robotPicUrl = createString("robotPicUrl");
public final NumberPath<Integer> scoreRuleComplete = createNumber("scoreRuleComplete", Integer.class);
public final NumberPath<Integer> scoreRuleExpress = createNumber("scoreRuleExpress", Integer.class);
public final NumberPath<Integer> scoreRuleKeyword = createNumber("scoreRuleKeyword", Integer.class);
public final NumberPath<Integer> scoreRulePolite = createNumber("scoreRulePolite", Integer.class);
public final NumberPath<Integer> scoreRuleSmooth = createNumber("scoreRuleSmooth", Integer.class);
public final StringPath similarityFailedMsg = createString("similarityFailedMsg");
public final NumberPath<Integer> similarityFailedMsgType = createNumber("similarityFailedMsgType", Integer.class);
public final NumberPath<Integer> similarityRate = createNumber("similarityRate", Integer.class);
public final NumberPath<Long> siteId = createNumber("siteId", Long.class);
public final NumberPath<Integer> skipType = createNumber("skipType", Integer.class);
public final NumberPath<Integer> startNextRoundScore = createNumber("startNextRoundScore", Integer.class);
public final NumberPath<Integer> startNextRoundType = createNumber("startNextRoundType", Integer.class);
public final NumberPath<Integer> status = createNumber("status", Integer.class);
public final DateTimePath<java.util.Date> updatedAt = createDateTime("updatedAt", java.util.Date.class);
public final NumberPath<Long> updatedUid = createNumber("updatedUid", Long.class);
public final NumberPath<Integer> useType = createNumber("useType", Integer.class);
public final NumberPath<Integer> visibleType = createNumber("visibleType", Integer.class);
public QPracticeConfig(String variable) {
super(PracticeConfig.class, forVariable(variable));
}
public QPracticeConfig(Path<? extends PracticeConfig> path) {
super(path.getType(), path.getMetadata());
}
public QPracticeConfig(PathMetadata metadata) {
super(PracticeConfig.class, metadata);
}
}
package com.yizhi.practice.application.pojo.domain;
import com.querydsl.core.types.Path;
import com.querydsl.core.types.PathMetadata;
import com.querydsl.core.types.dsl.BooleanPath;
import com.querydsl.core.types.dsl.DateTimePath;
import com.querydsl.core.types.dsl.EntityPathBase;
import com.querydsl.core.types.dsl.NumberPath;
import javax.annotation.Generated;
import static com.querydsl.core.types.PathMetadataFactory.forVariable;
/**
* QPracticePointGivenLog is a Querydsl query type for PracticePointGivenLog
*/
@Generated("com.querydsl.codegen.EntitySerializer")
public class QPracticePointGivenLog extends EntityPathBase<PracticePointGivenLog> {
private static final long serialVersionUID = -394842309L;
public static final QPracticePointGivenLog practicePointGivenLog = new QPracticePointGivenLog("practicePointGivenLog");
public final NumberPath<Long> accountId = createNumber("accountId", Long.class);
public final NumberPath<Long> companyId = createNumber("companyId", Long.class);
public final DateTimePath<java.util.Date> createdAt = createDateTime("createdAt", java.util.Date.class);
public final BooleanPath deleted = createBoolean("deleted");
public final NumberPath<Long> id = createNumber("id", Long.class);
public final NumberPath<Long> orgId = createNumber("orgId", Long.class);
public final NumberPath<Integer> point = createNumber("point", Integer.class);
public final NumberPath<Long> pointRuleId = createNumber("pointRuleId", Long.class);
public final NumberPath<Long> practiceId = createNumber("practiceId", Long.class);
public final DateTimePath<java.util.Date> practicePassTime = createDateTime("practicePassTime", java.util.Date.class);
public final NumberPath<Integer> practiceScore = createNumber("practiceScore", Integer.class);
public final NumberPath<Long> siteId = createNumber("siteId", Long.class);
public QPracticePointGivenLog(String variable) {
super(PracticePointGivenLog.class, forVariable(variable));
}
public QPracticePointGivenLog(Path<? extends PracticePointGivenLog> path) {
super(path.getType(), path.getMetadata());
}
public QPracticePointGivenLog(PathMetadata metadata) {
super(PracticePointGivenLog.class, metadata);
}
}
package com.yizhi.practice.application.pojo.domain;
import com.querydsl.core.types.Path;
import com.querydsl.core.types.PathMetadata;
import com.querydsl.core.types.dsl.BooleanPath;
import com.querydsl.core.types.dsl.DateTimePath;
import com.querydsl.core.types.dsl.EntityPathBase;
import com.querydsl.core.types.dsl.NumberPath;
import javax.annotation.Generated;
import static com.querydsl.core.types.PathMetadataFactory.forVariable;
/**
* QPracticePointRuleConfig is a Querydsl query type for PracticePointRuleConfig
*/
@Generated("com.querydsl.codegen.EntitySerializer")
public class QPracticePointRuleConfig extends EntityPathBase<PracticePointRuleConfig> {
private static final long serialVersionUID = -1014627054L;
public static final QPracticePointRuleConfig practicePointRuleConfig = new QPracticePointRuleConfig("practicePointRuleConfig");
public final NumberPath<Long> companyId = createNumber("companyId", Long.class);
public final DateTimePath<java.util.Date> createdAt = createDateTime("createdAt", java.util.Date.class);
public final NumberPath<Long> createdUid = createNumber("createdUid", Long.class);
public final BooleanPath deleted = createBoolean("deleted");
public final NumberPath<Long> id = createNumber("id", Long.class);
public final NumberPath<Integer> maxScore = createNumber("maxScore", Integer.class);
public final NumberPath<Integer> minScore = createNumber("minScore", Integer.class);
public final NumberPath<Long> orgId = createNumber("orgId", Long.class);
public final NumberPath<Integer> point = createNumber("point", Integer.class);
public final NumberPath<Long> practiceId = createNumber("practiceId", Long.class);
public final NumberPath<Long> siteId = createNumber("siteId", Long.class);
public final DateTimePath<java.util.Date> updatedAt = createDateTime("updatedAt", java.util.Date.class);
public final NumberPath<Long> updatedUid = createNumber("updatedUid", Long.class);
public QPracticePointRuleConfig(String variable) {
super(PracticePointRuleConfig.class, forVariable(variable));
}
public QPracticePointRuleConfig(Path<? extends PracticePointRuleConfig> path) {
super(path.getType(), path.getMetadata());
}
public QPracticePointRuleConfig(PathMetadata metadata) {
super(PracticePointRuleConfig.class, metadata);
}
}
package com.yizhi.practice.application.pojo.domain;
import com.querydsl.core.types.Path;
import com.querydsl.core.types.PathMetadata;
import com.querydsl.core.types.dsl.*;
import javax.annotation.Generated;
import static com.querydsl.core.types.PathMetadataFactory.forVariable;
/**
* QPracticeVisible is a Querydsl query type for PracticeVisible
*/
@Generated("com.querydsl.codegen.EntitySerializer")
public class QPracticeVisible extends EntityPathBase<PracticeVisible> {
private static final long serialVersionUID = -365567370L;
public static final QPracticeVisible practiceVisible = new QPracticeVisible("practiceVisible");
public final NumberPath<Long> companyId = createNumber("companyId", Long.class);
public final DateTimePath<java.util.Date> createdAt = createDateTime("createdAt", java.util.Date.class);
public final NumberPath<Long> createdUid = createNumber("createdUid", Long.class);
public final BooleanPath deleted = createBoolean("deleted");
public final NumberPath<Long> id = createNumber("id", Long.class);
public final NumberPath<Long> practiceId = createNumber("practiceId", Long.class);
public final DateTimePath<java.util.Date> updatedAt = createDateTime("updatedAt", java.util.Date.class);
public final NumberPath<Long> updatedUid = createNumber("updatedUid", Long.class);
public final StringPath visibleAccountFullName = createString("visibleAccountFullName");
public final NumberPath<Long> visibleAccountId = createNumber("visibleAccountId", Long.class);
public final StringPath visibleAccountName = createString("visibleAccountName");
public final StringPath visibleAccountWorkNum = createString("visibleAccountWorkNum");
public final NumberPath<Long> visibleOrgId = createNumber("visibleOrgId", Long.class);
public final StringPath visibleOrgName = createString("visibleOrgName");
public final NumberPath<Long> visibleSiteId = createNumber("visibleSiteId", Long.class);
public final NumberPath<Integer> visibleType = createNumber("visibleType", Integer.class);
public QPracticeVisible(String variable) {
super(PracticeVisible.class, forVariable(variable));
}
public QPracticeVisible(Path<? extends PracticeVisible> path) {
super(path.getType(), path.getMetadata());
}
public QPracticeVisible(PathMetadata metadata) {
super(PracticeVisible.class, metadata);
}
}
package com.yizhi.practice.application.pojo.domain;
import com.querydsl.core.types.Path;
import com.querydsl.core.types.PathMetadata;
import com.querydsl.core.types.dsl.DateTimePath;
import com.querydsl.core.types.dsl.EntityPathBase;
import com.querydsl.core.types.dsl.NumberPath;
import com.querydsl.core.types.dsl.StringPath;
import javax.annotation.Generated;
import static com.querydsl.core.types.PathMetadataFactory.forVariable;
/**
* QRobotConfig is a Querydsl query type for RobotConfig
*/
@Generated("com.querydsl.codegen.EntitySerializer")
public class QRobotConfig extends EntityPathBase<RobotConfig> {
private static final long serialVersionUID = -1163117173L;
public static final QRobotConfig robotConfig = new QRobotConfig("robotConfig");
public final StringPath contentVoiceUrl = createString("contentVoiceUrl");
public final DateTimePath<java.util.Date> createdAt = createDateTime("createdAt", java.util.Date.class);
public final StringPath description = createString("description");
public final NumberPath<Long> id = createNumber("id", Long.class);
public final StringPath name = createString("name");
public final StringPath params = createString("params");
public final DateTimePath<java.util.Date> updatedAt = createDateTime("updatedAt", java.util.Date.class);
public QRobotConfig(String variable) {
super(RobotConfig.class, forVariable(variable));
}
public QRobotConfig(Path<? extends RobotConfig> path) {
super(path.getType(), path.getMetadata());
}
public QRobotConfig(PathMetadata metadata) {
super(RobotConfig.class, metadata);
}
}
package com.yizhi.practice.application.pojo.domain;
import static com.querydsl.core.types.PathMetadataFactory.*;
import com.querydsl.core.types.dsl.*;
import com.querydsl.core.types.PathMetadata;
import javax.annotation.Generated;
import com.querydsl.core.types.Path;
/**
* QSceneChatConfig is a Querydsl query type for SceneChatConfig
*/
@Generated("com.querydsl.codegen.EntitySerializer")
public class QSceneChatConfig extends EntityPathBase<SceneChatConfig> {
private static final long serialVersionUID = 99121701L;
public static final QSceneChatConfig sceneChatConfig = new QSceneChatConfig("sceneChatConfig");
public final StringPath accountContent = createString("accountContent");
public final StringPath accountContentFileName = createString("accountContentFileName");
public final StringPath accountContentKeyword = createString("accountContentKeyword");
public final StringPath accountContentTabooWord = createString("accountContentTabooWord");
public final NumberPath<Long> accountContentVoiceDuration = createNumber("accountContentVoiceDuration", Long.class);
public final StringPath accountContentVoiceUrl = createString("accountContentVoiceUrl");
public final NumberPath<Long> companyId = createNumber("companyId", Long.class);
public final DateTimePath<java.util.Date> createdAt = createDateTime("createdAt", java.util.Date.class);
public final NumberPath<Long> createdUid = createNumber("createdUid", Long.class);
public final BooleanPath deleted = createBoolean("deleted");
public final NumberPath<Long> id = createNumber("id", Long.class);
public final NumberPath<Integer> level = createNumber("level", Integer.class);
public final NumberPath<Long> orgId = createNumber("orgId", Long.class);
public final NumberPath<Long> pid = createNumber("pid", Long.class);
public final NumberPath<Long> practiceId = createNumber("practiceId", Long.class);
public final StringPath robotContent = createString("robotContent");
public final NumberPath<Long> robotContentVoiceDuration = createNumber("robotContentVoiceDuration", Long.class);
public final StringPath robotContentVoiceUrl = createString("robotContentVoiceUrl");
public final NumberPath<Long> sceneId = createNumber("sceneId", Long.class);
public final StringPath sceneName = createString("sceneName");
public final NumberPath<Integer> sceneNodeType = createNumber("sceneNodeType", Integer.class);
public final NumberPath<Long> siteId = createNumber("siteId", Long.class);
public final DateTimePath<java.util.Date> updatedAt = createDateTime("updatedAt", java.util.Date.class);
public final NumberPath<Long> updatedUid = createNumber("updatedUid", Long.class);
public final StringPath xAxis = createString("xAxis");
public final StringPath yAxis = createString("yAxis");
public QSceneChatConfig(String variable) {
super(SceneChatConfig.class, forVariable(variable));
}
public QSceneChatConfig(Path<? extends SceneChatConfig> path) {
super(path.getType(), path.getMetadata());
}
public QSceneChatConfig(PathMetadata metadata) {
super(SceneChatConfig.class, metadata);
}
}
package com.yizhi.practice.application.pojo.domain;
import com.querydsl.core.types.Path;
import com.querydsl.core.types.PathMetadata;
import com.querydsl.core.types.dsl.*;
import javax.annotation.Generated;
import static com.querydsl.core.types.PathMetadataFactory.forVariable;
/**
* QSceneConfig is a Querydsl query type for SceneConfig
*/
@Generated("com.querydsl.codegen.EntitySerializer")
public class QSceneConfig extends EntityPathBase<SceneConfig> {
private static final long serialVersionUID = 395201069L;
public static final QSceneConfig sceneConfig = new QSceneConfig("sceneConfig");
public final NumberPath<Long> companyId = createNumber("companyId", Long.class);
public final DateTimePath<java.util.Date> createdAt = createDateTime("createdAt", java.util.Date.class);
public final NumberPath<Long> createdUid = createNumber("createdUid", Long.class);
public final BooleanPath deleted = createBoolean("deleted");
public final StringPath description = createString("description");
public final NumberPath<Long> id = createNumber("id", Long.class);
public final StringPath name = createString("name");
public final NumberPath<Long> orgId = createNumber("orgId", Long.class);
public final NumberPath<Long> practiceId = createNumber("practiceId", Long.class);
public final NumberPath<Long> siteId = createNumber("siteId", Long.class);
public final NumberPath<Integer> sort = createNumber("sort", Integer.class);
public final DateTimePath<java.util.Date> updatedAt = createDateTime("updatedAt", java.util.Date.class);
public final NumberPath<Long> updatedUid = createNumber("updatedUid", Long.class);
public QSceneConfig(String variable) {
super(SceneConfig.class, forVariable(variable));
}
public QSceneConfig(Path<? extends SceneConfig> path) {
super(path.getType(), path.getMetadata());
}
public QSceneConfig(PathMetadata metadata) {
super(SceneConfig.class, metadata);
}
}
package com.yizhi.practice.application.pojo.domain;
import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.annotations.TableName;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import javax.persistence.Entity;
import javax.persistence.Id;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
* 机器人配置
* </p>
*
* @author MybatisCodeGenerator123
* @since 2020-10-29
*/
@DynamicUpdate
@DynamicInsert
@Api(tags = "RobotConfig", description = "机器人配置")
@TableName("robot_config")
@Entity
public class RobotConfig implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private Long id;
@ApiModelProperty(value = "机器人名")
private String name;
@ApiModelProperty(value = "机器人描述")
private String description;
@ApiModelProperty(value = "机器人参数,根据参数来确定音频效果")
private String params;
@ApiModelProperty(value = "机器人语音demoURL")
@TableField("content_voice_url")
private String contentVoiceUrl;
@TableField("created_at")
private Date createdAt;
@TableField("updated_at")
private Date updatedAt;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getParams() {
return params;
}
public void setParams(String params) {
this.params = params;
}
public String getContentVoiceUrl() {
return contentVoiceUrl;
}
public void setContentVoiceUrl(String contentVoiceUrl) {
this.contentVoiceUrl = contentVoiceUrl;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public Date getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
@Override
public String toString() {
return "RobotConfig{" +
", id=" + id +
", name=" + name +
", description=" + description +
", params=" + params +
", contentVoiceUrl=" + contentVoiceUrl +
", createdAt=" + createdAt +
", updatedAt=" + updatedAt +
"}";
}
}
package com.yizhi.practice.application.pojo.domain;
import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.annotations.TableName;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import javax.persistence.Entity;
import javax.persistence.Id;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
* 场景对话配置
* </p>
*
* @author MybatisCodeGenerator123
* @since 2020-11-09
*/
@DynamicUpdate
@DynamicInsert
@Api(tags = "SceneChatConfig", description = "场景对话配置")
@TableName("scene_chat_config")
@Entity
public class SceneChatConfig implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private Long id;
@ApiModelProperty(value = "陪练ID")
@TableField("practice_id")
private Long practiceId;
@ApiModelProperty(value = "场景ID")
@TableField("scene_id")
private Long sceneId;
@ApiModelProperty(value = "节点标识 10:机器人,20:学员 节点,80:开始节点")
@TableField("scene_node_type")
private Integer sceneNodeType;
@ApiModelProperty(value = "场景名")
@TableField("scene_name")
private String sceneName;
@ApiModelProperty(value = "层级 开始为 0")
private Integer level;
@ApiModelProperty(value = "父节点ID")
private Long pid;
@ApiModelProperty(value = "该轮 机器人话术")
@TableField("robot_content")
private String robotContent;
@ApiModelProperty(value = "机器人话术音频URL")
@TableField("robot_content_voice_url")
private String robotContentVoiceUrl;
@ApiModelProperty(value = "机器人话术时长")
@TableField("robot_content_voice_duration")
private Long robotContentVoiceDuration;
@ApiModelProperty(value = "该轮学员话术")
@TableField("account_content")
private String accountContent;
@ApiModelProperty(value = "学员上传真人话术文件名")
@TableField("account_content_file_name")
private String accountContentFileName;
@ApiModelProperty(value = "学员标准话术音频URL ,没有上传则使用语音合成")
@TableField("account_content_voice_url")
private String accountContentVoiceUrl;
@ApiModelProperty(value = "学员话术时长")
@TableField("account_content_voice_duration")
private Long accountContentVoiceDuration;
@ApiModelProperty(value = "学员话术关键字 使用json存储,key为关键字,value为拓展词")
@TableField("account_content_keyword")
private String accountContentKeyword;
@ApiModelProperty(value = "禁忌词,")
@TableField("account_content_taboo_word")
private String accountContentTabooWord;
@ApiModelProperty(value = "节点坐标;x轴坐标")
@TableField("x_axis")
private String xAxis;
@ApiModelProperty(value = "节点坐标;y轴坐标")
@TableField("y_axis")
private String yAxis;
@ApiModelProperty(value = "0:not del 1:del")
private Boolean deleted;
@TableField("org_id")
private Long orgId;
@TableField("site_id")
private Long siteId;
@TableField("company_id")
private Long companyId;
@ApiModelProperty(value = "创建时间")
@TableField("created_at")
private Date createdAt;
@ApiModelProperty(value = "创建管理员Id")
@TableField("created_uid")
private Long createdUid;
@ApiModelProperty(value = "最后一次修改管理员ID")
@TableField("updated_uid")
private Long updatedUid;
@ApiModelProperty(value = "更新时间")
@TableField("updated_at")
private Date updatedAt;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getPracticeId() {
return practiceId;
}
public void setPracticeId(Long practiceId) {
this.practiceId = practiceId;
}
public Long getSceneId() {
return sceneId;
}
public void setSceneId(Long sceneId) {
this.sceneId = sceneId;
}
public Integer getSceneNodeType() {
return sceneNodeType;
}
public void setSceneNodeType(Integer sceneNodeType) {
this.sceneNodeType = sceneNodeType;
}
public String getSceneName() {
return sceneName;
}
public void setSceneName(String sceneName) {
this.sceneName = sceneName;
}
public Integer getLevel() {
return level;
}
public void setLevel(Integer level) {
this.level = level;
}
public Long getPid() {
return pid;
}
public void setPid(Long pid) {
this.pid = pid;
}
public String getRobotContent() {
return robotContent;
}
public void setRobotContent(String robotContent) {
this.robotContent = robotContent;
}
public String getRobotContentVoiceUrl() {
return robotContentVoiceUrl;
}
public void setRobotContentVoiceUrl(String robotContentVoiceUrl) {
this.robotContentVoiceUrl = robotContentVoiceUrl;
}
public Long getRobotContentVoiceDuration() {
return robotContentVoiceDuration;
}
public void setRobotContentVoiceDuration(Long robotContentVoiceDuration) {
this.robotContentVoiceDuration = robotContentVoiceDuration;
}
public String getAccountContent() {
return accountContent;
}
public void setAccountContent(String accountContent) {
this.accountContent = accountContent;
}
public String getAccountContentFileName() {
return accountContentFileName;
}
public void setAccountContentFileName(String accountContentFileName) {
this.accountContentFileName = accountContentFileName;
}
public String getAccountContentVoiceUrl() {
return accountContentVoiceUrl;
}
public void setAccountContentVoiceUrl(String accountContentVoiceUrl) {
this.accountContentVoiceUrl = accountContentVoiceUrl;
}
public Long getAccountContentVoiceDuration() {
return accountContentVoiceDuration;
}
public void setAccountContentVoiceDuration(Long accountContentVoiceDuration) {
this.accountContentVoiceDuration = accountContentVoiceDuration;
}
public String getAccountContentKeyword() {
return accountContentKeyword;
}
public void setAccountContentKeyword(String accountContentKeyword) {
this.accountContentKeyword = accountContentKeyword;
}
public String getAccountContentTabooWord() {
return accountContentTabooWord;
}
public void setAccountContentTabooWord(String accountContentTabooWord) {
this.accountContentTabooWord = accountContentTabooWord;
}
public String getxAxis() {
return xAxis;
}
public void setxAxis(String xAxis) {
this.xAxis = xAxis;
}
public String getyAxis() {
return yAxis;
}
public void setyAxis(String yAxis) {
this.yAxis = yAxis;
}
public Boolean getDeleted() {
return deleted;
}
public void setDeleted(Boolean deleted) {
this.deleted = deleted;
}
public Long getOrgId() {
return orgId;
}
public void setOrgId(Long orgId) {
this.orgId = orgId;
}
public Long getSiteId() {
return siteId;
}
public void setSiteId(Long siteId) {
this.siteId = siteId;
}
public Long getCompanyId() {
return companyId;
}
public void setCompanyId(Long companyId) {
this.companyId = companyId;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public Long getCreatedUid() {
return createdUid;
}
public void setCreatedUid(Long createdUid) {
this.createdUid = createdUid;
}
public Long getUpdatedUid() {
return updatedUid;
}
public void setUpdatedUid(Long updatedUid) {
this.updatedUid = updatedUid;
}
public Date getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
@Override
public String toString() {
return "SceneChatConfig{" +
", id=" + id +
", practiceId=" + practiceId +
", sceneId=" + sceneId +
", sceneNodeType=" + sceneNodeType +
", sceneName=" + sceneName +
", level=" + level +
", pid=" + pid +
", robotContent=" + robotContent +
", robotContentVoiceUrl=" + robotContentVoiceUrl +
", robotContentVoiceDuration=" + robotContentVoiceDuration +
", accountContent=" + accountContent +
", accountContentFileName=" + accountContentFileName +
", accountContentVoiceUrl=" + accountContentVoiceUrl +
", accountContentVoiceDuration=" + accountContentVoiceDuration +
", accountContentKeyword=" + accountContentKeyword +
", accountContentTabooWord=" + accountContentTabooWord +
", xAxis=" + xAxis +
", yAxis=" + yAxis +
", deleted=" + deleted +
", orgId=" + orgId +
", siteId=" + siteId +
", companyId=" + companyId +
", createdAt=" + createdAt +
", createdUid=" + createdUid +
", updatedUid=" + updatedUid +
", updatedAt=" + updatedAt +
"}";
}
}
package com.yizhi.practice.application.pojo.domain;
import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.annotations.TableName;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import javax.persistence.Entity;
import javax.persistence.Id;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
* 场景配置
* </p>
*
* @author MybatisCodeGenerator123
* @since 2020-10-29
*/
@DynamicUpdate
@DynamicInsert
@Api(tags = "SceneConfig", description = "场景配置")
@TableName("scene_config")
@Entity
public class SceneConfig implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private Long id;
@ApiModelProperty(value = "practice_config表ID")
@TableField("practice_id")
private Long practiceId;
@ApiModelProperty(value = "场景名")
private String name;
@ApiModelProperty(value = "场景描述")
private String description;
@ApiModelProperty(value = "排序")
private Integer sort;
@ApiModelProperty(value = "0 not deleted ,1 deleted")
private Boolean deleted;
@TableField("org_id")
private Long orgId;
@TableField("site_id")
private Long siteId;
@TableField("company_id")
private Long companyId;
@TableField("created_at")
private Date createdAt;
@ApiModelProperty(value = "创建人ID")
@TableField("created_uid")
private Long createdUid;
@TableField("updated_at")
private Date updatedAt;
@ApiModelProperty(value = "最后一次修改人ID")
@TableField("updated_uid")
private Long updatedUid;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getPracticeId() {
return practiceId;
}
public void setPracticeId(Long practiceId) {
this.practiceId = practiceId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Integer getSort() {
return sort;
}
public void setSort(Integer sort) {
this.sort = sort;
}
public Boolean getDeleted() {
return deleted;
}
public void setDeleted(Boolean deleted) {
this.deleted = deleted;
}
public Long getOrgId() {
return orgId;
}
public void setOrgId(Long orgId) {
this.orgId = orgId;
}
public Long getSiteId() {
return siteId;
}
public void setSiteId(Long siteId) {
this.siteId = siteId;
}
public Long getCompanyId() {
return companyId;
}
public void setCompanyId(Long companyId) {
this.companyId = companyId;
}
public Date getCreatedAt() {
return createdAt;
}
public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}
public Long getCreatedUid() {
return createdUid;
}
public void setCreatedUid(Long createdUid) {
this.createdUid = createdUid;
}
public Date getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}
public Long getUpdatedUid() {
return updatedUid;
}
public void setUpdatedUid(Long updatedUid) {
this.updatedUid = updatedUid;
}
@Override
public String toString() {
return "SceneConfig{" +
", id=" + id +
", practiceId=" + practiceId +
", name=" + name +
", description=" + description +
", sort=" + sort +
", deleted=" + deleted +
", orgId=" + orgId +
", siteId=" + siteId +
", companyId=" + companyId +
", createdAt=" + createdAt +
", createdUid=" + createdUid +
", updatedAt=" + updatedAt +
", updatedUid=" + updatedUid +
"}";
}
}
package com.yizhi.practice.application.pojo.dto
/**
* @Date 2020/11/9 6:57 下午
* @Author lvjianhui
**/
class PracticeAllScoreDto {
// 关键词得分
var keyWordScore: Pair<Int, List<String>> = Pair(0, arrayListOf())
// 完整性得分
var complateScore = 0
// 流畅性得分
var fluencyScore = 0
// 表达能力得分
var expressScore = 0
// 礼貌用语得分
var politeScore = 0
// 总和得分
var average = 0
var hitTabooWord = arrayListOf<String>()
}
\ No newline at end of file
package com.yizhi.practice.application.pojo.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
@Data
public class PracticeBaseInfoDto {
private Long id;
@ApiModelProperty(value = "陪练名")
private String name;
@ApiModelProperty(value = "陪练logoURL")
private String logoUrl;
@ApiModelProperty(value = "陪练描述")
private String description;
@ApiModelProperty(value = "陪练模式",allowableValues = "80:训练+考核 ,10:训练 20:考核")
private Integer useType;
@ApiModelProperty(value = "训练开始时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
private Date practiceStartAt;
@ApiModelProperty(value = "训练结束时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
private Date practiceEndAt;
@ApiModelProperty(value = "考核开始时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
private Date examStartAt;
@ApiModelProperty(value = "考核结束时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
private Date examEndAt;
@ApiModelProperty(value = "允许最大考试次数 0:无限次;其他有限次;默认0")
private Integer maxExamCount;
@ApiModelProperty(value = "自定义关键词,逗号分隔")
private String keyWord;
@ApiModelProperty(value = "机器人id")
private Long robotId;
@ApiModelProperty(value = "机器人参数")
private String robotParams;
@ApiModelProperty(value = "机器人称呼")
private String robotAliasName;
@ApiModelProperty(value = "机器人头像URL null时走默认头像")
private String robotPicUrl;
}
package com.yizhi.practice.application.pojo.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
@ApiModel(value = "PracticeChartRoundLogDto", description = "陪练记录-详情页面-本题分析")
public class PracticeChartRoundLogDto {
@ApiModelProperty(value = "本题得分")
private Integer totalScore;
@ApiModelProperty(value = "关键词得分")
private Integer keywordScore;
@ApiModelProperty(value = "完整性得分")
private Integer completeScore;
@ApiModelProperty(value = "流畅度得分")
private Integer smoothScore;
@ApiModelProperty(value = "表达能力得分")
private Integer expressScore;
@ApiModelProperty(value = "礼貌性得分")
private Integer politeScore;
@ApiModelProperty(value = "学员话术")
private String accountContent;
@ApiModelProperty(value = "学员话术URL")
private String accountContentVoiceUrl;
@ApiModelProperty(value = "学员话术时长")
private Long accountDuration;
@ApiModelProperty(value = "学员话术配置的关键字 使用json存储,key为关键字,value为拓展词")
private String keyWord;
@ApiModelProperty(value = "机器人话术")
private String robotContent;
@ApiModelProperty(value = "机器人话术URL")
private String robotContentUrl;
@ApiModelProperty(value = "机器人话术时长")
private Long robotDuration;
@ApiModelProperty(value = "命中的关键词 逗号分隔")
private String accountHitKeyword;
@ApiModelProperty(value = "命中的禁忌词 分号分隔")
private String forbidHit;
}
package com.yizhi.practice.application.pojo.dto;
import java.math.BigDecimal;
/**
* @Date 2020/11/24 8:26 下午
* @Author lvjianhui
**/
public class PracticeLogScoreDto {
private BigDecimal keyWordScore;
private BigDecimal complateScore;
private BigDecimal fluencyScore;
private BigDecimal expressScore;
private BigDecimal politeScore;
private BigDecimal averageScore;
public BigDecimal getAverageScore() {
return averageScore;
}
public void setAverageScore(BigDecimal averageScore) {
this.averageScore = averageScore;
}
public BigDecimal getKeyWordScore() {
return keyWordScore;
}
public void setKeyWordScore(BigDecimal keyWordScore) {
this.keyWordScore = keyWordScore;
}
public BigDecimal getComplateScore() {
return complateScore;
}
public void setComplateScore(BigDecimal complateScore) {
this.complateScore = complateScore;
}
public BigDecimal getFluencyScore() {
return fluencyScore;
}
public void setFluencyScore(BigDecimal fluencyScore) {
this.fluencyScore = fluencyScore;
}
public BigDecimal getExpressScore() {
return expressScore;
}
public void setExpressScore(BigDecimal expressScore) {
this.expressScore = expressScore;
}
public BigDecimal getPoliteScore() {
return politeScore;
}
public void setPoliteScore(BigDecimal politeScore) {
this.politeScore = politeScore;
}
}
package com.yizhi.practice.application.pojo.dto;
import com.yizhi.practice.application.pojo.vo.PracticePointVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@Data
@Api(tags = "陪练基本信息和策略信息")
public class PracticeStrategyInfoDto {
private Long id;
@ApiModelProperty(value = "练习可见范围 ",allowableValues = "80:平台可见 40:指定用户可见")
private Integer visibleType;
@ApiModelProperty(value = "是否跳过对话 80允许,10:不允许")
private Integer skipType;
@ApiModelProperty(value = "陪练模式",allowableValues = "80:训练+考核 ,10:训练 20:考核")
private Integer useType;
@ApiModelProperty(value = "每轮对话过关条件 80:开启 10:关闭")
private Integer startNextRoundType;
@ApiModelProperty(value = "过关分数")
private Integer startNextRoundScore;
@ApiModelProperty(value = "强制练习轮次")
private Integer practiceFailedMaxCount;
@ApiModelProperty(value = "考核策略是否允许重复提交; 80:允许重复提交 10:不允许重复提交")
private Integer repeatPush;
@ApiModelProperty(value = "多轮对话:80:开启 10:关闭")
private Integer manyRoundChat;
@ApiModelProperty(value = "相似度")
private Integer similarityRate;
@ApiModelProperty(value = "考核强制对话轮次")
private Integer examFailedMaxCount;
@ApiModelProperty(value = "未识别回复类型 80:默认回复,10:自定义回复")
private Integer similarityFailedMsgType;
@ApiModelProperty(value = "自定义未识别回复,分号分隔。")
private String similarityFailedMsg;
@ApiModelProperty(value = "考试及格分")
private Integer examPassMinScore;
@ApiModelProperty(value = "是否发放积分 80:发放 10:不发放")
private Integer examGivenPointType;
@ApiModelProperty(value = "积分策略")
private List<PracticePointVo> practicePointList;
@ApiModelProperty(value = "完整性")
private Integer scoreRuleComplete;
@ApiModelProperty(value = "关键词命中")
private Integer scoreRuleKeyword;
@ApiModelProperty(value = "流畅性")
private Integer scoreRuleSmooth;
@ApiModelProperty(value = "表达能力")
private Integer scoreRuleExpress;
@ApiModelProperty(value = "礼貌用语")
private Integer scoreRulePolite;
}
package com.yizhi.practice.application.pojo.po
import com.yizhi.core.application.context.RequestContext
import io.swagger.annotations.ApiModel
import io.swagger.annotations.ApiModelProperty
/**
* @Date 2020/10/30 3:49 下午
* @Author lvjianhui
**/
@ApiModel
class AnalyzeStudentVoicePo {
@ApiModelProperty("学员录音URL")
var voiceUrl:String ? = null
@ApiModelProperty("用户语音时长")
var voiceDuration:Long ? = null
@ApiModelProperty("学员标准话术ID")
var chatRoundConfigId:Long ? = null
@ApiModelProperty("学员话是层级",required = true)
var chatRoundLevel:Int ? = null
@ApiModelProperty("模式类型 10:训练 20:考核",allowableValues = "10,20",required = true)
var useType:Int ? = null
@ApiModelProperty("陪练ID")
var practiceId:Long ? = null
@ApiModelProperty("场景ID")
var senceId:Long ? = null
@ApiModelProperty("陪练记录ID")
var practiceLogId:Long ? = null
@ApiModelProperty(hidden = true)
var requestContext:RequestContext ? = null
@ApiModelProperty("跳过传 true")
var ignore:Boolean = false
@ApiModelProperty("微信上传录音mediaId")
var wechatMediaId:String ? = null
@ApiModelProperty("微信公众号Appid")
var wechatAppId:String ? = null
@ApiModelProperty("企业微信应用ID")
var agentId:String ? = null
@ApiModelProperty("平台类型 WECHAT,QYWECHAT,H5",allowableValues = "WECHAT,QYWECHAT,H5")
var platform:String = "WECHAT"
}
package com.yizhi.practice.application.pojo.po;
import java.util.List;
import com.yizhi.practice.application.pojo.vo.PracticeChatLogListVo;
import io.swagger.annotations.ApiModel;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
@ApiModel(value = "PracticeChatLogExportPo", description = "陪练记录-列表页面-导出-PO")
public class PracticeChatLogExportPo {
private Long taskId;
private String serialNo;
private String taskName;
private Long companyId;
private Long siteId;
private Long orgId;
private Long accountId;
private Boolean isAdmin;
private List<PracticeChatLogListVo> datas;
}
package com.yizhi.practice.application.pojo.po
import com.yizhi.core.application.context.RequestContext
import io.swagger.annotations.ApiModel
import io.swagger.annotations.ApiModelProperty
/**
* @Date 2020/10/26 3:58 下午
* @Author lvjianhui
**/
@ApiModel
class StartPracticePO {
@ApiModelProperty("陪练ID",required = true)
var practiceId:Long ? = null
@ApiModelProperty("模式 10:训练 20:考核")
var useType:Int ? = null
@ApiModelProperty("陪练级别 10:初级 40:中级 80:高级")
var level:Int ? = null
@ApiModelProperty(hidden = true)
var requestContext: RequestContext ? = null
}
\ No newline at end of file
package com.yizhi.practice.application.pojo.vo
import io.swagger.annotations.ApiModel
import io.swagger.annotations.ApiModelProperty
/**
* @Date 2020/10/29 4:30 下午
* @Author lvjianhui
**/
@ApiModel
class ChatContextVo {
@ApiModelProperty("对话ID")
var chatId:Long ? = null
@ApiModelProperty("姓名",hidden = true)
var name: String? = null
@ApiModelProperty("话术内容")
var context: String? = null
@ApiModelProperty("音频地址")
var voiceUrl: String? = null
@ApiModelProperty("音频时长",hidden = true)
var voiceDuration: Long? = null
@ApiModelProperty("头像URL",hidden = true)
var picUrl: String? = null
@ApiModelProperty("层级")
var level:Int ? = null
}
\ No newline at end of file
package com.yizhi.practice.application.pojo.vo
import io.swagger.annotations.ApiModel
import io.swagger.annotations.ApiModelProperty
import org.apache.xpath.operations.Bool
/**
* @Date 2020/11/9 7:26 下午
* @Author lvjianhui
**/
@ApiModel
class ChatResultVo {
@ApiModelProperty("通过为true,不通过false")
var passSuccess:Boolean = false
@ApiModelProperty("得分")
var score:Int ? = null
@ApiModelProperty("音频时长")
var duration:Long ? = null
@ApiModelProperty("音频地址")
var voiceUrl:String ? = null
@ApiModelProperty("音频转换后的文字")
var content:String ? = null
@ApiModelProperty("命中的关键词,可能需要高亮")
var contentHitKeyWord:List<String> ? = null
@ApiModelProperty("该语音匹配到的学员分支")
var chatRoundConfigId:Long ? = null
@ApiModelProperty("为true时提示用户可以跳过或重新输入")
var unPassTipSskip:Boolean = false
@ApiModelProperty("未识别的自定已回复")
var customizeFileMsg:String ? = null
@ApiModelProperty("命中的禁忌词")
var hitTabooWord = arrayListOf<String>()
@ApiModelProperty("用户上传ID")
var accountUploadId:Long ?= null
}
\ No newline at end of file
package com.yizhi.practice.application.pojo.vo;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class LocalJSONObject {
private String key;
private String value;
}
package com.yizhi.practice.application.pojo.vo;
import java.util.Date;
import java.util.List;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
@ApiModel(value = "PracticeChatLogBaseInfoVo", description = "陪练记录-详情页面-基本信息")
public class PracticeChatLogBaseInfoVo {
@ApiModelProperty(value = "陪练log ID")
private Long id;
@ApiModelProperty(value = "陪练 ID")
private Long practiceId;
@ApiModelProperty(value = "用户名")
private String accountName;
@ApiModelProperty(value = "用户姓名")
private String accountFullName;
@ApiModelProperty(value = "陪练模式")
private String mode;
@ApiModelProperty(value = "完成时间")
private Date endAt;
@ApiModelProperty(value = "总得分")
private Integer totalScore;
@ApiModelProperty(value = "关键词得分")
private Integer keywordScore;
@ApiModelProperty(value = "关键词 完成度 单位%")
private Integer keywordRate;
@ApiModelProperty(value = "完整性得分")
private Integer completeScore;
@ApiModelProperty(value = "完整性 完成度 单位%")
private Integer completeRate;
@ApiModelProperty(value = "流畅性得分")
private Integer smoothScore;
@ApiModelProperty(value = "流畅性 完整度 单位%")
private Integer smoothRate;
@ApiModelProperty(value = "表达能力得分")
private Integer expressScore;
@ApiModelProperty(value = "表达能力 完成度 单位%")
private Integer expressRate;
@ApiModelProperty(value = "礼貌用语得分")
private Integer politeScore;
@ApiModelProperty(value = "礼貌用语 完成度 单位%")
private Integer politeRate;
@ApiModelProperty(value = "机器人名称")
private String robotName;
@ApiModelProperty(value = "该陪练记录下对应的所有场景")
private List<PracticeChatLogSceneVo> scenes;
}
package com.yizhi.practice.application.pojo.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "PracticeChatLogDetailParamVo", description = "陪练记录-详情-入参")
public class PracticeChatLogDetailParamVo {
@ApiModelProperty("陪练ID")
private Long practiceId;
@ApiModelProperty("陪练记录的ID(不是陪练的ID)")
private Long practiceLogId;
@ApiModelProperty(value = "列表页的查询条件(如果列表页有才需要)")
private String search;
@ApiModelProperty(value = "列表页的陪练模式 10:初级 40:中级 80:高级 20:考核 (如果列表页有才需要)")
private Integer[] modes;
}
package com.yizhi.practice.application.pojo.vo;
import java.util.Date;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
@ApiModel(value = "PracticeChatLogVo", description = "陪练记录-列表页面-头部基本信息")
public class PracticeChatLogListHeaderVo {
private Long practiceId;
@ApiModelProperty(value = "陪练名称")
private String practiceName;
@ApiModelProperty(value = "训练开始时间")
private Date practiceStartAt;
@ApiModelProperty(value = "训练结束时间")
private Date practiceEndAt;
@ApiModelProperty(value = "考核开始时间")
private Date examStartAt;
@ApiModelProperty(value = "考核结束时间")
private Date examEndAt;
@ApiModelProperty(value = "参与训练人数")
private Integer practicePeopleNumber;
@ApiModelProperty(value = "参与训练人次")
private Integer practiceTimesNumber;
@ApiModelProperty(value = "参与考核人数")
private Integer examPeopleNumber;
@ApiModelProperty(value = "参与考核人次")
private Integer examTimesNumber;
}
package com.yizhi.practice.application.pojo.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Builder;
import lombok.Data;
@Builder
@Data
@ApiModel(value = "PracticeChatLogListParamVo", description = "陪练记录-列表页面-入参")
public class PracticeChatLogListParamVo {
@ApiModelProperty("陪练ID")
private Long practiceId;
@ApiModelProperty("陪练名称")
private String practiceName;
@ApiModelProperty(value = "查询条件")
private String search;
@ApiModelProperty(value = "陪练模式 10:初级 40:中级 80:高级 20:考核")
private Integer[] modes;
@ApiModelProperty(value = "当前页")
private Integer pageNo;
@ApiModelProperty(value = "一页多少条")
private Integer pageSize;
public PracticeChatLogListParamVo() {
super();
}
public PracticeChatLogListParamVo(Long practiceId, String practiceName, String search, Integer[] modes,
Integer pageNo, Integer pageSize) {
super();
this.practiceId = practiceId;
this.practiceName = practiceName;
this.search = search;
this.modes = modes;
this.pageNo = pageNo;
this.pageSize = pageSize;
}
}
package com.yizhi.practice.application.pojo.vo;
import java.util.Date;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
@ApiModel(value = "PracticeChatLogListVo", description = "陪练记录-列表页面-列表信息")
public class PracticeChatLogListVo {
@ApiModelProperty(value = "陪练记录ID")
private Long id;
@ApiModelProperty(value = "陪练ID")
private Long practiceId;
@ApiModelProperty(value = "用户名")
private String accountName;
@ApiModelProperty(value = "用户姓名")
private String accountFullName;
@ApiModelProperty(value = "10:训练 20:考核")
private Integer useType;
@ApiModelProperty(value = "部门名")
private String orgName;
@ApiModelProperty(value = "陪练模式")
private String mode;
@ApiModelProperty(value = "陪练级别 10:初级 40:中级 80:高级")
private Integer level;
@ApiModelProperty(value = "完成时间")
private Date endAt;
@ApiModelProperty(value = "总得分")
private Integer totalScore;
}
package com.yizhi.practice.application.pojo.vo;
import java.util.List;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
@ApiModel(value = "PracticeChatLogSceneVo", description = "陪练记录-详情页面-场景信息")
public class PracticeChatLogSceneVo {
@ApiModelProperty(value = "场景ID")
private Long sceneId;
@ApiModelProperty(value = "场景名称")
private String sceneName;
@ApiModelProperty(value = "场景的排序号")
private Integer sort;
@ApiModelProperty(value = "该场景下的实际对话")
private List<PracticeChatRoundLogVo> chats;
}
package com.yizhi.practice.application.pojo.vo;
import java.util.List;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
@ApiModel(value = "PracticeChatRoundLogDetailVo", description = "陪练记录-详情页面-本题分析")
public class PracticeChatRoundLogDetailVo {
@ApiModelProperty(value = "关键词")
private List<LocalJSONObject> keyWord;
@ApiModelProperty(value = "命中的关键词")
private List<String> keywordHit;
@ApiModelProperty(value = "命中的禁忌词")
private List<String> forbidHit;
@ApiModelProperty(value = "本题得分")
private Integer totalScore;
@ApiModelProperty(value = "关键词得分")
private Integer keywordScore;
@ApiModelProperty(value = "完整性得分")
private Integer completeScore;
@ApiModelProperty(value = "流畅度得分")
private Integer smoothScore;
@ApiModelProperty(value = "流畅度 提示信息")
private String smoothHint;
@ApiModelProperty(value = "表达能力得分")
private Integer expressScore;
@ApiModelProperty(value = "表达能力 提示信息")
private String expressHint;
@ApiModelProperty(value = "礼貌性得分")
private Integer politeScore;
@ApiModelProperty(value = "礼貌性 提示信息")
private String politeHint;
@ApiModelProperty(value = "学员话术")
private String accountContent;
@ApiModelProperty(value = "学员话术URL")
private String accountContentVoiceUrl;
@ApiModelProperty(value = "学员话术时长")
private Long accountDuration;
@ApiModelProperty(value = "机器人话术")
private String robotContent;
@ApiModelProperty(value = "机器人话术URL")
private String robotContentUrl;
@ApiModelProperty(value = "机器人话术时长")
private Long robotDuration;
}
package com.yizhi.practice.application.pojo.vo;
import java.util.Date;
import java.util.List;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
@ApiModel(value = "PracticeChatRoundLogVo", description = "陪练记录-详情页面-场景对话信息(话术,得分)")
public class PracticeChatRoundLogVo {
private Long id;
@ApiModelProperty(value = "陪练记录ID")
private Long practiceChatId;
@ApiModelProperty(value = "场景ID")
private Long sceneId;
@ApiModelProperty(value = "场景名称")
private String sceneName;
@ApiModelProperty(value = "场景的排序号")
private Integer sort;
@ApiModelProperty(value = "节点标识 10:机器人,20:学员 节点,80:开始节点")
private Integer sceneNodeType;
@ApiModelProperty(value = "机器人话术")
private String robotContent;
@ApiModelProperty(value = "机器人话术URL")
private String robotContentUrl;
@ApiModelProperty(value = "机器人话术时长")
private Long robotDuration;
@ApiModelProperty(value = "学员话术")
private String accountContent;
@ApiModelProperty(value = "学员话术中命中的关键词")
private List<String> accountHitKeyWord;
@ApiModelProperty(value = "学员话术中命中的禁忌词")
private List<String> hitForbidWord;
@ApiModelProperty(value = "学员话术URL")
private String accountContentVoiceUrl;
@ApiModelProperty(value = "学员话术时长")
private Long accountDuration;
@ApiModelProperty(value = "本轮对话层级 ")
private Integer roundLevel;
@ApiModelProperty(value = "本轮对话过关方式 80:正常通过。10:跳过")
private Integer roundSkipType;
@ApiModelProperty(value = "是否跳过对话")
private Boolean isSkip;
@ApiModelProperty(value = "本轮平均得分")
private Integer averageScore;
@ApiModelProperty(value = "创建日期")
private Date createdAt;
}
package com.yizhi.practice.application.pojo.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
import java.util.List;
@Data
@ApiModel(value = "陪练基本信息和策略信息")
public class PracticeConfigInfoVo {
@ApiModelProperty(value = "陪练id")
private Long id;
@ApiModelProperty(value = "陪练名")
private String name;
@ApiModelProperty(value = "陪练logoURL")
private String logoUrl;
@ApiModelProperty(value = "陪练描述")
private String description;
@ApiModelProperty(value = "陪练模式",allowableValues = "80:训练+考核 ,10:训练 20:考核")
private Integer useType;
@ApiModelProperty(value = "训练开始时间")
private Date practiceStartAt;
@ApiModelProperty(value = "训练结束时间")
private Date practiceEndAt;
@ApiModelProperty(value = "考核开始时间")
private Date examStartAt;
@ApiModelProperty(value = "考核结束时间")
private Date examEndAt;
@ApiModelProperty(value = "允许最大考试次数 0:无限次;其他有限次;默认0")
private Integer maxExamCount;
@ApiModelProperty(value = "自定义关键词,逗号分隔")
private String keyWord;
@ApiModelProperty(value = "机器人参数")
private Long robotId;
@ApiModelProperty(value = "机器人参数")
private String robotParams;
@ApiModelProperty(value = "机器人名称.第三方支持的机器人名称")
private String robotName;
@ApiModelProperty(value = "机器人称呼.自定义机器人的名称")
private String robotAliasName;
@ApiModelProperty(value = "机器人头像URL null时走默认头像")
private String robotPicUrl;
@ApiModelProperty(value = "机器人声音URL")
private String robotVoiceUrl;
@ApiModelProperty(value = "陪练状态",allowableValues = "陪练状态 80:上架 30:下架 10:草稿",example = "10")
private Integer status;
@ApiModelProperty(value = "练习可见范围 ",allowableValues = "80:平台可见 40:指定用户可见",example = "80")
private Integer visibleType;
@ApiModelProperty(value = "是否跳过对话 80允许,10:不允许")
private Integer skipType;
@ApiModelProperty(value = "每轮对话过关条件 80:开启 10:关闭")
private Integer startNextRoundType;
@ApiModelProperty(value = "过关分数")
private Integer startNextRoundScore;
@ApiModelProperty(value = "强制练习轮次")
private Integer practiceFailedMaxCount;
@ApiModelProperty(value = "考核策略是否允许重复提交; 80:允许重复提交 10:不允许重复提交")
private Integer repeatPush;
@ApiModelProperty(value = "多轮对话:80:开启 10:关闭")
private Integer manyRoundChat;
@ApiModelProperty(value = "相似度")
private Integer similarityRate;
@ApiModelProperty(value = "考核强制对话轮次")
private Integer examFailedMaxCount;
@ApiModelProperty(value = "未识别回复类型 80:默认回复,10:自定义回复")
private Integer similarityFailedMsgType;
@ApiModelProperty(value = "自定义未识别回复,分号分隔。")
private String similarityFailedMsg;
@ApiModelProperty(value = "考试及格分")
private Integer examPassMinScore;
@ApiModelProperty(value = "是否发放积分 80:发放 10:不发放")
private Integer examGivenPointType;
@ApiModelProperty(value = "积分策略")
private List<PracticePointVo> practicePointList;
@ApiModelProperty(value = "完整性")
private Integer scoreRuleComplete;
@ApiModelProperty(value = "关键词命中")
private Integer scoreRuleKeyword;
@ApiModelProperty(value = "流畅性")
private Integer scoreRuleSmooth;
@ApiModelProperty(value = "表达能力")
private Integer scoreRuleExpress;
@ApiModelProperty(value = "礼貌用语")
private Integer scoreRulePolite;
}
package com.yizhi.practice.application.pojo.vo
import io.swagger.annotations.ApiModel
import io.swagger.annotations.ApiModelProperty
import java.util.*
/**
* @Date 2020/10/23 11:54 上午
* @Author lvjianhui
**/
@ApiModel
class PracticeConfigVo {
@ApiModelProperty("陪练Id")
var practiceId:Long ? = null
@ApiModelProperty("陪练名")
var name:String ? = null
@ApiModelProperty("训练开始时间")
var practiceStartAt: Date? = null
@ApiModelProperty("训练结束时间")
var practiceEndAt: Date ? = null
@ApiModelProperty("考试开始时间")
var examStartAt: Date ? = null
@ApiModelProperty("考试结束时间")
var examEndAt: Date ? = null
@ApiModelProperty("陪练介绍")
var description:String ? = null
@ApiModelProperty("10:训练 20:考试 80:训练加考试")
var useType:Int ? = null
@ApiModelProperty("最大允许考核次数")
var maxExamCount:Int ? = 0
@ApiModelProperty("已参加考试次数")
var joinExamCount:Long ? = 0
@ApiModelProperty("参加训练次数")
var joinPracticeCount:Long ? = 0
@ApiModelProperty("训练模式 跳过对话类型 80允许,10:不允许")
var practiceSkipType:Int ? = null
@ApiModelProperty("考试是否允许重复提交 80:允许重复提交 10:不允许重复提交")
var examRepeatPush:Int ? = null
var robotName:String ? = null
}
\ No newline at end of file
package com.yizhi.practice.application.pojo.vo
import io.swagger.annotations.ApiModel
import io.swagger.annotations.ApiModelProperty
/**
* @Date 2020/11/10 6:54 下午
* @Author lvjianhui
**/
@ApiModel("陪练结果")
class PracticeEndResultVo {
@ApiModelProperty("陪练得分")
var score:Int ? = null
@ApiModelProperty("陪练结果 true:通过 false:不通过")
var passSuccess:Boolean ? = null
}
\ No newline at end of file
package com.yizhi.practice.application.pojo.vo
import io.swagger.annotations.ApiModel
import io.swagger.annotations.ApiModelProperty
/**
* @Date 2020/11/5 9:09 上午
* @Author lvjianhui
*/
@ApiModel
class PracticeJoinedVo {
@ApiModelProperty("初级参加次数 次数大于0,则表示已参加")
var primaryLevelCount:Long = 0L
@ApiModelProperty("中级参加次数")
var intermediateLevel:Long = 0L
@ApiModelProperty("高级参加次数")
var seniorLevel:Long = 0L
}
\ No newline at end of file
package com.yizhi.practice.application.pojo.vo;
import com.yizhi.practice.application.request.PracticeChatNodeReq;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
* 陪练下的场景对话
*/
@Data
@Api(tags = "陪练下的场景对话")
public class PracticeSceneDialogueVo {
@ApiModelProperty(name = "场景所属陪练id")
private Long practiceId;
@ApiModelProperty(name = "场景id")
private Long sceneId;
@ApiModelProperty(name = "场景名称")
private String sceneName;
@ApiModelProperty(name = "场景描述")
private String sceneDescription;
@ApiModelProperty(name = "场景排序序号;从0开始")
private int sort;
//节点列表
private List<PracticeChatNodeReq> chatNodes;
}
package com.yizhi.practice.application.pojo.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
@Data
@ApiModel(value = "陪练指定用户/部门范围")
public class PracticeVisibleAccountVo {
@ApiModelProperty(value = "陪练主键id")
private Long practiceId;
@ApiModelProperty(value = "陪练指定用户或者部门信息")
private List<PracticeVisibleInfoVo> visibleInfoList;
}
package com.yizhi.practice.application.pojo.vo;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "可用范围")
public class PracticeVisibleInfoVo {
@ApiModelProperty(value = "表主键id")
private Long id;
@ApiModelProperty(value = "可见范围用户或者部门id")
@JsonSerialize(using = ToStringSerializer.class)
private Long visibleId;
@ApiModelProperty(value = "可见范围类型; 50:部门可见 40:指定用户可见")
private Integer visibleType;
@ApiModelProperty(value = "用户或者部门名称")
private String name;
@ApiModelProperty(value = "全名")
private String fullName;
@ApiModelProperty(value = "工号")
private String workNum;
}
package com.yizhi.practice.application.pojo.vo;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 机器人信息
*/
@Data
public class RobotVo {
@ApiModelProperty(value = "机器人id")
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
@ApiModelProperty(value = "机器人名称")
private String robotName;
@ApiModelProperty(value = "机器人参数,根据参数来确定音频效果")
private String robotParams;
@ApiModelProperty(value = "机器人合成语音demoURL")
private String contentVoiceUrl;
}
package com.yizhi.practice.application.pojo.vo
import io.swagger.annotations.ApiModel
import io.swagger.annotations.ApiModelProperty
/**
* @Date 2020/10/26 4:37 下午
* @Author lvjianhui
**/
@ApiModel
class SceneChatVO {
@ApiModelProperty("场景名")
var sceneName:String ? = null
@ApiModelProperty("场景ID")
var sceneId:Long ? = null
@ApiModelProperty("场景描述")
var sceneDescription:String ? = null
}
\ No newline at end of file
package com.yizhi.practice.application.pojo.vo
import io.swagger.annotations.ApiModel
import io.swagger.annotations.ApiModelProperty
/**
* @Date 2020/11/3 1:46 下午
* @Author lvjianhui
**/
@ApiModel
class StuPracticeLogVo {
@ApiModelProperty("陪练记录id")
var practiceLogId:Long ? = null
@ApiModelProperty("陪练类型 10:训练 20:考核")
var useType :Int ? = null
@ApiModelProperty("陪练配置ID")
var practiceId:Long ? = null
}
\ No newline at end of file
package com.yizhi.practice.application.pojo.vo
import io.swagger.annotations.ApiModel
import io.swagger.annotations.ApiModelProperty
/**
* @Date 2020/10/30 1:56 下午
* @Author lvjianhui
**/
@ApiModel
class StudentChatContextVo {
@ApiModelProperty("聊天ID")
var chatRoundConfigId:Long ? = null
var context:String ? = null
var voiceUrl:String ? = null
@ApiModelProperty("")
var keyWord:List<String> ? = null
var level:Int ? = null
}
\ No newline at end of file
package com.yizhi.practice.application.pojo.vo;
import java.util.Date;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
@ApiModel(value = "StudentPracticeLogVo", description = "学员端-陪练记录-列表")
public class StudentPracticeLogVo {
@ApiModelProperty(value = "陪练记录ID")
private Long id;
@ApiModelProperty(value = "陪练ID")
private Long practiceId;
@ApiModelProperty(value = "10:训练 20:考核")
private Integer useType;
@ApiModelProperty(value = "陪练模式")
private String mode;
@ApiModelProperty(value = "陪练级别 10:初级 40:中级 80:高级")
private Integer level;
@ApiModelProperty(value = "完成时间")
private Date endAt;
@ApiModelProperty(value = "总得分")
private Integer totalScore;
}
package com.yizhi.practice.application.repository;
import com.yizhi.practice.application.pojo.domain.PracticeChatLog;
import com.yizhi.practice.application.pojo.dto.PracticeAllScoreDto;
import org.apache.ibatis.annotations.Param;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
/**
* <p>
* 场景对话结果记录 Mapper 接口
* </p>
*
* @author MybatisCodeGenerator123
* @since 2020-10-22
*/
public interface PracticeChatLogRepository extends JpaRepository<PracticeChatLog,Long>, QuerydslPredicateExecutor<PracticeChatLog>{
}
package com.yizhi.practice.application.repository;
import com.yizhi.practice.application.pojo.domain.PracticeChatRoundLog;
import com.yizhi.practice.application.pojo.dto.PracticeAllScoreDto;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.data.repository.query.Param;
/**
* <p>
* 场景中每轮对话记录 Mapper 接口
* </p>
*
* @author MybatisCodeGenerator123
* @since 2020-10-22
*/
public interface PracticeChatRoundLogRepository extends JpaRepository<PracticeChatRoundLog,Long>, QuerydslPredicateExecutor<PracticeChatRoundLog>{
// @Query(value =
// "select " +
// "avg(a.keyword_score) as keywordScore, " +
// "avg(a.complete_score) as completeScore, " +
// "avg(a.smooth_score) as smoothScore, " +
// "avg(a.polite_score) as politeScore, " +
// "avg(a.express_score) as expressScore " +
// "from practice_chat_round_log a inner join ( " +
// "select max(created_at) as created_at , " +
// "scene_chat_id as scene_chat_id " +
// "from practice_chat_round_log " +
// "where " +
// "practice_chat_id = ?1 " +
// "and round_skip_type = 80 " +
// "and account_id = ?2 " +
// "and org_id = ?3 " +
// "and site_id = ?4 " +
// "and company_id = ?5 " +
// "and deleted = 0 " +
// "group by scene_chat_id) b " +
// "on a.created_at = b.created_at " +
// "and a.scene_chat_id = b.scene_chat_id " +
// "where a.practice_chat_id = ?1 " +
// "and a.round_skip_type = 80 " +
// "and a.account_id = ?2 " +
// "and a.org_id = ?3 " +
// "and a.site_id = ?4 " +
// "and a.company_id = ?5 " +
// "and a.deleted = 0 " +
// "order by a.scene_id,a.round_level ",nativeQuery = true)
// public PracticeAllScoreDto getScoreByAccount(@Param(value = "practiceChatId") Long practiceChatId,
// @Param(value = "accountId") Long accountId,
// @Param(value = "orgId") Long orgId,
// @Param(value = "siteId") Long siteId,
// @Param(value = "companyId") Long companyId);
}
package com.yizhi.practice.application.repository;
import com.yizhi.practice.application.pojo.domain.PracticeConfig;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
/**
* <p>
* 陪练配置 Mapper 接口
* </p>
*
* @author MybatisCodeGenerator123
* @since 2020-10-22
*/
public interface PracticeConfigRepository extends JpaRepository<PracticeConfig,Long>, QuerydslPredicateExecutor<PracticeConfig>{
}
package com.yizhi.practice.application.repository;
import com.yizhi.practice.application.pojo.domain.PracticePointGivenLog;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
/**
* <p>
* 陪练积分发放记录 Mapper 接口
* </p>
*
* @author MybatisCodeGenerator123
* @since 2020-10-22
*/
public interface PracticePointGivenLogRepository extends JpaRepository<PracticePointGivenLog,Long>, QuerydslPredicateExecutor<PracticePointGivenLog>{
}
package com.yizhi.practice.application.repository;
import com.yizhi.practice.application.pojo.domain.PracticePointRuleConfig;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.data.repository.query.Param;
import java.util.List;
/**
* <p>
* 陪练积分发放规则 Mapper 接口
* </p>
*
* @author MybatisCodeGenerator123
* @since 2020-10-22
*/
public interface PracticePointRuleConfigRepository extends JpaRepository<PracticePointRuleConfig,Long>, QuerydslPredicateExecutor<PracticePointRuleConfig>{
@Modifying
@Query("update PracticePointRuleConfig rule set rule.deleted = true where rule.practiceId = :practiceId")
void deleteRulesByPractice(@Param(value = "practiceId") Long practiceId);
/**
* 查询陪练下的积分规则
* @param practiceId 陪练id
*/
@Query("select r from PracticePointRuleConfig r where r.practiceId = :practiceId and r.deleted = false ")
List<PracticePointRuleConfig> selectListByPracticeId(@Param(value = "practiceId") Long practiceId);
}
package com.yizhi.practice.application.repository;
import com.yizhi.practice.application.pojo.domain.PracticeVisible;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.data.repository.query.Param;
import java.util.List;
/**
* <p>
* Mapper 接口
* </p>
*
* @author MybatisCodeGenerator123
* @since 2020-10-22
*/
public interface PracticeVisibleRepository extends JpaRepository<PracticeVisible, Long>, QuerydslPredicateExecutor<PracticeVisible> {
@Query(nativeQuery = true,
value = "select distinct practice_id " +
"from " +
"practice_visible " +
"where company_id = :companyId " +
"and visible_site_id = :siteId " +
"and visible_account_id = :accountId " +
"and visible_type = 40 " +
"and deleted = false " +
"union " +
"select distinct practice_id " +
"from " +
"practice_visible " +
"where company_id = :companyId " +
"and visible_site_id = :siteId " +
"and visible_org_id in ( :parendOrgIdAndOrgId )" +
"and visible_type = 50 " +
"and deleted = false ")
public List<Long> getIdsByAccountId(@Param("accountId") Long accountId,
@Param("parendOrgIdAndOrgId") List<Long> parendOrgIdAndOrgId,
@Param("siteId") Long siteId,
@Param("companyId") Long companyId);
@Modifying
@Query("update PracticeVisible v set v.deleted = true where v.practiceId = :practiceId")
void deleteVisibleRangeByPractice(@Param(value = "practiceId") Long practiceId);
@Query(nativeQuery = true, value="select * from practice_visible where practice_id = :practiceId and deleted=0")
public List<PracticeVisible> findByPracticeId(@Param(value = "practiceId") Long practiceId);
}
package com.yizhi.practice.application.repository;
import com.yizhi.practice.application.pojo.domain.RobotConfig;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
/**
* <p>
* 机器人配置 Mapper 接口
* </p>
*
* @author MybatisCodeGenerator123
* @since 2020-10-22
*/
public interface RobotConfigRepository extends JpaRepository<RobotConfig,Long>, QuerydslPredicateExecutor<RobotConfig>{
}
package com.yizhi.practice.application.repository;
import com.yizhi.practice.application.pojo.domain.SceneChatConfig;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.data.repository.query.Param;
/**
* <p>
* 场景对话配置 Mapper 接口
* </p>
*
* @author MybatisCodeGenerator123
* @since 2020-10-22
*/
public interface SceneChatConfigRepository extends JpaRepository<SceneChatConfig,Long>, QuerydslPredicateExecutor<SceneChatConfig>{
@Modifying
@Query("update SceneChatConfig v set v.deleted = true where v.sceneId = :sceneId")
void deleteSceneNodesByPracticeId(@Param(value = "sceneId") Long sceneId);
/**
* 修改场景对话中场景名称
* @param newSceneName 新的场景名称
*/
@Modifying
@Query("update SceneChatConfig v set v.sceneName = :newSceneName where v.sceneId = :sceneId")
void updateSceneNameBySceneId(@Param(value = "newSceneName") String newSceneName,@Param(value = "sceneId") Long sceneId);
/**
* 按照practice_id和scene_id查找未删除的话术节点
* @param practiceId
* @param sceneId
* @return
*/
@Query("select s from SceneChatConfig s where s.practiceId = :practiceId and s.sceneId = :sceneId and s.deleted = false order by s.level asc")
public List<SceneChatConfig> findByPracticeIdAndSceneId(@Param(value = "practiceId") Long practiceId
, @Param(value = "sceneId") Long sceneId);
}
package com.yizhi.practice.application.repository;
import com.yizhi.practice.application.pojo.domain.SceneConfig;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.data.repository.query.Param;
import java.util.List;
/**
* <p>
* 场景配置 Mapper 接口
* </p>
*
* @author MybatisCodeGenerator123
* @since 2020-10-22
*/
public interface SceneConfigRepository extends JpaRepository<SceneConfig,Long>, QuerydslPredicateExecutor<SceneConfig>{
@Query("select s from SceneConfig s where s.practiceId = :practiceId and s.deleted = false order by s.sort asc ")
List<SceneConfig> selectByPracticeId(@Param(value = "practiceId") Long practiceId);
}
package com.yizhi.practice.application.service
import com.querydsl.jpa.impl.JPAQueryFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import javax.annotation.PostConstruct
import javax.persistence.EntityManager
/**
* @Date 2020/10/22 3:21 下午
* @Author lvjianhui
*/
@Service
open class BaseService {
@Autowired
lateinit var entityManager: EntityManager;
lateinit var jpaqueryFactory:JPAQueryFactory;
@PostConstruct
fun initFactory() {
jpaqueryFactory = JPAQueryFactory(entityManager)
}
}
\ No newline at end of file
package com.yizhi.practice.application.service;
import com.yizhi.core.application.context.RequestContext;
import com.yizhi.practice.application.pojo.domain.PracticeChatLog;
import com.yizhi.practice.application.pojo.vo.*;
import com.yizhi.util.application.page.PageInfo;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* <p>
* 场景对话结果记录 服务类
* </p>
*
* @author MybatisCodeGenerator123
* @since 2020-10-22
*/
public interface IPracticeChatLogService {
public Map<Integer, Long> getExamAndPracticeCount(Long accountId, Long practiceId, Long orgId, Long siteId, Long companyId);
/**
* 获取带有分页信息的 陪练记录 列表
*
* @param param
* @param userIds
* @return
*/
public PageInfo<PracticeChatLogListVo> listPage(PracticeChatLogListParamVo param, RequestContext relation);
/**
* 学员端 - 获取带有分页信息的 陪练记录 列表
*
* @param param
* @param relation
* @return
*/
public PageInfo<StudentPracticeLogVo> studentListPage(PracticeChatLogListParamVo param, RequestContext relation);
/**
* 获取符合条件的所有陪练记录
*
* @param param
* @param userIds
* @return
*/
public List<PracticeChatLogListVo> listAll(PracticeChatLogListParamVo param, RequestContext relation);
/**
* 根据 陪练ID和陪练模式 获取陪练的参与人数
*
* @param practiceId
* @param mode
* @return
*/
public Integer peopleNumber(Long practiceId, Integer mode, RequestContext relation);
/**
* 根据 陪练ID和陪练模式 获取陪练的参与人次
*
* @param practiceId
* @param mode
* @return
*/
public Integer timesNumber(Long practiceId, Integer mode, RequestContext relation);
/**
* 根据陪练记录的ID获取基本信息,包括学员信息,总得分信息
*
* @param practiceLogId
* @return
*/
public PracticeChatLogBaseInfoVo get(Long practiceLogId);
/**
* 查询学员当前陪练的考试次数
*
* @param accountId
* @param practiceId
* @return
*/
public Long getExamCountByPractice(Long accountId, Long practiceId);
Map<Integer,Long> getPracticeLogByLevel(Long practiceId, Long accountId, Long companyId, Long siteId, Long orgId);
/**
* 根据搜索条件及当前ID,获取前一个ID
* @return
*/
public Long previous(PracticeChatLogDetailParamVo param, RequestContext relation);
/**
* 根据搜索条件及当前ID,获取后一个ID
* @return
*/
public Long next(PracticeChatLogDetailParamVo param, RequestContext relation);
List<PracticeChatLog> getListByTime(Date startDate, Date endDate);
}
package com.yizhi.practice.application.service;
import java.util.List;
import com.yizhi.practice.application.pojo.domain.PracticeChatRoundLog;
import com.yizhi.practice.application.pojo.dto.PracticeAllScoreDto;
import com.yizhi.practice.application.pojo.dto.PracticeChartRoundLogDto;
import com.yizhi.practice.application.pojo.vo.PracticeChatRoundLogVo;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* <p>
* 场景中每轮对话记录 服务类
* </p>
*
* @author MybatisCodeGenerator123
* @since 2020-10-22
*/
public interface IPracticeChatRoundLogService {
public PracticeAllScoreDto getAccountChatLog(Long practiceChatId, Long accountId, Long orgId, Long siteId, Long companyId);
/**
* 根据陪练记录ID获取该陪练的所有陪练对话详情
* @param practiceChatId
* @return
*/
public List<PracticeChatRoundLogVo> getByPracticeChatId(Long practiceChatId);
/**
* 根据某一句对话的ID获取该句对话的信息(得分,各维度得分,包含的关键词等)
* @param roundLogId
* @return
*/
public PracticeChartRoundLogDto getRoundLogById(Long roundLogId);
/**
*
* @param practiceLogId
* @param chatId
* @param accountId
* @param orgId
* @param siteId
* @param companyId
* @return
*/
Long getCountByUserId(Long practiceLogId,Long chatId, Long accountId, Long orgId, Long siteId, Long companyId);
/**
*
* @param level
* @param practiceLogId
* @param practiceId
* @param accountId
* @param orgId
* @param siteId
* @param companyId
* @return
*/
Long getLevelCountByAccount(Integer level,Long practiceLogId,Long practiceId,Long accountId,Long orgId,Long siteId,Long companyId);
}
package com.yizhi.practice.application.service
import com.yizhi.practice.application.config.PracticeRunningStatusEnum
import com.yizhi.practice.application.pojo.domain.PracticeConfig
import com.yizhi.practice.application.pojo.vo.PracticeBaseInfoVo
import com.yizhi.practice.application.pojo.vo.PracticeConfigVo
import com.yizhi.practice.application.request.PracticesGetReq
import java.util.*
/**
*
*
* 陪练配置 服务类
*
*
* @author MybatisCodeGenerator123
* @since 2020-10-22
*/
interface IPracticeConfigService {
/**
* 更具状态 时间 陪练IDS
*/
fun getRunningCount(orgId: Long, siteId: Long, companyId: Long,date: Date?,state: PracticeRunningStatusEnum): List<Long>?
/**
* 根据ID获取陪练信息
*/
fun getConfigByIds(ids:List<Long>):List<PracticeConfigVo>
/**
* 条件查询陪练列表
*/
fun getPracticeConfigList(params : PracticesGetReq): List<PracticeBaseInfoVo>
/**
* 条件查询陪练列表总数
*/
fun getPracticeConfigCount(params : PracticesGetReq): Long
/**
* 获取全站点可见的陪练ID
*/
fun getSiteAllConfig(siteId: Long, companyId: Long): List<Long>
/**
* 删除陪练配置
*/
fun delete(practiceId: Long)
fun getListByTime(startDate: Date, endDate: Date) :List<PracticeConfig>
}
\ No newline at end of file
package com.yizhi.practice.application.service
/**
*
*
* 陪练积分发放记录 服务类
*
*
* @author MybatisCodeGenerator123
* @since 2020-10-22
*/
interface IPracticePointGivenLogService {
fun sumPointByUserAndPractice(accountId:Long,practiceId:Long,companyId:Long,siteId:Long,orgId:Long):Int
}
\ No newline at end of file
package com.yizhi.practice.application.service;
import com.yizhi.practice.application.pojo.domain.PracticePointRuleConfig;
import java.util.List;
/**
* <p>
* 陪练积分发放规则 服务类
* </p>
*
* @author MybatisCodeGenerator123
* @since 2020-10-22
*/
public interface IPracticePointRuleConfigService {
/**
* 查询陪练下所有生效的积分规则
* @param practiceId 陪练id
* @param isDeleted 是否删除 true:已删除; false: 未删除
* @return 积分规则集合
*/
List<PracticePointRuleConfig> selectPointRulesByPractice(Long practiceId, boolean isDeleted);
PracticePointRuleConfig selectPointRulesByPractice(Long practiceId, Integer userScore, boolean isDeleted);
}
package com.yizhi.practice.application.service
import com.yizhi.practice.application.pojo.domain.PracticeVisible
import java.util.*
/**
*
*
* 服务类
*
*
* @author MybatisCodeGenerator123
* @since 2020-10-22
*/
interface IPracticeVisibleService {
fun getIdsByAccountId(accountId: Long, parendOrgIdAndOrgId: List<Long>, siteId: Long, companyId: Long): MutableList<Long>
/**
* 删除陪练下用户部门信息
*/
fun deleteByPracticeId(practiceId: Long)
/**
* 查询陪练下授权用户和部门
*/
fun getListByPracticeId(practiceId:Long): List<PracticeVisible>
fun getListByTime(startDate: Date, endDate: Date) :List<PracticeVisible>
}
\ No newline at end of file
package com.yizhi.practice.application.service;
/**
* <p>
* 机器人配置 服务类
* </p>
*
* @author MybatisCodeGenerator123
* @since 2020-10-22
*/
public interface IRobotConfigService {
}
package com.yizhi.practice.application.service;
import com.yizhi.practice.application.pojo.domain.SceneChatConfig;
import java.util.List;
/**
* <p>
* 场景对话配置 服务类
* </p>
*
* @author MybatisCodeGenerator123
* @since 2020-10-22
*/
public interface ISceneChatConfigService {
/**
* 查询场景下节点信息
* @param practiceId 陪练id
* @param sceneId 场景id
* @param nodeType 节点类型 机器人;学员
* @param pId 父节点id ;开始节点id=0
* @param level 层级 开始节点level=0
*/
List<SceneChatConfig> selectChatNodes(Long practiceId, Long sceneId, Integer nodeType, Long pId, Integer level);
/**
* 删除场景下对话
* @param practiceId 陪练id
* @param sceneId 场景id
* @param nodeType 节点类型 机器人;学员
* @param pId 父节点id ;开始节点id=0
* @param level 层级 开始节点level=0
*/
void deleteChatNodes(Long practiceId, Long sceneId, Integer nodeType, Long pId, Integer level);
/**
* 查询陪练下所有场景对话机器人节点/学员节点标准话术未合成的节点集合
* @param practiceId 陪练id
*/
List<SceneChatConfig> selectChatVoiceIsEmpty(Long practiceId);
}
package com.yizhi.practice.application.service;
import com.yizhi.practice.application.pojo.domain.SceneConfig;
import java.util.List;
/**
* <p>
* 场景配置 服务类
* </p>
*
* @author MybatisCodeGenerator123
* @since 2020-10-22
*/
public interface ISceneConfigService {
List<SceneConfig> findSceneByPracticeId(Long pracitceId);
/**
* 删除场景
* @param sceneId 场景id
* @param practiceId 陪练id
*/
long deleteScene(Long practiceId,Long sceneId);
/**
* 修改场景排序
* @param sceneId 场景id
* @param sort 排序序号
*/
void updateSceneSort(Long sceneId, int sort);
}
package com.yizhi.practice.application.service.impl;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.querydsl.core.QueryResults;
import com.querydsl.core.Tuple;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.impl.JPAQuery;
import com.yizhi.core.application.context.RequestContext;
import com.yizhi.practice.application.enums.PracticeChatLogStatusEnum;
import com.yizhi.practice.application.enums.PracticeLevelMapEnum;
import com.yizhi.practice.application.enums.PracticeModelStatusEnum;
import com.yizhi.practice.application.enums.PracticeUseTypeEnum;
import com.yizhi.practice.application.pojo.domain.PracticeChatLog;
import com.yizhi.practice.application.pojo.domain.QPracticeChatLog;
import com.yizhi.practice.application.pojo.domain.QPracticeConfig;
import com.yizhi.practice.application.pojo.vo.PracticeChatLogBaseInfoVo;
import com.yizhi.practice.application.pojo.vo.PracticeChatLogDetailParamVo;
import com.yizhi.practice.application.pojo.vo.PracticeChatLogListParamVo;
import com.yizhi.practice.application.pojo.vo.PracticeChatLogListVo;
import com.yizhi.practice.application.pojo.vo.StudentPracticeLogVo;
import com.yizhi.practice.application.service.BaseService;
import com.yizhi.practice.application.service.IPracticeChatLogService;
import com.yizhi.practice.application.util.NumberUtil;
import com.yizhi.system.application.feign.AuthFeignClient;
import com.yizhi.system.application.vo.practice.AccountOrgVo;
import com.yizhi.system.application.vo.practice.OrgAccountVo;
import com.yizhi.util.application.page.PageInfo;
import lombok.extern.slf4j.Slf4j;
/**
* <p>
* 场景对话结果记录 服务实现类
* </p>
*
* @author MybatisCodeGenerator123
* @since 2020-10-22
*/
@Service
@Slf4j
public class PracticeChatLogServiceImpl extends BaseService implements IPracticeChatLogService {
@Autowired
private AuthFeignClient authFeignClient;
@Override
public Map<Integer, Long> getPracticeLogByLevel(Long practiceId, Long accountId, Long companyId, Long siteId, Long orgId) {
QPracticeChatLog log = QPracticeChatLog.practiceChatLog;
Predicate pre = log.accountId.eq(accountId)
.and(log.practiceId.eq(practiceId))
.and(log.companyId.eq(companyId))
.and(log.siteId.eq(siteId))
.and(log.orgId.eq(orgId))
.and(log.status.eq(PracticeChatLogStatusEnum.DONE.getStatus()))
.and(log.useType.eq(PracticeModelStatusEnum.PRACTICE.getStatus()));
List<Tuple> list = jpaqueryFactory.select(log.level,log.count())
.from(log)
.where(pre)
.groupBy(log.level)
.fetch();
if (list.isEmpty()) {
return null;
}
Map<Integer, Long> map = new HashMap<Integer, Long>();
for (Tuple tuple : list) {
map.put(tuple.get(0, Integer.class), tuple.get(1, Long.class));
}
return map;
}
@Override
public Map<Integer, Long> getExamAndPracticeCount(Long accountId, Long practiceId, Long orgId, Long siteId, Long companyId) {
QPracticeChatLog log = QPracticeChatLog.practiceChatLog;
List<Tuple> result = jpaqueryFactory.select(log.useType, log.count())
.from(log)
.where(log.accountId.eq(accountId)
.and(log.practiceId.eq(practiceId))
.and(log.companyId.eq(companyId))
.and(log.siteId.eq(siteId))
.and(log.orgId.eq(orgId))
.and(log.status.eq(PracticeChatLogStatusEnum.DONE.getStatus())))
.groupBy(log.useType)
.fetch();
if (result.size() == 0) return null;
Map<Integer, Long> map = new HashMap<Integer, Long>();
for (Tuple tuple : result) {
map.put(tuple.get(0, Integer.class), tuple.get(1, Long.class));
}
return map;
}
@Override
public PageInfo<PracticeChatLogListVo> listPage(PracticeChatLogListParamVo param, RequestContext requestContext) {
QPracticeChatLog clog = QPracticeChatLog.practiceChatLog;
Predicate condition = createSearchCondition(clog, param, requestContext);
JPAQuery<Tuple> results = jpaqueryFactory.select(
clog.id
, clog.practiceId
, clog.accountName
, clog.accountFullName
, clog.orgName
, clog.useType
, clog.level
, clog.endAt
, clog.averageScore)
.from(clog)
.where(condition)
.orderBy(clog.endAt.desc())
.offset((param.getPageNo() - 1) * param.getPageSize())
.limit(param.getPageSize());
List<PracticeChatLogListVo> data = results.fetch().stream()
.map(tuple -> PracticeChatLogListVo.builder()
.id(tuple.get(clog.id))
.practiceId(tuple.get(clog.practiceId))
.accountName(tuple.get(clog.accountName))
.accountFullName(tuple.get(clog.accountFullName))
.orgName(tuple.get(clog.orgName))
.useType(tuple.get(clog.useType))
.level(tuple.get(clog.level))
.mode(PracticeLevelMapEnum.getDescByStatus(new StringBuffer().append(tuple.get(clog.useType)).append(getNotNullNumber(tuple.get(clog.level))).toString()))
.endAt(tuple.get(clog.endAt))
.totalScore(tuple.get(clog.averageScore))
.build())
.collect(Collectors.toList());
Long totalSize = results.fetchCount();
totalSize = totalSize == null ? 0 : totalSize;
PageInfo<PracticeChatLogListVo> page = new PageInfo<PracticeChatLogListVo>();
page.setPageTotal(NumberUtil.getPageCount(totalSize, param.getPageSize()));
page.setPageRecords(totalSize.intValue());
page.setPageNo(param.getPageNo());
page.setPageSize(param.getPageSize());
page.setRecords(data);
if (data != null) {
log.info("Practice chat log - list - size : {} of user {} ", data.size(), requestContext.getAccountId());
}
return page;
}
private Integer getNotNullNumber(Integer input) {
if (null == input) {
return 0;
} else {
return input;
}
}
private Predicate headerCondition(QPracticeChatLog log, RequestContext relation, Long practiceId, Integer mode) {
Predicate condition = log.isNull().or(log.isNotNull());
condition = ExpressionUtils.and(condition, log.practiceId.eq(practiceId));
condition = ExpressionUtils.and(condition, log.useType.eq(mode));
condition = ExpressionUtils.and(condition, log.status.eq(PracticeChatLogStatusEnum.DONE.getStatus()));
if (null != relation) {
condition = ExpressionUtils.and(condition, log.companyId.eq(relation.getCompanyId()));
condition = ExpressionUtils.and(condition, log.siteId.eq(relation.getSiteId()));
// 非超管,只能看到辖区内的用户
if (!relation.isAdmin()) {
// 获取当前登录人的辖区(当前人管理的用户和部门)
OrgAccountVo managedGroup = authFeignClient.getOrgAndUserOfAdmin(relation.getAccountId(), relation.getSiteId());
if (null != managedGroup) {
List<AccountOrgVo> managedUsers = managedGroup.getUsers();
if (null != managedUsers) {
List<Long> managedUserIds = managedUsers.stream().map(AccountOrgVo::getAccountId).collect(Collectors.toList());
if (null != managedUserIds) {
condition = managedUserIds.isEmpty() ? condition : ExpressionUtils.and(condition, log.accountId.in(managedUserIds));
}
}
List<Long> managedOrgIds = managedGroup.getOrgs();
if (null != managedOrgIds) {
condition = managedOrgIds.isEmpty() ? condition : ExpressionUtils.and(condition, log.orgId.in(managedOrgIds));
}
}
}
}
return condition;
}
/**
* 获取参与的人数
*/
@Override
public Integer peopleNumber(Long practiceId, Integer mode, RequestContext relation) {
QPracticeChatLog log = QPracticeChatLog.practiceChatLog;
return (int) jpaqueryFactory.selectDistinct(log.accountId)
.from(log)
.where(headerCondition(log, relation, practiceId, mode))
.fetchCount();
}
/**
* 获取参与的人次
*/
@Override
public Integer timesNumber(Long practiceId, Integer mode, RequestContext relation) {
QPracticeChatLog log = QPracticeChatLog.practiceChatLog;
return (int) jpaqueryFactory.selectDistinct(log.id)
.from(log)
.where(headerCondition(log, relation, practiceId, mode))
.fetchCount();
}
private Predicate createSearchCondition(QPracticeChatLog clog, PracticeChatLogListParamVo param, RequestContext requestContext) {
Predicate condition = clog.isNull().or(clog.isNotNull());
condition = ExpressionUtils.and(condition, clog.status.eq(PracticeChatLogStatusEnum.DONE.getStatus()));
if (null != param.getPracticeId()) {
condition = ExpressionUtils.and(condition, clog.practiceId.eq(param.getPracticeId()));
}
if (null != requestContext) {
condition = null == requestContext.getCompanyId() ? condition : ExpressionUtils.and(condition, clog.companyId.eq(requestContext.getCompanyId()));
condition = null == requestContext.getSiteId() ? condition : ExpressionUtils.and(condition, clog.siteId.eq(requestContext.getSiteId()));
// 判断当前登陆人是否为超级管理员
// ,若是,则可以看到当前site所有用户参加的所有陪练的记录
// ;若否,则只能看到他管理的用户参加的陪练记录,并且是当前人能看到的陪练的记录
if (!requestContext.isAdmin()) {
// 获取当前登录人的辖区(当前人管理的用户和部门)
OrgAccountVo managedGroup = authFeignClient.getOrgAndUserOfAdmin(requestContext.getAccountId(), requestContext.getSiteId());
if (null != managedGroup) {
List<AccountOrgVo> managedUsers = managedGroup.getUsers();
if (null != managedUsers) {
List<Long> managedUserIds = managedUsers.stream().map(AccountOrgVo::getAccountId).collect(Collectors.toList());
if (null != managedUserIds) {
log.info("User {}-{} has {} users.", requestContext.getAccountId(), requestContext.getAccountFullName(), managedUserIds.size());
condition = managedUserIds.isEmpty() ? condition : ExpressionUtils.and(condition, clog.accountId.in(managedUserIds));
}
}
List<Long> managedOrgIds = managedGroup.getOrgs();
if (null != managedOrgIds) {
log.info("User {}-{} has {} orgs.", requestContext.getAccountId(), requestContext.getAccountFullName(), managedOrgIds.size());
condition = managedOrgIds.isEmpty() ? condition : ExpressionUtils.and(condition, clog.orgId.in(managedOrgIds));
}
}
// 获取当前登录人可见的陪练
List<Long> manageIds = requestContext.getManagerIds();
if (null != manageIds) {
manageIds.add(requestContext.getAccountId());
condition = ExpressionUtils.and(condition, clog.practiceId.in(manageIds));
}
}
}
condition = handleModeCondition(param.getModes(), condition, clog);
condition = StringUtils.isEmpty(param.getSearch()) ? condition : ExpressionUtils.and(condition, clog.accountName.like("%" + param.getSearch() + "%")
.or(clog.accountFullName.like("%" + param.getSearch() + "%"))
.or(clog.orgName.like("%" + param.getSearch() + "%")));
return condition;
}
private Predicate handleModeCondition(Integer[] modes, Predicate condition, QPracticeChatLog log) {
if(null == modes || ArrayUtils.isEmpty(modes)) {
return condition;
}
if(ArrayUtils.contains(modes, PracticeUseTypeEnum.EXAM.getCode())) {
// use_type=20 or level in (...)
condition = ExpressionUtils.and(condition, log.useType.eq(PracticeUseTypeEnum.EXAM.getCode()).or(log.level.in(modes)));
}else {
// level in (...)
condition = ExpressionUtils.and(condition, log.level.in(modes));
}
return condition;
}
/**
* 学员端 - 构造查询条件
*
* @param log
* @param param
* @param requestContext
* @return
*/
private Predicate studentCreateSearchCondition(QPracticeChatLog log, PracticeChatLogListParamVo param, RequestContext requestContext) {
Predicate condition = log.isNull().or(log.isNotNull());
condition = ExpressionUtils.and(condition, log.status.eq(PracticeChatLogStatusEnum.DONE.getStatus()));
condition = null == param.getPracticeId() ? condition : ExpressionUtils.and(condition, log.practiceId.eq(param.getPracticeId()));
condition = ExpressionUtils.and(condition, log.companyId.eq(requestContext.getCompanyId()));
condition = ExpressionUtils.and(condition, log.siteId.eq(requestContext.getSiteId()));
condition = ExpressionUtils.and(condition, log.orgId.eq(requestContext.getOrgId()));
condition = ExpressionUtils.and(condition, log.accountId.eq(requestContext.getAccountId()));
condition = handleModeCondition(param.getModes(), condition, log);
condition = StringUtils.isEmpty(param.getSearch()) ? condition : ExpressionUtils.and(condition, log.accountName.like("%" + param.getSearch() + "%")
.or(log.accountFullName.like("%" + param.getSearch() + "%"))
.or(log.orgName.like("%" + param.getSearch() + "%")));
return condition;
}
@Override
public List<PracticeChatLogListVo> listAll(PracticeChatLogListParamVo param, RequestContext requestContext) {
QPracticeChatLog log = QPracticeChatLog.practiceChatLog;
Predicate condition = createSearchCondition(log, param, requestContext);
return jpaqueryFactory.select(
log.id
, log.practiceId
, log.accountName
, log.accountFullName
, log.orgName
, log.useType
, log.level
, log.endAt
, log.averageScore)
.from(log)
.where(condition)
.orderBy(log.endAt.desc())
.fetch()
.stream()
.map(tuple -> PracticeChatLogListVo.builder()
.id(tuple.get(log.id))
.practiceId(tuple.get(log.practiceId))
.accountName(tuple.get(log.accountName))
.accountFullName(tuple.get(log.accountFullName))
.orgName(tuple.get(log.orgName))
.useType(tuple.get(log.useType))
.level(tuple.get(log.level))
.mode(PracticeLevelMapEnum.getDescByStatus(new StringBuffer().append(tuple.get(log.useType)).append(getNotNullNumber(tuple.get(log.level))).toString()))
.endAt(tuple.get(log.endAt))
.totalScore(tuple.get(log.averageScore))
.build())
.collect(Collectors.toList());
}
@Override
public PracticeChatLogBaseInfoVo get(Long practiceLogId) {
QPracticeChatLog log = QPracticeChatLog.practiceChatLog;
QPracticeConfig config = QPracticeConfig.practiceConfig;
Tuple tuple = jpaqueryFactory.select(log.id
, log.practiceId
, log.accountName
, log.accountFullName
, log.useType
, log.level
, log.endAt
, log.averageScore
, log.keywordScore
, log.keywordRate
, log.completeScore
, log.completeRate
, log.smoothScore
, log.smoothRate
, log.expressScore
, log.expressRate
, log.politeScore
, log.politeRate
, config.robotName)
.from(log)
.leftJoin(config)
.on(log.practiceId.eq(config.id))
.where(log.id.eq(practiceLogId))
.fetchOne();
if (null == tuple) {
return PracticeChatLogBaseInfoVo.builder().build();
}
return PracticeChatLogBaseInfoVo.builder()
.id(tuple.get(log.id))
.practiceId(tuple.get(log.practiceId))
.accountName(tuple.get(log.accountName))
.accountFullName(tuple.get(log.accountFullName))
.mode(PracticeLevelMapEnum.getDescByStatus(new StringBuffer().append(tuple.get(log.useType)).append(getNotNullNumber(tuple.get(log.level))).toString()))
.endAt(tuple.get(log.endAt))
.totalScore(tuple.get(log.averageScore))
.keywordScore(tuple.get(log.keywordScore))
.keywordRate(tuple.get(log.keywordRate))
.completeScore(tuple.get(log.completeScore))
.completeRate(tuple.get(log.completeRate))
.smoothScore(tuple.get(log.smoothScore))
.smoothRate(tuple.get(log.smoothRate))
.expressScore(tuple.get(log.expressScore))
.expressRate(tuple.get(log.expressRate))
.politeScore(tuple.get(log.politeScore))
.politeRate(tuple.get(log.politeRate))
.robotName(tuple.get(config.robotName))
.build();
}
@Override
public Long getExamCountByPractice(Long accountId, Long practiceId) {
QPracticeChatLog log = QPracticeChatLog.practiceChatLog;
Predicate predicate = log.practiceId.eq(practiceId)
.and(log.accountId.eq(accountId))
.and(log.useType.eq(PracticeModelStatusEnum.ASSESSMENT.getStatus()))
.and(log.status.eq(10));
Long count = jpaqueryFactory.select(log.count())
.from(log)
.where(predicate)
.fetchCount();
return count;
}
public Long previous(PracticeChatLogDetailParamVo detailParam, RequestContext relation) {
QPracticeChatLog log = QPracticeChatLog.practiceChatLog;
PracticeChatLogListParamVo param = PracticeChatLogListParamVo.builder()
.practiceId(detailParam.getPracticeId())
.modes(detailParam.getModes()).search(detailParam.getSearch()).build();
// 基本条件: 列表搜索的条件
Predicate condition = createSearchCondition(log, param, relation);
// 最终目标: 获取完成日期>=当前记录的完成日期 的 最小完成日期 的ID (因为列表页是按完成日期倒序排列)
// 额外条件: 完成日期 >= 当前记录的完成日期
condition = ExpressionUtils.and(condition, log.endAt.goe(
jpaqueryFactory.select(log.endAt).from(log).where(log.id.eq(detailParam.getPracticeLogId()))));
// 额外条件: ID不等于当前记录ID
condition = ExpressionUtils.and(condition, log.id.ne(detailParam.getPracticeLogId()));
return jpaqueryFactory.select(
log.id)
.from(log)
.where(condition)
// 按照 完成日期 正序排列
.orderBy(log.endAt.asc())
// 获取完成日期最小的
.fetchFirst();
}
@Override
public Long next(PracticeChatLogDetailParamVo detailParam, RequestContext relation) {
QPracticeChatLog log = QPracticeChatLog.practiceChatLog;
PracticeChatLogListParamVo param = PracticeChatLogListParamVo.builder()
.practiceId(detailParam.getPracticeId())
.modes(detailParam.getModes()).search(detailParam.getSearch()).build();
// 基本条件: 列表搜索的条件
Predicate condition = createSearchCondition(log, param, relation);
// 最终目标: 获取完成日期<=当前记录的完成日期 的 最大完成日期 的ID (因为列表页是按完成日期倒序排列)
// 额外条件: 完成日期 <= 当前记录的完成日期
condition = ExpressionUtils.and(condition, log.endAt.loe(
jpaqueryFactory.select(log.endAt).from(log).where(log.id.eq(detailParam.getPracticeLogId()))));
// 额外条件: ID不等于当前记录ID
condition = ExpressionUtils.and(condition, log.id.ne(detailParam.getPracticeLogId()));
return jpaqueryFactory.select(
log.id)
.from(log)
.where(condition)
// 按照 完成日期 倒序排列
.orderBy(log.endAt.desc())
// 获取完成日期最大的
.fetchFirst();
}
@Override
public List<PracticeChatLog> getListByTime(Date startDate, Date endDate) {
QPracticeChatLog chatLog = QPracticeChatLog.practiceChatLog;
BooleanExpression expression = chatLog.updatedAt.between(startDate, endDate).and(chatLog.status.eq(PracticeChatLogStatusEnum.DONE.getStatus()));
List<PracticeChatLog> fetch = jpaqueryFactory.select(
chatLog)
.from(chatLog)
.where(expression)
.fetch();
return fetch;
}
@Override
public PageInfo<StudentPracticeLogVo> studentListPage(PracticeChatLogListParamVo param, RequestContext relation) {
QPracticeChatLog log = QPracticeChatLog.practiceChatLog;
Predicate condition = studentCreateSearchCondition(log, param, relation);
QueryResults<Tuple> results = jpaqueryFactory.select(
log.id
, log.practiceId
, log.useType
, log.level
, log.endAt
, log.averageScore)
.from(log)
.where(condition)
.orderBy(log.endAt.desc())
.offset((param.getPageNo() - 1) * param.getPageSize())
.limit(param.getPageSize())
.fetchResults();
List<StudentPracticeLogVo> data = results.getResults().stream()
.map(tuple -> StudentPracticeLogVo.builder()
.id(tuple.get(log.id))
.practiceId(tuple.get(log.practiceId))
.useType(tuple.get(log.useType))
.level(tuple.get(log.level))
.mode(PracticeLevelMapEnum.getDescByStatus(new StringBuffer().append(tuple.get(log.useType)).append(getNotNullNumber(tuple.get(log.level))).toString()))
.endAt(tuple.get(log.endAt))
.totalScore(tuple.get(log.averageScore))
.build())
.collect(Collectors.toList());
Long totalSize = results.getTotal();
totalSize = totalSize == null ? 0 : totalSize;
PageInfo<StudentPracticeLogVo> page = new PageInfo<StudentPracticeLogVo>();
page.setPageTotal(NumberUtil.getPageCount(totalSize, param.getPageSize()));
page.setPageRecords(totalSize.intValue());
page.setPageNo(param.getPageNo());
page.setPageSize(param.getPageSize());
page.setRecords(data);
return page;
}
}
package com.yizhi.practice.application.service.impl;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.stereotype.Service;
import com.querydsl.core.Tuple;
import com.querydsl.core.types.Predicate;
import com.yizhi.practice.application.enums.PracticeSkipEnum;
import com.yizhi.practice.application.pojo.domain.QPracticeChatRoundLog;
import com.yizhi.practice.application.pojo.domain.QSceneChatConfig;
import com.yizhi.practice.application.pojo.domain.QSceneConfig;
import com.yizhi.practice.application.pojo.dto.PracticeAllScoreDto;
import com.yizhi.practice.application.pojo.dto.PracticeChartRoundLogDto;
import com.yizhi.practice.application.pojo.vo.PracticeChatRoundLogVo;
import com.yizhi.practice.application.service.BaseService;
import com.yizhi.practice.application.service.IPracticeChatRoundLogService;
import com.yizhi.practice.application.util.LocalStringUtil;
import kotlin.Pair;
/**
* <p>
* 场景中每轮对话记录 服务实现类
* </p>
*
* @author MybatisCodeGenerator123
* @since 2020-10-22
*/
@Service
public class PracticeChatRoundLogServiceImpl extends BaseService implements IPracticeChatRoundLogService {
@Override
public PracticeAllScoreDto getAccountChatLog(Long practiceChatId, Long accountId, Long orgId, Long siteId, Long companyId) {
QPracticeChatRoundLog roundLog = QPracticeChatRoundLog.practiceChatRoundLog;
Predicate pre = roundLog.practiceChatId.eq(practiceChatId)
.and(roundLog.accountId.eq(accountId))
.and(roundLog.companyId.eq(companyId))
.and(roundLog.siteId.eq(siteId))
.and(roundLog.orgId.eq(orgId))
.and(roundLog.deleted.eq(false))
.and(roundLog.roundSkipType.eq(PracticeSkipEnum.NOT_SKIP.getCode()));
Tuple result = jpaqueryFactory
.select(roundLog.keywordScore.avg(),
roundLog.completeScore.avg(),
roundLog.smoothScore.avg(),
roundLog.politeScore.avg(),
roundLog.expressScore.avg())
.from(roundLog)
.where(pre)
.fetchOne();
PracticeAllScoreDto dto = new PracticeAllScoreDto();
Double expressScore = result.get(roundLog.expressScore.avg());
Double completeScore = result.get(roundLog.completeScore.avg());
Double smoothScore = result.get(roundLog.smoothScore.avg());
Double politeScore = result.get(roundLog.politeScore.avg());
Double keywordScore = result.get(roundLog.keywordScore.avg());
if (null != expressScore) {
dto.setExpressScore(expressScore.intValue());
}
if (null != completeScore ) {
dto.setComplateScore(completeScore.intValue());
}
if (null != smoothScore ) {
dto.setFluencyScore(smoothScore.intValue());
}
if (null != politeScore ) {
dto.setPoliteScore(politeScore.intValue());
}
if (null != keywordScore ) {
dto.setKeyWordScore(new Pair(keywordScore.intValue(),null));
}
return dto;
}
@Override
public Long getLevelCountByAccount(Integer level, Long practiceLogId, Long practiceId, Long accountId, Long orgId, Long siteId, Long companyId) {
QPracticeChatRoundLog roundLog = QPracticeChatRoundLog.practiceChatRoundLog;
Predicate pre = roundLog.roundLevel.eq(level)
.and(roundLog.practiceId.eq(practiceId))
.and(roundLog.practiceChatId.eq(practiceLogId))
.and(roundLog.accountId.eq(accountId))
.and(roundLog.companyId.eq(companyId))
.and(roundLog.siteId.eq(siteId))
.and(roundLog.deleted.eq(false))
.and(roundLog.orgId.eq(orgId));
Long count = jpaqueryFactory.select(roundLog.count())
.from(roundLog)
.where(pre)
.fetchCount();
return count;
}
@Override
public Long getCountByUserId(Long practiceLogId, Long chatId, Long accountId, Long orgId, Long siteId, Long companyId) {
QPracticeChatRoundLog roundLog = QPracticeChatRoundLog.practiceChatRoundLog;
Predicate pre = roundLog.sceneChatId.eq(chatId)
.and(roundLog.practiceChatId.eq(practiceLogId))
.and(roundLog.accountId.eq(accountId))
.and(roundLog.companyId.eq(companyId))
.and(roundLog.siteId.eq(siteId))
.and(roundLog.deleted.eq(false))
.and(roundLog.orgId.eq(orgId));
return jpaqueryFactory.select(roundLog.count())
.from(roundLog)
.where(pre)
.fetchCount();
}
@Override
public List<PracticeChatRoundLogVo> getByPracticeChatId(Long practiceChatId) {
QPracticeChatRoundLog roundLog = QPracticeChatRoundLog.practiceChatRoundLog;
QSceneConfig scene = QSceneConfig.sceneConfig;
QSceneChatConfig sceneChat = QSceneChatConfig.sceneChatConfig;
return jpaqueryFactory.select(
roundLog.id
, roundLog.practiceChatId
, roundLog.sceneId
, scene.name
, scene.sort
, roundLog.robotContent
, roundLog.robotContentVoiceUrl
, roundLog.robotContentVoiceDuration
, roundLog.accountContent
, roundLog.accountHitKeyword
, roundLog.accountContentVoiceUrl
, roundLog.accountContentVoiceDuration
, roundLog.roundLevel
, roundLog.roundSkipType
, roundLog.averageScore
, sceneChat.sceneNodeType
, roundLog.createdAt
, roundLog.accountHitTabooWord)
.from(roundLog)
.leftJoin(scene)
.on(roundLog.sceneId.eq(scene.id))
.leftJoin(sceneChat)
.on(roundLog.sceneChatId.eq(sceneChat.id))
.where(roundLog.practiceChatId.eq(practiceChatId).and(roundLog.deleted.eq(false)))
.orderBy(scene.sort.asc(), roundLog.roundLevel.asc())
.fetch()
.stream()
.map(tuple -> PracticeChatRoundLogVo.builder()
.id(tuple.get(roundLog.id))
.practiceChatId(tuple.get(roundLog.practiceChatId))
.sceneId(tuple.get(roundLog.sceneId))
.sceneName(tuple.get(scene.name))
.sort(tuple.get(scene.sort))
.robotContent(tuple.get(roundLog.robotContent))
.robotContentUrl(tuple.get(roundLog.robotContentVoiceUrl))
.robotDuration(tuple.get(roundLog.robotContentVoiceDuration))
.accountContent(tuple.get(roundLog.accountContent))
.accountHitKeyWord(LocalStringUtil.hit(tuple.get(roundLog.accountHitKeyword)))
.accountContentVoiceUrl(tuple.get(roundLog.accountContentVoiceUrl))
.accountDuration(tuple.get(roundLog.accountContentVoiceDuration))
.roundLevel(tuple.get(roundLog.roundLevel))
.roundSkipType(tuple.get(roundLog.roundSkipType))
.isSkip(PracticeSkipEnum.NOT_SKIP.getCode().equals(tuple.get(roundLog.roundSkipType)) ? false : true)
.averageScore(tuple.get(roundLog.averageScore))
.sceneNodeType(tuple.get(sceneChat.sceneNodeType))
.createdAt(tuple.get(roundLog.createdAt))
.hitForbidWord(LocalStringUtil.hit(tuple.get(roundLog.accountHitTabooWord)))
.build())
.collect(Collectors.toList());
}
@Override
public PracticeChartRoundLogDto getRoundLogById(Long roundLogId) {
QPracticeChatRoundLog roundLog = QPracticeChatRoundLog.practiceChatRoundLog;
QSceneChatConfig sceneChat = QSceneChatConfig.sceneChatConfig;
Tuple result = jpaqueryFactory.select(
roundLog.averageScore
, roundLog.accountHitKeyword
, roundLog.keywordScore
, roundLog.completeScore
, roundLog.smoothScore
, roundLog.expressScore
, roundLog.politeScore
, roundLog.accountContent
, roundLog.accountContentVoiceUrl
, roundLog.accountContentVoiceDuration
, sceneChat.accountContentKeyword
, roundLog.robotContent
, roundLog.robotContentVoiceUrl
, roundLog.robotContentVoiceDuration
, roundLog.accountHitTabooWord)
.from(roundLog)
.leftJoin(sceneChat)
.on(roundLog.sceneChatId.eq(sceneChat.id))
.where(roundLog.id.eq(roundLogId).and(roundLog.deleted.eq(false)))
.fetchOne();
return PracticeChartRoundLogDto.builder()
.totalScore(result.get(roundLog.averageScore))
.keywordScore(result.get(roundLog.keywordScore))
.completeScore(result.get(roundLog.completeScore))
.smoothScore(result.get(roundLog.smoothScore))
.expressScore(result.get(roundLog.expressScore))
.politeScore(result.get(roundLog.politeScore))
.accountContent(result.get(roundLog.accountContent))
.accountContentVoiceUrl(result.get(roundLog.accountContentVoiceUrl))
.accountDuration(result.get(roundLog.accountContentVoiceDuration))
.keyWord(result.get(sceneChat.accountContentKeyword))
.accountHitKeyword(result.get(roundLog.accountHitKeyword))
.robotContent(result.get(roundLog.robotContent))
.robotContentUrl(result.get(roundLog.robotContentVoiceUrl))
.robotDuration(result.get(roundLog.robotContentVoiceDuration))
.forbidHit(result.get(roundLog.accountHitTabooWord))
.build();
}
}
package com.yizhi.practice.application.service.impl
import com.querydsl.core.types.dsl.BooleanExpression
import com.yizhi.practice.application.config.PracticeRunningStatusEnum
import com.yizhi.practice.application.enums.PracticeStatusEnum
import com.yizhi.practice.application.enums.PracticeVisibleTypeEnum
import com.yizhi.practice.application.pojo.domain.PracticeConfig
import com.yizhi.practice.application.pojo.domain.QPracticeConfig
import com.yizhi.practice.application.pojo.vo.PracticeBaseInfoVo
import com.yizhi.practice.application.pojo.vo.PracticeConfigVo
import com.yizhi.practice.application.request.PracticesGetReq
import com.yizhi.practice.application.service.BaseService
import com.yizhi.practice.application.service.IPracticeConfigService
import org.springframework.stereotype.Service
import java.util.*
import kotlin.collections.ArrayList
/**
*
*
* 陪练配置 服务实现类
*
*
* @author MybatisCodeGenerator123
* @since 2020-10-22
*/
@Service
class PracticeConfigServiceImpl : IPracticeConfigService, BaseService() {
override fun getSiteAllConfig(siteId: Long, companyId: Long): List<Long> {
val config = QPracticeConfig.practiceConfig
val predicate = config.companyId.eq(companyId)
.and(config.siteId.eq(siteId))
.and(config.visibleType.eq(PracticeVisibleTypeEnum.ALL.status))
return jpaqueryFactory.select(config.id)
.from(config)
.where(predicate)
.fetch()
}
override fun getConfigByIds(ids: List<Long>): List<PracticeConfigVo> {
val config = QPracticeConfig.practiceConfig
val predicate = config.id.`in`(ids)
val result = jpaqueryFactory.select(
config.name,
config.practiceStartAt,
config.practiceEndAt,
config.examStartAt,
config.examEndAt,
config.id,
config.skipType,
config.repeatPush)
.from(config)
.where(predicate)
.orderBy(config.createdAt.desc())
.fetch()
val vos = ArrayList<PracticeConfigVo>()
result.forEach {
val vo = PracticeConfigVo()
vo.name = it.get(config.name)
vo.practiceStartAt = it.get(config.practiceStartAt)
vo.practiceEndAt = it.get(config.practiceEndAt)
vo.examStartAt = it.get(config.examStartAt)
vo.examEndAt = it.get(config.examEndAt)
vo.practiceId = it.get(config.id)
vo.practiceSkipType = it.get(config.skipType)
vo.examRepeatPush = it.get(config.repeatPush)
vos.add(vo)
}
return vos
}
override fun getRunningCount(orgId: Long, siteId: Long, companyId: Long, date: Date?, state: PracticeRunningStatusEnum): List<Long>? {
val time = date ?: Date()
val config = QPracticeConfig.practiceConfig
var pre = config.id.isNotNull
// 进行中的陪练
if (state.status == PracticeRunningStatusEnum.RUNNING.status) {
pre = pre.and((config.practiceStartAt.isNotNull.and(config.practiceStartAt.lt(time)).and(
config.practiceEndAt.isNotNull.and(config.practiceEndAt.goe(time))))
.or(
config.examStartAt.isNotNull.and(config.examStartAt.lt(time)).and(
config.examEndAt.isNotNull.and(config.examEndAt.goe(time)))
))
}
// 已结束的陪练
if (state.status == PracticeRunningStatusEnum.ENDED.status) {
pre = pre.and((config.practiceEndAt.isNotNull.and(config.practiceEndAt.lt(time)).and(
config.examEndAt.isNotNull.and(config.examEndAt.lt(time))
)).or(
config.practiceEndAt.isNull.and(config.examEndAt.isNotNull.and(config.examEndAt.lt(time)))
).or(
config.examEndAt.isNull.and(config.practiceEndAt.isNotNull.and(config.practiceEndAt.lt(time)))
))
}
// 未开始
if (state.status == PracticeRunningStatusEnum.NOT_STARTED.status) {
pre = pre.and(((config.practiceStartAt.isNotNull.and(config.practiceStartAt.goe(time)).and(
config.examStartAt.isNotNull.and(config.examStartAt.goe(time))
))).or(
config.practiceStartAt.isNull.and(config.examStartAt.isNotNull.and(config.examStartAt.goe(time)))
).or(
config.examStartAt.isNull.and(config.practiceStartAt.isNotNull.and(config.practiceStartAt.goe(time)))
))
}
val predicate = config.companyId.eq(companyId)
.and(config.siteId.eq(siteId))
.and(pre)
.and(config.status.eq(PracticeStatusEnum.UP.status))
.and(config.deleted.isFalse)
return jpaqueryFactory
.selectDistinct(config.id)
.from(config)
.where(predicate)
.orderBy(config.createdAt.desc())
.fetch()
}
override fun getListByTime(startDate: Date, endDate: Date): List<PracticeConfig> {
val config = QPracticeConfig.practiceConfig
val expression = config.updatedAt.between(startDate,endDate).and(config.status.ne(PracticeStatusEnum.DRAFT.status))
return jpaqueryFactory.select(
config)
.from(config)
.where(expression)
.fetch()
}
fun getPracticeConfigExpresion(params: PracticesGetReq): BooleanExpression {
val nameOrKeyword = params.name
val practiceStatus = params.status
val models = params.models
val companyId = params.companyId
val siteId = params.siteId
val config = QPracticeConfig.practiceConfig
var expression = config.deleted.eq(false).and(config.companyId.eq(companyId)).and(config.siteId.eq(siteId))
if (null != params.ids && params.ids.isNotEmpty()){
expression = expression.and(config.createdUid.`in`(params.ids))
}
if (null != nameOrKeyword && nameOrKeyword.isNotBlank()){
expression = expression.and(config.name.like("%${params.name}%").or(config.keyWord.like("%${params.name}%")))
}
if (null != practiceStatus && practiceStatus > 0) {
expression = expression.and(config.status.eq(practiceStatus))
}
if (null != models && models.isNotEmpty()) {
expression = expression.and(config.useType.`in`(models))
}
return expression
}
override fun getPracticeConfigList(params: PracticesGetReq): List<PracticeBaseInfoVo> {
val config = QPracticeConfig.practiceConfig
val pageNo = params.pageNo
val pageSize = params.pageSize
val offset = (pageNo-1) * pageSize
val expression = getPracticeConfigExpresion(params)
val fetch = jpaqueryFactory.select(
config.id,
config.name,
config.useType,
config.practiceStartAt,
config.practiceEndAt,
config.examStartAt,
config.examEndAt,
config.status,
config.visibleType,
config.logoUrl)
.from(config)
.where(expression)
.orderBy(config.createdAt.desc())
.offset(offset.toLong())
.limit(params.pageSize.toLong())
.fetch()
var vos = ArrayList<PracticeBaseInfoVo>()
fetch.forEach {
val vo = PracticeBaseInfoVo()
vo.id = it.get(config.id)
vo.name = it.get(config.name)
vo.useType = it.get(config.useType)
vo.practiceStartAt = it.get(config.practiceStartAt)
vo.practiceEndAt = it.get(config.practiceEndAt)
vo.examStartAt = it.get(config.examStartAt)
vo.examEndAt = it.get(config.examEndAt)
vo.status = it.get(config.status)
vo.visibleType = it.get(config.visibleType)
vo.logoUrl = it.get(config.logoUrl)
vos.add(vo)
}
return vos
}
override fun getPracticeConfigCount(params: PracticesGetReq): Long {
val config = QPracticeConfig.practiceConfig
val expression = getPracticeConfigExpresion(params)
return jpaqueryFactory.select(
config.id,
config.name,
config.useType,
config.practiceStartAt,
config.practiceEndAt,
config.examStartAt,
config.examEndAt,
config.status)
.from(config)
.where(expression)
.orderBy(config.createdAt.desc())
.fetchCount()
}
override fun delete(practiceId: Long) {
val config = QPracticeConfig.practiceConfig
val expression = config.id.eq(practiceId)
jpaqueryFactory.update(config).set(config.deleted,true).where(expression).execute();
}
}
\ No newline at end of file
package com.yizhi.practice.application.service.impl
import com.yizhi.practice.application.pojo.domain.QPracticePointGivenLog
import com.yizhi.practice.application.service.BaseService
import com.yizhi.practice.application.service.IPracticePointGivenLogService
import org.springframework.stereotype.Service
import java.util.function.Predicate
import kotlin.math.hypot
/**
*
*
* 陪练积分发放记录 服务实现类
*
*
* @author MybatisCodeGenerator123
* @since 2020-10-22
*/
@Service
class PracticePointGivenLogServiceImpl : BaseService(), IPracticePointGivenLogService {
override fun sumPointByUserAndPractice(accountId: Long, practiceId: Long, companyId: Long, siteId: Long, orgId: Long):Int {
val log = QPracticePointGivenLog.practicePointGivenLog
val pre = log.accountId.eq(accountId)
.and(log.practiceId.eq(practiceId))
.and(log.companyId.eq(companyId))
.and(log.siteId.eq(siteId))
.and(log.orgId.eq(orgId))
return jpaqueryFactory.select(log.point.sum()).from(log).where(pre).fetchOne() ?: 0
}
}
\ No newline at end of file
package com.yizhi.practice.application.service.impl;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.yizhi.practice.application.pojo.domain.PracticePointRuleConfig;
import com.yizhi.practice.application.pojo.domain.QPracticePointRuleConfig;
import com.yizhi.practice.application.repository.PracticePointRuleConfigRepository;
import com.yizhi.practice.application.service.BaseService;
import com.yizhi.practice.application.service.IPracticePointRuleConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* <p>
* 陪练积分发放规则 服务实现类
* </p>
*
* @author MybatisCodeGenerator123
* @since 2020-10-22
*/
@Service
public class PracticePointRuleConfigServiceImpl extends BaseService implements IPracticePointRuleConfigService{
@Autowired
PracticePointRuleConfigRepository pointRuleConfigRepository;
@Override
public List<PracticePointRuleConfig> selectPointRulesByPractice(Long practiceId, boolean isDeleted) {
QPracticePointRuleConfig query = QPracticePointRuleConfig.practicePointRuleConfig;
BooleanExpression expression = query.practiceId.eq(practiceId).and(query.deleted.eq(isDeleted));
List<PracticePointRuleConfig> list = jpaqueryFactory.select(query).from(query).where(expression).orderBy(query.point.desc()).fetch();
return list;
}
@Override
public PracticePointRuleConfig selectPointRulesByPractice(Long practiceId, Integer userScore, boolean isDeleted) {
QPracticePointRuleConfig query = QPracticePointRuleConfig.practicePointRuleConfig;
BooleanExpression expression = query.practiceId.eq(practiceId)
.and(query.deleted.eq(isDeleted))
.and(query.minScore.lt(userScore))
.and(query.maxScore.goe(userScore));
PracticePointRuleConfig config = jpaqueryFactory.select(query).from(query).where(expression).orderBy(query.point.desc()).limit(1).fetchOne();
return config;
}
}
package com.yizhi.practice.application.service.impl
import com.yizhi.practice.application.pojo.domain.PracticeVisible
import com.yizhi.practice.application.pojo.domain.QPracticeVisible
import com.yizhi.practice.application.repository.PracticeVisibleRepository
import com.yizhi.practice.application.service.BaseService
import com.yizhi.practice.application.service.IPracticeVisibleService
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import java.util.*
/**
*
*
* 服务实现类
*
*
* @author MybatisCodeGenerator123
* @since 2020-10-22
*/
@Service
class PracticeVisibleServiceImpl : BaseService(), IPracticeVisibleService {
@Autowired
lateinit var practiceVisibleRepository: PracticeVisibleRepository
override fun getIdsByAccountId(accountId: Long, parendOrgIdAndOrgId: List<Long>, siteId: Long, companyId: Long): MutableList<Long> {
return practiceVisibleRepository.getIdsByAccountId(accountId,parendOrgIdAndOrgId,siteId,companyId)
}
override fun deleteByPracticeId(practiceId: Long) {
val practiceVisible = QPracticeVisible.practiceVisible
val expression = practiceVisible.practiceId.eq(practiceId).and(practiceVisible.deleted.eq(false))
jpaqueryFactory.update(practiceVisible).set(practiceVisible.deleted, true).where(expression).execute()
}
override fun getListByPracticeId(practiceId: Long): List<PracticeVisible> {
val practiceVisible = QPracticeVisible.practiceVisible
val expression = practiceVisible.practiceId.eq(practiceId).and(practiceVisible.deleted.eq(false))
return jpaqueryFactory.select(practiceVisible).from(practiceVisible).where(expression).fetch()
}
override fun getListByTime(startDate: Date, endDate: Date): List<PracticeVisible> {
val practiceVisible = QPracticeVisible.practiceVisible
val expression = practiceVisible.updatedAt.between(startDate,endDate)
return jpaqueryFactory.select(
practiceVisible)
.from(practiceVisible)
.where(expression)
.fetch()
}
}
\ No newline at end of file
package com.yizhi.practice.application.service.impl;
import com.yizhi.practice.application.service.BaseService;
import com.yizhi.practice.application.service.IRobotConfigService;
import org.springframework.stereotype.Service;
/**
* <p>
* 机器人配置 服务实现类
* </p>
*
* @author MybatisCodeGenerator123
* @since 2020-10-22
*/
@Service
public class RobotConfigServiceImpl extends BaseService implements IRobotConfigService{
}
package com.yizhi.practice.application.service.impl;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.yizhi.practice.application.enums.PracticeNodeEnum;
import com.yizhi.practice.application.pojo.domain.QSceneChatConfig;
import com.yizhi.practice.application.pojo.domain.SceneChatConfig;
import com.yizhi.practice.application.repository.SceneChatConfigRepository;
import com.yizhi.practice.application.service.BaseService;
import com.yizhi.practice.application.service.ISceneChatConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* <p>
* 场景对话配置 服务实现类
* </p>
*
* @author MybatisCodeGenerator123
* @since 2020-10-22
*/
@Service
public class SceneChatConfigServiceImpl extends BaseService implements ISceneChatConfigService{
@Autowired
SceneChatConfigRepository chatConfigRepository;
@Override
public List<SceneChatConfig> selectChatNodes(Long practiceId, Long sceneId, Integer nodeType, Long pId, Integer level) {
QSceneChatConfig query = QSceneChatConfig.sceneChatConfig;
BooleanExpression expresson = query.practiceId.eq(practiceId).and(query.deleted.eq(false));
if (null != sceneId){
expresson = expresson.and(query.sceneId.eq(sceneId));
}
if (null != nodeType){
expresson = expresson.and(query.sceneNodeType.eq(nodeType));
}
if (null != level){
expresson = expresson.and(query.level.eq(level));
}
if (null != pId){
expresson = expresson.and(query.pid.eq(pId));
}
List<SceneChatConfig> sceneChatConfigs = jpaqueryFactory.select(query).from(query).where(expresson).fetch();
return sceneChatConfigs;
}
@Override
public void deleteChatNodes(Long practiceId, Long sceneId, Integer nodeType, Long pId, Integer level) {
QSceneChatConfig query = QSceneChatConfig.sceneChatConfig;
BooleanExpression expresson = query.practiceId.eq(practiceId).and(query.deleted.eq(false)).and(query.sceneId.eq(sceneId));
if (null != nodeType){
expresson = expresson.and(query.sceneNodeType.eq(nodeType));
}
if (null != level){
expresson = expresson.and(query.level.eq(level));
}
if (null != pId){
expresson = expresson.and(query.pid.eq(pId));
}
jpaqueryFactory.update(query).set(query.deleted,true).where(expresson).execute();
}
@Override
public List<SceneChatConfig> selectChatVoiceIsEmpty(Long practiceId) {
QSceneChatConfig query = QSceneChatConfig.sceneChatConfig;
BooleanExpression expresson = query.practiceId.eq(practiceId)
.and(query.deleted.eq(false))
.and(
(query.sceneNodeType.eq(PracticeNodeEnum.STUDENT.getStatus()).and(query.accountContentVoiceUrl.isNull().or(query.accountContentVoiceUrl.isEmpty())))
.or(query.sceneNodeType.eq(PracticeNodeEnum.ROBOT.getStatus()).and(query.robotContentVoiceUrl.isNull().or(query.robotContentVoiceUrl.isEmpty())))
);
return jpaqueryFactory.select(query).from(query).where(expresson).fetch();
}
}
package com.yizhi.practice.application.service.impl;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.yizhi.core.application.context.ContextHolder;
import com.yizhi.core.application.context.RequestContext;
import com.yizhi.practice.application.pojo.domain.QSceneConfig;
import com.yizhi.practice.application.pojo.domain.SceneConfig;
import com.yizhi.practice.application.service.BaseService;
import com.yizhi.practice.application.service.ISceneConfigService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* <p>
* 场景配置 服务实现类
* </p>
*
* @author MybatisCodeGenerator123
* @since 2020-10-22
*/
@Service
public class SceneConfigServiceImpl extends BaseService implements ISceneConfigService{
private Logger logger = LoggerFactory.getLogger(SceneConfigServiceImpl.class);
@Override
public List<SceneConfig> findSceneByPracticeId(Long pracitceId) {
QSceneConfig config = QSceneConfig.sceneConfig;
Predicate pre = config.practiceId.eq(pracitceId).and(config.deleted.isFalse());
return jpaqueryFactory
.select(config)
.from(config)
.where(pre)
.orderBy(config.sort.asc())
.fetch();
}
@Override
public long deleteScene(Long practiceId,Long sceneId) {
RequestContext context = ContextHolder.get();
QSceneConfig config = QSceneConfig.sceneConfig;
if (null == practiceId && null == sceneId){
logger.error("[SceneConfigServiceImpl:deleteScene]删除场景传入参数全部为空!accountId = {}",context.getAccountId());
return -1;
}
BooleanExpression expression = config.deleted.eq(false);
if (null != practiceId){
expression = expression.and(config.practiceId.eq(practiceId));
}
if (null != sceneId){
expression = expression.and(config.id.eq(sceneId));
}
return jpaqueryFactory.update(config).set(config.deleted, true).where(expression).execute();
}
@Override
public void updateSceneSort(Long sceneId, int sort) {
QSceneConfig config = QSceneConfig.sceneConfig;
BooleanExpression expression = config.id.eq(sceneId).and(config.deleted.eq(false));
jpaqueryFactory.update(config).set(config.sort,sort).where(expression).execute();
}
}
package com.yizhi.practice.application.third.aliyun;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
/**
*
* @author xiaoyu
*
*/
@Configuration
public class AliyunConfig {
@Value("${third.aliyun.endpoint}")
private String endpoint;
@Value("${third.aliyun.accessKeyId}")
private String accessKeyId;
@Value("${third.aliyun.accessKeySecret}")
private String accessKeySecret;
@Value("${third.aliyun.bucketName}")
private String bucketName;
@Bean
public OSS ossClient() {
return new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
}
@Bean
public AliyunUtil aliyunUtil() {
return new AliyunUtil(bucketName, ossClient(), endpoint);
}
}
package com.yizhi.practice.application.third.aliyun;
import java.io.InputStream;
import com.aliyun.oss.OSS;
import com.aliyun.oss.model.OSSObject;
/**
*
* @author xiaoyu
*
*/
public class AliyunUtil {
private String bucketName;
private OSS ossClient;
private String endPoint;
public AliyunUtil() {
super();
}
public AliyunUtil(String bucketName, OSS ossClient, String endPoint) {
super();
this.bucketName = bucketName;
this.ossClient = ossClient;
this.endPoint = endPoint;
}
/**
* OSS文件上传
* @param path 文件名
* @param fileInputStream 文件流
* @return
*/
public String uploadByStream(String path, InputStream fileInputStream) {
this.ossClient.putObject(bucketName, path, fileInputStream);
return concatPath(path);
}
private String concatPath(String filePath){
return new StringBuffer().append("https://").append(this.bucketName).append(".")
.append(this.endPoint.replace("https://", "")).append("/").append(filePath).toString();
}
/**
* OSS文件下载,这里返回oss object,从中可以获取流,使用之后必须关闭oss object
* @param fileName
* @return
*/
public OSSObject download(String fileName) {
return this.ossClient.getObject(this.bucketName, fileName);
}
}
package com.yizhi.practice.application.third.baidu;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.baidu.aip.nlp.AipNlp;
/**
*
* @author xiaoyu
*
*/
@Configuration
public class BaiduConfig {
@Value("${third.baidu.appId}")
private String appId;
@Value("${third.baidu.apiKey}")
private String apiKey;
@Value("${third.baidu.secretKey}")
private String secretKey;
@Value("${third.baidu.connectionTimeoutInMillis}")
private Integer connectionTimeoutInMillis;
@Value("${third.baidu.socketTimeoutInMillis}")
private Integer socketTimeoutInMillis;
@Bean
public AipNlp clientBean() {
AipNlp client = new AipNlp(appId, apiKey, secretKey);
client.setConnectionTimeoutInMillis(connectionTimeoutInMillis);
client.setSocketTimeoutInMillis(socketTimeoutInMillis);
return client;
}
@Bean
public BaiduUtil baiduUtil() {
return new BaiduUtil(clientBean());
}
}
package com.yizhi.practice.application.third.baidu;
import java.math.BigDecimal;
import java.util.HashMap;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.baidu.aip.nlp.AipNlp;
/**
*
* @author xiaoyu
*
*/
public class BaiduUtil {
private static final Logger LOG = LoggerFactory.getLogger(BaiduUtil.class);
private static final String RESULT_KEY = "score";
private AipNlp client;
public BaiduUtil() {
super();
}
public BaiduUtil(AipNlp client) {
super();
this.client = client;
}
public AipNlp getClient() {
return client;
}
public void setClient(AipNlp client) {
this.client = client;
}
/**
* 获取两个文本的相似度
* @param text1
* @param text2
* @return
*/
public BigDecimal getSimilarRate(String text1, String text2) {
if(StringUtils.isEmpty(text1) || StringUtils.isEmpty(text2)) {
LOG.warn("Baidu similarRate : Input text is empty!");
return BigDecimal.ZERO;
}
HashMap<String, Object> options = new HashMap<String, Object>();
options.put("model", SimnetMode.CNN.getValue());
JSONObject result = client.simnet(text1, text2, options);
LOG.info("Baidu result : {}", result.toString());
BigDecimal rate = result.getBigDecimal(RESULT_KEY);
return rate;
}
/**
* 获取两个文本的相似度
* @param text1 不可为空
* @param text2 不可为空
* @param mode 可为空
* @return 相似度结果取值(0,1],分数越高说明相似度越高
*/
public BigDecimal getSimilarRate(String text1, String text2, String mode) {
if(StringUtils.isEmpty(text1) || StringUtils.isEmpty(text2)) {
LOG.warn("Baidu similarRate : Input text is empty!");
return BigDecimal.ZERO;
}
HashMap<String, Object> options = new HashMap<String, Object>();
options.put("model", null == mode ? SimnetMode.CNN.getValue() : mode);
JSONObject result = client.simnet(text1, text2, options);
LOG.info("Baidu result : {}", result.toString());
BigDecimal rate = result.getBigDecimal(RESULT_KEY);
return rate;
}
}
package com.yizhi.practice.application.third.baidu;
/**
* BOW(词包)模型
基于bag of words的BOW模型,特点是泛化性强,效率高,比较轻量级,适合任务:输入序列的 term “确切匹配”、不关心序列的词序关系,对计算效率有很高要求;<br/>
GRNN(循环神经网络)模型
基于recurrent,擅长捕捉短文本“跨片段”的序列片段关系,适合任务:对语义泛化要求很高,对输入语序比较敏感的任务;<br/>
CNN(卷积神经网络)模型
模型语义泛化能力介于 BOW/RNN 之间,对序列输入敏感,相较于 GRNN 模型的一个显著优点是计算效率会更高些。
* @author xiaoyu
*
*/
public enum SimnetMode {
BOW("BOW"), CNN("CNN"), GRNN("GRNN");
private String value;
private SimnetMode(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
package com.yizhi.practice.application.third.util;
import com.yizhi.practice.application.enums.PracticeXunFeiBusinessTypeEnum;
public class FrameUtil {
private static final Integer BASIC_FRAME_SIZE = 1280;
/**
* 根据讯飞业务类型,决定发送语音时的frame size
* @param businessType
* @param recognizeFactor
* @param evaluateFactor
* @return
*/
public static Integer determineFrameSize(PracticeXunFeiBusinessTypeEnum businessType, Integer recognizeFactor, Integer evaluateFactor) {
Integer result = null;
switch(businessType) {
case RECOGNIZE:
result = BASIC_FRAME_SIZE * recognizeFactor;
break;
case EVALUATE:
result = BASIC_FRAME_SIZE * evaluateFactor;
break;
default:
break;
}
return result;
}
}
package com.yizhi.practice.application.third.util;
import java.text.SimpleDateFormat;
import java.util.Date;
public class OssFileUtil {
/**
* 获取管理端标准话术上传路径
* @return 文件uri
* /企业ID/站点id/智能陪练/标准话术/yyyyMMdd/用户id/时间戳.mp3
*/
public static String getManageStandardVoiceUri(Long companyId,Long siteId,String business,String subBusiness,Long accountId,Long randomId){
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
String separator = "/";
StringBuffer path = new StringBuffer();
path.append(companyId).append(separator)
.append(siteId).append(separator)
.append(business).append(separator)
.append(subBusiness).append(separator)
.append(dateFormat.format(new Date())).append(separator)
.append(accountId).append(separator)
.append(randomId)
.append(".mp3");
return path.toString();
}
/**
* /企业ID/站点id/智能陪练/{子业务}/yyyyMMdd/用户id/时间戳{文件后缀}
* @param companyId
* @param siteId
* @param business
* @param subBusiness
* @param accountId
* @param suffix
* @return
*/
public static String getManageStandardFileUri(Long companyId,Long siteId,String business,String subBusiness,Long accountId, String suffix){
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
String separator = "/";
StringBuffer path = new StringBuffer();
path.append(companyId).append(separator)
.append(siteId).append(separator)
.append(business).append(separator)
.append(subBusiness).append(separator)
.append(dateFormat.format(new Date())).append(separator)
.append(accountId).append(separator)
.append(new Date().getTime())
.append(suffix);
return path.toString();
}
}
package com.yizhi.practice.application.third.xunfei;
public class Constants {
public static final int StatusFirstFrame = 0;
public static final int StatusContinueFrame = 1;
public static final int StatusLastFrame = 2;
public static final String SCORE_REGEX = "\"(\\d+\\.?\\d*)\"";
public static final String FLUENCY_REGEX = "fluency_score=" + SCORE_REGEX;
public static final String INTEGRITY_REGEX = "integrity_score=" + SCORE_REGEX;
public static final String PHONE_REGEX = "phone_score=" + SCORE_REGEX;
public static final String TONE_REGEX = "tone_score=" + SCORE_REGEX;
}
package com.yizhi.practice.application.third.xunfei;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Base64;
import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.yizhi.practice.application.enums.PracticeVoiceTypeEnum;
import com.yizhi.practice.application.enums.PracticeXunFeiBusinessTypeEnum;
import com.yizhi.practice.application.third.util.FrameUtil;
import lombok.Builder;
import lombok.experimental.Tolerate;
import okhttp3.WebSocket;
/**
*
* @author xiaoyu
*
*/
@Builder
public class EvaluateRunnable implements Runnable {
private static final Logger LOG = LoggerFactory.getLogger(EvaluateRunnable.class);
private static final String sub="ise";//服务类型sub,开放评测值为ise
private static final String ent="cn_vip";//语言标记参数 ent(cn_vip中文,en_vip英文)
//题型、文本、音频要请注意做同步变更(如果是英文评测,请注意变更ent参数的值)
private static final String category="read_sentence";//题型
private static long beginTime=(new Date()).getTime();
private static long endTime=(new Date()).getTime();
private String appId;
private String inputText;
private InputStream inputVoiceStream;
private WebSocket webSocket;
private PracticeVoiceTypeEnum voiceType;
private Integer recognizeFactor;
private Integer evaluateFactor;
@Tolerate
public EvaluateRunnable() {
super();
}
@Override
public void run() {
//连接成功,开始发送数据
int frameSize = FrameUtil.determineFrameSize(PracticeXunFeiBusinessTypeEnum.EVALUATE, this.recognizeFactor, this.evaluateFactor); //每一帧音频的大小,建议每 40ms 发送 1280B,大小可调整,但是不要超过19200B,即base64压缩后能超过26000B,否则会报错10163数据过长错误
int intervel = 40;
int status = 0; // 音频的状态
ssb(webSocket);
//ttp(webSocket);
beginTime=(new Date()).getTime();
try {
byte[] buffer = new byte[frameSize];
// 发送音频
end:
while (true) {
int len = this.inputVoiceStream.read(buffer);
if (len == -1) {
status = Constants.StatusLastFrame; //文件读完,改变status 为 2
}
switch (status) {
case Constants.StatusFirstFrame: // 第一帧音频status = 0
send(webSocket,1,1,Base64.getEncoder().encodeToString(Arrays.copyOf(buffer, len)));
status=Constants.StatusContinueFrame;//中间帧数
break;
case Constants.StatusContinueFrame: //中间帧status = 1
send(webSocket,2,1,Base64.getEncoder().encodeToString(Arrays.copyOf(buffer, len)));
break;
case Constants.StatusLastFrame: // 最后一帧音频status = 2 ,标志音频发送结束
send(webSocket,4,2,"");
LOG.info("sendlast");
endTime=(new Date()).getTime();
LOG.info("总耗时:"+(endTime-beginTime)+"ms");
break end;
}
Thread.sleep(intervel); //模拟音频采样延时
}
LOG.info("all data is send");
} catch (FileNotFoundException e) {
LOG.error("Error occurred:", e);
} catch (IOException e) {
LOG.error("Error occurred:", e);
} catch (Exception e) {
LOG.error("Error occurred:", e);
} finally {
try {
this.inputVoiceStream.close();
} catch (IOException e) {
LOG.error("Error occurred:", e);
}
}
}
//上传参数添加与发送
private void ssb(WebSocket webSocket) {
ParamBuilder p = new ParamBuilder();
p.add("common", new ParamBuilder()
.add("app_id", appId)
)
.add("business", new ParamBuilder()
.add("category", category)
.add("rstcd", "utf8")
//群体:adult成人 、youth(中学,效果与设置pupil参数一致)、pupil小学
//仅中文字、词、句题型支持
.add("group", "adult")
//打分门限值:hard、common、easy
//仅英文引擎支持
//.add("check_type","common")
//学段:junior(1,2年级) middle(3,4年级) senior(5,6年级)
//仅中文题型:中小学的句子、篇章题型支持
//.add("grade","junior")
//extra_ability生效条件:ise_unite=1,rst=entirety
//.add("ise_unite","1")
//.add("rst","entirety")
/*1.全维度(准确度分、流畅度分、完整度打分) ,extra_ability值为multi_dimension
2.支持因素错误信息显示(声韵、调型是否正确),extra_ability值为syll_phone_err_msg
3.单词基频信息显示(基频开始值、结束值),extra_ability值为pitch ,仅适用于单词和句子题型
4.(字词句篇均适用,如选多个能力,用分号;隔开如:syll_phone_err_msg;pitch;multi_dimension)*/
//.add("extra_ability","multi_dimension")
//试卷部分添加拼音,限制条件:添加拼音的汉字个数不超过整个试卷中汉字个数的三分之一。
//jin1|tian1|天气怎么样支持
//分制转换,rst=entirety是默认值,请根据文档推荐选择使用百分制
.add("sub",sub)
.add("ent",ent)
.add("tte", "utf-8")
.add("cmd", "ssb")
.add("auf", "audio/L16;rate=16000")
.add("aue", getAue(this.voiceType))
//评测文本(new String(new byte[] { (byte) 0xEF, (byte) 0xBB, (byte) 0xBF })+text)
.add("text",'\uFEFF'+inputText)//Base64.getEncoder().encodeToString(text.getBytes())
).add("data", new ParamBuilder()
.add("status", 0)
.add("data", ""));
//System.err.println(p.toString());
webSocket.send(p.toString());
}
//客户端给服务端发送数据
public void send(WebSocket webSocket, int aus,int status, String data) {
ParamBuilder p = new ParamBuilder();
p.add("business", new ParamBuilder()
.add("cmd", "auw")
.add("aus", aus)
.add("aue", getAue(this.voiceType))
).add("data",new ParamBuilder()
.add("status",status)
.add("data",data)
.add("data_type",1)
.add("encoding", getAue(this.voiceType))
);
//LOG.info("发送的数据"+p.toString());
webSocket.send(p.toString());
}
private String getAue(PracticeVoiceTypeEnum voiceType) {
String result = null;
switch(voiceType) {
case MP3:
result = "lame";
break;
case PCM:
result = "raw";
break;
case WAV:
result = "raw";
break;
default:
break;
}
return result;
}
}
package com.yizhi.practice.application.third.xunfei;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.Base64;
import java.util.concurrent.ExecutorService;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
import com.yizhi.practice.application.enums.PracticeVoiceTypeEnum;
import com.yizhi.practice.application.third.xunfei.param.IEvaluateResult;
import com.yizhi.practice.application.third.xunfei.vo.EvaluateResult;
import com.yizhi.practice.application.third.xunfei.vo.OkCondition;
import com.yizhi.practice.application.third.xunfei.vo.ResponseData;
import lombok.Builder;
import lombok.experimental.Tolerate;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
/**
*
* @author xiaoyu
*
*/
@Builder
public class EvaluateTask extends WebSocketListener {
private static final Logger LOG = LoggerFactory.getLogger(EvaluateTask.class);
final Base64.Encoder encoder = Base64.getEncoder();//编码
private final Base64.Decoder decoder = Base64.getDecoder();//解码
private static final Gson json = new Gson();
private String appId;
private String inputText;
private InputStream inputVoiceStream;
private OkCondition condition;
private ExecutorService threadPool;
private PracticeVoiceTypeEnum voiceType;
private Integer recognizeFactor;
private Integer evaluateFactor;
@Tolerate
public EvaluateTask() {
super();
}
@Override
public void onOpen(WebSocket webSocket, Response response) {
super.onOpen(webSocket, response);
this.threadPool.submit(EvaluateRunnable.builder()
.appId(this.appId)
.inputText(this.inputText)
.inputVoiceStream(this.inputVoiceStream)
.webSocket(webSocket)
.voiceType(this.voiceType)
.recognizeFactor(this.recognizeFactor)
.evaluateFactor(this.evaluateFactor)
.build());
}
@Override
public void onMessage(WebSocket webSocket, String text) {
super.onMessage(webSocket, text);
ResponseData resp = json.fromJson(text, ResponseData.class);
if (resp != null) {
if (resp.getCode() != 0) {
LOG.info( "code=>" + resp.getCode() + " error=>" + resp.getMessage() + " sid=" + resp.getSid());
closeWebSocket(webSocket);
return;
}
if (resp.getData() != null) {
if (resp.getData().getStatus() == 2) {
try {
String result = new String(decoder.decode(resp.getData().getData()), "UTF-8");
condition.ok(getResultFromXML(result));
LOG.trace("sid:{} 最终识别结果 {}", resp.getSid(), result);
} catch (Exception e) {
LOG.error("Error occurred:", e);
} finally {
closeWebSocket(webSocket);
}
}
}
}
}
private IEvaluateResult getResultFromXML(String total) {
String flucencyString = getStringByRegex(Constants.FLUENCY_REGEX, total);
String integrityString = getStringByRegex(Constants.INTEGRITY_REGEX, total);
String phoneString = getStringByRegex(Constants.PHONE_REGEX, total);
String toneString = getStringByRegex(Constants.TONE_REGEX, total);
LOG.info("Xun fei - evaluate result: fluency[{}], integrity[{}], phone[{}], tone[{}]",flucencyString, integrityString, phoneString, toneString);
BigDecimal fluency = BigDecimal.valueOf(Double.valueOf(flucencyString)).divide(BigDecimal.valueOf(100));
BigDecimal integrity = BigDecimal.valueOf(Double.valueOf(integrityString)).divide(BigDecimal.valueOf(100));
BigDecimal phone = BigDecimal.valueOf(Double.valueOf(phoneString)).divide(BigDecimal.valueOf(100));
BigDecimal tone = BigDecimal.valueOf(Double.valueOf(toneString)).divide(BigDecimal.valueOf(100));
return new EvaluateResult(fluency, integrity, phone, tone);
}
@Override
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
super.onFailure(webSocket, t, response);
try {
if (null != response) {
int code = response.code();
LOG.info("onFailure code:" + code);
LOG.info("onFailure body:" + response.body().string());
if (101 != code) {
LOG.info("connection failed");
}
}
} catch (IOException e) {
LOG.error("Fail when resolve response body:",e);
} finally {
closeWebSocket(webSocket);
}
}
private void closeWebSocket(WebSocket webSocket) {
webSocket.close(1000, "");
}
private String getStringByRegex(String regex, String input) {
String result = null;
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
matcher.find();
result = matcher.group(1);
return result;
}
}
package com.yizhi.practice.application.third.xunfei;
import com.google.gson.JsonObject;
public class ParamBuilder {
private JsonObject jsonObject = new JsonObject();
public ParamBuilder add(String key, String val) {
this.jsonObject.addProperty(key, val);
return this;
}
public ParamBuilder add(String key, int val) {
this.jsonObject.addProperty(key, val);
return this;
}
public ParamBuilder add(String key, boolean val) {
this.jsonObject.addProperty(key, val);
return this;
}
public ParamBuilder add(String key, float val) {
this.jsonObject.addProperty(key, val);
return this;
}
public ParamBuilder add(String key, JsonObject val) {
this.jsonObject.add(key, val);
return this;
}
public ParamBuilder add(String key, ParamBuilder val) {
this.jsonObject.add(key, val.jsonObject);
return this;
}
@Override
public String toString() {
return this.jsonObject.toString();
}
}
package com.yizhi.practice.application.third.xunfei;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.JsonObject;
import com.yizhi.practice.application.enums.PracticeVoiceTypeEnum;
import com.yizhi.practice.application.enums.PracticeXunFeiBusinessTypeEnum;
import com.yizhi.practice.application.third.util.FrameUtil;
import lombok.Builder;
import lombok.experimental.Tolerate;
import okhttp3.WebSocket;
/**
*
* @author xiaoyu
*
*/
@Builder
public class RecognizeRunnable implements Runnable {
private static final Logger LOG = LoggerFactory.getLogger(RecognizeRunnable.class);
private WebSocket webSocket;
private InputStream fileStream;
private String appId;
private PracticeVoiceTypeEnum voiceType;
private Integer recognizeFactor;
private Integer evaluateFactor;
@Tolerate
public RecognizeRunnable() {
super();
}
@Override
public void run() {
//连接成功,开始发送数据
int frameSize = FrameUtil.determineFrameSize(PracticeXunFeiBusinessTypeEnum.RECOGNIZE, this.recognizeFactor, this.evaluateFactor); //每一帧音频的大小,建议每 40ms 发送 122B
int intervel = 40;
int status = 0; // 音频的状态
try {
byte[] buffer = new byte[frameSize];
// 发送音频
end:
while (true) {
int len = this.fileStream.read(buffer);
if (len == -1) {
status = Constants.StatusLastFrame; //文件读完,改变status 为 2
}
switch (status) {
case Constants.StatusFirstFrame: // 第一帧音频status = 0
JsonObject frame = new JsonObject();
JsonObject business = new JsonObject(); //第一帧必须发送
JsonObject common = new JsonObject(); //第一帧必须发送
JsonObject data = new JsonObject(); //每一帧都要发送
// 填充common
common.addProperty("app_id", this.appId);
//填充business
business.addProperty("language", "zh_cn");
//business.addProperty("language", "en_us");//英文
//business.addProperty("language", "ja_jp");//日语,在控制台可添加试用或购买
//business.addProperty("language", "ko_kr");//韩语,在控制台可添加试用或购买
//business.addProperty("language", "ru-ru");//俄语,在控制台可添加试用或购买
business.addProperty("domain", "iat");
business.addProperty("accent", "mandarin");//中文方言请在控制台添加试用,添加后即展示相应参数值
//business.addProperty("nunum", 0);
//business.addProperty("ptt", 0);//标点符号
//business.addProperty("rlang", "zh-hk"); // zh-cn :简体中文(默认值)zh-hk :繁体香港(若未授权不生效,在控制台可免费开通)
//business.addProperty("vinfo", 1);
business.addProperty("dwa", "wpgs");//动态修正(若未授权不生效,在控制台可免费开通)
//business.addProperty("nbest", 5);// 句子多候选(若未授权不生效,在控制台可免费开通)
//business.addProperty("wbest", 3);// 词级多候选(若未授权不生效,在控制台可免费开通)
//填充data
data.addProperty("status", Constants.StatusFirstFrame);
data.addProperty("format", "audio/L16;rate=16000");
data.addProperty("encoding", getEncoding(this.voiceType)); // lame: mp3
data.addProperty("audio", Base64.getEncoder().encodeToString(Arrays.copyOf(buffer, len)));
//填充frame
frame.add("common", common);
frame.add("business", business);
frame.add("data", data);
webSocket.send(frame.toString());
status = Constants.StatusContinueFrame; // 发送完第一帧改变status 为 1
break;
case Constants.StatusContinueFrame: //中间帧status = 1
JsonObject frame1 = new JsonObject();
JsonObject data1 = new JsonObject();
data1.addProperty("status", Constants.StatusContinueFrame);
data1.addProperty("format", "audio/L16;rate=16000");
data1.addProperty("encoding", getEncoding(this.voiceType));
data1.addProperty("audio", Base64.getEncoder().encodeToString(Arrays.copyOf(buffer, len)));
frame1.add("data", data1);
webSocket.send(frame1.toString());
// System.out.println("send continue");
break;
case Constants.StatusLastFrame: // 最后一帧音频status = 2 ,标志音频发送结束
JsonObject frame2 = new JsonObject();
JsonObject data2 = new JsonObject();
data2.addProperty("status", Constants.StatusLastFrame);
data2.addProperty("audio", "");
data2.addProperty("format", "audio/L16;rate=16000");
data2.addProperty("encoding", getEncoding(this.voiceType));
frame2.add("data", data2);
webSocket.send(frame2.toString());
LOG.info("Recognize:send last.");
break end;
}
Thread.sleep(intervel); //模拟音频采样延时
}
LOG.info("Recognize:all data is send");
} catch (FileNotFoundException e) {
LOG.error("Exception occurred:", e);
} catch (IOException e) {
LOG.error("Exception occurred:", e);
} catch (InterruptedException e) {
LOG.error("Exception occurred:", e);
} finally {
try {
this.fileStream.close();
} catch (IOException e) {
LOG.error("Error occurred:", e);
}
}
}
/**
* 参数encoding对于不同的文件格式,参数的值不同
* raw:原生音频(支持单声道的pcm)
speex:speex压缩后的音频(8k)
speex-wb:speex压缩后的音频(16k)
请注意压缩前也必须是采样率16k或8k单声道的pcm。
lame:mp3格式(仅中文普通话和英文支持,方言及小语种暂不支持)
* @param voiceType
* @return
*/
private String getEncoding(PracticeVoiceTypeEnum voiceType) {
String result = null;
switch(voiceType) {
case MP3:
result = "lame";
break;
case PCM:
result = "raw";
break;
default:
break;
}
return result;
}
}
package com.yizhi.practice.application.third.xunfei;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
import com.yizhi.practice.application.enums.PracticeVoiceTypeEnum;
import com.yizhi.practice.application.third.xunfei.vo.Decoder;
import com.yizhi.practice.application.third.xunfei.vo.OkCondition;
import com.yizhi.practice.application.third.xunfei.vo.ResponseData;
import com.yizhi.practice.application.third.xunfei.vo.Text;
import lombok.Builder;
import lombok.experimental.Tolerate;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
/**
*
* @author xiaoyu
*
*/
@Builder
public class RecognizeTask extends WebSocketListener {
private static final Logger LOG = LoggerFactory.getLogger(RecognizeTask.class);
private static final Gson json = new Gson();
@Builder.Default
private Decoder decoder = new Decoder();
// 开始时间
private static Date dateBegin = new Date();
// 结束时间
private static Date dateEnd = new Date();
private static final SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd HH:mm:ss.SSS");
private InputStream fileStream;
private String appId;
private OkCondition condition;
private ExecutorService threadPool;
private PracticeVoiceTypeEnum voiceType;
private Integer recognizeFactor;
private Integer evaluateFactor;
@Tolerate
public RecognizeTask() {
super();
}
@Override
public void onOpen(WebSocket webSocket, Response response) {
super.onOpen(webSocket, response);
this.threadPool.submit(RecognizeRunnable.builder().webSocket(webSocket)
.fileStream(this.fileStream)
.appId(this.appId)
.voiceType(this.voiceType)
.recognizeFactor(this.recognizeFactor)
.evaluateFactor(this.evaluateFactor)
.build());
}
@Override
public void onMessage(WebSocket webSocket, String text) {
super.onMessage(webSocket, text);
ResponseData resp = json.fromJson(text, ResponseData.class);
if (resp != null) {
if (resp.getCode() != 0) {
LOG.info("Received failed result.");
LOG.info("code=>" + resp.getCode() + " error=>" + resp.getMessage() + " sid=" + resp.getSid());
closeWebSocket(webSocket);
return;
}
if (resp.getData() != null) {
if (resp.getData().getResult() != null) {
Text te = resp.getData().getResult().getText();
try {
this.decoder.decode(te);
LOG.info("中间识别结果 [{}]", decoder.toString());
} catch (Exception e) {
LOG.error("Error occurred:", e);
}
}
if (resp.getData().getStatus() == 2) {
// resp.data.status ==2 说明数据全部返回完毕,可以关闭连接,释放资源
dateEnd = new Date();
String result = decoder.toString();
condition.ok(result);
LOG.info(sdf.format(dateBegin) + "start");
LOG.info(sdf.format(dateEnd) + "end");
LOG.info("Last result:[{}]", result);
LOG.info("sid :[{}]", resp.getSid());
decoder.discard();
closeWebSocket(webSocket);
}
}
}
}
@Override
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
super.onFailure(webSocket, t, response);
try {
if (null != response) {
int code = response.code();
LOG.info("onFailure code:" + code);
LOG.info("onFailure body:" + response.body().string());
if (101 != code) {
LOG.info("connection failed");
}
}
} catch (IOException e) {
LOG.error("Fail when resolve response body:",e);
} finally {
closeWebSocket(webSocket);
}
}
private void closeWebSocket(WebSocket webSocket) {
webSocket.close(1000, "");
}
}
package com.yizhi.practice.application.third.xunfei;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.yizhi.practice.application.enums.PracticeVoiceTypeEnum;
import com.yizhi.practice.application.third.xunfei.vo.OkCondition;
import com.yizhi.practice.application.third.xunfei.vo.ResponseData;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
/**
*
* @author xiaoyu
*
*/
public class SynthesisTask extends WebSocketListener {
private static final Logger LOG = LoggerFactory.getLogger(SynthesisTask.class);
public static final Gson json = new Gson();
private String appId;
private String inputText;
private Map<String, Object> robotConfig;
private OkCondition condition;
private PracticeVoiceTypeEnum voiceType;
private List<String> results = new ArrayList<String>();
public SynthesisTask() {
super();
}
public SynthesisTask(String appId, String inputText, Map<String, Object> robotConfig
, OkCondition condition, PracticeVoiceTypeEnum voiceType) {
super();
this.appId = appId;
this.inputText = inputText;
this.robotConfig = robotConfig;
this.condition = condition;
this.voiceType = voiceType;
}
@Override
public void onOpen(WebSocket webSocket, Response response) {
super.onOpen(webSocket, response);
//发送数据
JsonObject frame = new JsonObject();
JsonObject business = new JsonObject();
JsonObject common = new JsonObject();
JsonObject data = new JsonObject();
// 填充common
common.addProperty("app_id", appId);
//填充business
business.addProperty("aue", getAue(this.voiceType));
if(PracticeVoiceTypeEnum.MP3.equals(this.voiceType)) {
business.addProperty("sfl", 1);
}
business.addProperty("tte", "UTF8");//小语种必须使用UNICODE编码
business.addProperty("vcn", (String) this.robotConfig.get("name"));//到控制台-我的应用-语音合成-添加试用或购买发音人,添加后即显示该发音人参数值,若试用未添加的发音人会报错11200
business.addProperty("pitch", 50);
business.addProperty("speed", 50);
//填充data
data.addProperty("status", 2);//固定位2
try {
LOG.info("Xunfei string -> voice, ready to send: [{}]", inputText);
data.addProperty("text", Base64.getEncoder().encodeToString(inputText.getBytes("utf8")));
//使用小语种须使用下面的代码,此处的unicode指的是 utf16小端的编码方式,即"UTF-16LE"”
//data.addProperty("text", Base64.getEncoder().encodeToString(text.getBytes("UTF-16LE")));
} catch (UnsupportedEncodingException e) {
LOG.error("Error occurred:", e);
}
//填充frame
frame.add("common", common);
frame.add("business", business);
frame.add("data", data);
webSocket.send(frame.toString());
}
@Override
public void onMessage(WebSocket webSocket, String text) {
super.onMessage(webSocket, text);
//处理返回数据
LOG.trace("receive=>" + text);
ResponseData resp = null;
try {
resp = json.fromJson(text, ResponseData.class);
} catch (Exception e) {
LOG.error("Error occurred:", e);
}
if (resp != null) {
if (resp.getCode() != 0) {
LOG.info("error=>" + resp.getMessage() + " sid=" + resp.getSid());
closeWebSocket(webSocket);
return;
}
if (resp.getData() != null) {
String result = resp.getData().getAudio();
this.results.add(result);
if (resp.getData().getStatus() == 2) {
LOG.info("session end");
if(null != this.results) {
LOG.info("Results size from xunfei is {}.", this.results.size());
}
condition.ok(this.results);
closeWebSocket(webSocket);
}
}
}
}
@Override
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
super.onFailure(webSocket, t, response);
try {
if (null != response) {
int code = response.code();
LOG.info("onFailure code:" + code);
LOG.info("onFailure body:" + response.body().string());
if (101 != code) {
LOG.info("connection failed");
}
}
} catch (IOException e) {
LOG.error("Fail when resolve response body:",e);
} finally {
closeWebSocket(webSocket);
}
}
private void closeWebSocket(WebSocket webSocket) {
webSocket.close(1000, "");
}
private String getAue(PracticeVoiceTypeEnum voiceType) {
String result = null;
switch(voiceType) {
case MP3:
result = "lame";
break;
case PCM:
result = "raw";
break;
default:
break;
}
return result;
}
}
package com.yizhi.practice.application.third.xunfei;
import java.util.concurrent.ExecutorService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.yizhi.practice.application.third.aliyun.AliyunUtil;
import okhttp3.OkHttpClient;
/**
*
* @author xiaoyu
*
*/
@Configuration
public class XunfeiConfig {
// 语音识别 api url
@Value("${third.xunfei.recognizeUrl}")
private String recognizeUrl;
// 语音合成 api url
@Value("${third.xunfei.synthesisUrl}")
private String synthesisUrl;
// 语音评测 api url
@Value("${third.xunfei.evaluateUrl}")
private String evaluateUrl;
@Value("${third.xunfei.appId}")
private String appId;
@Value("${third.xunfei.apiSecret}")
private String apiSecret;
@Value("${third.xunfei.apiKey}")
private String apiKey;
@Value("${third.xunfei.maxWait.ms}")
private Long maxWait;
@Value("${third.xunfei.eachWait.ms}")
private Long waitEachRound;
@Autowired
private AliyunUtil uploader;
@Autowired
@Qualifier("practiceThreadPool")
private ExecutorService threadPool;
@Value("${third.xunfei.recognize.framesize}")
private Integer recognizeFactor;
@Value("${third.xunfei.evaluate.framesize}")
private Integer evaluateFactor;
@Bean
public OkHttpClient okHttpClient() {
return new OkHttpClient.Builder().build();
}
@Bean
public XunfeiUtil xunfeiUtil() {
return XunfeiUtil.builder()
.recognizeUrl(this.recognizeUrl)
.synthesisUrl(this.synthesisUrl)
.evaluateUrl(this.evaluateUrl)
.appId(this.appId)
.apiKey(this.apiKey)
.apiSecret(this.apiSecret)
.aliyunUtil(this.uploader)
.okHttpClient(okHttpClient())
.threadPool(this.threadPool)
.maxWait(this.maxWait)
.waitEachRound(this.waitEachRound)
.evaluateFactor(this.evaluateFactor)
.recognizeFactor(this.recognizeFactor)
.build();
}
}
package com.yizhi.practice.application.third.xunfei;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import java.util.concurrent.ExecutorService;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.oss.model.OSSObject;
import com.google.common.io.Files;
import com.yizhi.practice.application.enums.PracticeVoiceTypeEnum;
import com.yizhi.practice.application.third.aliyun.AliyunUtil;
import com.yizhi.practice.application.third.xunfei.param.IEvaluateResult;
import com.yizhi.practice.application.third.xunfei.vo.OkCondition;
import lombok.Builder;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
/**
*
* @author xiaoyu
*
*/
@Builder
public class XunfeiUtil {
private static final Logger LOG = LoggerFactory.getLogger(XunfeiUtil.class);
// 语音识别 api url
private String recognizeUrl;
// 语音合成 api url
private String synthesisUrl;
// 语音评测 api url
private String evaluateUrl;
private String appId;
private String apiSecret;
private String apiKey;
private AliyunUtil aliyunUtil;
private OkHttpClient okHttpClient;
private ExecutorService threadPool;
private Integer recognizeFactor;
private Integer evaluateFactor;
// websocket最大等待时间(单位:毫秒)
private Long maxWait;
// 每次等待时间(单位:毫秒)
private Long waitEachRound;
// private static final SimpleDateFormat PATH_DATE = new SimpleDateFormat("yyyyMMdd");
/**
* 文件地址方式 语音识别.
* @param voiceFilePath 待识别的语音的文件地址
* @param voiceType 可接受:PCM, MP3
* @return
* @throws Exception
*/
public String voiceToString(String voiceFilePath, PracticeVoiceTypeEnum voiceType) throws Exception {
if(StringUtils.isEmpty(voiceFilePath)) {
LOG.error("Xunfei voice->string, input file is empty.");
return null;
}
OSSObject ossObj = aliyunUtil.download(voiceFilePath);
InputStream ins = ossObj.getObjectContent();
String result = null;
try {
result = voiceToString(ins, voiceType);
} catch (Exception e) {
LOG.error("Error occurred:", e);
throw e;
} finally {
if(null != ins) {
ins.close();
}
ossObj.close();
}
return result;
}
/**
* 流式 语音识别.
* @param fileStream
* @param voiceType 可接受:PCM, MP3
* @return
* @throws Exception
*/
public String voiceToString(InputStream fileStream, PracticeVoiceTypeEnum voiceType) throws Exception {
if(null == fileStream) {
LOG.error("Xunfei voice->string, input file is empty.");
return null;
}
String url = null;
try {
url = getAuthUrl(recognizeUrl, apiKey, apiSecret);
Request request = new Request.Builder().url(url).build();
OkCondition condition = new OkCondition();
this.okHttpClient.newWebSocket(request, RecognizeTask.builder()
.fileStream(fileStream)
.appId(this.appId)
.condition(condition)
.threadPool(this.threadPool)
.voiceType(voiceType)
.recognizeFactor(this.recognizeFactor)
.evaluateFactor(this.evaluateFactor)
.build());
waitAndBlock(condition, this.maxWait);
return condition.getResult();
} catch (Exception e) {
LOG.error("Error occurred when getting Auth url of [voice -> string].", e);
throw e;
} finally {
fileStream.close();
}
}
/**
* 等待websocket返回结果
* @param condition
* @param maxWait
* @throws InterruptedException
*/
private void waitAndBlock(OkCondition condition, Long maxWait) throws InterruptedException {
long maxWaitTime = maxWait;
while(!condition.isDone() && maxWaitTime > 0) {
Thread.sleep(this.waitEachRound);
maxWaitTime = maxWaitTime - this.waitEachRound;
}
}
/**
* 语音合成. 可接受:PCM, MP3
* @param inputText 要合成的文字
* @param robotConfig 发音机器人的配置(包含发音机器人的声音,语速等,practice_config表的robot_params字段)例如:"{name:'xiaoyan'}"
* @param savePath 合成的语音文件保存在阿里云的目录 例如:yizhi/practice/xx/xx.pcm
* @param voiceType 可接受:PCM, MP3
* @return
* @throws Exception
*/
public String stringToVoice(String inputText, String robotConfig, String savePath, PracticeVoiceTypeEnum voiceType) throws Exception {
if(StringUtils.isEmpty(inputText) || StringUtils.isEmpty(robotConfig) || StringUtils.isEmpty(savePath)) {
LOG.error("Xunfei string->voice, params are empty.");
return null;
}
if(inputText.length() > 2000) {
LOG.error("Xunfei string->voice, length of input string [{}] > 2000.", inputText);
return null;
}
String url = null;
try {
url = getAuthUrl(synthesisUrl, apiKey, apiSecret);
} catch (Exception e) {
LOG.error("Error occurred when getting Auth url of [string -> voice].", e);
throw e;
}
Request request = new Request.Builder().url(url).build();
OkCondition condition = new OkCondition();
Map<String, Object> robotConfigMap = (Map<String, Object>) JSONObject.parse(robotConfig);
this.okHttpClient.newWebSocket(request, new SynthesisTask(this.appId, inputText, robotConfigMap, condition, voiceType));
waitAndBlock(condition, this.maxWait);
return uploadOss(convertToByte(condition.getResultList()), savePath);
}
/**
* for test
* @param inputText
* @param robotConfig
* @throws Exception
*/
/*
* @Deprecated public void stringToVoice(String inputText, String robotConfig,
* PracticeVoiceTypeEnum vt) throws Exception { String url = null; try { url =
* getAuthUrl(synthesisUrl, apiKey, apiSecret); } catch (Exception e) {
* LOG.error("Error occurred when getting Auth url of [string -> voice].", e);
* throw e; }
*
* Request request = new Request.Builder().url(url).build(); OkCondition
* condition = new OkCondition();
*
* Map<String, Object> robotConfigMap = (Map<String,
* Object>)JSONObject.parse(robotConfig);
* this.okHttpClient.newWebSocket(request, new SynthesisTask(this.appId,
* inputText, robotConfigMap, condition, vt));
*
* waitAndBlock(condition, this.maxWait);
*
* saveFileToLocal(condition.getResultList(), new File("forTest.mp3")); }
*/
private void saveFileToLocal(List<String> origin, File target) throws IOException {
byte[] bytes = convertToByte(origin);
Files.write(bytes, target);
}
/*
* private String createFolderPath(IFolderPathParam param) { StringBuffer path =
* new StringBuffer(); path.append(param.getCompanyId()).append("/")
* .append(param.getBusiness()).append("/")
* .append(param.getSubBusiness()).append("/") .append(PATH_DATE.format(new
* Date())).append("/") .append(param.getUserId()).append("/") .append(new
* Date().getTime()) .append(".mp3"); return path.toString(); }
*/
private byte[] convertToByte(List<String> results) {
byte[] result = null;
if(null != results && !results.isEmpty()) {
for(int i = 0 ; i < results.size(); i++) {
if(null != results.get(i)) {
if(i == 0) {
result = Base64.getDecoder().decode(results.get(i));
}else {
result = ArrayUtils.addAll(result, Base64.getDecoder().decode(results.get(i)));
}
}
}
}
return result;
}
private String uploadOss(byte[] input, String fileName) throws IOException {
if(null == input) {
LOG.error("No results from Xunfei, do not upload to Ali yun.");
return null;
}
try(InputStream ins = new ByteArrayInputStream(input)){
return aliyunUtil.uploadByStream(fileName, ins);
}
}
/**
* 文件地址方式 语音评测. 可接受:PCM, MP3, WAV
* @param inputText 待对比文本
* @param inputVoicePath 待对比语音的地址
* @param voiceType 可接受:PCM, MP3, WAV
* @return
* @throws Exception
*/
public IEvaluateResult evaluate(String inputText, String inputVoicePath, PracticeVoiceTypeEnum voiceType) throws Exception {
if(StringUtils.isEmpty(inputText) || StringUtils.isEmpty(inputVoicePath)) {
LOG.error("Xunfei evaluate, params are empty.");
return null;
}
OSSObject ossObj = aliyunUtil.download(inputVoicePath);
InputStream ins = ossObj.getObjectContent();
IEvaluateResult result = null;
try {
result =
evaluate(inputText, ins, voiceType);
} catch (Exception e) {
LOG.error("Error occurred:", e);
throw e;
} finally {
if(null != ins) {
ins.close();
}
ossObj.close();
}
return result;
}
/**
* 流式 语音评测. 可接受:PCM, MP3, WAV
* @param inputText
* @param inputVoiceStream
* @param voiceType 可接受:PCM, MP3, WAV
* @return
* @throws Exception
*/
public IEvaluateResult evaluate(String inputText
, InputStream inputVoiceStream, PracticeVoiceTypeEnum voiceType) throws Exception {
if(StringUtils.isEmpty(inputText) || null == inputVoiceStream) {
LOG.error("Xunfei evaluate, params are empty.");
return null;
}
String url = null;
try {
url = getAuthUrl(evaluateUrl, apiKey, apiSecret);
} catch (Exception e) {
LOG.error("Error occurred when getting Auth url of [evaluate].", e);
throw e;
}
Request request = new Request.Builder().url(url).build();
OkCondition condition = new OkCondition();
this.okHttpClient.newWebSocket(request, EvaluateTask.builder()
.appId(this.appId)
.inputText(inputText)
.inputVoiceStream(inputVoiceStream)
.condition(condition)
.threadPool(this.threadPool)
.voiceType(voiceType)
.recognizeFactor(this.recognizeFactor)
.evaluateFactor(this.evaluateFactor)
.build());
waitAndBlock(condition, this.maxWait);
return condition.getEvaluateResult();
}
/**
* 根据不同的业务拼接不同的讯飞API接口,分为 语音识别、语音合成、语音评测
* @param hostUrl
* @param key
* @param secret
* @return
* @throws Exception
*/
public String getAuthUrl(String hostUrl, String key, String secret) throws Exception {
URL url = new URL(hostUrl);
SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
format.setTimeZone(TimeZone.getTimeZone("GMT"));
String date = format.format(new Date());
StringBuilder builder = new StringBuilder("host: ").append(url.getHost()).append("\n").//
append("date: ").append(date).append("\n").//
append("GET ").append(url.getPath()).append(" HTTP/1.1");
Charset charset = Charset.forName("UTF-8");
Mac mac = Mac.getInstance("hmacsha256");
SecretKeySpec spec = new SecretKeySpec(secret.getBytes(charset), "hmacsha256");
mac.init(spec);
byte[] hexDigits = mac.doFinal(builder.toString().getBytes(charset));
String sha = Base64.getEncoder().encodeToString(hexDigits);
String authorization = String.format("api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"", key, "hmac-sha256", "host date request-line", sha);
HttpUrl httpUrl = HttpUrl.parse("https://" + url.getHost() + url.getPath()).newBuilder().//
addQueryParameter("authorization", Base64.getEncoder().encodeToString(authorization.getBytes(charset))).//
addQueryParameter("date", date).//
addQueryParameter("host", url.getHost()).//
build();
// http,https 换成 ws,wss
String wsUrl = httpUrl.toString().replace("http://", "ws://").replace("https://", "wss://");
return wsUrl;
}
}
package com.yizhi.practice.application.third.xunfei.param;
import java.math.BigDecimal;
public interface IEvaluateResult {
/**
* 流畅性得分
* @return
*/
public BigDecimal getFluencyScore();
/**
* 完整性得分
* @return
*/
public BigDecimal getIntegrityScore();
/**
* 声韵分
* @return
*/
public BigDecimal getPhoneScore();
/**
* 调型分
* @return
*/
public BigDecimal getToneScore();
}
package com.yizhi.practice.application.third.xunfei.param;
public interface IFolderPathParam {
public Long getCompanyId();
public String getBusiness();
public String getSubBusiness();
public Long getUserId();
}
package com.yizhi.practice.application.third.xunfei.vo;
public class Cw {
int sc;
String w;
}
package com.yizhi.practice.application.third.xunfei.vo;
public class Data {
private int status;
private Result result;
private String audio; //返回的音频,base64 编码
private String ced; // 合成进度
private String data;
public int getStatus() {
return status;
}
public Result getResult() {
return result;
}
public String getData() {
return data;
}
public String getAudio() {
return audio;
}
public String getCed() {
return ced;
}
}
package com.yizhi.practice.application.third.xunfei.vo;
public class Decoder {
private Text[] texts;
private int defc = 10;
public Decoder() {
this.texts = new Text[this.defc];
}
public synchronized void decode(Text text) {
if (text.sn >= this.defc) {
this.resize();
}
if ("rpl".equals(text.pgs)) {
for (int i = text.rg[0]; i <= text.rg[1]; i++) {
this.texts[i].deleted = true;
}
}
this.texts[text.sn] = text;
}
public String toString() {
StringBuilder sb = new StringBuilder();
for (Text t : this.texts) {
if (t != null && !t.deleted) {
sb.append(t.text);
}
}
return sb.toString();
}
public void resize() {
int oc = this.defc;
this.defc <<= 1;
Text[] old = this.texts;
this.texts = new Text[this.defc];
for (int i = 0; i < oc; i++) {
this.texts[i] = old[i];
}
}
public void discard(){
for(int i=0;i<this.texts.length;i++){
this.texts[i]= null;
}
}
}
package com.yizhi.practice.application.third.xunfei.vo;
import java.math.BigDecimal;
import com.yizhi.practice.application.third.xunfei.param.IEvaluateResult;
/**
*
* @author xiaoyu
*
*/
public class EvaluateResult implements IEvaluateResult {
private BigDecimal flucencyScore;
private BigDecimal integrityScore;
private BigDecimal phoneScore;
private BigDecimal toneScore;
public EvaluateResult() {
super();
}
public EvaluateResult(BigDecimal flucencyScore, BigDecimal integrityScore, BigDecimal phoneScore,
BigDecimal toneScore) {
super();
this.flucencyScore = flucencyScore;
this.integrityScore = integrityScore;
this.phoneScore = phoneScore;
this.toneScore = toneScore;
}
public BigDecimal getFlucencyScore() {
return flucencyScore;
}
public void setFlucencyScore(BigDecimal flucencyScore) {
this.flucencyScore = flucencyScore;
}
public void setIntegrityScore(BigDecimal integrityScore) {
this.integrityScore = integrityScore;
}
public void setPhoneScore(BigDecimal phoneScore) {
this.phoneScore = phoneScore;
}
public void setToneScore(BigDecimal toneScore) {
this.toneScore = toneScore;
}
@Override
public BigDecimal getFluencyScore() {
return this.flucencyScore;
}
@Override
public BigDecimal getIntegrityScore() {
return this.integrityScore;
}
@Override
public BigDecimal getPhoneScore() {
return this.phoneScore;
}
@Override
public BigDecimal getToneScore() {
return this.toneScore;
}
@Override
public String toString() {
return "EvaluateResult [flucencyScore=" + flucencyScore + ", integrityScore=" + integrityScore + ", phoneScore="
+ phoneScore + ", toneScore=" + toneScore + "]";
}
}
package com.yizhi.practice.application.third.xunfei.vo;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import com.yizhi.practice.application.third.xunfei.param.IEvaluateResult;
/**
*
* @author xiaoyu
*
*/
public class OkCondition {
private AtomicBoolean condition = new AtomicBoolean(false);
private String result;
private List<String> resultList;
private IEvaluateResult evaluateResult;
public void ok(String text) {
this.condition.set(true);
this.result = text;
}
public void ok(List<String> text) {
this.condition.set(true);
this.resultList = text;
}
public void ok(IEvaluateResult evaluateResult) {
this.condition.set(true);
this.evaluateResult = evaluateResult;
}
public boolean isDone() {
if(condition.get() == true) {
return true;
}else {
return false;
}
}
public String getResult() {
return this.result;
}
public List<String> getResultList() {
return resultList;
}
public IEvaluateResult getEvaluateResult() {
return evaluateResult;
}
}
package com.yizhi.practice.application.third.xunfei.vo;
public class ResponseData {
private int code;
private String message;
private String sid;
private Data data;
public int getCode() {
return code;
}
public String getMessage() {
return this.message;
}
public String getSid() {
return sid;
}
public Data getData() {
return data;
}
}
package com.yizhi.practice.application.third.xunfei.vo;
import com.google.gson.JsonObject;
public class Result {
int bg;
int ed;
String pgs;
int[] rg;
int sn;
Ws[] ws;
boolean ls;
JsonObject vad;
public Text getText() {
Text text = new Text();
StringBuilder sb = new StringBuilder();
for (Ws ws : this.ws) {
sb.append(ws.cw[0].w);
}
text.sn = this.sn;
text.text = sb.toString();
text.sn = this.sn;
text.rg = this.rg;
text.pgs = this.pgs;
text.bg = this.bg;
text.ed = this.ed;
text.ls = this.ls;
text.vad = this.vad==null ? null : this.vad;
return text;
}
}
package com.yizhi.practice.application.third.xunfei.vo;
import java.util.Arrays;
import com.google.gson.JsonObject;
public class Text {
int sn;
int bg;
int ed;
String text;
String pgs;
int[] rg;
boolean deleted;
boolean ls;
JsonObject vad;
@Override
public String toString() {
return "Text{" +
"bg=" + bg +
", ed=" + ed +
", ls=" + ls +
", sn=" + sn +
", text='" + text + '\'' +
", pgs=" + pgs +
", rg=" + Arrays.toString(rg) +
", deleted=" + deleted +
", vad=" + (vad==null ? "null" : vad.getAsJsonArray("ws").toString()) +
'}';
}
}
package com.yizhi.practice.application.third.xunfei.vo;
public class Ws {
Cw[] cw;
int bg;
int ed;
}
package com.yizhi.practice.application.util;
import java.util.List;
import com.mysql.jdbc.StringUtils;
import com.yizhi.practice.application.constants.PracticeConstant;
public class LocalStringUtil {
/**
* 分解命中的关键词/禁忌词
* @param text
* @param keywords
* @return
*/
public static List<String> hit(String hitKeyWord) {
if(StringUtils.isNullOrEmpty(hitKeyWord)) {
return null;
}
return StringUtils.split(hitKeyWord.replaceAll(PracticeConstant.KEY_WORD_SPERATOR_CN, PracticeConstant.KEY_WORD_SPERATOR_EN), PracticeConstant.KEY_WORD_SPERATOR_EN, false);
}
}
package com.yizhi.practice.application.util;
public class NumberUtil {
/**
* 根据 总条数 和 每页条数 计算 总页数
* @param totalSize
* @param pageSize
* @return
*/
public static Integer getPageCount(Long totalSize, Integer pageSize) {
if(totalSize % pageSize == 0) {
return (int) (totalSize/pageSize);
}else {
return (int) (totalSize/pageSize +1);
}
}
}
package com.yizhi.practice.application.xservice;
import com.yizhi.practice.application.pojo.vo.*;
import com.yizhi.util.application.page.PageInfo;
import java.util.Date;
import java.util.List;
public interface PracticeChatLogXService {
public PracticeChatLogListHeaderVo baseInfo(Long practiceId);
public PageInfo<PracticeChatLogListVo> list(PracticeChatLogListParamVo param);
public PageInfo<StudentPracticeLogVo> studentList(PracticeChatLogListParamVo param);
public String export(PracticeChatLogListParamVo param);
/**
* 查询时间范围内更新的陪练记录
*/
List<PracticeChatLogVo> selectChatLogRangeList(Date startOfDate, Date endOfDate);
}
package com.yizhi.practice.application.xservice;
import com.yizhi.practice.application.pojo.vo.PracticeChatLogBaseInfoVo;
import com.yizhi.practice.application.pojo.vo.PracticeChatRoundLogDetailVo;
public interface PracticeChatRoundLogXService {
/**
* 陪练记录-详情页面-根据陪练记录ID获取学员信息,总得分信息,具体对话信息
* @param practiceChatId
* @return
*/
public PracticeChatLogBaseInfoVo getLogByPracticeChatId(Long practiceChatId);
/**
* 陪练详情-本题分析
* @param chatRoundId
* @return
*/
public PracticeChatRoundLogDetailVo analysis(Long chatRoundId);
}
package com.yizhi.practice.application.xservice
import com.yizhi.core.application.context.RequestContext
import com.yizhi.practice.application.pojo.po.AnalyzeStudentVoicePo
import com.yizhi.practice.application.pojo.po.StartPracticePO
import com.yizhi.practice.application.pojo.vo.*
import org.apache.xpath.operations.Bool
/**
* @Date 2020/10/28 4:48 下午
* @Author lvjianhui
**/
interface PracticeStuChatXService {
/**
* 开始陪练
*/
fun startPractice(startPracticePO: StartPracticePO): StuPracticeLogVo
/**
* 获取所有场景
*/
fun getAllScene(practiceId: Long): List<SceneChatVO>?
/**
* 获取场景第一句机器人话术
*/
fun getRobotFirstChat(practiceId: Long, sceneId: Long, useType: Int): List<ChatContextVo>?
/**
* 更具机器人话术,查询学员话术
*/
fun getStudentContent(sceneId: Long, useType: Int, practiceId: Long, practiceChatLogId: Long, robotChatId: Long): List<StudentChatContextVo>?
/**
* 用户上传录音
*/
fun analyzeStudentVoice(po: AnalyzeStudentVoicePo): ChatResultVo
/**
* 更具学员话术返回机器人话术
*/
fun getRobotLevelChat(practiceId: Long, sceneId: Long, chatRoundConfigId: Long, useType: Int): List<ChatContextVo>
/**
* 陪练结束,返回结果
*/
fun endPractice(practiceId: Long, practiceLogId: Long, useType: Int, requestContext: RequestContext, errorEnd: Boolean): PracticeEndResultVo
fun getLogResult(practiceLogId: Long, accountId: Long): PracticeEndResultVo?
fun deletedAccountUploadId(accountUploadId: Long, context: RequestContext)
}
\ No newline at end of file
package com.yizhi.practice.application.xservice
import com.yizhi.core.application.context.RequestContext
import com.yizhi.practice.application.config.PracticeRunningStatusEnum
import com.yizhi.practice.application.pojo.vo.PracticeConfigVo
import com.yizhi.practice.application.pojo.vo.PracticeJoinedVo
import com.yizhi.util.application.domain.BizResponse
import com.yizhi.util.application.page.PageInfo
/**
* @Date 2020/10/26 3:18 下午
* @Author lvjianhui
**/
interface PracticeStudentXSerice {
/**
* 获取该用户可见的 可参加的陪练数量
* @param accountId
* @param orgId
* @param siteId
* @param companyId
* @return
*/
fun getRunningCount(accountId: Long, orgId: Long, siteId: Long, companyId: Long): Int
/**
* 获取正在进行的陪练
* @param accountId
* @param orgId
* @param siteId
* @param companyId
* @param state
* @see PracticeRunningStatusEnum
*
* @return
*/
fun getRunningList(accountId: Long, orgId: Long, siteId: Long, companyId: Long, state: Int, pageIndex: Int, pageSize: Int): PageInfo<PracticeConfigVo>?
fun getPracticeInfo(practiceId: Long, accountId: Long, orgId: Long, siteId: Long, companyId: Long): PracticeConfigVo
/**
* 获取陪练等级的参加情况
*/
fun getPracticeJoined(practiceId: Long, context: RequestContext): PracticeJoinedVo
/**
* 获取前端走哪个tab 0:未开始 1:进行中 2:已完成
*/
fun getTabIndex(requestContext: RequestContext): Int
/**
* 用户是否可见陪练
*/
fun getUserPracticeAuth(requestContext: RequestContext, practiceId: Long): BizResponse<Boolean>
}
\ No newline at end of file
package com.yizhi.practice.application.xservice;
import com.yizhi.practice.application.pojo.vo.SceneVo;
import com.yizhi.practice.application.request.SceneReq;
import com.yizhi.util.application.domain.BizResponse;
import java.util.List;
/**
* 陪练场景
**/
public interface PracticeXSceneservice {
/**
* 添加/修改场景
* @param sceneReq 场景入参
* @return 场景实体
*/
BizResponse save(SceneReq sceneReq);
/**
* 根据场景id查询场景详情
* @param sceneId 场景id
*/
SceneVo selectScene(Long sceneId);
/**
* 删除场景
* @param sceneId 场景id
*/
BizResponse deleteScene(Long sceneId);
/**
* 查询场景列表
* @param practiceId 陪练id
* @return 场景列表
*/
List<SceneVo> selectSceneList(Long practiceId);
/**
* 修改场景排序
*/
BizResponse updateSceneSort(List<SceneReq> sceneReqList);
}
package com.yizhi.practice.application.xservice;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.yizhi.practice.application.pojo.vo.*;
import com.yizhi.practice.application.request.*;
import com.yizhi.util.application.domain.BizResponse;
import com.yizhi.util.application.page.PageInfo;
import java.util.Date;
import java.util.List;
/**
* @Date 2020/10/22 1:43 下午
* @Author lvjianhui
**/
public interface PracticeXservice {
/**
* 初始化空白草稿状态的陪练
* @return 陪练信息
*/
PracticeBlankDraftVo initBlankDraftPractice();
/**
* 保存智能陪练配置信息
*/
BizResponse savePracticeConfInfo(PracticeConfigInfoReq practiceConfigInfoReq);
/**
* 保存智能陪练策略配置信息
*/
BizResponse savePracticeStrategyInfo(PracticeConfigInfoReq practiceConfigInfoReq);
/**
* 保存对话
*/
BizResponse savePracticeDialogue(List<PracticeSceneDialogueReq> sceneNodeList);
/**
* 获取机器人列表
*/
List<RobotVo> getRobotList();
/**
* 查询陪练列表
* @param practicesGetReq 高级查询参数
* @return 陪练列表
*/
BizResponse<PageInfo<PracticeBaseInfoVo>> getPracticeList(PracticesGetReq practicesGetReq);
/**
* 查询陪练配置信息:基本信息、策略信息
* @param practiceId 陪练id
*/
PracticeConfigInfoVo getPracticeConfigInfo(Long practiceId);
/**
* 查询陪练下所有场景对话
* @param practiceId 陪练id
*/
List<PracticeSceneDialogueVo> getPracticeSceneChatList(Long practiceId,Long sceneId) throws JsonProcessingException;
/**
* 智能陪练上架、下架
* @param practiceId 陪练id
* @param status 陪练状态 上架、下架
*/
BizResponse updatePracticeStatus(Long practiceId, Integer status) throws Exception;
/**
* 保存智能陪练用户信息
* @param practiceAccountReq 陪练用户或者部门信息
*/
BizResponse addPracticeAccount(PracticeAccountReq practiceAccountReq);
/**
* 查询陪练下可见范围的用户和部门
* @param practiceId 陪练id
*/
PracticeVisibleAccountVo getPracticeVisibleList(Long practiceId);
/**
* 导入陪练对话
* @param sceneChatImportReq 对话文件信息
*/
BizResponse importPracticeChat(SceneChatImportReq sceneChatImportReq) throws Exception;
/**
* 清空场景对话
* @param sceneId 场景id
*/
BizResponse clearSceneChat(Long sceneId);
/**
* 复制 陪练
* @param practiceId
* @return
*/
public Long copyPractice(Long practiceId) throws Exception;
/**
* 删除陪练
* @param practiceId 陪练id
*/
BizResponse delete(Long practiceId);
/**
* 导入用户
*/
BizResponse importAccount(PracticeImportAccountReq importAccountReq);
/**
* 导出可见范围
*/
BizResponse exportAccount(Long practiceId);
/**
* 校验陪练下场景以及场景对话是否符合规范
* @param practiceId 陪练id
*/
BizResponse checkPracticeSceneValid(Long practiceId);
/**
* 查询指定时间范围内更新的陪练信息
*/
List<PracticeVo> selectRangeList(Date startDate, Date endDate);
/**
* 查询指定时间范围内更新的陪练信息
*/
List<PracticeVisibleVo> selectVisibleRangeList(Date startOfDate, Date endOfDate);
}
package com.yizhi.practice.application.xservice.impl;
import com.yizhi.core.application.context.ContextHolder;
import com.yizhi.core.application.context.RequestContext;
import com.yizhi.practice.application.controller.manage.export.PracticeChatLogExport;
import com.yizhi.practice.application.enums.PracticeModelStatusEnum;
import com.yizhi.practice.application.pojo.domain.PracticeChatLog;
import com.yizhi.practice.application.pojo.po.PracticeChatLogExportPo;
import com.yizhi.practice.application.pojo.vo.*;
import com.yizhi.practice.application.service.IPracticeChatLogService;
import com.yizhi.practice.application.service.IPracticeConfigService;
import com.yizhi.practice.application.xservice.PracticeChatLogXService;
import com.yizhi.util.application.page.PageInfo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
@Service
public class PracticeChatLogXServiceImpl implements PracticeChatLogXService {
@Autowired
private IPracticeConfigService practiceConfigService;
@Autowired
private IPracticeChatLogService practiceChatLogService;
@Autowired
private PracticeChatLogExport exporter;
@Autowired
private IPracticeChatLogService chatLogService;
@Override
public PracticeChatLogListHeaderVo baseInfo(Long practiceId) {
RequestContext requestContext = ContextHolder.get();
List<Long> ids = new ArrayList<Long>();
ids.add(practiceId);
List<PracticeConfigVo> result = practiceConfigService.getConfigByIds(ids);
if(null == result || result.size() == 0) {
return null;
}
PracticeConfigVo vo = result.get(0);
return PracticeChatLogListHeaderVo.builder().practiceName(vo.getName())
.practiceStartAt(vo.getPracticeStartAt())
.practiceEndAt(vo.getPracticeEndAt())
.examStartAt(vo.getExamStartAt())
.examEndAt(vo.getExamEndAt())
.practicePeopleNumber(practiceChatLogService.peopleNumber(practiceId, PracticeModelStatusEnum.PRACTICE.getStatus(), requestContext))
.practiceTimesNumber(practiceChatLogService.timesNumber(practiceId, PracticeModelStatusEnum.PRACTICE.getStatus(), requestContext))
.examPeopleNumber(practiceChatLogService.peopleNumber(practiceId, PracticeModelStatusEnum.ASSESSMENT.getStatus(), requestContext))
.examTimesNumber(practiceChatLogService.timesNumber(practiceId, PracticeModelStatusEnum.ASSESSMENT.getStatus(), requestContext))
.build();
}
@Override
public PageInfo<PracticeChatLogListVo> list(PracticeChatLogListParamVo param) {
RequestContext requestContext = ContextHolder.get();
return practiceChatLogService.listPage(param, requestContext);
}
@Override
public String export(PracticeChatLogListParamVo param) {
RequestContext requestContext = ContextHolder.get();
List<PracticeChatLogListVo> data = practiceChatLogService.listAll(param, null);
Date date = new Date();
Long taskId = date.getTime();
String serialNo = "PRACTICE-CHAT-LOG-EXPORT" + taskId.toString();
String taskName = param.getPracticeName() + "-导出陪练记录" + taskId.toString();
PracticeChatLogExportPo exportParam = PracticeChatLogExportPo.builder()
.taskId(taskId).serialNo(serialNo)
.taskName(taskName).datas(data)
.companyId(requestContext.getCompanyId())
.siteId(requestContext.getSiteId())
.orgId(requestContext.getOrgId())
.accountId(requestContext.getAccountId())
.isAdmin(requestContext.isAdmin())
.build();
exporter.execute(exportParam, true);
return serialNo;
}
@Override
public List<PracticeChatLogVo> selectChatLogRangeList(Date startDate, Date endDate) {
List<PracticeChatLog> list = chatLogService.getListByTime(startDate,endDate);
if (null == list || list.size() == 0){
return Collections.emptyList();
}
List<PracticeChatLogVo> voList = new ArrayList<>();
for (PracticeChatLog chatLog : list) {
PracticeChatLogVo vo = new PracticeChatLogVo();
BeanUtils.copyProperties(chatLog,vo);
voList.add(vo);
}
return voList;
}
@Override
public PageInfo<StudentPracticeLogVo> studentList(PracticeChatLogListParamVo param) {
RequestContext requestContext = ContextHolder.get();
return practiceChatLogService.studentListPage(param, requestContext);
}
}
package com.yizhi.practice.application.xservice.impl;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSONObject;
import com.mysql.jdbc.StringUtils;
import com.yizhi.practice.application.pojo.dto.PracticeChartRoundLogDto;
import com.yizhi.practice.application.pojo.vo.LocalJSONObject;
import com.yizhi.practice.application.pojo.vo.PracticeChatLogBaseInfoVo;
import com.yizhi.practice.application.pojo.vo.PracticeChatLogSceneVo;
import com.yizhi.practice.application.pojo.vo.PracticeChatRoundLogDetailVo;
import com.yizhi.practice.application.pojo.vo.PracticeChatRoundLogVo;
import com.yizhi.practice.application.service.IPracticeChatLogService;
import com.yizhi.practice.application.service.IPracticeChatRoundLogService;
import com.yizhi.practice.application.util.LocalStringUtil;
import com.yizhi.practice.application.xservice.PracticeChatRoundLogXService;
@Service
public class PracticeChatRoundLogXServiceImpl implements PracticeChatRoundLogXService {
@Autowired
private IPracticeChatRoundLogService roundService;
@Autowired
private IPracticeChatLogService chatService;
@Override
public PracticeChatLogBaseInfoVo getLogByPracticeChatId(Long practiceChatId) {
PracticeChatLogBaseInfoVo base = chatService.get(practiceChatId);
List<PracticeChatRoundLogVo> details = roundService.getByPracticeChatId(practiceChatId);
List<PracticeChatRoundLogVo> maxScoreDetails = new ArrayList<PracticeChatRoundLogVo>();
// 按照场景ID,对话层级分组,选出同一个场景,同一个对话层级中分数最高的(同一个会话可以重复作答,选出分数最高的)
details.stream().collect(Collectors.groupingBy(PracticeChatRoundLogVo::getSceneId
, Collectors.groupingBy(PracticeChatRoundLogVo::getRoundLevel
, Collectors.maxBy(Comparator.comparing(PracticeChatRoundLogVo::getCreatedAt)))))
.forEach((k, v) -> {v.forEach((k1, v1) -> maxScoreDetails.add(v1.get()));});
// 对上一步的结果 按照 场景sort,对话层级 进行排序
List<PracticeChatLogSceneVo> scenes = maxScoreDetails.stream()
.sorted(Comparator.comparing(PracticeChatRoundLogVo::getSort).thenComparing(Comparator.comparing(PracticeChatRoundLogVo::getRoundLevel)))
// 对上一步排序后的结果 按照 场景ID进行分组
.collect(Collectors.groupingBy(PracticeChatRoundLogVo::getSceneId, LinkedHashMap::new, Collectors.toList()))
.entrySet().stream()
// 分组后的场景 组装成VO
.map(kvSet -> PracticeChatLogSceneVo.builder()
.sceneId(kvSet.getKey())
.sceneName(kvSet.getValue().get(0).getSceneName())
.sort(kvSet.getValue().get(0).getSort())
.chats(kvSet.getValue()).build())
.collect(Collectors.toList());
base.setScenes(scenes);
return base;
}
/**
* 返回json对象集合,json对象生成规则<br/>
* :1.如果关键词命中,则key为关键词,value为空字符串;<br/>
* 2.如果关键词没命中,如果拓展词命中,则key为关键词,value是命中的首个拓展词<br/>
* 3.如果关键词没命中,拓展词没命中,则key为关键词,value为空字符串
* @param hitKeywordString 命中的关键词,以及拓展词 的字符串,分号分隔
* @param keywordString 话术配置的关键词以及拓展词的字符串,形如:"{'关键词1':'拓展词11;拓展词12', '关键词2':'拓展词2'}"
* @return 返回这样的json对象集合,形如:[{'关键词1':'拓展词2'}, {'关键词2':''},...]
*/
public List<LocalJSONObject> constructKeyWordInfo(String hitKeywordString, String keywordString){
// 没配置关键词拓展词
if(StringUtils.isNullOrEmpty(keywordString)) {
return null;
}
List<LocalJSONObject> result = new ArrayList<LocalJSONObject>();
// 解析配置的关键词拓展词
Map<String, Object> keywordMap = (Map<String, Object>) JSONObject.parse(keywordString);
// 没命中任何关键词拓展词
if(StringUtils.isNullOrEmpty(hitKeywordString)) {
for(String keyword : keywordMap.keySet()) {
result.add(LocalJSONObject.builder().key(keyword).value("").build());
}
return result;
}
// 解析命中的关键词拓展词
List<String> hitWords = LocalStringUtil.hit(hitKeywordString);
// 遍历配置的关键词拓展词,构造json对象
for(String keyword : keywordMap.keySet()) {
// 关键词直接命中
if(hitWords.contains(keyword)) {
result.add(LocalJSONObject.builder().key(keyword).value("").build());
}else {
// 关键词没命中,判断拓展词是否命中
result.add(LocalJSONObject.builder()
.key(keyword)
.value(findHitExtendWord((String)keywordMap.get(keyword), hitWords))
.build());
}
}
return result;
}
private String findHitExtendWord(String allExtendWord, List<String> hitWords) {
String hitExtendWord = "";
for(String hit : hitWords) {
if(allExtendWord.indexOf(hit) != -1) {
hitExtendWord = hit;
break;
}
}
return hitExtendWord;
}
@Override
public PracticeChatRoundLogDetailVo analysis(Long chatRoundId) {
PracticeChartRoundLogDto origin = roundService.getRoundLogById(chatRoundId);
return PracticeChatRoundLogDetailVo.builder()
.keyWord(constructKeyWordInfo(origin.getAccountHitKeyword(), origin.getKeyWord()))
.keywordHit(LocalStringUtil.hit(origin.getAccountHitKeyword()))
.forbidHit(LocalStringUtil.hit(origin.getForbidHit()))
.totalScore(origin.getTotalScore())
.keywordScore(origin.getKeywordScore())
.completeScore(origin.getCompleteScore())
.smoothScore(origin.getSmoothScore())
// TODO 分数段 提示语 map
.smoothHint("您的话术很流畅")
.expressScore(origin.getExpressScore())
// TODO 分数段 提示语 map
.expressHint("您的表达能力很不错")
.politeScore(origin.getPoliteScore())
// TODO 分数段 提示语 map
.politeHint("您未使用礼貌用语")
.accountContent(origin.getAccountContent())
.accountContentVoiceUrl(origin.getAccountContentVoiceUrl())
.accountDuration(origin.getAccountDuration())
.robotContent(origin.getRobotContent())
.robotContentUrl(origin.getRobotContentUrl())
.robotDuration(origin.getRobotDuration())
.build();
}
}
package com.yizhi.practice.application.xservice.impl
import cn.hutool.core.util.RandomUtil
import com.alibaba.fastjson.JSON
import com.alibaba.fastjson.JSONObject
import com.yizhi.application.orm.id.IdGenerator
import com.yizhi.core.application.context.ContextHolder
import com.yizhi.core.application.context.RequestContext
import com.yizhi.core.application.enums.InternationalEnums
import com.yizhi.core.application.exception.BizException
import com.yizhi.point.application.feign.PointRedisFeignClients
import com.yizhi.point.application.vo.PointParamVO
import com.yizhi.practice.application.config.AudioUtils
import com.yizhi.practice.application.config.PracticeLevelEnum
import com.yizhi.practice.application.config.PracticeRunningStatusEnum
import com.yizhi.practice.application.constants.PracticeConstant
import com.yizhi.practice.application.constants.PracticePointConstant
import com.yizhi.practice.application.enums.*
import com.yizhi.practice.application.enums.PracticePassResultEnum.PASS
import com.yizhi.practice.application.enums.PracticePassResultEnum.UN_PASS
import com.yizhi.practice.application.mapper.PracticeChatRoundLogMapper
import com.yizhi.practice.application.pojo.domain.*
import com.yizhi.practice.application.pojo.dto.PracticeAllScoreDto
import com.yizhi.practice.application.pojo.po.AnalyzeStudentVoicePo
import com.yizhi.practice.application.pojo.po.StartPracticePO
import com.yizhi.practice.application.pojo.vo.*
import com.yizhi.practice.application.repository.*
import com.yizhi.practice.application.service.*
import com.yizhi.practice.application.third.aliyun.AliyunUtil
import com.yizhi.practice.application.third.baidu.BaiduUtil
import com.yizhi.practice.application.third.util.OssFileUtil
import com.yizhi.practice.application.third.xunfei.XunfeiUtil
import com.yizhi.practice.application.xservice.PracticeStuChatXService
import com.yizhi.system.application.system.remote.OrganizationClient
import com.yizhi.wechat.application.feign.AccessTokenClient
import com.yizhi.wechat.application.feign.WeChatTokenClient
import org.apache.commons.io.FileUtils
import org.apache.commons.lang.StringUtils
import org.springframework.amqp.core.AmqpTemplate
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Service
import ws.schild.jave.*
import java.io.File
import java.io.InputStream
import java.math.BigDecimal
import java.math.RoundingMode
import java.net.URL
import java.util.*
import kotlin.collections.ArrayList
import kotlin.collections.HashMap
import kotlin.random.Random
/**
* @Date 2020/10/28 4:49 下午
* @Author lvjianhui
**/
@Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS")
@Service
class PracticeStuXServiceImpl : PracticeStuChatXService {
@Autowired
lateinit var practiceChatLogRepository: PracticeChatLogRepository
@Autowired
lateinit var practiceChatLogService: IPracticeChatLogService
@Autowired
lateinit var practiceConfigRepository: PracticeConfigRepository
@Autowired
lateinit var sceneConfigService: ISceneConfigService
@Autowired
lateinit var sceneChatConfigService: ISceneChatConfigService
@Autowired
lateinit var practiceChatRoundLogService: IPracticeChatRoundLogService
@Autowired
lateinit var practiceChatroundLogRepository: PracticeChatRoundLogRepository
@Autowired
lateinit var sceneChatConfigRepository: SceneChatConfigRepository
@Autowired
lateinit var iPracticePointRuleConfigService: IPracticePointRuleConfigService
@Autowired
lateinit var iPracticePointGivenLogService: IPracticePointGivenLogService
@Autowired
lateinit var idGenerator: IdGenerator
private val logger = org.slf4j.LoggerFactory.getLogger(javaClass)
@Autowired
lateinit var xunfeiUtil: XunfeiUtil
@Autowired
lateinit var baiduUtil: BaiduUtil
@Value("\${yizhi.practice.polite.word}")
var politeWord: String? = null
@Autowired
lateinit var practicePointGivenLogRepository: PracticePointGivenLogRepository
@Autowired
lateinit var practiceChatRoundLogMapper: PracticeChatRoundLogMapper
@Autowired
lateinit var amqpTemplate: AmqpTemplate
@Autowired
lateinit var pointRedisFeignClients: PointRedisFeignClients
@Autowired
lateinit var organizationClient: OrganizationClient
@Autowired
lateinit var accessTokenClient: AccessTokenClient
@Autowired
lateinit var weChatTokenClient: WeChatTokenClient
@Autowired
lateinit var aliyunUtil: AliyunUtil
constructor()
override fun getRobotLevelChat(practiceId: Long, sceneId: Long, chatRoundConfigId: Long, useType: Int): List<ChatContextVo> {
val list = sceneChatConfigService.selectChatNodes(practiceId, sceneId, PracticeNodeEnum.ROBOT.status, chatRoundConfigId, null)
val vos = arrayListOf<ChatContextVo>()
list.forEach {
val vo = ChatContextVo()
vo.chatId = it.id
vo.context = it.robotContent
vo.voiceUrl = it.robotContentVoiceUrl
vo.voiceDuration = it.robotContentVoiceDuration
vos.add(vo)
}
return vos.shuffled()
}
override fun deletedAccountUploadId(accountUploadId: Long, context: RequestContext) {
val log = practiceChatroundLogRepository.findById(accountUploadId).get()
log.deleted = true
practiceChatroundLogRepository.save(log)
}
override fun getLogResult(practiceLogId: Long, accountId: Long): PracticeEndResultVo? {
val log = practiceChatLogService.get(practiceLogId) ?: let {
logger.error("陪练结束时查询陪练记录出错 practiceLogId:$practiceLogId")
throw BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2)
}
val vo = PracticeEndResultVo()
return vo
}
override fun endPractice(practiceId: Long, practiceLogId: Long, useType: Int, requestContext: RequestContext, errorEnd: Boolean): PracticeEndResultVo {
val practiceConfig = practiceConfigRepository.getOne(practiceId) ?: let {
logger.error("查询陪练参数有误 practiceId:${practiceId}")
throw BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2)
}
val log = practiceChatLogRepository.findById(practiceLogId).get()
if (log.status != PracticeChatLogStatusEnum.ING.status) {
logger.error("陪练结束时陪练状态出错 practiceLogId:$practiceLogId status:${log.status}")
throw BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2)
}
val vo = PracticeEndResultVo()
if (errorEnd) {
log.status = PracticeChatLogStatusEnum.QUIT.status
log.endAt = Date()
practiceChatLogRepository.save(log)
return vo
}
log.status = PracticeChatLogStatusEnum.DONE.status
log.endAt = Date()
val dto = practiceChatRoundLogMapper.getScoreByAccount(practiceLogId, requestContext.accountId, requestContext.orgId, requestContext.siteId, requestContext.companyId)
logger.info("all Score" + JSONObject.toJSONString(dto) + "practiceLogId :$practiceLogId accountIdL:${requestContext.accountId} orgId:${requestContext.orgId}")
log.keywordScore = dto?.keyWordScore?.toInt() ?: 0
log.keywordRate = practiceConfig.scoreRuleKeyword
log.completeScore = dto?.complateScore?.toInt() ?: 0
log.completeRate = practiceConfig.scoreRuleComplete
log.politeScore = dto?.politeScore?.toInt() ?: 0
log.politeRate = practiceConfig.scoreRulePolite
log.expressScore = dto?.expressScore?.toInt() ?: 0
log.expressRate = practiceConfig.scoreRuleExpress
log.smoothScore = dto?.fluencyScore?.toInt() ?: 0
log.smoothRate = practiceConfig.scoreRuleSmooth
log.averageScore = dto?.averageScore?.toInt() ?: 0
vo.score = log.averageScore
if (null == log.passMinScore) {
practiceChatLogRepository.save(log)
return vo
}
if (log.averageScore >= log.passMinScore) {
log.passResult = PASS.status
vo.passSuccess = true
} else {
log.passResult = UN_PASS.status
vo.passSuccess = false
}
practiceChatLogRepository.save(log)
// 送积分
givenPoint(log, practiceConfig.name)
return vo
}
private fun givenPoint(practiceLog: PracticeChatLog, practiceName: String) {
if (practiceLog.useType == PracticeModelStatusEnum.PRACTICE.status) {
return
}
if (practiceLog.givenPointType != PracticePointGivenEnum.TRUE.status) {
return
}
val score = practiceLog.averageScore ?: 0
val configRule = iPracticePointRuleConfigService.selectPointRulesByPractice(practiceLog.practiceId, score, false)
?: return
// 统计已送出的分数
val pointSum = iPracticePointGivenLogService.sumPointByUserAndPractice(
accountId = practiceLog.accountId,
practiceId = practiceLog.practiceId,
companyId = practiceLog.companyId,
siteId = practiceLog.siteId,
orgId = practiceLog.orgId)
val planGivenPoint = configRule.point ?: let {
return
}
val actualPoint = planGivenPoint - pointSum
if (actualPoint <= 0) {
logger.info("完成对话不赠送积分,得分已够 accountId:${practiceLog.accountId} ${practiceLog.accountFullName} planGivenPoint:$planGivenPoint pointSum:$pointSum")
return
}
// 更新log
practiceLog.status = PracticeChatLogStatusEnum.DONE.status
practiceLog.endAt = Date()
practiceLog.givenPointCount = actualPoint
practiceChatLogRepository.save(practiceLog)
// 送积分
val givenLog = PracticePointGivenLog()
givenLog.accountId = practiceLog.accountId
givenLog.companyId = practiceLog.companyId
givenLog.siteId = practiceLog.siteId
givenLog.orgId = practiceLog.orgId
givenLog.practiceId = practiceLog.practiceId
givenLog.practiceScore = practiceLog.averageScore
givenLog.point = actualPoint
givenLog.pointRuleId = configRule.id
givenLog.id = idGenerator.generate()
practicePointGivenLogRepository.save(givenLog)
mqSendPoint(givenLog, practiceName)
}
private fun mqSendPoint(pointLog: PracticePointGivenLog, practiceName: String) {
val pointParamVO = PointParamVO()
pointParamVO.eventName = PracticePointConstant.POINT_EVENT_NAME //事件名称
pointParamVO.activityType = PracticePointConstant.POINT_ACTIVITY_TYPE //事件类型
pointParamVO.activitySource = PracticePointConstant.POINT_ACTIVITY_SOURCE //学习活动来源
pointParamVO.activityName = practiceName //学习活动名称
pointParamVO.releaseCondition = "范围发放" //发放条件
pointParamVO.releaseRules = "按照范围取积分" //发放规则
pointParamVO.createPointTime = Date() //积分创建时间
pointParamVO.sourceId = pointLog.id //积分来源ID,(业务ID主键)
pointParamVO.operatingPoint = pointLog.point //积分数量, 正数 加积分, 负数减积分
pointParamVO.accountId = pointLog.accountId //学员ID
pointParamVO.companyId = pointLog.companyId //企业ID
pointParamVO.siteId = pointLog.siteId //站点ID
pointParamVO.orgId = pointLog.orgId //组织ID
pointParamVO.score = pointLog.point
val sitePointId = pointRedisFeignClients.addPointRedis(pointParamVO) //调用积分接口添加积分
amqpTemplate.convertAndSend(pointParamVO.eventName, sitePointId) //发送积分获取消息
}
// 第二步 查看是否保存上句机器人话术log,如果没有 则保存,否则nothing
// 第三步 调用第三发打分,计算得分,保存log
// 第四步 如果是考试,判断语意相识度
// 第五步 根据考试或者陪练,计算是否通过。
// 最后返回结果
override fun analyzeStudentVoice(po: AnalyzeStudentVoicePo): ChatResultVo {
if (!po.ignore) {
buildAliOSSUrl(po)
}
var inputStream: InputStream? = null
var pcmFile: File? = null
try {
if (!PracticeModelStatusEnum.getAllStatus().contains(po.useType)) {
logger.error("陪练参数错误:${po.useType}")
throw BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2)
}
val practiceConfig = practiceConfigRepository.getOne(po.practiceId!!) ?: let {
logger.error("查询陪练参数有误 practiceId:${po.practiceId}")
throw BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2)
}
// 得分
var allScore: PracticeAllScoreDto? = null
// 学员话术
var accountUploadContext: String? = null
var similar: Pair<Int, Long>? = null
var accountChatConfigId = po.chatRoundConfigId
var accountChatConfig = sceneChatConfigRepository.getOne(accountChatConfigId)
if (!po.ignore) {
if (StringUtils.isNotEmpty(po.voiceUrl)) {
pcmFile = AudioUtils.wavToPcm(po.voiceUrl!!)
inputStream = pcmFile!!.inputStream()
}
// 解析学员话术
accountUploadContext = getAccountContent(inputStream!!)
// 根据学员话术相似度判断走那条分支
similar = similarScore(po, accountUploadContext)
accountChatConfigId = similar.second
accountChatConfig = sceneChatConfigRepository.getOne(accountChatConfigId)
// 获取学员话术分支
inputStream = pcmFile!!.inputStream()
allScore = getAllScore(inputStream, practiceConfig, accountUploadContext, accountChatConfig!!, PracticeModelStatusEnum.getByStatus(po.useType))
inputStream.close()
pcmFile.deleteOnExit()
}
val robotChatConfig = sceneChatConfigRepository.getOne(accountChatConfig?.pid ?: accountChatConfigId)
// 保存机器人话术log
saveRobotChatLog(po, robotChatConfig)
val accountLog = saveAccountChatLog(
practiceConfig.examPassMinScore,
practiceConfig.similarityRate,
similar?.first,
po,
accountChatConfig,
allScore,
accountUploadContext)
val vo = ChatResultVo()
vo.accountUploadId = accountLog.id
vo.hitTabooWord = allScore?.hitTabooWord ?: arrayListOf<String>()
vo.duration = accountLog.accountContentVoiceDuration
vo.score = allScore?.average
vo.voiceUrl = accountLog.accountContentVoiceUrl
vo.content = accountUploadContext
vo.chatRoundConfigId = accountChatConfigId
vo.contentHitKeyWord = accountLog.accountHitKeyword.split(PracticeConstant.KEY_WORD_SPERATOR_EN)
if (po.ignore) {
vo.passSuccess = true
vo.content = accountChatConfig.accountContent
} else {
vo.passSuccess = getPassResult(po, allScore!!, practiceConfig, accountChatConfigId, similar)
}
if (vo.passSuccess) {
return vo
}
// 失败次数大于允许次数,则弹窗提示
var limitPushCount = practiceConfig.examFailedMaxCount
if (po.useType!! == PracticeModelStatusEnum.PRACTICE.status) {
limitPushCount = practiceConfig.practiceFailedMaxCount
vo.customizeFileMsg = "您的回答与标准话术不符,请重新回答。"
} else {
vo.customizeFileMsg = PracticeConstant.EXAM_FAIL_MESSAGE
}
// 未通过且次数大于限制次数
val pushCount = getLevelChatCunt(po.chatRoundLevel!!, po.practiceLogId!!, practiceConfig.id!!, po.requestContext!!)
if (pushCount > limitPushCount) {
vo.unPassTipSskip = true
}
// 考核模式下 未通过时且 设置自定已回复
if (po.useType!! == PracticeModelStatusEnum.ASSESSMENT.status
&& !vo.passSuccess
&& practiceConfig.similarityFailedMsgType == PracticeSimilaryFailedEnum.FALSE.status) {
vo.customizeFileMsg = practiceConfig.similarityFailedMsg.split(PracticeConstant.KEY_WORD_SPERATOR_EN).shuffled().firstOrNull()
}
return vo
} catch (e: Exception) {
e.printStackTrace()
logger.error("用户上传语音异常====${po.requestContext!!.accountFullName} ===${po.requestContext!!.orgName} ====${po.requestContext!!.companyName}", e)
throw BizException(InternationalEnums.TPPLANCONTROLLER6)
} finally {
inputStream?.close()
pcmFile?.deleteOnExit()
}
}
/**
* 获取是否通过的结果
*/
private fun getPassResult(po: AnalyzeStudentVoicePo, allScore: PracticeAllScoreDto, practiceConfig: PracticeConfig, accountChatConfigId: Long?, similar: Pair<Int, Long>?): Boolean {
var passSuccess = po.ignore
if (passSuccess) return passSuccess
if (po.useType!! == PracticeModelStatusEnum.PRACTICE.status) {
when {
po.ignore -> {
passSuccess = true
}
practiceConfig.startNextRoundType == PracticeDiaConditionEnum.FALSE.status -> {
passSuccess = true
}
practiceConfig.startNextRoundScore < allScore.average -> {
passSuccess = true
}
}
} else if (po.useType!! == PracticeModelStatusEnum.ASSESSMENT.status) {
when {
practiceConfig.manyRoundChat == PracticeManyRoudChatEnum.FALSE.status -> {
passSuccess = true
}
similar!!.first >= practiceConfig.similarityRate -> {
passSuccess = true
}
checkPushCount(po.practiceLogId!!, accountChatConfigId!!, po.requestContext!!) > practiceConfig.examFailedMaxCount -> {
passSuccess = true
}
}
}
return passSuccess
}
private fun saveAccountChatLog(
passMinScore: Int?,
passSimilarityRate: Int?,
similarityScore: Int?,
po: AnalyzeStudentVoicePo,
accountChatConfig: SceneChatConfig,
allScore: PracticeAllScoreDto?,
accountVoiceContent: String?
): PracticeChatRoundLog {
val context = po.requestContext!!
var log = PracticeChatRoundLog();
log.id = idGenerator.generate()
log.practiceId = po.practiceId
log.sceneId = po.senceId
log.sceneChatId = accountChatConfig.id
log.practiceChatId = po.practiceLogId
log.accountId = context.accountId
log.accountName = context.accountName
log.accountFullName = context.accountFullName
log.accountContent = accountVoiceContent
log.accountContentVoiceDuration = accountChatConfig.accountContentVoiceDuration
log.accountContentVoiceUrl = accountChatConfig.accountContentVoiceUrl
log.passMinScore = passMinScore
log.passSimilarityRate = passSimilarityRate
log.roundSkipType = PracticeSkipEnum.SKIP.code
log.roundLevel = po.chatRoundLevel
log.accountHitTabooWord = allScore?.hitTabooWord?.joinToString(PracticeConstant.KEY_WORD_SPERATOR_EN)
log.accountHitKeyword =
JSON.parseObject(accountChatConfig.accountContentKeyword, Map::class.java).keys.joinToString(PracticeConstant.KEY_WORD_SPERATOR_EN)
if (!po.ignore) {
log.roundSkipType = PracticeSkipEnum.NOT_SKIP.code
log.similarityScore = similarityScore
log.accountContentVoiceUrl = po.voiceUrl
log.accountContentVoiceDuration = po.voiceDuration
log.accountHitKeyword = allScore!!.keyWordScore!!.second.joinToString(PracticeConstant.KEY_WORD_SPERATOR_EN)
log.keywordScore = allScore.keyWordScore!!.first
log.completeScore = allScore.complateScore
log.smoothScore = allScore.fluencyScore
log.expressScore = allScore.expressScore
log.politeScore = allScore.politeScore
log.averageScore = allScore.average
} else {
log.accountContent = accountChatConfig.accountContent
}
log.orgId = context.orgId
log.siteId = context.siteId
log.orgName = context.orgName
log.companyId = context.companyId
log = practiceChatroundLogRepository.save(log)
return log
}
private fun saveRobotChatLog(po: AnalyzeStudentVoicePo, robotChatConfig: SceneChatConfig) {
// 首先查看机器人话术有没有保存
val context = po.requestContext!!
insertRobotRoundLog(po.practiceId!!,po.senceId!!,po.practiceLogId!!,context,robotChatConfig)
}
// 查看指定对话提交次数
fun checkPushCount(practiceLogId: Long, chatRoundConfigId: Long, context: RequestContext): Long {
val count = practiceChatRoundLogService.getCountByUserId(
practiceLogId,
chatRoundConfigId,
context.accountId,
context.orgId,
context.siteId,
context.companyId)
return count
}
fun getLevelChatCunt(level: Int, practiceLogId: Long, practiceId: Long, context: RequestContext): Long {
return practiceChatRoundLogService.getLevelCountByAccount(level, practiceLogId, practiceId, context.accountId, context.orgId, context.siteId, context.companyId)
?: 0
}
fun getAccountContent(inputStream: InputStream): String {
return xunfeiUtil.voiceToString(inputStream, PracticeVoiceTypeEnum.PCM)
}
/**
* 相似度得分
*/
private fun similarScore(po: AnalyzeStudentVoicePo, accountContent: String): Pair<Int, Long> {
val list = arrayListOf<SceneChatConfig>()
if (po.useType == PracticeModelStatusEnum.PRACTICE.status) {
val sceneConfig = sceneChatConfigRepository.findById(po.chatRoundConfigId).get()
list.add(sceneConfig)
} else {
val manyRound = sceneChatConfigService.selectChatNodes(po.practiceId, po.senceId, PracticeNodeEnum.STUDENT.status, null, po.chatRoundLevel)
?: let {
logger.error("查询学员标准话术失败。accountId:${po.requestContext!!.accountId},practiceId:${po.practiceId},sceneId:${po.senceId},level:${po.chatRoundLevel}")
throw BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2)
}
list.addAll(manyRound)
}
val map = HashMap<Int, Long>()
list.forEach {
val score = baiduUtil.getSimilarRate(accountContent, it.accountContent).multiply(BigDecimal(100)).toInt()
map[score] = it.id
}
val similarScore = map.keys.sortedDescending().firstOrNull() ?: 0
// 相似度
val scenChatId = map[similarScore]!!
return Pair(similarScore, scenChatId)
}
/**
* 获取各个维度得分
* 1、评分从五个维度打分:完整性、关键词命中、流畅性、表达能力、礼貌用语;五个维度加起来为100分,各个维度为【0,100】的正整数。
默认占比:关键词:40、完整性:30、流畅性:20、表达能力:5、礼貌用语:5
1)关键词命中得分:通过对话中的关键词命中判断得分,一段标准答案中有n个关键词,命中m(m<=n)个,则该段对话关键词得分为: m/n*关键词分数,
训练模式下:只有关键词命中才算得分
考核模式下:关键词及关键词对应的拓展词命中算得分
2) 完整性得分:完整性得分系数(讯飞接口)%*完整性设置的分数,
3) 流畅性得分:流畅性得分系数(讯飞接口)%*流畅性设置的分数
4) 表达能力得分:(声韵分系数+调型分系数)/2%*表达能力设置的分数
5) 礼貌用语得分:使用礼貌用语得分、未使用礼貌用语或命中敏感词则不得分
1~5中得分四舍五入取整
2、一句话的综合得分为 K=完整性得分+关键词命中得分+流畅性得分+表达能力得分+礼貌用语得分
3、陪练综合得分每题得分的平均分,四舍五入取整
4、若一句对话中命中禁忌词,则该句所有分数项为0分
*/
fun getAllScore(inputStream: InputStream,
practiceconfig: PracticeConfig,
accountContent: String?,
accountSceneChatConfig: SceneChatConfig,
practiceModel: PracticeModelStatusEnum): PracticeAllScoreDto {
val dto = PracticeAllScoreDto()
if (StringUtils.isEmpty(accountContent)) {
return dto;
}
val hitTabooWord = arrayListOf<String>()
if (!StringUtils.isEmpty(accountSceneChatConfig.accountContentTabooWord)) {
val taboo = accountSceneChatConfig.accountContentTabooWord.replace(PracticeConstant.KEY_WORD_SPERATOR_CN, PracticeConstant.KEY_WORD_SPERATOR_EN).split(PracticeConstant.KEY_WORD_SPERATOR_EN)
// 命中禁忌词,所有分数为0
taboo.filter { !StringUtils.isEmpty(it) && accountContent!!.contains(it) }.forEach {
hitTabooWord.add(it)
}
dto.hitTabooWord = hitTabooWord
if (hitTabooWord.size > 0) {
return dto
}
}
val result = xunfeiUtil.evaluate(accountSceneChatConfig.accountContent, inputStream, PracticeVoiceTypeEnum.PCM)
logger.info("打分结果 result:$result")
dto.fluencyScore = result.fluencyScore.multiply(BigDecimal(practiceconfig.scoreRuleSmooth)).toInt()
dto.complateScore = result.integrityScore.multiply(BigDecimal(practiceconfig.scoreRuleComplete)).toInt()
dto.keyWordScore = getKeyWordScore(accountContent!!,
practiceconfig.scoreRuleKeyword,
accountSceneChatConfig.accountContentKeyword,
practiceModel)
dto.expressScore = (result.phoneScore.add(result.toneScore)).divide(BigDecimal(2)).multiply(BigDecimal(practiceconfig.scoreRuleExpress)).toInt()
var politeScore = 0
val politeList = replaceSperatorCn(politeWord!!)
politeList.filter { accountContent.contains(it) }.forEach { _ ->
politeScore = practiceconfig.scoreRulePolite
}
dto.politeScore = politeScore
dto.average = dto.fluencyScore + dto.complateScore + dto.keyWordScore.first + dto.expressScore + dto.politeScore
return dto
}
private fun replaceSperatorCn(content: String): List<String> {
return content.replace(PracticeConstant.KEY_WORD_SPERATOR_CN, PracticeConstant.KEY_WORD_SPERATOR_EN).split(PracticeConstant.KEY_WORD_SPERATOR_EN)
}
/**
* 获取关键词得分
*/
private fun getKeyWordScore(accountContent: String,
scoreRuleKeyword: Int,
accountContentKeyword: String,
practiceModel: PracticeModelStatusEnum): Pair<Int, List<String>> {
val keyWord = accountContentKeyword
val map = JSON.parseObject(keyWord, Map::class.java)
var count = 0
val list = arrayListOf<String>()
// 训练模式
if (practiceModel.status == PracticeModelStatusEnum.PRACTICE.status) {
map.keys.filter { !StringUtils.isEmpty(it as String) && accountContent.contains(it) }.forEach {
count++
list.add(it as String)
}
val score = BigDecimal(count).divide(BigDecimal(map.keys.size), 2, RoundingMode.HALF_UP).multiply(BigDecimal(scoreRuleKeyword))
return Pair(score.toInt(), list)
}
// 考核模式 命中关键词和拓展词均得分
map.forEach {
val key = it.key as String
val valueList = replaceSperatorCn(it.value as String).toMutableList()
valueList.add(key)
for (value in valueList) {
if (!StringUtils.isEmpty(value) && accountContent.contains(value)) {
count++
list.add(value)
return@forEach
}
}
}
var score = BigDecimal(count).divide(BigDecimal(map.keys.size), 2, RoundingMode.HALF_UP).multiply(BigDecimal(scoreRuleKeyword)).toInt()
if (score > scoreRuleKeyword) {
score = scoreRuleKeyword
}
return Pair(score, list)
}
override fun getStudentContent(sceneId: Long, useType: Int, practiceId: Long, practiceChatLogId: Long, robotChatId: Long): List<StudentChatContextVo>? {
var list = sceneChatConfigService.selectChatNodes(practiceId, sceneId, PracticeNodeEnum.STUDENT.status, robotChatId, null)
if (list == null || list.isEmpty()) {
//TODO 如果学员话术为空,则保存一条机器人话术至roundLog
val context = ContextHolder.get()
val robotChatConfig = sceneChatConfigRepository.findById(robotChatId).get()
insertRobotRoundLog(practiceId, sceneId, practiceChatLogId, context,robotChatConfig)
return null
}
// 如果是考试 只返回随机一条
if (useType == PracticeModelStatusEnum.ASSESSMENT.status) {
list = arrayListOf(list[Random.nextInt(0, list.size)])
}
val vos = arrayListOf<StudentChatContextVo>()
list.forEach {
val vo = StudentChatContextVo()
vo.chatRoundConfigId = it.id
vo.context = it.accountContent
vo.voiceUrl = it.accountContentVoiceUrl
vo.keyWord = getKeyWord(it.accountContentKeyword)
vo.level = it.level
vos.add(vo)
}
return vos
}
private fun insertRobotRoundLog(practiceId: Long, sceneId: Long, practiceChatLogId: Long, context: RequestContext,robotSceneChatConfig: SceneChatConfig) {
val count = practiceChatRoundLogService.getCountByUserId(
practiceChatLogId,
robotSceneChatConfig.id,
context.accountId,
context.orgId,
context.siteId,
context.companyId)
if (count > 0) {
return
}
val log = PracticeChatRoundLog();
log.id = idGenerator.generate()
log.practiceId = practiceId
log.sceneId = sceneId
log.sceneChatId = robotSceneChatConfig.id
log.practiceChatId = practiceChatLogId
log.accountId = context.accountId
log.accountName = context.accountName
log.accountFullName = context.accountFullName
log.robotContent = robotSceneChatConfig.robotContent
log.robotContentVoiceUrl = robotSceneChatConfig.robotContentVoiceUrl
log.robotContentVoiceDuration = robotSceneChatConfig.robotContentVoiceDuration
log.roundLevel = robotSceneChatConfig.level
log.orgId = context.orgId
log.siteId = context.siteId
log.orgName = context.orgName
log.companyId = context.companyId
practiceChatroundLogRepository.save(log)
}
private fun getKeyWord(keyWordContext: String): List<String> {
return JSONObject.parseObject(keyWordContext).toMap().keys.toList()
}
override fun getRobotFirstChat(practiceId: Long, sceneId: Long, useType: Int): List<ChatContextVo>? {
val list = sceneChatConfigService.selectChatNodes(practiceId, sceneId, PracticeNodeEnum.ROBOT.status, null, 1)
if (list == null || list.isEmpty()) {
return null
}
// 如果是考试 只返回随机一条
if (useType == PracticeModelStatusEnum.ASSESSMENT.status) {
val chatConfig = list.shuffled().first()
list.clear()
list.add(chatConfig)
}
val vos = arrayListOf<ChatContextVo>()
list.forEach {
val vo = ChatContextVo()
vo.chatId = it.id
vo.context = it.robotContent
vo.voiceUrl = it.robotContentVoiceUrl
vo.voiceDuration = it.robotContentVoiceDuration
vos.add(vo)
}
return vos
}
override fun getAllScene(practiceId: Long): List<SceneChatVO>? {
val list = sceneConfigService.findSceneByPracticeId(practiceId) ?: let {
return null
}
val vos = ArrayList<SceneChatVO>()
list.forEach {
val vo = SceneChatVO();
vo.sceneDescription = it.description
vo.sceneName = it.name
vo.sceneId = it.id
vos.add(vo)
}
return vos
}
override fun startPractice(params: StartPracticePO): StuPracticeLogVo {
if (!PracticeModelStatusEnum.getAllStatus().contains(params.useType)
|| !PracticeLevelEnum.getAlllevel().contains(params.level)) {
logger.error("startPractice useType :{} is erro Or level :{} is error", params.useType, params.level)
throw BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2)
}
val practice = practiceConfigRepository.getOne(params.practiceId!!)
if (practice == null) {
logger.error("startPractice practiceId:{} ,未查询到陪练配置", params.practiceId)
throw BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2)
}
val context = params.requestContext!!
// 考试需要考虑次数限制
if (practice.useType != PracticeModelStatusEnum.PRACTICE.status) {
if (practice.maxExamCount > 0
&& practice.maxExamCount <= practiceChatLogService.getExamCountByPractice(context.accountId, params.practiceId)) {
throw BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2)
}
}
// 新建一条陪练
var log = PracticeChatLog()
log.id = idGenerator.generate()
log.practiceId = params.practiceId
log.accountId = context.accountId
log.accountName = context.accountName
log.accountFullName = context.accountFullName
log.useType = params.useType
val orgInfo = organizationClient.listByOrgIds(listOf(context.orgId))
if (null != orgInfo && orgInfo.size > 0) {
log.orgName = orgInfo[0].name
}
if (params.useType == PracticeModelStatusEnum.PRACTICE.status) {
log.level = params.level
}
log.status = PracticeRunningStatusEnum.RUNNING.status
log.passMinScore = practice.examPassMinScore
log.givenPointType = practice.examGivenPointType
log.siteId = context.siteId
log.orgId = context.orgId
log.companyId = context.companyId
log.passMinScore = practice.examPassMinScore
log = practiceChatLogRepository.save(log)
val vo = StuPracticeLogVo()
vo.useType = log.useType
vo.practiceLogId = log.id
vo.practiceId = log.practiceId
return vo
}
private fun buildAliOSSUrl(po: AnalyzeStudentVoicePo) {
if (!StringUtils.isEmpty(po.voiceUrl)) {
return
}
if (po.platform == "H5") {
return
}
val mediaId = po.wechatMediaId
val accessToken = weChatTokenClient.getWechatAccessTokenByAppId(po.wechatAppId,po.agentId)
if (accessToken == null || mediaId == null) {
logger.error("mediaId$mediaId accessToken$accessToken wechatAppId:${po.wechatAppId} agentId:${po.agentId}")
throw BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2)
}
var wechatMediaUrl = "https://api.weixin.qq.com/cgi-bin/media/get?access_token=$accessToken&media_id=$mediaId"
if (po.platform == "QYWECHAT") {
wechatMediaUrl = "https://qyapi.weixin.qq.com/cgi-bin/media/get?access_token=$accessToken&media_id=$mediaId"
}
logger.info("wechatMediaUrl $wechatMediaUrl")
val fileName = RandomUtil.randomString(10)
val file = File(AudioUtils.dir, "$fileName.amr")
val target = File(AudioUtils.dir, "$fileName.wav")
logger.info("file url $wechatMediaUrl")
FileUtils.copyURLToFile(URL(wechatMediaUrl), file)
logger.info("source file size :${file.totalSpace}")
val audio = AudioAttributes()
audio.setCodec("libmp3lame")
val attrs = EncodingAttributes()
attrs.format = "wav"
attrs.audioAttributes = audio
val encoder = Encoder()
try {
val multimediaObject = MultimediaObject(file)
encoder.encode(multimediaObject, target, attrs)
} catch (e: Exception) {
logger.error("文件转换异常 amr>>>>>>>>>wav",e);
}
logger.info("target file size :${target.totalSpace}")
val multimediaObject = MultimediaObject(target)
po.voiceDuration = multimediaObject.info.duration
val inputStream = target.inputStream()
val context = po.requestContext!!
val path = OssFileUtil.getManageStandardVoiceUri(
context.companyId,
context.siteId,
"PRACTICE",
"SUDENT/UPLOAD",
context.accountId,
RandomUtil.randomLong())
po.voiceUrl = aliyunUtil.uploadByStream(path, inputStream)
inputStream.close()
file.deleteOnExit()
target.deleteOnExit()
}
}
package com.yizhi.practice.application.xservice.impl
import com.alibaba.fastjson.JSONObject
import com.yizhi.core.application.cache.RedisCache
import com.yizhi.core.application.context.RequestContext
import com.yizhi.core.application.enums.InternationalEnums
import com.yizhi.core.application.exception.BizException
import com.yizhi.practice.application.config.PracticeLevelEnum
import com.yizhi.practice.application.config.PracticeRunningStatusEnum
import com.yizhi.practice.application.enums.PracticeModelStatusEnum
import com.yizhi.practice.application.pojo.vo.PracticeConfigVo
import com.yizhi.practice.application.pojo.vo.PracticeJoinedVo
import com.yizhi.practice.application.repository.PracticeConfigRepository
import com.yizhi.practice.application.service.IPracticeChatLogService
import com.yizhi.practice.application.service.IPracticeConfigService
import com.yizhi.practice.application.service.IPracticeVisibleService
import com.yizhi.practice.application.xservice.PracticeStudentXSerice
import com.yizhi.system.application.system.remote.OrganizationClient
import com.yizhi.util.application.domain.BizResponse
import com.yizhi.util.application.page.PageInfo
import org.apache.commons.lang.StringUtils
import org.jetbrains.annotations.TestOnly
import org.slf4j.LoggerFactory
import org.springframework.beans.BeanUtils
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
/**
* @Date 2020/10/26 3:19 下午
* @Author lvjianhui
**/
@Service
class PracticeStudentXSericeImpl : PracticeStudentXSerice {
@Autowired
lateinit var iPracticeConfigService: IPracticeConfigService
@Autowired
lateinit var iPracticeChatLogService: IPracticeChatLogService
@Autowired
lateinit var practiceConfigRepository: PracticeConfigRepository
@Autowired
lateinit var iPracticeVisibleService: IPracticeVisibleService
@Autowired
lateinit var organizationClient: OrganizationClient
@Autowired
lateinit var redisCache: RedisCache
private val logger = LoggerFactory.getLogger(PracticeXserviceImpl::class.java)
override fun getTabIndex(requestContext: RequestContext): Int {
var index = 1
val runningCount = getRunningCount(
requestContext.accountId,
requestContext.orgId,
requestContext.siteId,
requestContext.companyId
)
if (runningCount > 0) {
return index
}
val unStartCount = getRunningList(
requestContext.accountId,
requestContext.orgId,
requestContext.siteId,
requestContext.companyId,
PracticeRunningStatusEnum.NOT_STARTED.status,
1,
1
)?.records?.size ?: 0
if (unStartCount > 0) {
return 0
}
val endCount = getRunningList(
requestContext.accountId,
requestContext.orgId,
requestContext.siteId,
requestContext.companyId,
PracticeRunningStatusEnum.ENDED.status,
1,
1
)?.records?.size ?: 0
if (endCount > 0) {
return 2
}
return 1
}
override fun getPracticeJoined(practiceId: Long, context: RequestContext): PracticeJoinedVo {
val vo = PracticeJoinedVo()
val map = iPracticeChatLogService.getPracticeLogByLevel(practiceId, context.accountId, context.companyId, context.siteId, context.orgId)
?: let { return vo }
vo.primaryLevelCount = map.get(PracticeLevelEnum.PRIMARY_LEVEL.level) ?: 0
vo.intermediateLevel = map.get(PracticeLevelEnum.INTERMEDIATE_LEVEL.level) ?: 0
vo.seniorLevel = map.get(PracticeLevelEnum.SENIOR_LEVEL.level) ?: 0
return vo
}
override fun getPracticeInfo(practiceId: Long, accountId: Long, orgId: Long, siteId: Long, companyId: Long): PracticeConfigVo {
val vo = PracticeConfigVo()
val config = practiceConfigRepository.getOne(practiceId)
// TODO Could not copy property 'description'
BeanUtils.copyProperties(config, vo)
val map = iPracticeChatLogService.getExamAndPracticeCount(accountId, practiceId, orgId, siteId, companyId)
?: return vo
vo.joinExamCount = map[PracticeModelStatusEnum.ASSESSMENT.status]
vo.joinPracticeCount = map[PracticeModelStatusEnum.PRACTICE.status]
vo.robotName = config.robotName
return vo
}
override fun getRunningList(accountId: Long, orgId: Long, siteId: Long, companyId: Long, state: Int, pageIndex: Int, pageSize: Int): PageInfo<PracticeConfigVo>? {
if (!PracticeRunningStatusEnum.getAllStatus().contains(state)) {
throw BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2)
}
val allIds = getVisiblePracticeIds(accountId, orgId, siteId, companyId, PracticeRunningStatusEnum.getEnumByState(state))
logger.info("")
val page = PageInfo<PracticeConfigVo>()
page.pageSize = pageSize
page.pageNo = pageIndex
if (allIds == null || allIds.isEmpty()) {
return page
}
var pageNum = allIds.size / pageSize
if (allIds.size % pageSize != 0) {
pageNum++
}
page.pageTotal = pageNum
var startNum = (pageIndex - 1) * pageSize
var endNum = startNum + pageSize
if (startNum >= allIds.size) {
startNum = allIds.size
}
if (endNum > allIds.size) {
endNum = allIds.size
}
val idsPage = allIds.subList(startNum, endNum)
page.records = iPracticeConfigService.getConfigByIds(idsPage)
return page
}
override fun getRunningCount(accountId: Long, orgId: Long, siteId: Long, companyId: Long): Int {
val allIds: List<Long> = getVisiblePracticeIds(accountId, orgId, siteId, companyId, PracticeRunningStatusEnum.RUNNING)
?: return 0
return allIds.size
}
/**
* 获取 用户可见的指定状态的陪练IDS
*
* @param accountId
* @param orgId
* @param siteId
* @param companyId
* @param state
* @return
*/
private fun getVisiblePracticeIds(accountId: Long, orgId: Long, siteId: Long, companyId: Long, state: PracticeRunningStatusEnum): List<Long>? {
val allIds = iPracticeConfigService.getRunningCount(orgId, siteId, companyId, null, state)
logger.info("当前站点:{} 当前部门:{}可参加的陪练Id:{}", siteId, orgId, JSONObject.toJSON(allIds).toString())
if (allIds == null || allIds.isEmpty()) {
return null
}
// 查询改部门的父部门,父部门可见的话,子部门的用户也是可见的。
val parentIdsAndOrgIdList = getParentOrgIdByChildOrgId(orgId)
parentIdsAndOrgIdList.add(orgId)
val visiableId = iPracticeVisibleService.getIdsByAccountId(accountId, parentIdsAndOrgIdList, siteId, companyId)
val siteVisiableIds = iPracticeConfigService.getSiteAllConfig(siteId, companyId)
visiableId.addAll(siteVisiableIds)
logger.info("当前站点:{} 当前部门:{} 当前用户:{}可见的陪练Id:{}", siteId, orgId, accountId, JSONObject.toJSON(visiableId).toString())
if (visiableId.isEmpty()) {
return null
}
return allIds.intersect(visiableId).toList()
}
/**
* 缓存父部门ID
*/
private fun getParentOrgIdByChildOrgId(orgId: Long): MutableList<Long> {
// val key = "practice_stu_org_parent_ids"
// val orgStr = orgId.toString()
// val orgIds = redisCache.hget(key, orgStr)
// if (null != orgIds && !StringUtils.isEmpty(JSONObject.toJSONString(orgIds))) {
// return JSONObject.parseArray(JSONObject.toJSONString(orgIds), Long::class.java)
// }
val parentIds = organizationClient.orgIdParentIds(orgId) ?: arrayListOf()
// redisCache.hset(key, orgStr, JSONObject.toJSONString(parentIds))
return parentIds
}
override fun getUserPracticeAuth(requestContext: RequestContext, practiceId: Long): BizResponse<Boolean> {
val visiblePracticeIds = getVisiblePracticeIds(requestContext.accountId, requestContext.orgId, requestContext.siteId, requestContext.companyId, PracticeRunningStatusEnum.ALL)
if (visiblePracticeIds != null && visiblePracticeIds.contains(practiceId)) {
return BizResponse.ok(true)
}
return BizResponse.ok(false)
}
}
\ No newline at end of file
package com.yizhi.practice.application.xservice.impl;
import com.alibaba.fastjson.JSONObject;
import com.yizhi.application.orm.id.IdGenerator;
import com.yizhi.core.application.context.ContextHolder;
import com.yizhi.core.application.context.RequestContext;
import com.yizhi.core.application.enums.InternationalEnums;
import com.yizhi.core.application.exception.BizException;
import com.yizhi.practice.application.enums.PracticeStatusEnum;
import com.yizhi.practice.application.pojo.domain.PracticeConfig;
import com.yizhi.practice.application.pojo.domain.SceneConfig;
import com.yizhi.practice.application.pojo.vo.SceneVo;
import com.yizhi.practice.application.repository.PracticeConfigRepository;
import com.yizhi.practice.application.repository.SceneChatConfigRepository;
import com.yizhi.practice.application.repository.SceneConfigRepository;
import com.yizhi.practice.application.request.SceneReq;
import com.yizhi.practice.application.service.ISceneChatConfigService;
import com.yizhi.practice.application.service.ISceneConfigService;
import com.yizhi.practice.application.xservice.PracticeXSceneservice;
import com.yizhi.util.application.domain.BizResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.List;
@Service
public class PracticeXSceneserviceImpl implements PracticeXSceneservice {
private static Logger logger = LoggerFactory.getLogger(PracticeXSceneserviceImpl.class);
@Autowired
PracticeConfigRepository practiceConfigRepository;
@Autowired
IdGenerator idGenerator;
@Autowired
SceneConfigRepository sceneConfigRepository;
@Autowired
SceneChatConfigRepository chatConfigRepository;
@Autowired
ISceneConfigService sceneConfigService;
@Autowired
ISceneChatConfigService sceneChatConfigService;
@Override
@Transactional
public BizResponse save(SceneReq sceneReq) {
RequestContext context = ContextHolder.get();
Long practiceId = sceneReq.getPracticeId();
String newSceneName = sceneReq.getSceneName();
String desc = sceneReq.getDesc();
if (StringUtils.isEmpty(newSceneName) || newSceneName.length() > 10
|| (!StringUtils.isEmpty(desc) && desc.length() > 500)
){
logger.error("[PracticeXSceneServiceImpl: save]陪练场景,场景名称为空或长度大于10,或描述长度大于500! 请求入参: {},accountId={}"
, JSONObject.toJSONString(sceneReq),context.getAccountId());
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2.getCode(),"场景名称不符合规范");
}
PracticeConfig practice = practiceConfigRepository.getOne(practiceId);
if (null == practice){
logger.error("[PracticeXSceneserviceImpl: save]陪练场景,未查询到陪练信息! practiceId = {} ,场景名称= {}",practiceId,sceneReq.getSceneName());
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2.getCode(),"未查询到陪练");
}
SceneConfig scene = new SceneConfig();
Long sceneId = sceneReq.getSceneId();
if (null != sceneId){
scene = sceneConfigRepository.getOne(sceneId);
String oldSceneName = scene.getName();
if (!StringUtils.isEmpty(oldSceneName) && !oldSceneName.equals(newSceneName)){
//场景名称修改,同步修改场景对话中名称;
chatConfigRepository.updateSceneNameBySceneId(newSceneName,sceneId);
}
scene.setUpdatedUid(ContextHolder.get().getAccountId());
}else {
scene.setId(idGenerator.generate());
scene.setPracticeId(practiceId);
setCreatedAccountInfo(scene);
}
scene.setName(sceneReq.getSceneName());
scene.setDescription(sceneReq.getDesc());
scene.setSort(sceneReq.getSort());
sceneConfigRepository.save(scene);
return BizResponse.ok();
}
@Override
public SceneVo selectScene(Long sceneId) {
SceneConfig scene = sceneConfigRepository.getOne(sceneId);
SceneVo sceneVo = new SceneVo();
if (null != scene){
sceneVo.setId(scene.getId());
sceneVo.setName(scene.getName());
sceneVo.setDescription(scene.getDescription());
sceneVo.setPracticeId(scene.getPracticeId());
}
return sceneVo;
}
@Override
@Transactional
public BizResponse deleteScene(Long sceneId) {
RequestContext context = ContextHolder.get();
SceneConfig scene = sceneConfigRepository.getOne(sceneId);
if (null == scene || null == scene.getId()){
logger.error("[PracticeXSceneServiceImpl:deleteScene]删除场景失败。为查询到场景 sceneId = {}. accountId = {}",sceneId,context.getAccountId());
throw new BizException(InternationalEnums.CLASSIFYCONTROLLER4);
}
Long practiceId = scene.getPracticeId();
if (null == practiceId || practiceId.longValue() == 0){
logger.error("智能陪练删除场景[PracticeXServiceImpl:deleteScene] 场景陪练id为空.sceneId={}",sceneId);
throw new BizException(InternationalEnums.CLASSIFYCONTROLLER4);
}
PracticeConfig practice = practiceConfigRepository.getOne(practiceId);
Integer status = practice.getStatus();
if (PracticeStatusEnum.UP.getStatus().equals(status)){
logger.error("智能陪练删除场景失败。上架的陪练不能删除场景;sceneId = {}",sceneId);
throw new BizException(InternationalEnums.CLASSIFYCONTROLLER4);
}
//删除场景
long delCount = sceneConfigService.deleteScene(practiceId, sceneId);
if (-1 == delCount){
logger.error("[PracticeXSceneServiceImpl:deleteScene]删除场景失败。删除场景传入参数都为空.sceneId = {}. accountId = {}",sceneId,context.getAccountId());
throw new BizException(InternationalEnums.CLASSIFYCONTROLLER4);
}
//删除场景对话
sceneChatConfigService.deleteChatNodes(scene.getPracticeId(),sceneId,null,null,null);
return BizResponse.ok();
}
@Override
public List<SceneVo> selectSceneList(Long practiceId) {
List<SceneVo> sceneVoList = new ArrayList<>();
List<SceneConfig> sceneConfigList = sceneConfigService.findSceneByPracticeId(practiceId);
if (null != sceneConfigList && sceneConfigList.size() > 0){
for (SceneConfig sceneConfig : sceneConfigList) {
SceneVo sceneVo = new SceneVo();
sceneVo.setId(sceneConfig.getId());
sceneVo.setPracticeId(sceneConfig.getPracticeId());
sceneVo.setDescription(sceneConfig.getDescription());
sceneVo.setName(sceneConfig.getName());
sceneVo.setSort(sceneConfig.getSort());
sceneVoList.add(sceneVo);
}
}
return sceneVoList;
}
@Override
@Transactional
public BizResponse updateSceneSort(List<SceneReq> sceneReqList) {
if (null != sceneReqList && sceneReqList.size() > 0){
for (SceneReq sceneReq : sceneReqList) {
Long sceneId = sceneReq.getSceneId();
int sort = sceneReq.getSort();
if (null != sceneId){
sceneConfigService.updateSceneSort(sceneId,sort);
}
}
}
return BizResponse.ok();
}
/**设置数据更新人信息*/
private void setCreatedAccountInfo(SceneConfig scene) {
RequestContext requestContext = ContextHolder.get();
scene.setCreatedUid(requestContext.getAccountId());
scene.setSiteId(requestContext.getSiteId());
scene.setCompanyId(requestContext.getCompanyId());
scene.setOrgId(requestContext.getOrgId());
}
}
package com.yizhi.practice.application.xservice.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yizhi.application.orm.id.IdGenerator;
import com.yizhi.core.application.context.ContextHolder;
import com.yizhi.core.application.context.RequestContext;
import com.yizhi.core.application.enums.InternationalEnums;
import com.yizhi.core.application.exception.BizException;
import com.yizhi.core.application.file.domain.Template;
import com.yizhi.core.application.file.domain.TemplateColumn;
import com.yizhi.core.application.log.LogEventPublisher;
import com.yizhi.core.application.task.TaskExecutor;
import com.yizhi.practice.application.config.AudioUtils;
import com.yizhi.practice.application.constants.PracticeConstant;
import com.yizhi.practice.application.enums.*;
import com.yizhi.practice.application.excel.*;
import com.yizhi.practice.application.pojo.domain.*;
import com.yizhi.practice.application.pojo.dto.PracticeBaseInfoDto;
import com.yizhi.practice.application.pojo.dto.PracticeStrategyInfoDto;
import com.yizhi.practice.application.pojo.vo.*;
import com.yizhi.practice.application.repository.*;
import com.yizhi.practice.application.request.*;
import com.yizhi.practice.application.service.*;
import com.yizhi.practice.application.third.util.OssFileUtil;
import com.yizhi.practice.application.third.xunfei.XunfeiUtil;
import com.yizhi.practice.application.util.NumberUtil;
import com.yizhi.practice.application.xservice.PracticeXservice;
import com.yizhi.util.application.domain.BizResponse;
import com.yizhi.util.application.page.PageInfo;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @Date 2020/10/22 1:44 下午
* @Author lvjianhui
**/
@Service
public class PracticeXserviceImpl implements PracticeXservice {
//关键词正则 : 只能是中文/数字/点(.)/%
private String keywordRegex = "[0-9\u4e00-\u9fa5.%]+";
//机器人和学员标准话术正则:包含英文
private String contentRegex = ".*[a-zA-Z].*";
//拓展词、禁忌词正则: 只能包含中文和英文分号、数字
private String commentRegex = "[\u4e00-\u9fa5;0-9]+";
@Autowired
IPracticeConfigService iPracticeConfigService;
@Autowired
PracticeConfigRepository practiceConfigRepository;
@Autowired
IdGenerator idGenerator;
@Autowired
IPracticeVisibleService iPracticeVisibleService;
@Autowired
PracticePointRuleConfigRepository pointRuleConfigRepository;
@Autowired
IPracticePointRuleConfigService pointRuleConfigService;
@Autowired
PracticeVisibleRepository visibleRepository;
@Autowired
SceneChatConfigRepository chatConfigRepository;
@Autowired
XunfeiUtil xunfeiUtil;
@Autowired
RobotConfigRepository robotConfigRepository;
@Autowired
SceneConfigRepository sceneConfigRepository;
@Autowired
ISceneChatConfigService chatConfigService;
@Autowired
ISceneConfigService sceneConfigService;
@Autowired
LogEventPublisher publisher;
@Autowired
TaskExecutor taskExecutor;
@Autowired
PracticeAccountImport accountImport;
@Autowired
PracticeAccountExport accountExport;
@Autowired
PracticeExcelImporter excelImporter;
private Logger logger = LoggerFactory.getLogger(PracticeXserviceImpl.class);
/**
* 初始化空白草稿状态的陪练
*
* @return 陪练信息
*/
@Override
@Transactional(propagation = Propagation.REQUIRED)
public PracticeBlankDraftVo initBlankDraftPractice() {
PracticeConfig practiceConfig = new PracticeConfig();
Long practiceId = idGenerator.generate();
practiceConfig.setId(practiceId);
practiceConfig.setStatus(PracticeStatusEnum.DRAFT.getStatus());
setCreatedAccountInfo(practiceConfig);
practiceConfig = practiceConfigRepository.save(practiceConfig);
PracticeBlankDraftVo baseInfoVo = new PracticeBlankDraftVo();
baseInfoVo.setId(practiceConfig.getId());
baseInfoVo.setStatus(practiceConfig.getStatus());
return baseInfoVo;
}
/**
* 保存智能陪练配置信息
*/
@Override
@Transactional
public BizResponse savePracticeConfInfo(PracticeConfigInfoReq practiceReq) {
Long practiceId = practiceReq.getId();
PracticeConfig practice = practiceConfigRepository.getOne(practiceId);
if (null == practice) {
logger.error("根据陪练id未查询到陪练信息! practiceId = {}", practiceId);
throw new BizException(InternationalEnums.MATERIALCONTROLLER1);
}
PracticeBaseInfoDto baseInfoDto = new PracticeBaseInfoDto();
BeanUtils.copyProperties(practiceReq, baseInfoDto);
checkPracticeBaseParamsValid(baseInfoDto);
BeanUtils.copyProperties(baseInfoDto, practice);
String logoUrl = baseInfoDto.getLogoUrl();
if (StringUtils.isEmpty(logoUrl)){
String defaultUrl = PracticeConstant.PRACTICE_DEFAULT_LOGO_URL;
practice.setLogoUrl(defaultUrl);
}
practice.setId(practiceId);
practice.setRobotId(baseInfoDto.getRobotId());
practice.setRobotName(baseInfoDto.getRobotAliasName());
setUpdatedAccountInfo(practice);
practiceConfigRepository.save(practice);
return BizResponse.ok();
}
@Override
@Transactional
public BizResponse savePracticeStrategyInfo(PracticeConfigInfoReq practiceConfigInfoReq) {
PracticeStrategyInfoDto strategyInfoDto = new PracticeStrategyInfoDto();
BeanUtils.copyProperties(practiceConfigInfoReq, strategyInfoDto);
Long practiceId = strategyInfoDto.getId();
PracticeConfig practice = practiceConfigRepository.getOne(practiceId);
if (null == practice) {
logger.error("根据陪练id未查询到陪练信息! practiceId = {}", practiceId);
return BizResponse.fail("新增陪练策略信息失败");
}
strategyInfoDto.setUseType(practice.getUseType());
checkPracticeStrategyParamsValid(strategyInfoDto);
BeanUtils.copyProperties(strategyInfoDto, practice);
setUpdatedAccountInfo(practice);
//未识别回复类型 80:默认回复,10:自定义回复
Integer similarityFailedMsgType = strategyInfoDto.getSimilarityFailedMsgType();
if (PracticeManyRoudChatEnum.TRUE.equals(similarityFailedMsgType)){
strategyInfoDto.setSimilarityFailedMsg(PracticeConstant.EXAM_FAIL_MESSAGE);
practice.setSimilarityFailedMsg(PracticeConstant.EXAM_FAIL_MESSAGE);
}
//可见范围修改
Integer oldVisibleType = practice.getVisibleType();
Integer newVisibleType = strategyInfoDto.getVisibleType();
//由part->all 删除关系表原来所有可见范围;其他改变均由‘指定用户’接口做修改
if (PracticeVisibleTypeEnum.PART.getStatus().equals(oldVisibleType) && PracticeVisibleTypeEnum.ALL.getStatus().equals(newVisibleType)){
visibleRepository.deleteVisibleRangeByPractice(practiceId);
}
// 积分规则修改
Integer newExamGivenPointType = strategyInfoDto.getExamGivenPointType();
List<PracticePointVo> practicePointList = practiceConfigInfoReq.getPracticePointList();
saveOrUpdatePracticePointRule(newExamGivenPointType, practiceId, practicePointList);
practiceConfigRepository.save(practice);
return BizResponse.ok();
}
@Override
@Transactional
public BizResponse savePracticeDialogue(List<PracticeSceneDialogueReq> sceneNodeList) {
RequestContext context = ContextHolder.get();
for (PracticeSceneDialogueReq dialogueReq : sceneNodeList){
Long practiceId = dialogueReq.getPracticeId();
Long sceneId = dialogueReq.getSceneId();
if (null == practiceId || null == sceneId ){
logger.error("保存对话传入id为空; practiceId = {} ,sceneId = {} ,accountId = {}",practiceId,sceneId,context.getAccountId());
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2);
}
List<PracticeChatNodeReq> chatNodes = dialogueReq.getChatNodes();
if (null == chatNodes || chatNodes.size() == 0){
logger.error("保存对话传入对话内容为空; practiceId = {} ,sceneId = {} ,accountId = {}",practiceId,sceneId,context.getAccountId());
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2);
}
//校验对话节点是否符合‘开始-机器人-学员-机器人-学员-...’结构要求
checkChatNodeOrderValid(chatNodes);
//校验对话节点参数
checkChatNodeParams(chatNodes);
PracticeConfig practice = practiceConfigRepository.getOne(practiceId);
//保存场景对话节点信息.将原有的节点都逻辑删除,然后再进行保存和更新操作
chatConfigRepository.deleteSceneNodesByPracticeId(sceneId);
saveOrUpdatePracticeDialogue(practice,sceneId,0L,chatNodes);
}
return BizResponse.ok();
}
/**
* 校验对话节点参数是否符合要求
* @param chatNodeList 节点对话数据
*/
private void checkChatNodeParams(List<PracticeChatNodeReq> chatNodeList) {
if (null == chatNodeList || chatNodeList.size() == 0){
return;
}
for (PracticeChatNodeReq chatNode : chatNodeList) {
Integer sceneNodeType = chatNode.getSceneNodeType();
if (PracticeNodeEnum.STUDENT.getStatus().equals(sceneNodeType)){
String accountContent = chatNode.getAccountContent();
List<KeyWordsReq> keyWordList = chatNode.getKeyWordList();
if (StringUtils.isEmpty(accountContent) || accountContent.length() > 250){
logger.error("[PracticeXServiceImpl:checkChatNodeParams]学员节点话术为空或长度超出限制,accountContent = {}",accountContent);
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2.getCode(),"话术配置有误,请重新编辑");
}
/*if (checkRegex(accountContent,contentRegex)){
//学员话术包含英文
logger.error("[PracticeXServiceImpl:checkChatNodeParams]学员节点话术包含英文,accountContent = {}",accountContent);
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2.getCode(),"话术配置有误,请重新编辑");
}*/
//关键词
if (null == keyWordList || keyWordList.isEmpty()){
logger.error("[PracticeXServiceImpl:checkChatNodeParams]学员节点话术关键字为空,accountContent = {}",accountContent);
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2.getCode(),"话术配置有误,请重新编辑");
}
for (KeyWordsReq keyWordsReq : keyWordList) {
String key = keyWordsReq.getKey();
String extendWord = keyWordsReq.getValue();
//校验关键词和扩展词
boolean result = checkKeywordAndExtend(key, extendWord, new HashSet<>(), keywordRegex, commentRegex, 0, accountContent);
if (!result){
logger.error("[PracticeXServiceImpl:checkChatNodeParams]学员节点话术关键字/扩展词校验结果result={},accountContent = {},keywordList = {}",result,accountContent,JSONObject.toJSONString(keyWordList));
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2.getCode(),"话术配置有误,请重新编辑");
}
}
//禁忌词
String accountContentTabooWord = chatNode.getAccountContentTabooWord();
if (!StringUtils.isEmpty(accountContentTabooWord)){
if (!checkRegex(accountContentTabooWord,commentRegex)){
logger.error("[PracticeXServiceImpl:checkChatNodeParams]学员节点话术禁忌词包含中文英文分号以外字符,accountContent = {},tabooWord = {}",accountContent,accountContentTabooWord);
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2.getCode(),"话术配置有误,请重新编辑");
}
}
}else if (PracticeNodeEnum.ROBOT.getStatus().equals(sceneNodeType)){
String robotContent = chatNode.getRobotContent();
if (StringUtils.isEmpty(robotContent) || robotContent.length() > 250){
logger.error("[PracticeXServiceImpl:checkChatNodeParams]机器人节点话术为空或长度超出限制,robotContent = {}",robotContent);
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2.getCode(),"话术配置有误,请重新编辑");
}
/* if (checkRegex(robotContent,contentRegex)){
//学员话术包含英文
logger.error("[PracticeXServiceImpl:checkChatNodeParams]机器人节点话术包含中文,robotContent = {}",robotContent);
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2.getCode(),"话术配置有误,请重新编辑");
}*/
}
List<PracticeChatNodeReq> childNodes = chatNode.getChildNodes();
checkChatNodeParams(childNodes);
}
}
/**
* 校验对话节点顺序是否符合规则
* @param chatNodeList 前端传入节点集合,包括开始节点;
* 机器人节点下只能是学员;学员下只能是机器人;开始节点下只能是机器人
*/
private void checkChatNodeOrderValid(List<PracticeChatNodeReq> chatNodeList) {
if (null == chatNodeList || chatNodeList.size() == 0){
return;
}
for (PracticeChatNodeReq chatNode : chatNodeList) {
Long nodeId = chatNode.getId();
Integer level = chatNode.getLevel();
Integer sceneNodeType = chatNode.getSceneNodeType();
List<PracticeChatNodeReq> startChildNodes = chatNode.getChildNodes();
if (null == startChildNodes || startChildNodes.size() == 0){
continue;
}
if (!PracticeNodeEnum.START.getStatus().equals(sceneNodeType) && !PracticeNodeEnum.STUDENT.getStatus().equals(sceneNodeType)
&& !PracticeNodeEnum.ROBOT.getStatus().equals(sceneNodeType)){
logger.error("[practiceXServiceImpl:checkChatNodeOrderValid]校验对话节点,没有查询到节点类型。chatId = {},chatNodeType = {},chatNodes = {}",nodeId,sceneNodeType,JSONObject.toJSONString(chatNode));
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2.getCode(),"节点类型错误");
}
if (PracticeNodeEnum.START.getStatus().equals(sceneNodeType) || PracticeNodeEnum.STUDENT.getStatus().equals(sceneNodeType)){
for (PracticeChatNodeReq startChildNode : startChildNodes) {
Integer childNodeType = startChildNode.getSceneNodeType();
if (!PracticeNodeEnum.ROBOT.getStatus().equals(childNodeType)){
logger.error("[practiceXServiceImpl:checkChatNodeOrderValid]校验对话节点顺序,开始节点子节点类型不是机器人,开始子节点列表chatNodes = {}",JSONObject.toJSONString(startChildNodes));
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2.getCode(),"开始节点下必须是机器人节点");
}
}
}else if (PracticeNodeEnum.ROBOT.getStatus().equals(sceneNodeType)){
for (PracticeChatNodeReq startChildNode : startChildNodes) {
Integer childNodeType = startChildNode.getSceneNodeType();
if (!PracticeNodeEnum.STUDENT.getStatus().equals(childNodeType)){
logger.error("[practiceXServiceImpl:checkChatNodeOrderValid]校验对话节点顺序,机器人节点子节点类型不是学员,机器人子节点列表chatNodes = {}",JSONObject.toJSONString(startChildNodes));
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2.getCode(),"机器人节点下只能连接学员节点");
}
}
}
}
}
@Override
public List<RobotVo> getRobotList() {
List<RobotVo> list = new ArrayList<>();
List<RobotConfig> all = robotConfigRepository.findAll();
if (null != all && all.size() > 0){
all.forEach(robotConfig -> {
RobotVo robotVo = new RobotVo();
robotVo.setId(robotConfig.getId());
robotVo.setRobotName(robotConfig.getName());
robotVo.setRobotParams(robotConfig.getParams());
robotVo.setContentVoiceUrl(robotConfig.getContentVoiceUrl());
list.add(robotVo);
});
}
return list;
}
@Override
public BizResponse<PageInfo<PracticeBaseInfoVo>> getPracticeList(PracticesGetReq practicesGetReq) {
List<Long> ids = new ArrayList<>();
RequestContext context = ContextHolder.get();
Long accountId = context.getAccountId();
ids.add(accountId);
for(Long id : context.getManagerIds()) {
ids.add(id);
}
practicesGetReq.setCompanyId(context.getCompanyId());
practicesGetReq.setSiteId(context.getSiteId());
// 不是超级管理员时,增加 分级授权 条件
if(!context.isAdmin()) {
practicesGetReq.setIds(ids);
}
Long total = iPracticeConfigService.getPracticeConfigCount(practicesGetReq);
List<PracticeBaseInfoVo> list = iPracticeConfigService.getPracticeConfigList(practicesGetReq);
PageInfo<PracticeBaseInfoVo> pageInfo = new PageInfo<>();
pageInfo.setRecords(list);
pageInfo.setPageTotal(NumberUtil.getPageCount(total, practicesGetReq.getPageSize()));
pageInfo.setPageNo(practicesGetReq.getPageNo());
pageInfo.setPageSize(practicesGetReq.getPageSize());
pageInfo.setPageRecords(total.intValue());
return BizResponse.ok(pageInfo);
}
@Override
public PracticeConfigInfoVo getPracticeConfigInfo(Long practiceId) {
PracticeConfig practice = practiceConfigRepository.getOne(practiceId);
PracticeConfigInfoVo vo = new PracticeConfigInfoVo();
BeanUtils.copyProperties(practice,vo);
Integer examGivenPointType = practice.getExamGivenPointType();
List<PracticePointVo> practicePointList = new ArrayList<>();
if (null != examGivenPointType && PracticePointGivenEnum.TRUE.getStatus().equals(examGivenPointType)){
//发放积分;查询积分数据
List<PracticePointRuleConfig> pointRuleList = pointRuleConfigRepository.selectListByPracticeId(practiceId);
// if (null == pointRuleList || pointRuleList.isEmpty()) {
// return
// }
if (null != pointRuleList && pointRuleList.size() > 0){
pointRuleList.forEach(practicePointRuleConfig -> {
PracticePointVo pointVo = new PracticePointVo();
pointVo.setId(practicePointRuleConfig.getId());
pointVo.setMaxScore(practicePointRuleConfig.getMaxScore());
pointVo.setMinScore(practicePointRuleConfig.getMinScore());
pointVo.setPoint(practicePointRuleConfig.getPoint());
practicePointList.add(pointVo);
});
}
}
vo.setPracticePointList(practicePointList);
//设置机器人信息
Long robotId = practice.getRobotId();
RobotConfig robot = robotConfigRepository.getOne(robotId);
vo.setRobotId(robotId);
vo.setRobotName(robot.getName());
vo.setRobotParams(practice.getRobotParams());
vo.setRobotAliasName(practice.getRobotName());
vo.setRobotVoiceUrl(robot.getContentVoiceUrl());
return vo;
}
@Override
public List<PracticeSceneDialogueVo> getPracticeSceneChatList(Long practiceId,Long practiceSceneId) throws JsonProcessingException {
List<PracticeSceneDialogueVo> sceneDialogueVoList = new ArrayList<>();
List<SceneConfig> sceneConfigs = new ArrayList<>();
if (null != practiceSceneId){
SceneConfig scene = sceneConfigRepository.getOne(practiceSceneId);
sceneConfigs.add(scene);
}else {
sceneConfigs = sceneConfigRepository.selectByPracticeId(practiceId);
}
if (null != sceneConfigs && sceneConfigs.size() > 0){
for (SceneConfig scene : sceneConfigs){
Long sceneId = scene.getId();
PracticeSceneDialogueVo sceneDialogueVo = new PracticeSceneDialogueVo();
sceneDialogueVo.setPracticeId(practiceId);
sceneDialogueVo.setSceneId(sceneId);
sceneDialogueVo.setSceneName(scene.getName());
sceneDialogueVo.setSort(scene.getSort());
sceneDialogueVo.setSceneDescription(scene.getDescription());
//查询场景下开始及以下节点列表
List<SceneChatConfig> startRobotNodes = chatConfigService.selectChatNodes(practiceId, sceneId, PracticeNodeEnum.START.getStatus(), 0L, 0);
//遍历开始下节点,递归查询字节
//将节点信息设置到vo中 递归获取节点和字节点
List<PracticeChatNodeReq> chatNodeReqList = new ArrayList<>();
if (null != startRobotNodes && startRobotNodes.size() > 0){
for (SceneChatConfig startChatNode : startRobotNodes){
PracticeChatNodeReq chatNodeReq = new PracticeChatNodeReq();
getSceneChatChildNodes(startChatNode,chatNodeReq);
chatNodeReqList.add(chatNodeReq);
}
}
sceneDialogueVo.setChatNodes(chatNodeReqList);
sceneDialogueVoList.add(sceneDialogueVo);
}
}
return sceneDialogueVoList;
}
@Override
//@Transactional
public BizResponse updatePracticeStatus(Long practiceId, Integer status) throws Exception {
PracticeConfig practice = practiceConfigRepository.getOne(practiceId);
RequestContext context = ContextHolder.get();
if (null == practice){
logger.error("[PracticeXserviceImpl:updatePracticeStatus]上下架失败!没有查询到陪练practiceId= {} ,status = {} ,accountId= {}",practiceId,status,context.getAccountId());
return BizResponse.fail("操作失败!");
}
if (!PracticeStatusEnum.DOWN.getStatus().equals(status) && !PracticeStatusEnum.UP.getStatus().equals(status) ){
logger.error("[PracticeXserviceImpl:updatePracticeStatus]上下架失败!错误的陪练状态!practiceId= {} ,status = {} ,accountId= {}",practiceId,status,context.getAccountId());
return BizResponse.fail("操作失败!");
}
if (PracticeStatusEnum.DOWN.getStatus().equals(status) ){
//下架直接设置
practice.setStatus(status);
practiceConfigRepository.save(practice);
return BizResponse.ok();
}
//上架需要校验参数
PracticeBaseInfoDto practiceBaseInfoDto = new PracticeBaseInfoDto();
BeanUtils.copyProperties(practice,practiceBaseInfoDto);
practiceBaseInfoDto.setRobotAliasName(practice.getRobotName());
checkPracticeBaseParamsValid(practiceBaseInfoDto);
//校验场景和对话
List<SceneConfig> sceneConfigList = sceneConfigService.findSceneByPracticeId(practiceId);
if (null == sceneConfigList || sceneConfigList.size() == 0){
logger.error("[PracticeXserviceImpl:updatePracticeStatus]上架失败!该陪练下没有场景不能上架!practiceId= {} ,status = {} ,accountId= {}",practiceId,status,context.getAccountId());
return BizResponse.fail("上架失败");
}
for (SceneConfig sceneConfig : sceneConfigList) {
Long sceneId = sceneConfig.getId();
//校验场景下对话项
checkSceneChatValid(practiceId,sceneId);
}
PracticeStrategyInfoDto strategyInfoDto = new PracticeStrategyInfoDto();
BeanUtils.copyProperties(practice,strategyInfoDto);
//获取积分
List<PracticePointRuleConfig> pointList = pointRuleConfigService.selectPointRulesByPractice(practiceId, false);
List<PracticePointVo> pointVoList = new ArrayList<>();
if (null != pointList && !pointList.isEmpty()){
pointList.forEach(point -> {
PracticePointVo pointVo = new PracticePointVo();
pointVo.setPoint(point.getPoint());
pointVo.setMinScore(point.getMinScore());
pointVo.setMaxScore(point.getMaxScore());
pointVo.setId(point.getId());
pointVoList.add(pointVo);
});
}
strategyInfoDto.setPracticePointList(pointVoList);
//校验策略
checkPracticeStrategyParamsValid(strategyInfoDto);
//语音合成 查询陪练下所有场景对话标准话术未合成的节点
List<SceneChatConfig> list = chatConfigService.selectChatVoiceIsEmpty(practiceId);
if (null == list || list.isEmpty()){
practice.setStatus(status);
practice.setUpdatedUid(context.getAccountId());
practiceConfigRepository.save(practice);
return BizResponse.ok();
}
//获取需要更新的语音合成对话
getChatNodeVoiceUps(practice, context, list);
//再次验证语音合成
for (SceneConfig sceneConfig : sceneConfigList) {
Long sceneId = sceneConfig.getId();
List<SceneChatConfig> sceneChatConfigs = chatConfigService.selectChatNodes(practiceId, sceneId, null, null, null);
checkVoice(sceneChatConfigs);
}
practice.setStatus(status);
practiceConfigRepository.save(practice);
return BizResponse.ok();
}
/**
* 获取需要更新的语音合成对话
* @param practice 陪练
* @param context 上下文信息
* @param list 需要语音合成的节点列表
*/
@NotNull
private List<SceneChatConfig> getChatNodeVoiceUps(PracticeConfig practice, RequestContext context, List<SceneChatConfig> list) throws Exception {
List<SceneChatConfig> updateChatList = new ArrayList<>();
list.parallelStream().forEach(sceneChatConfig -> {
Integer sceneNodeType = sceneChatConfig.getSceneNodeType();
if (PracticeNodeEnum.STUDENT.getStatus().equals(sceneNodeType)){
String accountContentVoiceUrl = sceneChatConfig.getAccountContentVoiceUrl();
String accountContent = sceneChatConfig.getAccountContent();
if (StringUtils.isEmpty(accountContent)){
logger.error("智能陪练上架失败,学员标准话术文本为空.accountId= {},siteId={},chatId= {},practiceId = {}"
,context.getAccountId(),context.getSiteId(),sceneChatConfig.getId(),practice.getId());
throw new BizException(InternationalEnums.DOCUMENTRELATIONCONTROLLER6);
}
if (StringUtils.isEmpty(accountContentVoiceUrl)){
String accountVoiceUrl = null;
try {
accountVoiceUrl = upFileToOss(practice, accountContent,context);
} catch (Exception e) {
logger.error("智能陪练语音合成异常",e);
throw new BizException(InternationalEnums.DOCUMENTRELATIONCONTROLLER6);
}
sceneChatConfig.setAccountContentVoiceUrl(accountVoiceUrl);
long audioDuration = AudioUtils.INSTANCE.getAudioDuration(accountVoiceUrl);
sceneChatConfig.setAccountContentVoiceDuration(audioDuration);
sceneChatConfig.setUpdatedUid(context.getAccountId());
//updateChatList.add(sceneChatConfig);
}
}else if (PracticeNodeEnum.ROBOT.getStatus().equals(sceneNodeType)){
String robotContentVoiceUrl = sceneChatConfig.getRobotContentVoiceUrl();
String robotContent = sceneChatConfig.getRobotContent();
if (StringUtils.isEmpty(robotContent)){
logger.error("智能陪练上架失败,机器人标准话术文本为空.accountId= {},siteId={},chatId= {},practiceId = {}"
,context.getAccountId(),context.getSiteId(),sceneChatConfig.getId(),practice.getId());
throw new BizException(InternationalEnums.DOCUMENTRELATIONCONTROLLER6);
}
if (StringUtils.isEmpty(robotContentVoiceUrl)){
String robotVoiceUrl = null;
try {
robotVoiceUrl = upFileToOss(practice, robotContent,context);
} catch (Exception e) {
logger.error("智能陪练语音合成异常",e);
throw new BizException(InternationalEnums.DOCUMENTRELATIONCONTROLLER6);
}
sceneChatConfig.setRobotContentVoiceUrl(robotVoiceUrl);
long audioDuration = AudioUtils.INSTANCE.getAudioDuration(robotVoiceUrl);
sceneChatConfig.setRobotContentVoiceDuration(audioDuration);
sceneChatConfig.setUpdatedUid(context.getAccountId());
//updateChatList.add(sceneChatConfig);
}
}
chatConfigRepository.save(sceneChatConfig);
});
return updateChatList;
}
@Override
@Transactional
public BizResponse addPracticeAccount(PracticeAccountReq practiceAccountReq) {
RequestContext context = ContextHolder.get();
Long practiceId = practiceAccountReq.getPracticeId();
List<PracticeVisibleAccount> accountList = practiceAccountReq.getAccountList();
if (null == accountList || null == practiceId){
logger.error("[PracticeXServiceImpl:addPracticeAccount] 保存陪练用户部门信息包含null;accountId = {} ,practiceId = {}",context.getAccountId(),practiceId);
throw new BizException(InternationalEnums.MATERIALCONTROLLER1);
}
//逻辑删除所有用户
iPracticeVisibleService.deleteByPracticeId(practiceId);
if (accountList.size() == 0){
return BizResponse.ok();
}
//否则遍历保存或者修改
for (PracticeVisibleAccount visibleAccount : accountList) {
//全部新增
PracticeVisible practiceVisible = new PracticeVisible();
practiceVisible.setId(idGenerator.generate());
Integer visibleType = visibleAccount.getVisibleType();
practiceVisible.setVisibleType(visibleType);
practiceVisible.setCompanyId(context.getCompanyId());
practiceVisible.setVisibleSiteId(context.getSiteId());
practiceVisible.setCreatedUid(context.getAccountId());
practiceVisible.setPracticeId(practiceId);
if (PracticeVisibleTypeEnum.PART.getStatus().equals(visibleType)){
//用户
practiceVisible.setVisibleAccountId(visibleAccount.getVisibleId());
practiceVisible.setVisibleAccountWorkNum(visibleAccount.getWorkNum());
practiceVisible.setVisibleAccountFullName(visibleAccount.getFullName());
practiceVisible.setVisibleAccountName(visibleAccount.getName());
}
if (PracticeVisibleTypeEnum.ORG.getStatus().equals(visibleType)){
//部门
practiceVisible.setVisibleOrgId(visibleAccount.getVisibleId());
practiceVisible.setVisibleOrgName(visibleAccount.getName());
}
visibleRepository.save(practiceVisible);
}
return BizResponse.ok();
}
@Override
public PracticeVisibleAccountVo getPracticeVisibleList(Long practiceId) {
PracticeVisibleAccountVo visibleAccountVo = new PracticeVisibleAccountVo();
visibleAccountVo.setPracticeId(practiceId);
List<PracticeVisibleInfoVo> practiceVisibleInfoVoList = new ArrayList<>();
List<PracticeVisible> practiceVisibleList = iPracticeVisibleService.getListByPracticeId(practiceId);
if (practiceVisibleList.isEmpty()){
visibleAccountVo.setVisibleInfoList(practiceVisibleInfoVoList);
return visibleAccountVo;
}
for (PracticeVisible practiceVisible : practiceVisibleList) {
Integer visibleType = practiceVisible.getVisibleType();
PracticeVisibleInfoVo visibleInfoVo = new PracticeVisibleInfoVo();
visibleInfoVo.setId(practiceVisible.getId());
visibleInfoVo.setVisibleType(practiceVisible.getVisibleType());
if (PracticeVisibleTypeEnum.ORG.getStatus().equals(visibleType)){
//部门
visibleInfoVo.setName(practiceVisible.getVisibleOrgName());
visibleInfoVo.setVisibleId(practiceVisible.getVisibleOrgId());
}else if (PracticeVisibleTypeEnum.PART.getStatus().equals(visibleType)){
//用户
visibleInfoVo.setName(practiceVisible.getVisibleAccountName());
visibleInfoVo.setVisibleId(practiceVisible.getVisibleAccountId());
visibleInfoVo.setFullName(practiceVisible.getVisibleAccountFullName());
visibleInfoVo.setWorkNum(practiceVisible.getVisibleAccountWorkNum());
}
practiceVisibleInfoVoList.add(visibleInfoVo);
}
visibleAccountVo.setVisibleInfoList(practiceVisibleInfoVoList);
return visibleAccountVo;
}
@Override
@Transactional
public BizResponse importPracticeChat(SceneChatImportReq sceneChatImportReq) throws Exception {
RequestContext context = ContextHolder.get();
String fileName = sceneChatImportReq.getFileName();
String fileUrl = sceneChatImportReq.getFileUrl();
Long practiceId = sceneChatImportReq.getPracticeId();
Long sceneId = sceneChatImportReq.getSceneId();
List<List<String>> parse = excelImporter.parse(fileUrl, createChatImportTemplate());
if (null == parse || parse.size() == 0){
logger.error("智能陪练导入对话失败。解析excel数据为空; accountId = {} , 入参: {}",context.getAccountId(),JSONObject.toJSONString(sceneChatImportReq));
return BizResponse.fail("导入对话失败,解析对话excel数据为空");
}
logger.info("智能演练导入对话数据: {}",JSONObject.toJSONString(parse));
SceneConfig scene = sceneConfigRepository.getOne(sceneId);
PracticeConfig practice = practiceConfigRepository.getOne(practiceId);
//清空原有对话
clearSceneChat(sceneId);
//默认开始节点坐标
int startXAxis = PracticeConstant.CHAT_DEFAULT_XAXIS;
int startYAxis = PracticeConstant.CHAT_DEFAULT_YAXIS;
//纵坐标依次递增数值
int autoIncrement = PracticeConstant.YAXIS_STEP_LEN;
AtomicInteger latestLevel = new AtomicInteger(0);
AtomicInteger latestYAxis = new AtomicInteger(startYAxis);
SceneChatConfig startNode = new SceneChatConfig();
Long startNodeId = idGenerator.generate();
logger.info("导入对话开始节点id:={} ,accountId = {},参数 = {} ",startNodeId,context.getAccountId(),JSONObject.toJSONString(sceneChatImportReq));
startNode.setId(startNodeId);
setChatProperties(startNode,0L,latestLevel.get(),PracticeNodeEnum.START,String.valueOf(startXAxis),String.valueOf(startYAxis),practice,scene,context);
chatConfigRepository.save(startNode);
Long pId = startNodeId;
//错误信息的列表
Set<String> errMsgs = new TreeSet<>();
//需要新增的对话节点
HashMap<Long,SceneChatConfig> addNodeMap = new HashMap<>();
List<SceneChatConfig> addChatNodeList = new ArrayList<>();
//key=excel第一列序列号: value=学生节点SceneChatConfig ;
Map<String,SceneChatConfig> orderMap = new HashMap<>();
logger.info("获取到excel: {},序号列集合size = {}",fileName,parse.size());
int maxOrderValue = getMaxOrder(parse);
logger.info("智能演练导入对话解析到文件{}最大对话序列号= {}",fileName,maxOrderValue);
for (List<String> rowData : parse) {
String orderValue = rowData.get(0);
if (StringUtils.isEmpty(orderValue)){
continue;
}
int intOrderValue = Double.valueOf(orderValue).intValue();
String robotContent = rowData.get(1);
if (StringUtils.isEmpty(robotContent)){
logger.info("机器人节点话术内容为空该行数据无效!accountId = {} ,行数据为: {} ,文件数据为: {}",context.getAccountId(),JSONObject.toJSONString(rowData),JSONObject.toJSONString(sceneChatImportReq));
errMsgs.add("[第"+intOrderValue+"对话序机器人话术为空.]");
continue;
}
if (robotContent.length() > 250){
errMsgs.add("[第"+intOrderValue+"对话序机器人话术长度大于250.]");
continue;
}
/*if (checkRegex(robotContent,contentRegex)){
errMsgs.add("[第"+intOrderValue+"对话序机器人话术包含英文]");
}*/
if (orderMap.containsKey(orderValue)){
SceneChatConfig stuNode = orderMap.get(orderValue);
String accountContentKeyword = stuNode.getAccountContentKeyword();
ObjectMapper mapper = new ObjectMapper();
HashMap<String,String> keywordMap = new HashMap<>();
if (!StringUtils.isEmpty(accountContentKeyword)){
try {
keywordMap = mapper.readValue(accountContentKeyword, HashMap.class);
} catch (JsonProcessingException e) {
logger.error("智能陪练关键字解析失败;accountId = {} ,accountContentKeyword = {} ;",context.getAccountId(),accountContentKeyword,e);
errMsgs.add("[第"+intOrderValue+"对话序关键字解析失败]");
}
}
//关键词
String keyword = rowData.get(3);
if (!StringUtils.isEmpty(keyword)){
String extendWord = rowData.get(4);
boolean valid = checkKeywordAndExtend(keyword, extendWord, errMsgs, keywordRegex, commentRegex, intOrderValue,stuNode.getAccountContent());
if (!valid){
continue;
}
keywordMap.put(keyword,extendWord);
stuNode.setAccountContentKeyword(JSONObject.toJSONString(keywordMap));
addNodeMap.put(stuNode.getId(),stuNode);
orderMap.put(orderValue,stuNode);
}
//禁忌词汇
String tabooWord = rowData.get(5);
if (!StringUtils.isEmpty(tabooWord)){
boolean valid = checkTabooWord(tabooWord, stuNode.getAccountContentTabooWord(), errMsgs, commentRegex, intOrderValue);
if (!valid){
continue;
}
stuNode.setAccountContentTabooWord(tabooWord);
}
}else {
//机器人对话节点
SceneChatConfig robotNode = new SceneChatConfig();
Long robotNodeId = idGenerator.generate();
robotNode.setId(robotNodeId);
int robotLevel = latestLevel.incrementAndGet();
setChatProperties(robotNode,pId,robotLevel,PracticeNodeEnum.ROBOT,String.valueOf(startXAxis),String.valueOf(latestYAxis.addAndGet(autoIncrement)),practice,scene,context);
robotNode.setRobotContent(robotContent);
addNodeMap.put(robotNodeId,robotNode);
//学员对话节点
SceneChatConfig stuNode = new SceneChatConfig();
String studentContent = rowData.get(2);
if (StringUtils.isEmpty(studentContent)){
//判断是否是最后结束语句
if (maxOrderValue != intOrderValue){
errMsgs.add("[第"+intOrderValue+"对话序学员话术内容为空]");
}else {
logger.info("智能演练导入对话,学员话术为空,解析对话结束=========序列号={},机器人语句={}",intOrderValue,robotContent);
break;
}
}
if (studentContent.length() > 250){
errMsgs.add("[第"+intOrderValue+"对话序学员话术长度大于250.]");
continue;
}
/*if (checkRegex(studentContent,contentRegex)){
errMsgs.add("[第"+intOrderValue+"对话序学员话术包含英文.]");
}*/
Long stuNodeId = idGenerator.generate();
stuNode.setId(stuNodeId);
int stuLevel = latestLevel.incrementAndGet();
setChatProperties(stuNode,robotNodeId,stuLevel,PracticeNodeEnum.STUDENT,String.valueOf(startXAxis),String.valueOf(latestYAxis.addAndGet(autoIncrement)),practice,scene,context);
stuNode.setAccountContent(studentContent);
Map<String,String> keywordMap = new HashMap<>();
//关键词
String keyword = rowData.get(3);
if (!StringUtils.isEmpty(keyword)){
//扩展词
String extendWord = rowData.get(4);
boolean valid = checkKeywordAndExtend(keyword, extendWord, errMsgs, keywordRegex, commentRegex, intOrderValue,studentContent);
if (!valid){
continue;
}
keywordMap.put(keyword,extendWord);
stuNode.setAccountContentKeyword(JSONObject.toJSONString(keywordMap));
}
//禁忌词汇
String tabooWord = rowData.get(5);
if (!StringUtils.isEmpty(tabooWord)){
boolean valid = checkTabooWord(tabooWord, stuNode.getAccountContentTabooWord(), errMsgs, commentRegex, intOrderValue);
if (!valid){
continue;
}
stuNode.setAccountContentTabooWord(tabooWord);
}
addNodeMap.put(stuNodeId,stuNode);
pId = stuNodeId;
orderMap.put(orderValue,stuNode);
}
}
addNodeMap.forEach((id,chatNode) -> {
Integer sceneNodeType = chatNode.getSceneNodeType();
if (PracticeNodeEnum.STUDENT.getStatus().equals(sceneNodeType)){
String accountContentKeyword = chatNode.getAccountContentKeyword();
String accountContent = chatNode.getAccountContent();
String msg = accountContent;
if (accountContent.length() > 5){
msg = accountContent.substring(0,5);
}
if (StringUtils.isEmpty(accountContentKeyword)){
errMsgs.add("['"+msg+"...' 对话内容关键词为空]");
}else {
ObjectMapper mapper = new ObjectMapper();
try {
Map<String,String> map = mapper.readValue(accountContentKeyword, Map.class);
if (null == map || map.isEmpty()){
errMsgs.add("['"+msg+"...' 对话内容关键词为空]");
}
} catch (JsonProcessingException e) {
logger.error("导入对话关键字解析异常",e);
errMsgs.add("['"+msg+"...' 对话内容关键词解析异常;keyword = "+accountContentKeyword+"']");
}
}
}
addChatNodeList.add(chatNode);
});
if (errMsgs.size() > 0){
logger.error("导入对话失败;accountId = {},practiceId = {},sceneId = {},错误信息: {}",context.getAccountId(),practiceId,sceneId,JSONArray.toJSON(errMsgs));
throw new BizException(InternationalEnums.MATERIALCONTROLLER1.getCode(), JSONArray.toJSONString(errMsgs));
}
chatConfigRepository.saveAll(addChatNodeList);
return BizResponse.ok();
}
/**
* 校验禁忌词
* @param tabooWord 禁忌词文本
* @param accountContentTabooWord 已设置的禁忌词
*/
private boolean checkTabooWord(String tabooWord,String accountContentTabooWord,Set<String> errMsgs,String commentRegex,int intOrderValue){
if (!StringUtils.isEmpty(accountContentTabooWord) && !accountContentTabooWord.equals(tabooWord)){
errMsgs.add("[第"+intOrderValue+"对话序禁忌词格式错误]");
return false;
}
if (!checkRegex(tabooWord,commentRegex)){
errMsgs.add("[第"+intOrderValue+"对话序禁忌词包含中文/英文分号以外其他字符]");
return false;
}
return true;
}
//校验关键词和扩展词汇
private boolean checkKeywordAndExtend(String keyword,String extendWord,Set<String> errMsgs,String keywordRegex,String commentRegex,int intOrderValue,String accountContent){
if (keyword.length() > 10){
errMsgs.add("[第"+intOrderValue+"对话序关键字长度大于10]");
return false;
}
if (!checkRegex(keyword,keywordRegex)){
errMsgs.add("[第"+intOrderValue+"对话序关键词包含非中文]");
return false;
}
//扩展词
if (!StringUtils.isEmpty(extendWord)){
if (!checkRegex(extendWord,commentRegex)){
errMsgs.add("[第"+intOrderValue+"对话序拓展词包含中文/英文分号以外其他字符]");
return false;
}
}
if (!accountContent.contains(keyword)){
errMsgs.add("[第"+intOrderValue+"对话序,关键词不属于标准话术内容]");
return false;
}
return true;
}
/**
* 校验字符串是否全是中文
* @param str 文本
* @param regex 正则表达式
* @return true 符合正则规则;false 不符合
*/
private boolean checkRegex(String str,String regex) {
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(str);
return m.matches();
}
//获取最大的序列号
private int getMaxOrder(List<List<String>> parse) {
Set<Integer> orderSet = new HashSet<>();
for (List<String> rowData : parse) {
String orderValue = rowData.get(0);
if (StringUtils.isEmpty(orderValue)){
continue;
}
Integer integer = Double.valueOf(orderValue).intValue();
orderSet.add(integer);
}
Integer maxOrder = orderSet.stream().distinct().max((e1, e2) -> e1.compareTo(e2)).get();
return maxOrder;
}
private void setChatProperties(SceneChatConfig chatNode,Long pId,int level,PracticeNodeEnum nodeType, String xAxis,String yAxis,PracticeConfig practice,SceneConfig scene,RequestContext context){
chatNode.setLevel(level);
chatNode.setPid(pId);
chatNode.setSceneNodeType(nodeType.getStatus());
chatNode.setxAxis(xAxis);
chatNode.setyAxis(yAxis);
chatNode.setPracticeId(practice.getId());
chatNode.setSceneId(scene.getId());
chatNode.setSceneName(scene.getName());
chatNode.setOrgId(context.getOrgId());
chatNode.setSiteId(context.getSiteId());
chatNode.setCompanyId(context.getCompanyId());
chatNode.setCreatedUid(context.getAccountId());
}
private Template createChatImportTemplate(){
Template template = new Template();
List<TemplateColumn> columns = new ArrayList<>();
columns.add(new TemplateColumn("order","序列号",1));
columns.add(new TemplateColumn("robotNode","机器人节点话术(必填)",2));
columns.add(new TemplateColumn("studentNode","学员节点话术(必填)",3));
columns.add(new TemplateColumn("keyword","关键词(必填)",4));
columns.add(new TemplateColumn("extendWord","扩展词(非必填)",5));
columns.add(new TemplateColumn("tabooWord","禁忌词",6));
template.setColumns(columns);
return template;
}
@Override
@Transactional
public BizResponse clearSceneChat(Long sceneId) {
RequestContext context = ContextHolder.get();
SceneConfig scene = sceneConfigRepository.getOne(sceneId);
Long practiceId = scene.getPracticeId();
if (null == practiceId){
logger.error("[PracticeXServiceImpl:clearSceneChat]场景对应陪练id为空.sceneId = {},accountId = {}",sceneId,context.getAccountId());
return BizResponse.fail("清空对话失败");
}
List<SceneChatConfig> sceneChatConfigs = chatConfigService.selectChatNodes(practiceId, sceneId, null, null, null);
for (SceneChatConfig sceneChatConfig : sceneChatConfigs) {
sceneChatConfig.setDeleted(true);
sceneChatConfig.setUpdatedUid(context.getAccountId());
}
chatConfigRepository.saveAll(sceneChatConfigs);
return BizResponse.ok();
}
/**
* 递归获取节点及其子节点信息
* @param chatNode 节点
*/
private void getSceneChatChildNodes(SceneChatConfig chatNode,PracticeChatNodeReq chatNodeReq) throws JsonProcessingException {
if (null == chatNode){
return;
}
List<PracticeChatNodeReq> childChatNodes = new ArrayList<>();
Long practiceId = chatNode.getPracticeId();
Long sceneId = chatNode.getSceneId();
BeanUtils.copyProperties(chatNode,chatNodeReq);
List<SceneChatConfig> nextChatNodes = chatConfigService.selectChatNodes(practiceId, sceneId,null, chatNode.getId(), null);
if (null != nextChatNodes && nextChatNodes.size() > 0 ){
for (SceneChatConfig childChat : nextChatNodes){
PracticeChatNodeReq childChatReq = new PracticeChatNodeReq();
BeanUtils.copyProperties(childChat,childChatReq);
childChatReq.setAccountRealVoiceUrl(childChat.getAccountContentVoiceUrl());
String accountContentKeyword = childChat.getAccountContentKeyword();
//解析关键字
List<KeyWordsReq> keyWordsReqList = new ArrayList<>();
if (!StringUtils.isEmpty(accountContentKeyword)){
ObjectMapper mapper = new ObjectMapper();
HashMap<String,String> keywordMap = mapper.readValue(accountContentKeyword, HashMap.class);
keywordMap.forEach((keyword,extendWord) -> {
KeyWordsReq keyWordsReq = new KeyWordsReq();
keyWordsReq.setKey(keyword);
keyWordsReq.setValue(extendWord);
keyWordsReqList.add(keyWordsReq);
});
}
childChatReq.setKeyWordList(keyWordsReqList);
getSceneChatChildNodes(childChat,childChatReq);
childChatNodes.add(childChatReq);
}
}
chatNodeReq.setChildNodes(childChatNodes);
}
/**保存或者修改陪练场景对话信息*/
private void saveOrUpdatePracticeDialogue(PracticeConfig practice,Long sceneId,Long pId, List<PracticeChatNodeReq> chatNodes) {
if (null == chatNodes || chatNodes.size() == 0){
return;
}
for (PracticeChatNodeReq chatNodeReq : chatNodes){
SceneChatConfig conversation = new SceneChatConfig();
SceneConfig scene = sceneConfigRepository.getOne(sceneId);
conversation.setSceneName(scene.getName());
Long chatNodeId = chatNodeReq.getId();
if (null == chatNodeId || chatNodeId <= 0){
Long id = idGenerator.generate();
conversation.setId(id);
}else {
conversation = chatConfigRepository.getOne(chatNodeId);
conversation.setDeleted(false);
}
conversation.setSceneId(sceneId);
conversation.setPid(pId);
conversation.setPracticeId(practice.getId());
conversation.setLevel(chatNodeReq.getLevel());
conversation.setSceneNodeType(chatNodeReq.getSceneNodeType());
conversation.setxAxis(chatNodeReq.getXAxis());
conversation.setyAxis(chatNodeReq.getYAxis());
Integer sceneNodeType = chatNodeReq.getSceneNodeType();
if (PracticeNodeEnum.ROBOT.getStatus().equals(sceneNodeType)){
//机器人节点
String oldRobotContent = conversation.getRobotContent();
String robotContent = chatNodeReq.getRobotContent();
conversation.setRobotContent(robotContent);
if (!StringUtils.isEmpty(oldRobotContent) && !oldRobotContent.equals(robotContent)){
//标准话术修改,合成语音置空
conversation.setRobotContentVoiceUrl(null);
conversation.setRobotContentVoiceDuration(null);
}
}
if (PracticeNodeEnum.STUDENT.getStatus().equals(sceneNodeType)){
//学员节点
String oldStuContent = conversation.getAccountContent();
String accountContent = chatNodeReq.getAccountContent();
conversation.setAccountContent(accountContent);
conversation.setAccountContentTabooWord(chatNodeReq.getAccountContentTabooWord());
String accountRealVoiceUrl = chatNodeReq.getAccountRealVoiceUrl();
String accountContentFileName = chatNodeReq.getAccountContentFileName();
conversation.setAccountContentFileName(accountContentFileName);
if (StringUtils.isEmpty(accountContentFileName)){
if (!StringUtils.isEmpty(oldStuContent) && !oldStuContent.equals(accountContent)){
//标准话术修改,合成语音置空
conversation.setAccountContentVoiceUrl(null);
conversation.setAccountContentVoiceDuration(null);
}
}else{
conversation.setAccountContentVoiceUrl(accountRealVoiceUrl);
long audioDuration = AudioUtils.INSTANCE.getAudioDuration(accountRealVoiceUrl);
conversation.setAccountContentVoiceDuration(audioDuration);
}
List<KeyWordsReq> keyWordList = chatNodeReq.getKeyWordList();
if (null != keyWordList){
HashMap<String,String> keyMap = new HashMap<>();
for (KeyWordsReq keyWordsReq : keyWordList) {
String keyword = keyWordsReq.getKey();
String extendWord = keyWordsReq.getValue();
if (!StringUtils.isEmpty(keyMap)){
keyMap.put(keyword,extendWord);
}
}
conversation.setAccountContentKeyword(JSONObject.toJSONString(keyMap));
}
}
//获取该节点下节点信息
List<PracticeChatNodeReq> childNodes = chatNodeReq.getChildNodes();
RequestContext context = ContextHolder.get();
conversation.setOrgId(context.getOrgId());
conversation.setSiteId(context.getSiteId());
conversation.setCompanyId(context.getCompanyId());
conversation.setCreatedUid(context.getAccountId());
conversation.setUpdatedUid(context.getAccountId());
chatConfigRepository.save(conversation);
//获取对话表id
Long newChatNodeId = conversation.getId();
//递归 保存节点下字节点信息
saveOrUpdatePracticeDialogue(practice,sceneId,newChatNodeId,childNodes);
}
}
//上传文件到oss
private String upFileToOss(PracticeConfig practice, String content,RequestContext context) throws Exception {
//RequestContext context = ContextHolder.get();
logger.info("context.getAccountId--->>>{}",context.getAccountId());
String filePath = OssFileUtil.getManageStandardVoiceUri(context.getCompanyId(), context.getSiteId(), PracticeConstant.BUSINESS_TYPE
, PracticeConstant.SUB_BUSINESS_TYPE, context.getAccountId(),idGenerator.generate());
return xunfeiUtil.stringToVoice(content, practice.getRobotParams(), filePath,PracticeVoiceTypeEnum.MP3);
}
/**保存或者修改陪练积分规则*/
private void saveOrUpdatePracticePointRule(Integer newExamGivenPointType, Long practiceId, List<PracticePointVo> practicePointList) {
// 1.新老相等 && 等于true 遍历saveOrUpdateOrDel
//2.新老规则不相等;false-> true 遍历新增;true->false 查询所有删除;
//查询陪练下所有积分规则,首先设置逻辑删除
pointRuleConfigRepository.deleteRulesByPractice(practiceId);
if (PracticePointGivenEnum.TRUE.getStatus().equals(newExamGivenPointType)) {
//设置积分规则
if (null != practicePointList && practicePointList.size() > 0) {
List<PracticePointRuleConfig> pointRuleList = new ArrayList<>();
practicePointList.forEach(pointVo -> {
Long pointId = pointVo.getId();
PracticePointRuleConfig pointRule = new PracticePointRuleConfig();
if (null == pointId || 0L == pointId) {
pointRule.setId(idGenerator.generate());
} else {
pointRule = pointRuleConfigRepository.getOne(pointId);
pointRule.setDeleted(false);
}
pointRule.setPracticeId(practiceId);
pointRule.setMinScore(pointVo.getMinScore());
pointRule.setMaxScore(pointVo.getMaxScore());
pointRule.setPoint(pointVo.getPoint());
pointRuleList.add(pointRule);
});
pointRuleConfigRepository.saveAll(pointRuleList);
}
}
}
/**
* 校验策略配置参数是否符合规则
* @param strategyInfoDto 策略配置入参
*/
private void checkPracticeStrategyParamsValid(PracticeStrategyInfoDto strategyInfoDto) {
// 校验策略参数
RequestContext context = ContextHolder.get();
Integer visibleType = strategyInfoDto.getVisibleType();
if (null == visibleType
|| (!PracticeVisibleTypeEnum.ALL.getStatus().equals(visibleType)
&& !PracticeVisibleTypeEnum.PART.getStatus().equals(visibleType)
)
){
logger.error("[checkPracticeStrategyParamsValid]没有匹配的可见范围 accountId= {} ,入参: {}",context.getAccountId(),JSONObject.toJSONString(strategyInfoDto));
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2);
}
// 校验评分规则
checkScoreRuleValid(strategyInfoDto);
//陪练模式 80:训练+考核 ,10:训练 20:考核
Integer useType = strategyInfoDto.getUseType();
//每轮对话过关条件 80:开启 10:关闭
Integer pracNextRoundCondition = strategyInfoDto.getStartNextRoundType();
Integer skipType = strategyInfoDto.getSkipType();
if (PracticeModelStatusEnum.ASSESSMENT.getStatus().equals(useType)){
//考核模式
if (null != skipType || null != pracNextRoundCondition){
logger.error("[checkPracticeStrategyParamsValid]考核模式下无需设置训练策略配置 accountId= {} ,入参: {}",context.getAccountId(),JSONObject.toJSONString(strategyInfoDto));
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2);
}
//校验考核模式下的参数
checkExamTypeParams(strategyInfoDto, context);
}else if (PracticeModelStatusEnum.PRA_ASSESS.getStatus().equals(useType)){
// 训练模式参数校验
checkPracticeTypeParams(strategyInfoDto, context);
//校验考核模式下的参数
checkExamTypeParams(strategyInfoDto, context);
}else {
//训练模式
Integer repeatPush = strategyInfoDto.getRepeatPush();
Integer manyRoundChat = strategyInfoDto.getManyRoundChat();
Integer examPassMinScore = strategyInfoDto.getExamPassMinScore();
Integer examGivenPointType = strategyInfoDto.getExamGivenPointType();
if (null != manyRoundChat || null != examPassMinScore || null != examGivenPointType || null != repeatPush){
logger.error("[checkPracticeStrategyParamsValid]训练模式下无需设置考核策略配置参数; accountId= {} ,入参: {}",context.getAccountId(), JSONObject.toJSONString(strategyInfoDto));
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2);
}
// 训练模式参数校验
checkPracticeTypeParams(strategyInfoDto, context);
}
}
/**
* 校验包含训练模式的参数
* @param strategyInfoDto 入参
* @param context requestContext
*/
private void checkPracticeTypeParams(PracticeStrategyInfoDto strategyInfoDto, RequestContext context) {
Integer skipType = strategyInfoDto.getSkipType();
//每轮对话过关条件 80:开启 10:关闭
Integer pracNextRoundCondition = strategyInfoDto.getStartNextRoundType();
if (null == skipType || null == pracNextRoundCondition){
logger.error("[checkPracticeStrategyParamsValid]训练策略配置必填参数包含空值 accountId= {} ,入参: {}",context.getAccountId(),JSONObject.toJSONString(strategyInfoDto));
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2);
}
if (pracNextRoundCondition.equals(PracticeManyRoudChatEnum.FALSE.getStatus())){
return;
}
//开启每轮对话过关条件
//过关分数
Integer startNextRoundScore = strategyInfoDto.getStartNextRoundScore();
//强制练习次数
Integer practiceFailedMaxCount = strategyInfoDto.getPracticeFailedMaxCount();
if (null == startNextRoundScore || null == practiceFailedMaxCount
|| 0 > startNextRoundScore || 0 >= practiceFailedMaxCount){
logger.error("[checkPracticeStrategyParamsValid]训练策略配置开启过关条件参数填写错误. accountId= {} ,入参: {}",context.getAccountId(),JSONObject.toJSONString(strategyInfoDto));
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2);
}
}
/**
* 校验包含考核的参数
* @param strategyInfoDto 入参
* @param context requestContext
*/
private void checkExamTypeParams(PracticeStrategyInfoDto strategyInfoDto, RequestContext context) {
//考核重复提交、多轮对话、考核及格分
Integer repeatPush = strategyInfoDto.getRepeatPush();
Integer manyRoundChat = strategyInfoDto.getManyRoundChat();
Integer examPassMinScore = strategyInfoDto.getExamPassMinScore();
Integer examGivenPointType = strategyInfoDto.getExamGivenPointType();
if (null == manyRoundChat || null == examPassMinScore || null == examGivenPointType || null == repeatPush){
logger.error("[checkPracticeStrategyParamsValid]考核策略配置必填参数包含空值 accountId= {} ,入参: {}",context.getAccountId(), JSONObject.toJSONString(strategyInfoDto));
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2);
}
if (examPassMinScore < 0 || examPassMinScore > 100){
logger.error("考核策略配置-考核及格分超出区间[0,100]; accountId= {} ,入参: {}",context.getAccountId(), JSONObject.toJSONString(strategyInfoDto));
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2);
}
if (examGivenPointType.equals(PracticePointGivenEnum.TRUE.getStatus())){
//发放积分
List<PracticePointVo> practicePointList = strategyInfoDto.getPracticePointList();
//校验积分规则
checkExamPointParams(strategyInfoDto, context, practicePointList);
}
if (PracticeManyRoudChatEnum.TRUE.getStatus().equals(manyRoundChat)){
//开启多轮对话
//相似度评分阈值
Integer similarityRate = strategyInfoDto.getSimilarityRate();
//强制对话轮次
Integer examFailedMaxCount = strategyInfoDto.getExamFailedMaxCount();
//未识别回复类型 80:默认回复,10:自定义回复
Integer similarityFailedMsgType = strategyInfoDto.getSimilarityFailedMsgType();
if (null == similarityRate || null == examFailedMaxCount || null == similarityFailedMsgType){
logger.error("[checkPracticeStrategyParamsValid]考核策略配置开启多轮对话必填参数包含空值 accountId= {} ,入参: {}",context.getAccountId(),JSONObject.toJSONString(strategyInfoDto));
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2);
}
if (examFailedMaxCount <= 0){
logger.error("[checkPracticeStrategyParamsValid]考核策略配置开启多轮对话,强制对话轮次小于0; accountId = {} ,入参: {}",context.getAccountId(),JSONObject.toJSONString(strategyInfoDto));
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2);
}
if (PracticeSimilaryFailedEnum.FALSE.getStatus().equals(similarityFailedMsgType)){
//自定义未识别回复
String similarityFailedMsg = strategyInfoDto.getSimilarityFailedMsg();
if (StringUtils.isEmpty(similarityFailedMsg)){
logger.error("[checkPracticeStrategyParamsValid]考核策略配置开启多轮对话,自定义未识别回复为空; accountId = {} ,入参: {}",context.getAccountId(),JSONObject.toJSONString(strategyInfoDto));
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2);
}
}
}
}
private void checkExamPointParams(PracticeStrategyInfoDto strategyInfoDto, RequestContext context, List<PracticePointVo> practicePointList) {
if (null == practicePointList || practicePointList.isEmpty()){
logger.error("考核策略配置-开启发放积分,参数为空; accountId= {} ,入参: {}",context.getAccountId(), JSONObject.toJSONString(strategyInfoDto));
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2);
}
practicePointList.sort(Comparator.comparing(PracticePointVo::getMinScore));
Integer preRuleMaxScore = -1;
Integer preRulePoint = 0;
for (PracticePointVo pointVo : practicePointList) {
Integer minScore = pointVo.getMinScore();
Integer maxScore = pointVo.getMaxScore();
Integer point = pointVo.getPoint();
if (null == minScore || null == maxScore || minScore < 0 || maxScore < 0 || null == point || point < 0){
logger.error("考核策略配置-开启发放积分,积分数值错误; accountId= {} ,入参: {}",context.getAccountId(), JSONObject.toJSONString(strategyInfoDto));
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2.getCode(),"得分或发放积分设置有误");
}
// 最大100分
if (pointVo.getPoint() >= 100 ){
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2.getCode(),"积分最大设置100分");
}
// 发放积分后面的大于前面的
if (pointVo.getPoint() <= preRulePoint) {
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2.getCode(),"发放积分数量设置有误");
}
//积分范围不能交叉
if (pointVo.getMinScore() <= preRuleMaxScore) {
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2.getCode(),"得分设置不能有交集");
}
preRuleMaxScore = pointVo.getMaxScore();
preRulePoint = pointVo.getPoint();
}
}
/**
* 校验评分规则参数是否符合限制要求
*/
private void checkScoreRuleValid(PracticeStrategyInfoDto strategyInfoDto) {
RequestContext context = ContextHolder.get();
Integer scoreRuleComplete = strategyInfoDto.getScoreRuleComplete();
Integer scoreRuleExpress = strategyInfoDto.getScoreRuleExpress();
Integer scoreRuleKeyword = strategyInfoDto.getScoreRuleKeyword();
Integer scoreRulePolite = strategyInfoDto.getScoreRulePolite();
Integer scoreRuleSmooth = strategyInfoDto.getScoreRuleSmooth();
if (null == scoreRuleComplete || null == scoreRuleExpress
|| null == scoreRuleKeyword || null == scoreRulePolite || null == scoreRuleSmooth){
logger.error("[checkScoreRuleValid]评分规则不能包含空值 accountId= {} ,入参: {}",context.getAccountId(),JSONObject.toJSONString(strategyInfoDto));
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2);
}
int sum = scoreRuleComplete + scoreRuleExpress + scoreRuleKeyword + scoreRulePolite + scoreRuleSmooth ;
if (sum != 100){
logger.error("[checkScoreRuleValid]评分规则总和不等于100 accountId= {} ,入参: {}",context.getAccountId(),JSONObject.toJSONString(strategyInfoDto));
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2);
}
}
/**
* 校验陪练基本信息参数是否符合规范
* @param practiceReq 入参
*/
private void checkPracticeBaseParamsValid(PracticeBaseInfoDto practiceReq) {
RequestContext context = ContextHolder.get();
String name = practiceReq.getName();
if (StringUtils.isEmpty(name) || name.length() > 100){
logger.error("[checkPracticeBaseParamsValid]名称长度不能大于100 accountId= {} ,入参: {}",context.getAccountId(),JSONObject.toJSONString(practiceReq));
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2.getCode(),"陪练名称不符合限制条件");
}
//校验应用模式
checkPracticeModelValid(practiceReq.getUseType(),practiceReq.getPracticeStartAt(),practiceReq.getPracticeEndAt()
,practiceReq.getExamStartAt(),practiceReq.getExamEndAt(),practiceReq.getMaxExamCount());
// 校验关键词个数,长度,是否重复
checkPracticeBaseInfoKeyWord(practiceReq.getKeyWord());
//校验机器人称呼长度
String robotAliasName = practiceReq.getRobotAliasName();
if (StringUtils.isEmpty(robotAliasName) || robotAliasName.length() > 3){
logger.error("[checkPracticeBaseParamsValid]机器人名称长度不符合要求 accountId= {} ,入参: {}",context.getAccountId(),JSONObject.toJSONString(practiceReq));
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2);
}
Long robotId = practiceReq.getRobotId();
if (null == robotId){
logger.error("[checkPracticeBaseParamsValid]机器人id不能为空 accountId= {} ,入参: {}",context.getAccountId(),JSONObject.toJSONString(practiceReq));
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2);
}
}
/**校验关键词*/
private void checkPracticeBaseInfoKeyWord(String keyWordStr) {
RequestContext context = ContextHolder.get();
// 校验关键词个数,长度,是否重复
if (StringUtils.isEmpty(keyWordStr)){
return;
}
String[] keywordArray = keyWordStr.split(",");
List<String> keyList = new ArrayList<>();
for (String elem : keywordArray) {
String keyword = elem.trim();
if (StringUtils.isEmpty(keyword)) {
continue;
}
if (keyList.contains(keyword)) {
logger.error("[checkPracticeBaseInfoKeyWord]关键词重复 accountId= {} ,关键词: {}", context.getAccountId(), keyWordStr);
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2.getCode(),"关键词重复");
}
if (keyword.length() > 10) {
logger.error("[checkPracticeBaseInfoKeyWord]关键词长度大于10 accountId= {} ,关键词: {}", context.getAccountId(), keyWordStr);
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2.getCode(),"关键词长度大于10");
}
keyList.add(keyword);
}
if (keyList.size() > 5){
logger.error("[checkPracticeBaseInfoKeyWord]最多添加5个关键词 accountId= {} ,关键词: {}",context.getAccountId(),keyWordStr);
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2.getCode(),"关键词个数大于5");
}
}
/**
* 校验应用模式
*/
private void checkPracticeModelValid(Integer useType, Date practiceStartAt, Date practiceEndAt, Date examStartAt, Date examEndAt, Integer maxExamCount) {
RequestContext context = ContextHolder.get();
if (useType == null
|| (!PracticeModelStatusEnum.ASSESSMENT.getStatus().equals(useType)
&& !PracticeModelStatusEnum.PRA_ASSESS.getStatus().equals(useType)
&& !PracticeModelStatusEnum.PRACTICE.getStatus().equals(useType))
) {
logger.error("[checkPracticeModelValid]没有匹配的应用模式 accountId= {} ,userType= {} ",context.getAccountId(),useType);
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2);
}
if (PracticeModelStatusEnum.ASSESSMENT.getStatus().equals(useType)) {
if (null == examStartAt || null == examEndAt) {
logger.error("[checkPracticeModelValid]考核应用模式下考核时间不能为空 accountId= {} ,userType= {} ",context.getAccountId(),useType);
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2);
}
if (examStartAt.after(examEndAt)){
logger.error("[checkPracticeModelValid]考核应用模式下考核开始时间大于结束时间 accountId= {} ,userType= {} ,examStartAt= {} ,examEndAt= {}"
,context.getAccountId(),useType,examStartAt,examEndAt);
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2);
}
// 校验考核次数数值
if (null == maxExamCount || maxExamCount < 0) {
logger.error("[checkPracticeModelValid]考核应用模式下考核次数填写不规范 accountId= {} ,userType= {} ,maxExamCount = {}",context.getAccountId(),useType,maxExamCount);
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2);
}
}else if (PracticeModelStatusEnum.PRACTICE.getStatus().equals(useType)) {
if (null == practiceStartAt || null == practiceEndAt) {
logger.error("[checkPracticeModelValid]训练应用模式下训练时间不能为空 accountId= {} ,userType= {} ",context.getAccountId(),useType);
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2);
}
if (practiceStartAt.after(practiceEndAt)){
logger.error("[checkPracticeModelValid]训练应用模式下开始时间大于结束时间 accountId= {} ,userType= {} ,practiceStartAt = {},practiceEndAt = {}"
,context.getAccountId(),useType,practiceStartAt,practiceEndAt);
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2);
}
}else if (PracticeModelStatusEnum.PRA_ASSESS.getStatus().equals(useType)) {
if (null == practiceStartAt || null == practiceEndAt
|| null == examStartAt || null == examEndAt) {
logger.error("[checkPracticeModelValid]训练+考核应用模式下训练和考核时间都不能为空! accountId= {} ,userType= {} ",context.getAccountId(),useType);
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2);
}
if (null == maxExamCount || maxExamCount < 0) {
logger.error("[checkPracticeModelValid]训练+考核应用模式下考核次数填写不规范 accountId= {} ,userType= {} ,maxExamCount = {}",context.getAccountId(),useType,maxExamCount);
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2);
}
if (practiceStartAt.after(practiceEndAt)){
logger.error("[checkPracticeModelValid]训练+考核应用模式下训练开始时间大于结束时间 accountId= {} ,userType= {} ,practiceStartAt = {},practiceEndAt = {}"
,context.getAccountId(),useType,practiceStartAt,practiceEndAt);
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2);
}
if (examStartAt.after(examEndAt)){
logger.error("[checkPracticeModelValid]训练+考核应用模式下考核开始时间大于结束时间 accountId= {} ,userType= {} ,examStartAt= {} ,examEndAt= {}"
,context.getAccountId(),useType,examStartAt,examEndAt);
throw new BizException(InternationalEnums.SITECLASSIFYMANAGECOMTROLLER2);
}
}
}
/**
* 设置陪练数据更新人信息
*/
private void setCreatedAccountInfo(PracticeConfig practiceConfig) {
RequestContext requestContext = ContextHolder.get();
practiceConfig.setCreatedUid(requestContext.getAccountId());
practiceConfig.setSiteId(requestContext.getSiteId());
practiceConfig.setCompanyId(requestContext.getCompanyId());
practiceConfig.setOrgId(requestContext.getOrgId());
}
/**
* 设置陪练数据更新人信息
*/
private void setUpdatedAccountInfo(PracticeConfig practiceConfig) {
RequestContext requestContext = ContextHolder.get();
practiceConfig.setUpdatedUid(requestContext.getAccountId());
}
@Override
@Transactional(rollbackFor=Exception.class)
public Long copyPractice(Long practiceId) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException {
RequestContext requestContext = ContextHolder.get();
String[] ignoreProperties = new String[] {"id", "orgId", "siteId", "companyId", "createdUid", "createdAt", "updatedUid", "updatedAt"};
Long targetId = idGenerator.generate();
copyPracticeConfig(practiceId, targetId, ignoreProperties);
// 复制practice_point_rule
copyRule(practiceId, targetId, ignoreProperties, requestContext);
// 复制practice_visible
copyVisible(practiceId, targetId, ignoreProperties, requestContext);
// 复制scene_config 这里不复制删除掉的场景,但是也不更新sort,例如1,2,3,4, 删除了3,但是1,2,4依然可以排序
copyScene(practiceId, targetId, ignoreProperties, requestContext);
return targetId;
}
@Override
@Transactional
public BizResponse delete(Long practiceId) {
RequestContext context = ContextHolder.get();
PracticeConfig practice = practiceConfigRepository.getOne(practiceId);
if (null == practice || null == practice.getId()){
logger.error("[PracticeXServiceImpl:delete]删除陪练失败! 没有查询到陪练信息 practiceId = {};accountId = {}",practiceId,context.getAccountId());
throw new BizException(InternationalEnums.CLASSIFYCONTROLLER4);
}
//删除陪练
Integer practiceStatus = practice.getStatus();
if (!PracticeStatusEnum.DRAFT.getStatus().equals(practiceStatus)){
//判断陪练状态;上架的不能删除
logger.warn("[PracticeXServiceImpl:delete]删除陪练失败! 上架/下架状态的陪练不能删除! practiceId = {};accountId = {}",practiceId,context.getAccountId());
throw new BizException(InternationalEnums.CLASSIFYCONTROLLER4);
}
iPracticeConfigService.delete(practiceId);
//删除陪练场景
sceneConfigService.deleteScene(practiceId, null);
//删除陪练场景对话
List<SceneChatConfig> sceneChatConfigs = chatConfigService.selectChatNodes(practiceId, null, null, null, null);
List<Long> delChatIds = new ArrayList<>();
if (null != sceneChatConfigs && !sceneChatConfigs.isEmpty()){
for (SceneChatConfig sceneChatConfig : sceneChatConfigs) {
chatConfigService.deleteChatNodes(practiceId,sceneChatConfig.getSceneId(),null,null,null);
delChatIds.add(sceneChatConfig.getId());
}
logger.info("[PracticeXServiceImpl:delete]删除陪练场景对话: accountId = {},delChatIds= {}",context.getAccountId(),JSONObject.toJSONString(delChatIds));
}
return BizResponse.ok();
}
@Override
public BizResponse importAccount(PracticeImportAccountReq importAccountReq) {
Long taskId = idGenerator.generate();
String serialNo = "PRACTICE-ACCOUNT-IMPORT-" + taskId;
String taskName = "智能陪练可见范围导入-" + taskId.toString();
String ossUrl = importAccountReq.getFileUrl();
Long practiceId = importAccountReq.getPracticeId();
PracticeAccountImportParam accountImportParam = new PracticeAccountImportParam();
accountImportParam.setFileUrl(ossUrl);
accountImportParam.setPracticeId(practiceId);
accountImportParam.setSerialNo(serialNo);
accountImportParam.setTaskId(taskId);
accountImportParam.setTaskName(taskName);
accountImportParam.setContext(ContextHolder.get());
accountImport.execute(accountImportParam, true);
return BizResponse.ok("任务序号:" + serialNo + ",任务名称:" + taskName);
}
@Override
public BizResponse exportAccount(Long practiceId) {
PracticeAccountExportParam exportParam = new PracticeAccountExportParam();
RequestContext context = ContextHolder.get();
exportParam.setContext(context);
exportParam.setPracticeId(practiceId);
//exportParam.setTaskContext(taskContext);
return BizResponse.ok(accountExport.execute(exportParam));
//return BizResponse.ok(serialNo);
}
@Override
public BizResponse checkPracticeSceneValid(Long practiceId) {
List<SceneConfig> sceneConfigList = sceneConfigService.findSceneByPracticeId(practiceId);
if (null == sceneConfigList || sceneConfigList.isEmpty()){
logger.error("陪练下场景对话校验不通过,未查询到陪练下场景列表. practiceId = {} ,accountId = {}",practiceId);
throw new BizException(PracticeInternationEnum.SCENE_CHAT_INCOMPLETE.getCode(),PracticeInternationEnum.SCENE_CHAT_INCOMPLETE.getName());
}
for (SceneConfig sceneConfig : sceneConfigList) {
Long sceneId = sceneConfig.getId();
//校验场景下对话
checkSceneChatValid(practiceId,sceneId);
}
return BizResponse.ok();
}
@Override
public List<PracticeVo> selectRangeList(Date startDate, Date endDate) {
List<PracticeConfig> list = iPracticeConfigService.getListByTime(startDate,endDate);
if (null == list || list.size() == 0){
return Collections.emptyList();
}
List<PracticeVo> voList = new ArrayList<>();
for (PracticeConfig practiceConfig : list) {
PracticeVo vo = new PracticeVo();
BeanUtils.copyProperties(practiceConfig,vo);
voList.add(vo);
}
return voList;
}
@Override
public List<PracticeVisibleVo> selectVisibleRangeList(Date startDate, Date endDate) {
List<PracticeVisible> list = iPracticeVisibleService.getListByTime(startDate,endDate);
if (null == list || list.size() == 0){
return Collections.emptyList();
}
List<PracticeVisibleVo> voList = new ArrayList<>();
for (PracticeVisible visible : list) {
PracticeVisibleVo vo = new PracticeVisibleVo();
BeanUtils.copyProperties(visible,vo);
voList.add(vo);
}
return voList;
}
/**
* 校验陪练场景下对话是否符合规范
* @param practiceId 陪练id
* @param sceneId 场景id
*/
private void checkSceneChatValid(Long practiceId, Long sceneId) {
RequestContext context = ContextHolder.get();
//场景对话至少包含 :开始-机器人-学员 三个节点
List<SceneChatConfig> startNode = chatConfigService.selectChatNodes(practiceId, sceneId, PracticeNodeEnum.START.getStatus(), 0L, 0);
if (null == startNode || startNode.isEmpty()){
logger.error("场景对话校验不通过.未查询到开始节点; practiceId = {} ,sceneId = {},accountId = {}",practiceId,sceneId,context.getAccountId());
throw new BizException(PracticeInternationEnum.SCENE_CHAT_INCOMPLETE.getCode(),PracticeInternationEnum.SCENE_CHAT_INCOMPLETE.getName());
}
List<SceneChatConfig> robotNode = chatConfigService.selectChatNodes(practiceId, sceneId, PracticeNodeEnum.ROBOT.getStatus(), null, 1);
if (null == robotNode || robotNode.isEmpty()){
logger.error("场景对话校验不通过.未查询到开始节点下的机器人节点; practiceId = {} ,sceneId = {},accountId = {}",practiceId,sceneId,context.getAccountId());
throw new BizException(PracticeInternationEnum.SCENE_CHAT_INCOMPLETE.getCode(),PracticeInternationEnum.SCENE_CHAT_INCOMPLETE.getName());
}
List<SceneChatConfig> stuNode = chatConfigService.selectChatNodes(practiceId, sceneId, PracticeNodeEnum.STUDENT.getStatus(), null, 2);
if (null == stuNode || stuNode.isEmpty()){
logger.error("场景对话校验不通过.未查询到开始节点下的学员节点; practiceId = {} ,sceneId = {},accountId = {}",practiceId,sceneId,context.getAccountId());
throw new BizException(PracticeInternationEnum.SCENE_CHAT_INCOMPLETE.getCode(),PracticeInternationEnum.SCENE_CHAT_INCOMPLETE.getName());
}
List<SceneChatConfig> nodeList = chatConfigService.selectChatNodes(practiceId, sceneId, null, null, null);
for (SceneChatConfig sceneChat : nodeList) {
Long sceneChatId = sceneChat.getId();
Integer sceneNodeType = sceneChat.getSceneNodeType();
//校验节点必填信息是否完整
if (PracticeNodeEnum.ROBOT.getStatus().equals(sceneNodeType)){
String robotContent = sceneChat.getRobotContent();
if (StringUtils.isEmpty(robotContent) || robotContent.length() > 250){
logger.error("场景对话校验不通过.机器人节点话术为空或长度超过限制; practiceId = {} ,sceneId = {},sceneChatId = {},accountId = {},robotContent = {}"
,practiceId,sceneId,sceneChatId,context.getAccountId(),robotContent);
throw new BizException(PracticeInternationEnum.SCENE_CHAT_INCOMPLETE.getCode(),PracticeInternationEnum.SCENE_CHAT_INCOMPLETE.getName());
}
}else if (PracticeNodeEnum.STUDENT.getStatus().equals(sceneNodeType)){
String accountContent = sceneChat.getAccountContent();
String keyword = sceneChat.getAccountContentKeyword();
if (StringUtils.isEmpty(accountContent) || accountContent.length() > 250 || StringUtils.isEmpty(keyword)){
logger.error("场景对话校验不通过.学员节点标准话术为空或长度超过限制或关键字为空; practiceId = {} ,sceneId = {},sceneChatId = {},accountId = {},accountContent = {}"
,practiceId,sceneId,sceneChatId,context.getAccountId(),accountContent);
throw new BizException(PracticeInternationEnum.SCENE_CHAT_INCOMPLETE.getCode(),PracticeInternationEnum.SCENE_CHAT_INCOMPLETE.getName());
}
}
}
}
/**
* 校验语音合成
*/
private void checkVoice(List<SceneChatConfig> nodeList){
if (null == nodeList || nodeList.isEmpty()){
return;
}
RequestContext context = ContextHolder.get();
for (SceneChatConfig sceneChat : nodeList) {
Integer sceneNodeType = sceneChat.getSceneNodeType();
Long practiceId = sceneChat.getPracticeId();
Long sceneId = sceneChat.getSceneId();
//校验节点必填信息是否完整
if (PracticeNodeEnum.ROBOT.getStatus().equals(sceneNodeType)){
//上架操作校验语音合成
String voiceUrl = sceneChat.getRobotContentVoiceUrl();
Long duration = sceneChat.getRobotContentVoiceDuration();
if (StringUtils.isEmpty(voiceUrl) || null == duration){
logger.error("场景对话校验不通过.机器人节点话术合成语音/时长为空; practiceId = {} ,sceneId = {},accountId = {}",practiceId,sceneId,context.getAccountId());
throw new BizException(PracticeInternationEnum.SCENE_CHAT_INCOMPLETE.getCode(),PracticeInternationEnum.SCENE_CHAT_INCOMPLETE.getName());
}
}else if (PracticeNodeEnum.STUDENT.getStatus().equals(sceneNodeType)){
Long duration = sceneChat.getAccountContentVoiceDuration();
String voiceUrl = sceneChat.getAccountContentVoiceUrl();
if (StringUtils.isEmpty(voiceUrl) || null == duration){
logger.error("场景对话校验不通过.学员节点话术合成语音/时长为空; practiceId = {} ,sceneId = {},accountId = {}",practiceId,sceneId,context.getAccountId());
throw new BizException(PracticeInternationEnum.SCENE_CHAT_INCOMPLETE.getCode(),PracticeInternationEnum.SCENE_CHAT_INCOMPLETE.getName());
}
}
}
}
private void copyChat(Long practiceId, Long targetId
, SceneConfig oldScene, Long newSceneId
, String[] ignoreProperties, RequestContext requestContext) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException {
List<SceneChatConfig> newChats = new ArrayList<SceneChatConfig>();
List<SceneChatConfig> oldChats = chatConfigRepository.findByPracticeIdAndSceneId(practiceId, oldScene.getId());
if(null == oldChats) {
logger.warn("SceneChatConfig with practiceId {} not exist!", practiceId);
}else {
Map<Long, Long> oldNewId = new HashMap<Long, Long>();
for(SceneChatConfig oldChat : oldChats) {
SceneChatConfig newChat = new SceneChatConfig();
BeanUtils.copyProperties(oldChat, newChat, ignoreProperties);
Long newChatId = idGenerator.generate();
newChat.setId(newChatId);
newChat.setPracticeId(targetId);
newChat.setSceneId(newSceneId);
setCommonProperties(newChat, requestContext);
if(oldNewId.containsKey(oldChat.getPid())) {
newChat.setPid(oldNewId.get(oldChat.getPid()));
}
oldNewId.put(oldChat.getId(), newChatId);
newChats.add(newChat);
}
if(null != newChats) {
chatConfigRepository.saveAll(newChats);
}
}
}
private void copyScene(Long practiceId, Long targetId, String[] ignoreProperties, RequestContext requestContext) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException {
List<SceneConfig> oldScenes = sceneConfigRepository.selectByPracticeId(practiceId);
if(null == oldScenes) {
logger.warn("SceneConfig with practiceId {} not exist!", practiceId);
}else {
List<SceneConfig> newScenes = new ArrayList<SceneConfig>();
for(SceneConfig oldScene : oldScenes) {
SceneConfig newScene = new SceneConfig();
BeanUtils.copyProperties(oldScene, newScene, ignoreProperties);
Long newSceneId = idGenerator.generate();
newScene.setId(newSceneId);
newScene.setPracticeId(targetId);
setCommonProperties(newScene, requestContext);
newScenes.add(newScene);
// 复制scene_chat_config
copyChat(practiceId, targetId, oldScene, newSceneId, ignoreProperties, requestContext);
}
if(null != newScenes) {
sceneConfigRepository.saveAll(newScenes);
}
}
}
private void copyVisible(Long practiceId, Long targetId, String[] ignoreProperties, RequestContext requestContext) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException {
List<PracticeVisible> oldVisibles = visibleRepository.findByPracticeId(practiceId);
if(null == oldVisibles) {
logger.warn("PracticeVisible with practiceId {} not exist!", practiceId);
}else {
List<PracticeVisible> newVisibles = new ArrayList<PracticeVisible>();
for(PracticeVisible oldVisible : oldVisibles) {
PracticeVisible newVisible = new PracticeVisible();
BeanUtils.copyProperties(oldVisible, newVisible, ignoreProperties);
newVisible.setId(idGenerator.generate());
newVisible.setPracticeId(targetId);
setCommonProperties(newVisible, requestContext);
newVisibles.add(newVisible);
}
visibleRepository.saveAll(newVisibles);
}
}
private void copyRule(Long practiceId, Long targetId, String[] ignoreProperties, RequestContext requestContext) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException {
List<PracticePointRuleConfig> originRules = pointRuleConfigRepository.selectListByPracticeId(practiceId);
if(null == originRules) {
logger.warn("PracticePointRuleConfig with practiceId {} not exist!", practiceId);
}else {
List<PracticePointRuleConfig> newRules = new ArrayList<PracticePointRuleConfig>();
for(PracticePointRuleConfig oldRule : originRules) {
PracticePointRuleConfig newRule = new PracticePointRuleConfig();
BeanUtils.copyProperties(oldRule, newRule, ignoreProperties);
newRule.setId(idGenerator.generate());
newRule.setPracticeId(targetId);
setCommonProperties(newRule, requestContext);
newRules.add(newRule);
}
pointRuleConfigRepository.saveAll(newRules);
}
}
private void copyPracticeConfig(Long practiceId, Long targetId, String[] ignoreProperties) {
PracticeConfig origin = practiceConfigRepository.getOne(practiceId);
if(null == origin) {
logger.warn("Practice with ID {} not exist!", practiceId);
return ;
}
PracticeConfig target = new PracticeConfig();
// 复制practice_config
BeanUtils.copyProperties(origin, target, ignoreProperties);
target.setId(targetId);
target.setName(origin.getName()+"[复制]");
target.setStatus(PracticeStatusEnum.DRAFT.getStatus());
setCreatedAccountInfo(target);
practiceConfigRepository.save(target);
}
private void setCommonProperties(Object target, RequestContext context) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, SecurityException {
if(target instanceof PracticePointRuleConfig
|| target instanceof PracticeVisible
|| target instanceof SceneConfig
|| target instanceof SceneChatConfig) {
try {
target.getClass().getMethod("setCompanyId", Long.class).invoke(target, context.getCompanyId());
}catch(NoSuchMethodException e) {
}
try {
target.getClass().getMethod("setSiteId", Long.class).invoke(target, context.getSiteId());
}catch(NoSuchMethodException e) {
}
try {
target.getClass().getMethod("setOrgId", Long.class).invoke(target, context.getOrgId());
}catch(NoSuchMethodException e) {
}
try {
target.getClass().getMethod("setCreatedUid", Long.class).invoke(target, context.getAccountId());
}catch(NoSuchMethodException e) {
}
try {
target.getClass().getMethod("setCreatedAt", Date.class).invoke(target, new Date());
}catch(NoSuchMethodException e) {
}
}
}
}
#spring.datasource.url=jdbc:mysql://220.248.15.46:26532/cloud_chat_practice?useUnicode=true&characterEncoding=UTF-8&relaxAutoCommit=true&zeroDateTimeBehavior=convertToNull
#spring.datasource.username=devDB
#spring.datasource.password=devDB@123
#
#
#mybatis-plus.global-config.logic-not-delete-value=0
#mybatis-plus.global-config.logic-delete-value=1
#mybatis-plus.global-config.sql-injector=com.baomidou.mybatisplus.mapper.LogicSqlInjector
#
#third.baidu.appId=22848990
#third.baidu.apiKey=7ETrHxVjTqe3ghe2hKUWggwT
#third.baidu.secretKey=bZMOG0DXFQxBA7b0LgzmYaQiUGzNGAt8
#third.baidu.connectionTimeoutInMillis=2000
#third.baidu.socketTimeoutInMillis=60000
#
#third.xunfei.recognizeUrl=https://iat-api.xfyun.cn/v2/iat
#third.xunfei.synthesisUrl=https://tts-api.xfyun.cn/v2/tts
#third.xunfei.evaluateUrl=https://ise-api.xfyun.cn/v2/open-ise
#third.xunfei.appId=5f8fb0d2
#third.xunfei.apiSecret=2617780e6c90e011ed58dfdff58a0f99
#third.xunfei.apiKey=67675a0a109d94153b9b88d03ec77918
#
#third.aliyun.endpoint=https://oss-cn-shanghai.aliyuncs.com
#third.aliyun.accessKeyId=LTAIeBliOjnD6v25
#third.aliyun.accessKeySecret=qd6iAV7tUvumvEiXxv9IGJbSdHcnmH
#third.aliyun.bucketName=cloud-wmy
#
#practice.thread.pool.corePoolSize=10
#practice.thread.pool.maxPoolSize=200
#practice.thread.pool.keepAliveTime=60000
#practice.thread.pool.queueSize=100
#
#
## redis #######################################
#spring.redis.host=220.248.15.46
#spring.redis.port=16379
#spring.redis.password=C2!LG!Ay$6qJiUWH
#spring.redis.jedis.pool.maxActive=8
#spring.redis.jedis.pool.maxWait=-1
#spring.redis.jedis.pool.maxIdle=8
#spring.redis.jedis.pool.minIdle=0
## rabbitmq #######################################
#spring.rabbitmq.host=192.168.1.31
#spring.rabbitmq.port=5672
#spring.rabbitmq.username=root
#spring.rabbitmq.password=rabbitmq.linuxs
#spring.rabbitmq.publisher-confirm-type=simple
#spring.rabbitmq.virtual-host=/wmy
## database
#spring.datasource.hikari.idle-timeout=60000
#spring.datasource.hikari.connection-timeout=60000
#spring.datasource.hikari.validation-timeout=3000
#spring.datasource.hikari.login-timeout=5
#spring.datasource.hikari.max-lifetime=60000
## mybatis #######################################
#mybatis-plus.configuration.mapUnderscoreToCamelCase=true
##mybatis-plus.global-config.logic-not-delete-value=0
##mybatis-plus.global-config.logic-delete-value=1
##mybatis-plus.global-config.sql-injector=com.baomidou.mybatisplus.mapper.LogicSqlInjector
##mybatis-plus.globalConfig.metaObjectHandler=com.fulan.application.orm.audit.AuditMetaObjectHandler
#mybatis-plus.mapper-locations=classpath:mapper/*.xml,classpath:com/fulan/drools/mapper/*.xml,classpath:com/fulan/application/mapper/*.xml,classpath:/xml/*.xml,classpath:mybatis/*.xml
## jdbc #######################################
#spring.datasource.driver-class-name=com.mysql.jdbc.Driver
## nacos
##spring.cloud.nacos.discovery.server-addr=192.168.1.22:3333,192.168.1.22:4444,192.168.1.22:5555
##spring.cloud.nacos.discovery.namespace=dev
##logging
#logging.level.root=info
#logging.config=classpath:logback-spring.xml
##logging.file.path=/app/log
#logging.file.name=${spring.application.name}-${spring.profiles.active}
#
#server.max-http-header-size=102400
#
## jwt
#cloud.token.jwt.issuer=elearn
#cloud.token.jwt.seed=ZWxlYXJu
#cloud.token.jwt.TTL=604800001
#cloud.token.jwt.refreshSpan=3300000
#cloud.token.jwt.retreshTTL=
## okHttp
#feign.httpclient.enabled=true
#feign.okhttp.enabled=false
## ribbon
#ribbon.ReadTimeout=360000
#ribbon.ConnectTimeout=3600
## 关闭禁用 接口
#endpoints.enabled = false
server:
port: 34666
spring:
application:
name: 'chat-practice'
profiles:
active: 'dev'
jpa:
show-sql: true
# nacos
cloud:
nacos:
config:
shared-dataids: 'common-${spring.profiles.active}.properties'
namespace: ${spring.profiles.active}
prefix: '${spring.application.name}'
file-extension: 'properties'
server-addr: '192.168.1.22:3333,192.168.1.22:4444,192.168.1.22:5555'
ACTIVE: ${spring.profiles.active}
yizhi:
practice:
polite:
word: "您好;你好"
#陪练功能学员端对接流程
## 1、用户点击START
前端传递practiceId,模式(陪练OR考核),难度等级
服务端保存一条陪练记录
返回第一条对话记录,
\ No newline at end of file
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.config.rules.DbType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import org.junit.Ignore;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* <p>
* 代码生成器演示
* </p>
*/
@Ignore
public class MybatisCodeGenerator {
/**
* <p>
* MySQL 生成演示
* </p>
*/
public static void main(String[] args) {
AutoGenerator mpg = new AutoGenerator();
// ConstVal.MAPPER = ""
// 全局配置
GlobalConfig gc = new GlobalConfig();
gc.setFileOverride(true);
gc.setActiveRecord(true);// 不需要ActiveRecord特性的请改为false
gc.setEnableCache(false);// XML 二级缓存
gc.setBaseResultMap(true);// XML ResultMap
gc.setBaseColumnList(false);// XML columList
// 第一次生成代码可直接放到代码中,开发中期不建议生成代码直接覆盖以前代码
gc.setOutputDir("chat-practice-service/src/test/java");
gc.setAuthor("MybatisCodeGenerator");
mpg.setGlobalConfig(gc);
// 数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setDbType(DbType.MYSQL);
dsc.setTypeConvert(new MySqlTypeConvert() {
// 自定义数据库表字段类型转换【可选】
@Override
public DbColumnType processTypeConvert(String fieldType) {
System.out.println("转换类型:" + fieldType);
// 注意!!processTypeConvert 存在默认类型转换,如果不是你要的效果请自定义返回、非如下直接返回。
return super.processTypeConvert(fieldType);
}
});
dsc.setDriverName("com.mysql.jdbc.Driver");
dsc.setUsername("devDB");
dsc.setPassword("devDB@123");
dsc.setUrl("jdbc:mysql://192.168.1.31:3306/cloud_chat_practice?useUnicode=true&characterEncoding=UTF-8&");
mpg.setDataSource(dsc);
// 策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setTablePrefix(new String[] { "" });// 此处可以修改为您的表前缀
strategy.setNaming(NamingStrategy.underline_to_camel);// 表名生成策略
strategy.setInclude(new String[] {"scene_chat_config","practice_chat_round_log"}); // 需要生成的表
strategy.setEntityLombokModel(false);
mpg.setStrategy(strategy);
// 包配置
PackageConfig pc = new PackageConfig();
pc.setParent("com.yizhi.practice.application");
pc.setController("controller");
pc.setEntity("domain");
pc.setMapper("repository");
mpg.setPackageInfo(pc);
// // 注入自定义配置,可以在 VM 中使用 cfg.abc 【可无】
// InjectionConfig cfg = new InjectionConfig() {
// @Override
// public void initMap() {
// Map<String, Object> map = new HashMap<String, Object>();
// map.put("abc", this.getConfig().getGlobalConfig().getAuthor() + "-mp");
// this.setMap(map);
// }
// };
// List<FileOutConfig> focList = new ArrayList<FileOutConfig>();
// 调整 xml 生成目录演示
// focList.add(new FileOutConfig("/mapper.xml.vm") {
// @Override
// public String outputFile(TableInfo tableInfo) {
// return "/develop/code/xml/" + tableInfo.getEntityName() + ".xml";
// }
// });
// cfg.setFileOutConfigList(focList);
// mpg.setCfg(cfg);
TemplateConfig tc = new TemplateConfig();
tc.setXml(null);
tc.setController(null);
tc.setEntity("entity.java.vm");
tc.setMapper(null);
tc.setServiceImpl(null);
tc.setService(null);
mpg.setTemplate(tc);
// 执行生成
mpg.execute();
}
}
\ No newline at end of file
package com.yizhi.practice.application.config
import org.junit.Test
import ws.schild.jave.*
import java.io.File
class AudioUtilsTest {
@Test
fun wavToMp3() {
val source = File("/Users/lvjianhui/work/yizhi/project/cloud-chat-practice/chat-practice-service/src/test/resources/tKa8x2deSdZQ2Q7VoQec3hJaRashaoAZwnfw8039cask4IOF1ozlZhOgoy-xbrkF.amr") //源文件
//
val target = File("/Users/lvjianhui/work/yizhi/project/cloud-chat-practice/chat-practice-service/src/test/resources/111.mp3") //目标文件
val audio = AudioAttributes()
audio.setCodec("libmp3lame")
val attrs = EncodingAttributes()
attrs.setFormat("mp3")
attrs.setAudioAttributes(audio)
val encoder = Encoder()
try {
val multimediaObject = MultimediaObject(source)
encoder.encode(multimediaObject, target, attrs)
// multimediaObject.info
} catch (e: IllegalArgumentException) {
e.printStackTrace()
} catch (e: EncoderException) {
e.printStackTrace()
}
val multimediaObject = MultimediaObject(target)
println(multimediaObject.info.duration)
// println(AudioUtils.getAudioDuration(target))
// val url = "https://cloud-wmy.oss-cn-shanghai.aliyuncs.com/practice/demo/tKa8x2deSdZQ2Q7VoQec3hJaRashaoAZwnfw8039cask4IOF1ozlZhOgoy-xbrkF.amr"
// AudioUtils.getAudioDuration(url)
// AudioUtils.wavToPcm(url)
// val keyWordContext = "{\"没问题\":\"\",\"重疾险\":\"\",\"份\":\"\",\"签\":\"\"}"
// val list = JSONObject.parseObject(keyWordContext).toMap().keys
//// val map = json
//// val list = map.stream().map(KeyWordsReq::getKey).collect(Collectors.toList())
// println(list)
// val score = BigDecimal(14).divide(BigDecimal(17), 2,RoundingMode.HALF_UP).multiply(BigDecimal(20)).toInt()
// println(score)
// val map = HashMap<Int,Long>()
//
// map.put(1,12L)
// map.put(2,13L)
// map.put(4,15L)
// map.put(10,25L)
// map.put(3,5L)
//
// println(map.keys.sortedDescending())
}
}
\ No newline at end of file
package com.yizhi.practice.application.controller.remote;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
/**
*
* @author xiaoyu
*
*/
@Ignore
@RunWith(SpringRunner.class)
@SpringBootTest
public class PracticeControllerApiTest {
@Autowired
private PracticeControllerApi api;
@Test
public void testSelectRangeList() {
api.selectRangeList(null, null);
}
@Test
public void testSelectVisibleRangeList() {
api.selectVisibleRangeList("2020-10-01 00:00:00", "2020-12-01 00:00:00");
}
@Test
public void testselectChatLogRangeList() {
api.selectChatLogRangeList(null, null);
}
}
package com.yizhi.practice.application.service.impl;
import java.util.ArrayList;
import java.util.List;
import com.yizhi.practice.application.service.IPracticeVisibleService;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.yizhi.practice.application.pojo.vo.PracticeChatLogListParamVo;
import com.yizhi.practice.application.pojo.vo.PracticeChatLogListVo;
import com.yizhi.practice.application.service.IPracticeChatLogService;
/**
*
* @author xiaoyu
*
*/
@Ignore
@RunWith(SpringRunner.class)
@SpringBootTest
public class PracticeChatLogServiceImplTest {
@Autowired
private IPracticeChatLogService service;
@Autowired
private IPracticeVisibleService iPracticeVisibleService;
@Test
public void testListAll() {
PracticeChatLogListParamVo param = PracticeChatLogListParamVo.builder()
.modes(new Integer[] {10,20})
.build();
List<PracticeChatLogListVo> list = service.listAll(param, null);
System.out.println(list.size());
}
@Test
public void getParentOrg() {
List<Long> orgId = new ArrayList();
orgId.add(1314L);
orgId.add(1315L);
iPracticeVisibleService.getIdsByAccountId(1314,orgId,1314,1314);
}
}
package com.yizhi.practice.application.service.impl;
import com.yizhi.practice.application.mapper.PracticeChatRoundLogMapper;
import com.yizhi.practice.application.pojo.dto.PracticeLogScoreDto;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
/**
* @Date 2020/11/24 9:14 下午
* @Author lvjianhui
**/
@RunWith(SpringRunner.class)
@SpringBootTest
public class PracticeLogTest {
@Autowired
private PracticeChatRoundLogMapper practiceChatRoundLogMapper;
@Test
public void getAllScore() {
PracticeLogScoreDto dto = practiceChatRoundLogMapper.getScoreByAccount(
1331222748650995712L,
1314L,
1113033336728522752L,
1314L,
1314L);
System.out.println(dto);
}
}
package com.yizhi.practice.application.statistic;
import com.alibaba.fastjson.annotation.JSONField;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @Date 2020/11/19 10:01 下午
* @Author lvjianhui
**/
@Data
public class DataTableVo {
@ApiModelProperty(name = "姓名",position = 1234)
private String name;
@ApiModelProperty(name = "主键",position = 2)
private Long id;
@ApiModelProperty(name = "年龄",position = 3)
private Integer age;
}
package com.yizhi.practice.application.statistic;
import cn.hutool.json.JSON;
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.ApiModelProperty;
import org.apache.tomcat.util.json.JSONParser;
import org.junit.Test;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.TreeMap;
/**
* @Date 2020/11/19 10:01 下午
* @Author lvjianhui
**/
public class VoTest {
@Test
public void testData() {
Field[] field = DataTableVo.class.getDeclaredFields();
Map<Integer,String> heards = new TreeMap<>();
for (Field fieldEntriy : field) {
ApiModelProperty an = fieldEntriy.getAnnotation(ApiModelProperty.class);
System.out.println(an.name());
heards.put(an.position(),an.name());
}
System.out.println(JSONObject.toJSONString(heards));
System.out.println(JSONObject.toJSONString(heards.values()));
}
}
package com.yizhi.practice.application.third.aliyun;
import com.aliyun.oss.OSSClientBuilder;
import org.junit.Ignore;
import org.junit.Test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
/**
* 需要测试时本地放开注释测试,不然浪费账号的可用免费次数
* @author xiaoyu
*
*/
@Ignore
public class AliyunUtilTest {
public static final String BUKET_NAME = "cloud-wmy";
public static final String END_POINT = "https://oss-cn-shanghai.aliyuncs.com";
public static final String ACCESSKEY_ID = "LTAIeBliOjnD6v25";
public static final String ACCESS_KEY_SECRET= "qd6iAV7tUvumvEiXxv9IGJbSdHcnmH";
@Test
public void testUploadByStream() throws FileNotFoundException {
AliyunUtil util = new AliyunUtil(BUKET_NAME,new OSSClientBuilder().build(END_POINT, ACCESSKEY_ID, ACCESS_KEY_SECRET), END_POINT);
InputStream ins = new FileInputStream("D:\\code\\cloud-chat-practice\\chat-practice-service\\src\\test\\resources\\forTest.mp3");
String result = util.uploadByStream("20201028/tmp.mp3",ins);
System.out.print(result);
}
}
package com.yizhi.practice.application.third.baidu;
import org.junit.Ignore;
import org.junit.Test;
import com.baidu.aip.nlp.AipNlp;
/**
* 需要测试时本地放开注释测试,不然浪费账号的可用免费次数
* @author xiaoyu
*
*/
@Ignore
public class BaiduUtilTest {
public static final String APP_ID = "22848990";
public static final String API_KEY = "7ETrHxVjTqe3ghe2hKUWggwT";
public static final String SECRET_KEY = "bZMOG0DXFQxBA7b0LgzmYaQiUGzNGAt8";
@Test
public void testGetSimilarRate() {
AipNlp client = new AipNlp(APP_ID, API_KEY, SECRET_KEY);
client.setConnectionTimeoutInMillis(2000);
client.setSocketTimeoutInMillis(60000);
String text1 = "你好,我是中国人";
String text2 = "你好,我是外国人";
BaiduUtil u = new BaiduUtil(client);
System.out.print(u.getSimilarRate(text1, text2));
}
}
package com.yizhi.practice.application.third.xunfei;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.yizhi.practice.application.enums.PracticeVoiceTypeEnum;
import com.yizhi.practice.application.third.xunfei.param.IEvaluateResult;
/**
* 仅在本地测试使用,避免浪费账号的免费额度-.-
*
* @author xiaoyu
*/
@Ignore
@RunWith(SpringRunner.class)
@SpringBootTest
public class XunfeiUtilTest {
@Autowired
XunfeiUtil x;
@Test
public void testStringToVoice() throws Exception {
System.out.println(x.stringToVoice("您好,我是讯飞机器人许小宝。", "{\"name\":\"aisbabyxu\"}", "practice/robot/xuxiaobao.mp3", PracticeVoiceTypeEnum.MP3));
}
@Test
public void testVoiceToString() throws Exception {
String mp3Path = new File("").getCanonicalPath() + File.separator + "src" + File.separator + "test" + File.separator + "resources" + File.separator + "read_sentence_cn.pcm";
InputStream ins = new FileInputStream(mp3Path);
System.out.println("============test reslut:" + x.voiceToString(ins, PracticeVoiceTypeEnum.PCM));
}
@Test
public void testEvaluate() throws Exception {
String input = "今天天气怎么样?";
String mp3Path = new File("").getCanonicalPath() + File.separator + "src" + File.separator + "test" + File.separator + "resources" + File.separator + "read_sentence_cn.wav";
InputStream ins = new FileInputStream(mp3Path);
IEvaluateResult res = x.evaluate(input, ins, PracticeVoiceTypeEnum.WAV);
System.out.println(res);
}
/*
* @Test public void test() throws Exception { //File file = new File(
* "D:\\workspace\\project\\cloud-chat-practice\\chat-practice-service\\src\\test\\resources\\1605146300193114688.wav"
* ); File f = AudioUtils.INSTANCE.wavToMp3(
* "https://cloud-wmy.oss-cn-shanghai.aliyuncs.com/20201028/forTest.wav");
* //InputStream ins = new FileInputStream(f);
* //System.out.println(x.voiceToString(ins, PracticeVoiceTypeEnum.MP3)); }
*/
}
package com.yizhi.practice.application.xservice.impl;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.yizhi.practice.application.pojo.vo.PracticeChatLogBaseInfoVo;
import com.yizhi.practice.application.pojo.vo.PracticeChatRoundLogDetailVo;
import com.yizhi.practice.application.xservice.PracticeChatRoundLogXService;
@Ignore
@RunWith(SpringRunner.class)
@SpringBootTest
public class PracticeChatRoundLogXServiceImplTest {
@Autowired
private PracticeChatRoundLogXService service;
@Test
public void testGetLogByPracticeChatId() {
PracticeChatLogBaseInfoVo vo = service.getLogByPracticeChatId(1330700827819823104L);
System.out.println("-----------------------"+vo.getRobotName());
}
@Test
public void testAnalysis() {
PracticeChatRoundLogDetailVo vo = service.analysis(1329687441707450368L);
for(String s : vo.getForbidHit()) {
System.out.println("------------------"+s);
}
}
}
package com.yizhi.practice.application.xservice.impl;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
@Ignore
public class PracticeStuXServiceImplTest {
@Autowired
private PracticeStuXServiceImpl imp;
@Test
public void testGetAccountContent() throws FileNotFoundException, IOException {
try(InputStream ins = new FileInputStream("C:\\Users\\xiaoyu\\eclipse-workspace\\test\\test7.pcm")){
System.out.println(imp.getAccountContent(ins));
}
}
}
package com.yizhi.practice.application.xservice.impl.no_context;
import java.util.List;
import org.junit.Ignore;
import org.junit.Test;
import com.yizhi.practice.application.pojo.vo.LocalJSONObject;
import com.yizhi.practice.application.xservice.impl.PracticeChatRoundLogXServiceImpl;
@Ignore
public class PracticeChatRoundLogXServiceImplTest {
@Test
public void testConstructKeyWordInfo() {
PracticeChatRoundLogXServiceImpl bean = new PracticeChatRoundLogXServiceImpl();
String hit = "aa;bb;cc";
String config = "{'aa':'11', 'dd':'bb', 'ee':'ff;cc'}";
List<LocalJSONObject> res = bean.constructKeyWordInfo(hit, config);
for(LocalJSONObject jo : res) {
System.out.println(jo.toString());
}
}
}
server:
port: 34666
spring:
application:
name: 'chat-practice'
profiles:
active: 'sit'
jpa:
show-sql: true
# # nacos
cloud:
nacos:
config:
shared-dataids: 'common-${spring.profiles.active}.properties'
namespace: ${spring.profiles.active}
prefix: '${spring.application.name}'
file-extension: 'properties'
# server-addr: '192.168.1.22:3333,192.168.1.22:4444,192.168.1.22:5555'
server-addr: '192.168.1.13:3333,192.168.1.24:4444,192.168.1.38:5555'
ACTIVE: ${spring.profiles.active}
yizhi:
practice:
polite:
word: "您好;你好"
package ${package.Entity};
#if(${activeRecord})
import java.io.Serializable;
#end
#foreach($pkg in ${table.importPackages})
import ${pkg};
#end
#if(${entityLombokModel})
import com.baomidou.mybatisplus.annotations.Version;
import lombok.Data;
#end
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import javax.persistence.Entity;
import javax.persistence.Id;
/**
* <p>
* $!{table.comment}
* </p>
*
* @author ${author}
* @since ${date}
*/
#if(${entityLombokModel})
@Data
#end
@DynamicUpdate
@DynamicInsert
@Api(tags = "${entity}", description = "${table.comment}")
#if(${table.convert})
@TableName("${table.name}")
@Entity
#end
#if(${superEntityClass})
public class ${entity} extends ${superEntityClass}#if(${activeRecord})<${entity}>#end {
###elseif(${activeRecord})
##public class ${entity} {
#else
public class ${entity} implements Serializable {
#end
private static final long serialVersionUID = 1L;
##
##
#foreach($field in ${table.fields})
#if(${field.keyFlag})
#set($keyPropertyName=${field.propertyName})
#end
#if("$!field.comment" != "")
@ApiModelProperty(value = "${field.comment}")
#end
##
#if(${field.name}=="id")
@Id
#end
##
#if(${field.keyFlag})
##
#if(${field.keyIdentityFlag})
@TableId(value="${field.name}", type= IdType.AUTO)
#elseif(${field.convert})
@TableId("${field.name}")
#end
##
#elseif(${field.fill})
##
#if(${field.convert})
@TableField(value = "${field.name}", fill = FieldFill.${field.fill})
#else
@TableField(fill = FieldFill.${field.fill})
#end
#elseif(${field.convert})
#if(${field.name}=="create_by_id" || ${field.name}=="create_by_name" || ${field.name}=="create_time"
|| ${field.name}=="update_by_id" || ${field.name}=="update_by_name" || ${field.name}=="update_time")
@TableField(value = "${field.name}", fill = FieldFill.INSERT)
#else
@TableField("${field.name}")
#end
#end
##
#if(${versionFieldName}==${field.name})
@Version
#end
##
#if(${logicDeleteFieldName}==${field.name})
@TableLogic
#end
private ${field.propertyType} ${field.propertyName};
#end
##
#if(!${entityLombokModel})
#foreach($field in ${table.fields})
#if(${field.propertyType.equals("boolean")})
#set($getprefix="is")
#else
#set($getprefix="get")
#end
public ${field.propertyType} ${getprefix}${field.capitalName}() {
return ${field.propertyName};
}
#if(${entityBuilderModel})
public ${entity} set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
#else
public void set${field.capitalName}(${field.propertyType} ${field.propertyName}) {
#end
this.${field.propertyName} = ${field.propertyName};
#if(${entityBuilderModel})
return this;
#end
}
#end
#end
#if(${entityColumnConstant})
#foreach($field in ${table.fields})
public static final String ${field.name.toUpperCase()} = "${field.name}";
#end
#end
###if(${activeRecord})
## @Override
## protected Serializable pkVal() {
###if(${keyPropertyName})
## return this.${keyPropertyName};
###else
## return this.id;
###end
## }
##
###end
#if(!${entityLombokModel})
@Override
public String toString() {
return "${entity}{" +
#foreach($field in ${table.fields})
#if($!{velocityCount}==1)
"${field.propertyName}=" + ${field.propertyName} +
#else
", ${field.propertyName}=" + ${field.propertyName} +
#end
#end
"}";
}
#end
}
package ${package.Mapper};
import ${package.Entity}.${entity};
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
/**
* <p>
* $!{table.comment} Mapper 接口
* </p>
*
* @author ${author}
* @since ${date}
*/
#if(${kotlin})
interface ${table.mapperName} : ${superMapperClass}<${entity}>
#else
public interface ${table.mapperName} extends JpaRepository<${entity},Long>, QuerydslPredicateExecutor<${entity}>{
}
#end
package ${package.Service};
/**
* <p>
* $!{table.comment} 服务类
* </p>
*
* @author ${author}
* @since ${date}
*/
#if(${kotlin})
interface ${table.serviceName} : ${superServiceClass}<${entity}>
#else
public interface ${table.serviceName} {
}
#end
package ${package.ServiceImpl};
import ${package.Service}.${table.serviceName};
import org.springframework.stereotype.Service;
import com.yizhi.practice.application.service.BaseService;
/**
* <p>
* $!{table.comment} 服务实现类
* </p>
*
* @author ${author}
* @since ${date}
*/
@Service
#if(${kotlin})
open class ${table.serviceImplName} : ${superServiceImplClass}<${table.mapperName}, ${entity}>(), ${table.serviceName} {
}
#else
public class ${table.serviceImplName} extends BaseService implements ${table.serviceName}{
}
#end
alter table `practice_chat_log` add primary key (`id`);
alter table `practice_chat_log` add index practice_id_idx (`practice_id`);
alter table `practice_chat_log` add index accountId_id_idx (`account_id`);
alter table `practice_chat_log` add index org_info_idx (`company_id, site_id, org_id`);
alter table `practice_chat_round_log` add primary key (`id`);
alter table `practice_chat_round_log` add index practice_id_idx (`practice_id`);
alter table `practice_chat_round_log` add index scene_id_idx (`scene_id`);
alter table `practice_chat_round_log` add index scene_chat_idx (`scene_chat_id`);
alter table `practice_chat_round_log` add index practice_chat_idx (`practice_chat_id`);
alter table `practice_chat_round_log` add index account_id_idx (`account_id`);
alter table `practice_chat_round_log` add index org_info_idx (`company_id, site_id, org_id`);
alter table `practice_config` add primary key (`id`);
alter table `practice_config` add index robot_idx (`robot_id`);
alter table `practice_config` add index org_info_idx (`company_id, site_id, org_id`);
alter table `practice_point_given_log` add primary k
ey (`id`);
alter table `practice_point_given_log` add index practice_id_idx (`practice_id`);
alter table `practice_point_given_log` add index rule_idx (`point_rule_id`);
alter table `practice_point_given_log` add index account_id_idx (`account_id`);
alter table `practice_point_given_log` add index org_info_idx (`company_id, site_id, org_id`);
alter table `practice_point_rule_config` add primary key (`id`);
alter table `practice_point_rule_config` add index practice_id_idx (`practice_id`);
alter table `practice_visible` add primary key (`id`);
alter table `practice_visible` add index practice_id_idx (`practice_id`);
alter table `practice_visible` add index visible_site_org_idx (`visible_site_id, visible_org_id`);
alter table `practice_visible` add index visible_account_idx (`visible_account_id`);
alter table `practice_visible` add index company_idx (`company_id`);
alter table `robot_config` add primary key (`id`);
alter table `scene_chat_config` add primary key (`id`);
alter table `scene_chat_config` add index practice_id_idx (`practice_id`);
alter table `scene_chat_config` add index scene_id_idx (`scene_id`);
alter table `scene_chat_config` add index pid_idx (`pid`);
alter table `scene_config` add primary key (`id`);
alter table `scene_config` add index practice_id_idx (`practice_id`);
alter table `practice_chat_round_log` alter column `average_score` set default 0;
\ No newline at end of file
<?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">
<modelVersion>4.0.0</modelVersion>
<modules>
<module>chat-practice-service</module>
<module>chat-practice-api</module>
</modules>
<parent>
<groupId>com.yizhi</groupId>
<artifactId>wmy-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath/>
</parent>
<groupId>com.yizhi</groupId>
<artifactId>cloud-chat-practice</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<kotlin.compiler.incremental>true</kotlin.compiler.incremental>
</properties>
<repositories>
<repository>
<id>wmy4.0</id>
<url>http://mvn.km365.pw/nexus/content/groups/wmy4.0-group/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</snapshots>
</repository>
</repositories>
<!-- <build>-->
<!-- <sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>-->
<!-- <testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>-->
<!-- </build>-->
<build>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<sourceDirs>
<sourceDir>${project.basedir}/src/main/kotlin</sourceDir>
<sourceDir>${project.basedir}/src/main/java</sourceDir>
</sourceDirs>
</configuration>
</execution>
<execution>
<id>test-compile</id>
<goals> <goal>test-compile</goal> </goals>
<configuration>
<sourceDirs>
<sourceDir>${project.basedir}/src/test/kotlin</sourceDir>
<sourceDir>${project.basedir}/src/test/java</sourceDir>
</sourceDirs>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<executions>
<!-- 替换会被 maven 特别处理的 default-compile -->
<execution>
<id>default-compile</id>
<phase>none</phase>
</execution>
<!-- 替换会被 maven 特别处理的 default-testCompile -->
<execution>
<id>default-testCompile</id>
<phase>none</phase>
</execution>
<execution>
<id>java-compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>java-test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>testCompile</goal>
</goals>
<!-- <configuration>-->
<!-- <skip>${maven.test.skip}</skip>-->
<!-- </configuration>-->
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment