语音指令

This commit is contained in:
tiger_zhou 2023-03-29 17:40:02 +08:00
parent 2445287f8c
commit a23bf72997
24 changed files with 416 additions and 108 deletions

View File

@ -10,8 +10,6 @@ import club.joylink.rtss.services.voice.IVoiceDataService;
import club.joylink.rtss.simulation.cbtc.command.voice.operate.HandleType;
import club.joylink.rtss.simulation.cbtc.command.voice.operate.OperateEnum;
import club.joylink.rtss.simulation.cbtc.command.voice.vo.OperateConfigData;
import club.joylink.rtss.simulation.cbtc.command.voice.vo.VoiceConfigData;
import club.joylink.rtss.util.JsonUtils;
import club.joylink.rtss.vo.LoginUserInfoVO;
import club.joylink.rtss.vo.client.PageVO;
import club.joylink.rtss.vo.voice.VoiceConfigVO;
@ -50,8 +48,8 @@ public class VoiceDataService implements IVoiceDataService, IVoiceCommandDataSer
private void checkData(VoiceConfigVO dataVO){
BusinessExceptionAssertEnum.DATA_INVALID.assertTrue(Objects.nonNull(dataVO.getWakeUpKw()),String.format("缺少类型匹配"));
BusinessExceptionAssertEnum.DATA_INVALID.assertTrue(ArrayUtils.isNotEmpty(dataVO.getWakeUpKw().getSourceMatch()),String.format("类型匹配需要关键字"));
OperateConfigData configData = dataVO.getConfig().stream().filter(d->ArrayUtils.isEmpty(d.getSourceMatch())).findFirst().orElse(null);
BusinessExceptionAssertEnum.DATA_INVALID.assertTrue(ArrayUtils.isNotEmpty(dataVO.getWakeUpKw().getActionMatch()),String.format("类型匹配需要关键字"));
OperateConfigData configData = dataVO.getConfig().stream().filter(d->ArrayUtils.isEmpty(d.getActionMatch())).findFirst().orElse(null);
BusinessExceptionAssertEnum.DATA_INVALID.assertNotTrue(Objects.nonNull(configData),String.format("操作数据关键字不能为空"));
Map<OperateEnum,List<OperateConfigData>> mapList = dataVO.getConfig().stream().collect(Collectors.groupingBy(OperateConfigData::getOperate));
for (List<OperateConfigData> value : mapList.values()) {

View File

@ -8,10 +8,13 @@ import club.joylink.rtss.simulation.cbtc.command.voice.vo.DeviceVoiceCommand;
import club.joylink.rtss.simulation.cbtc.command.voice.vo.WorkResult;
import club.joylink.rtss.simulation.cbtc.command.voice.work.VoiceCommandAnalyseWork;
import club.joylink.rtss.simulation.cbtc.data.map.MapNamedElement;
import club.joylink.rtss.simulation.cbtc.data.map.Station;
import club.joylink.rtss.util.PinYinUtil;
import club.joylink.rtss.vo.client.voice.VoiceRecognitionResult;
import club.joylink.rtss.vo.voice.VoiceConfigVO;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.ansj.library.DicLibrary;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
@ -38,6 +41,7 @@ public class DeviceVoiceCommandService{
private VoiceCommandAnalyseWork analyseWork;
private List<VoiceConfigVO> findVoiceConfig(Simulation simulation){
Long mapId = simulation.getBuildParams().getMap().getId();
List<VoiceConfigVO> configVOList = this.commandDataService.findData(mapId);
BusinessExceptionAssertEnum.VOICE_COMMAND_CONFIG_NULL.assertTrue(!CollectionUtils.isEmpty(configVOList),"未找到语音配置的相关信息");

View File

@ -7,6 +7,7 @@ import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.*;
@ -19,8 +20,10 @@ public class VoiceCommandMatchHandler {
public List<DeviceVoiceCommand> matcher(List<VoiceConfigVO> configVOList, String msg){
List<DeviceVoiceCommand> findParseDataList = Lists.newArrayList();
for (VoiceConfigVO configVO : configVOList) {
Optional<List<DeviceVoiceCommand>> optional = commandMatcher.matchCommand(configVO,msg);
optional.ifPresent(findParseDataList::addAll);
List<DeviceVoiceCommand> commandList = commandMatcher.matchCommand(configVO,msg);
if(!CollectionUtils.isEmpty(commandList)){
findParseDataList.addAll(commandList);
}
}
return findParseDataList;
}

View File

@ -1,54 +1,86 @@
package club.joylink.rtss.simulation.cbtc.command.voice.analyse;
import club.joylink.rtss.simulation.cbtc.command.voice.operate.HandleType;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.command.voice.vo.CommandParse;
import club.joylink.rtss.simulation.cbtc.command.voice.vo.ParseDetail;
import club.joylink.rtss.simulation.cbtc.command.voice.vo.DeviceVoiceCommand;
import club.joylink.rtss.simulation.cbtc.data.map.Station;
import club.joylink.rtss.util.PinYinUtil;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import org.ansj.domain.Result;
import org.ansj.domain.Term;
import org.ansj.library.DicLibrary;
import org.ansj.splitWord.analysis.DicAnalysis;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
import java.util.Objects;
public class PinYinSplitWordAnalyse implements VoiceCommandAnalyse {
@Override
public synchronized List<String> parseCommandDescribe(DeviceVoiceCommand command) {
this.initDic(command);
String pinyinStr = PinYinUtil.toPinYinSplitBlankSpace(command.getSourceDescrbe());
@Override
public synchronized CommandParse parseCommandDescribe(Simulation simulation, DeviceVoiceCommand command) {
this.initDic(simulation,command);
String pinyinStr = PinYinUtil.toPinYinSplitBlankSpace(command.getSourceDescrbe());
Result reslut = DicAnalysis.parse(pinyinStr);
List<String> resultList = Lists.newArrayList();
List<ParseDetail> resultList = Lists.newArrayList();
CommandParse commandParse = new CommandParse(command.getSourceDescrbe(),pinyinStr);
commandParse.setDetail(resultList);
for (Term term : reslut) {
String name = term.getName().toUpperCase();
String nature = term.getNatureStr();
if(Objects.nonNull(nature) && !StringUtils.startsWith(nature,"w")){
if(!StringUtils.equalsIgnoreCase(nature,"userDefine")){
// command.appendCommandDescribe(name);
resultList.add(name);
}/*else{
command.appendCommandDescribe(name);
}*/
if(Objects.nonNull(nature) && StringUtils.isNotEmpty(name) && !StringUtils.startsWith(nature,"w")){
if(!StringUtils.equalsIgnoreCase(nature,DicLibrary.DEFAULT_NATURE)){
resultList.add(new ParseDetail(name,nature,term.getOffe(), term.toValue()));
}
}
// commandList.add(command);
}
return resultList;
return commandParse;
}
/* @Override
public HandleType handleType() {
return HandleType.PINYIN;
}*/
private void initDic(DeviceVoiceCommand command){
private void initDic(Simulation simulation,DeviceVoiceCommand command){
DicLibrary.clear(DicLibrary.DEFAULT);
for (Station station : simulation.getRepository().getStationList()) {
String pinYinTmp = PinYinUtil.toPinYinSplitBlankSpace(station.getName()).toLowerCase();
List<String> pinyin = Splitter.onPattern("\\s").omitEmptyStrings().splitToList(pinYinTmp);
DicLibrary.insert(DicLibrary.DEFAULT,pinYinTmp,VoiceCommandAnalyse.DESCRIBE_NATURE,DicLibrary.DEFAULT_FREQ);
List<List<String>> subPinYinList = Lists.partition(pinyin,2);
for (List<String> strings : subPinYinList) {
String t = Joiner.on(" ").skipNulls().join(strings);
DicLibrary.insert(DicLibrary.DEFAULT,t,VoiceCommandAnalyse.DESCRIBE_NATURE,DicLibrary.DEFAULT_FREQ);
}
subPinYinList = Lists.partition(pinyin,3);
for (List<String> strings : subPinYinList) {
String t = Joiner.on(" ").skipNulls().join(strings);
DicLibrary.insert(DicLibrary.DEFAULT,t,VoiceCommandAnalyse.DESCRIBE_NATURE,DicLibrary.DEFAULT_FREQ);
}
}
for (String s : command.getTranslateWakeUpKW()) {
DicLibrary.insert(DicLibrary.DEFAULT,s,DicLibrary.DEFAULT_NATURE,DicLibrary.DEFAULT_FREQ);
DicLibrary.insert(DicLibrary.DEFAULT,s.toLowerCase(),DicLibrary.DEFAULT_NATURE,DicLibrary.DEFAULT_FREQ);
}
for (String s : command.getMatchCommandKW()) {
DicLibrary.insert(DicLibrary.DEFAULT,s,DicLibrary.DEFAULT_NATURE,DicLibrary.DEFAULT_FREQ);
for (String s : command.getOperateConfigData().getTranslateActionMatch()) {
DicLibrary.insert(DicLibrary.DEFAULT,s.toLowerCase(),DicLibrary.DEFAULT_NATURE,DicLibrary.DEFAULT_FREQ);
}
if(ArrayUtils.isNotEmpty(command.getOperateConfigData().getTranslateNatureKW())){
for (String s : command.getOperateConfigData().getTranslateNatureKW()) {
DicLibrary.insert(DicLibrary.DEFAULT,s.toLowerCase(),VoiceCommandAnalyse.DESCRIBE_NATURE,DicLibrary.DEFAULT_FREQ);
}
}
/* if(ArrayUtils.isNotEmpty(command.getOperateConfigData().getTranslateDescribeKW())){
for (String s : command.getOperateConfigData().getTranslateDescribeKW()) {
DicLibrary.insert(DicLibrary.DEFAULT,s.toLowerCase(),DicLibrary.DEFAULT_NATURE,DicLibrary.DEFAULT_FREQ);
}
}*/
}
}

View File

@ -1,16 +1,16 @@
package club.joylink.rtss.simulation.cbtc.command.voice.analyse;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.command.voice.vo.CommandParse;
import club.joylink.rtss.simulation.cbtc.command.voice.vo.DeviceVoiceCommand;
import java.util.List;
public interface VoiceCommandAnalyse {
String DESCRIBE_NATURE = "nature";
/**
* 解析命令
* @param Command 命令原文
* @return 解析后的数据
*/
List<String> parseCommandDescribe(DeviceVoiceCommand Command);
CommandParse parseCommandDescribe(Simulation simulation, DeviceVoiceCommand Command);
}

View File

@ -0,0 +1,14 @@
package club.joylink.rtss.simulation.cbtc.command.voice.match;
import club.joylink.rtss.simulation.cbtc.command.voice.vo.DeviceVoiceCommand;
import club.joylink.rtss.vo.voice.VoiceConfigVO;
import java.util.List;
import java.util.Optional;
public interface IMatchFilter {
List<DeviceVoiceCommand> filter();
Optional<List<DeviceVoiceCommand>> matchCommand(VoiceConfigVO configVOList, String msg);
}

View File

@ -1,15 +1,13 @@
package club.joylink.rtss.simulation.cbtc.command.voice.match;
import club.joylink.rtss.simulation.cbtc.command.voice.operate.HandleType;
import club.joylink.rtss.simulation.cbtc.command.voice.vo.DeviceVoiceCommand;
import club.joylink.rtss.vo.voice.VoiceConfigVO;
import java.util.List;
import java.util.Optional;
public interface IVoiceCommandMatcher {
Optional<List<DeviceVoiceCommand>> matchCommand(VoiceConfigVO configVOList, String msg);
List<DeviceVoiceCommand> matchCommand(VoiceConfigVO configVOList, String msg);
// HandleType handleType();
}

View File

@ -4,43 +4,48 @@ import club.joylink.rtss.simulation.cbtc.command.voice.vo.DeviceVoiceCommand;
import club.joylink.rtss.simulation.cbtc.command.voice.vo.OperateConfigData;
import club.joylink.rtss.util.PinYinUtil;
import club.joylink.rtss.vo.voice.VoiceConfigVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
@Slf4j
public class PinYinViolenceMatchHandler implements IVoiceCommandMatcher {
@Override
public Optional<List<DeviceVoiceCommand>> matchCommand(VoiceConfigVO configVO, String sourceMsg) {
public List<DeviceVoiceCommand> matchCommand(VoiceConfigVO configVO, String sourceMsg) {
String tmpPinYinContent = PinYinUtil.toPinYinSplitBlankSpace(sourceMsg);
List<DeviceVoiceCommand> commandList = this.match(configVO,sourceMsg,tmpPinYinContent);
commandList = commandList.stream().filter(d->Objects.nonNull(d.getDeviceType())
&& ArrayUtils.isNotEmpty(d.getMatchCommandKW())
&& Objects.nonNull(d.getOperateConfigData())
&& ArrayUtils.isNotEmpty(d.getTranslateWakeUpKW())
).collect(Collectors.toList());
if(CollectionUtils.isEmpty(commandList)){
return Optional.empty();
}
return Optional.of(commandList);
return commandList;
}
private List<DeviceVoiceCommand> match(VoiceConfigVO configVO,String sourceMsg, String pinyinStr){
List<DeviceVoiceCommand> commandList = new ArrayList<>();
for (OperateConfigData configData : configVO.getConfig()) {
DeviceVoiceCommand command = new DeviceVoiceCommand(configVO.getHandleType());
if(StringUtils.containsAny(pinyinStr,configVO.getWakeUpKw().getTranslateMatch())){
if(StringUtils.containsAny(pinyinStr,configVO.getWakeUpKw().getTranslateActionMatch())){
command.setDeviceType(configVO.getDeviceType());
command.setTranslateWakeUpKW(configVO.getWakeUpKw().getTranslateMatch());
command.setTranslateWakeUpKW(configVO.getWakeUpKw().getTranslateActionMatch());
}
if(StringUtils.containsAny(pinyinStr,configData.getTranslateMatch())){
command.setOperateConfigData(configData);
command.setMatchCommandKW(configData.getTranslateMatch());
if(StringUtils.containsAny(pinyinStr,configData.getTranslateActionMatch())){
if(configData.isForceMatchNature()){
if(ArrayUtils.isEmpty(configData.getTranslateNatureKW())){
log.error("强制匹配属性,但是属性为空 config id[{}]",configVO.getId());
return Collections.emptyList();
}else if(StringUtils.containsAny(pinyinStr,configData.getTranslateNatureKW())){
command.setOperateConfigData(configData);
}
}else{
command.setOperateConfigData(configData);
}
}
command.setSourceDescrbe(sourceMsg);
commandList.add(command);

View File

@ -1,12 +0,0 @@
package club.joylink.rtss.simulation.cbtc.command.voice.operate;
import java.util.List;
public enum OperateDeviceEnum {
SWITCH();
private OperateEnum[] operates;
OperateDeviceEnum(OperateEnum... operates) {
this.operates = operates;
}
}

View File

@ -1,5 +1,6 @@
package club.joylink.rtss.simulation.cbtc.command.voice.operate;
import club.joylink.rtss.simulation.cbtc.ATS.service.AtsStandService;
import club.joylink.rtss.simulation.cbtc.CI.device.CiSwitchControlService;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.data.map.MapElement;
@ -11,24 +12,69 @@ import lombok.Getter;
public enum OperateEnum {
SWITCH_DINGWEI(MapElement.DeviceType.SWITCH,"定位"){
@Override
public void handle(Simulation simulation,CiSwitchControlService service, MapElement device) {
public void handle(Simulation simulation,Object objectService, MapElement device) {
Switch aswitch = (Switch)device;
service.turn2NormalPosition(simulation,aswitch);
CiSwitchControlService controlService = (CiSwitchControlService) objectService;
controlService.turn2NormalPosition(simulation,aswitch);
}
},
SWITCH_FANWEI(MapElement.DeviceType.SWITCH,"反位"){
@Override
public void handle(Simulation simulation, CiSwitchControlService service, MapElement device) {
public void handle(Simulation simulation, Object objectService, MapElement device) {
Switch aswitch = (Switch)device;
service.turn2ReversePosition(simulation,aswitch);
CiSwitchControlService controlService = (CiSwitchControlService) objectService;
controlService.turn2ReversePosition(simulation,aswitch);
}
}
},
STAND_HOLD_TRAIN(MapElement.DeviceType.STAND,"扣车"){
@Override
public void handle(Simulation simulation, Object objectService, MapElement device) {
AtsStandService standService = (AtsStandService) objectService;
standService.holdTrain(simulation,device.getCode());
}
},
STAND_CANCEL_HOLD_TRAIN(MapElement.DeviceType.STAND,"取消扣车"){
@Override
public void handle(Simulation simulation, Object objectService, MapElement device) {
AtsStandService standService = (AtsStandService) objectService;
standService.cancelHoldTrain(simulation,device.getCode());
}
},
STAND_UP_HOLD_TRAIN(MapElement.DeviceType.STAND,"上行扣车"){
@Override
public void handle(Simulation simulation, Object objectService, MapElement device) {
AtsStandService standService = (AtsStandService) objectService;
standService.holdTrain(simulation,device.getCode());
}
},
STAND_DOWN_HOLD_TRAIN(MapElement.DeviceType.STAND,"下行扣车"){
@Override
public void handle(Simulation simulation, Object objectService, MapElement device) {
AtsStandService standService = (AtsStandService) objectService;
standService.holdTrain(simulation,device.getCode());
}
},
STAND_CANCEL_UP_HOLD_TRAIN(MapElement.DeviceType.STAND,"上行取消扣车"){
@Override
public void handle(Simulation simulation, Object objectService, MapElement device) {
AtsStandService standService = (AtsStandService) objectService;
standService.cancelHoldTrain(simulation,device.getCode());
}
},
STAND_CANCEL_DOWN_HOLD_TRAIN(MapElement.DeviceType.STAND,"下行取消扣车"){
@Override
public void handle(Simulation simulation, Object objectService, MapElement device) {
AtsStandService standService = (AtsStandService) objectService;
standService.cancelHoldTrain(simulation,device.getCode());
}
},
;
private MapElement.DeviceType deviceType;
@Getter
private String describe;
public abstract void handle(Simulation simulation,CiSwitchControlService service, MapElement device);
public abstract void handle(Simulation simulation,Object objectService, MapElement device);
OperateEnum(MapElement.DeviceType deviceType, String describe) {
this.deviceType = deviceType;

View File

@ -0,0 +1,31 @@
package club.joylink.rtss.simulation.cbtc.command.voice.vo;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
import java.util.stream.Collectors;
@Data
@NoArgsConstructor
public class CommandParse {
private String descrbeCommand;
private String translateDescrbeCommand;
private List<ParseDetail> detail;
public CommandParse(String descrbeCommand, String translateDescrbeCommand) {
this.descrbeCommand = descrbeCommand;
this.translateDescrbeCommand = translateDescrbeCommand;
}
public List<ParseDetail> findNatureDetail(String nature){
return this.detail.stream().filter(d-> StringUtils.equalsIgnoreCase(d.getNature(), nature)).collect(Collectors.toList());
}
public List<ParseDetail> findNotNatureDetail(String nature){
return this.detail.stream().filter(d->!StringUtils.equalsIgnoreCase(d.getNature(),nature)).collect(Collectors.toList());
}
}

View File

@ -26,17 +26,10 @@ public class DeviceVoiceCommand {
/**
* 匹配的命令关键字
*/
private String[] matchCommandKW;
private String matchCommandDescribe;
// private String[] matchCommandKW;
// private String matchCommandDescribe;
public void appendCommandDescribe(String d){
if(Objects.isNull(this.matchCommandDescribe)){
this.matchCommandDescribe = d;
}else{
this.matchCommandDescribe = this.matchCommandDescribe.concat(d);
}
}
@Override
public String toString(){

View File

@ -9,6 +9,22 @@ import lombok.NoArgsConstructor;
public class OperateConfigData extends VoiceConfigData {
private OperateEnum operate;
/**
* 描述
*/
// private String[] describeKW;
// private String[] translateDescribeKW;
/**
* 属性关键字
*/
private String[] natureKW;
private String[] translateNatureKW;
/**
* 是否强制匹配属性关键字
*/
private boolean forceMatchNature;
public OperateConfigData(OperateEnum operate) {
this.operate = operate;
}

View File

@ -0,0 +1,20 @@
package club.joylink.rtss.simulation.cbtc.command.voice.vo;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class ParseDetail {
private String name;
private String nature;
private int index;
private int end;
public ParseDetail(String name, String meta, int index, int end) {
this.name = name;
this.nature = meta;
this.index = index;
this.end = end;
}
}

View File

@ -4,7 +4,10 @@ import lombok.Data;
@Data
public class VoiceConfigData {
private String[] sourceMatch;
private String[] translateMatch;
/**
* 激活匹配关键字
*/
private String[] actionMatch;
private String[] translateActionMatch;
}

View File

@ -1,7 +1,9 @@
package club.joylink.rtss.simulation.cbtc.command.voice.work;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.command.voice.vo.WorkResult;
import club.joylink.rtss.simulation.cbtc.command.voice.vo.CommandParse;
import club.joylink.rtss.simulation.cbtc.command.voice.vo.ParseDetail;
import club.joylink.rtss.simulation.cbtc.command.voice.vo.OperateConfigData;
import club.joylink.rtss.simulation.cbtc.command.voice.vo.DeviceVoiceCommand;
import club.joylink.rtss.simulation.cbtc.data.map.MapElement;
import club.joylink.rtss.simulation.cbtc.data.map.MapNamedElement;
@ -11,8 +13,22 @@ import java.util.Optional;
public interface IDeviceWork {
Optional<MapNamedElement> findDevice(Simulation simulation, List<String> matchCommandDescribe);
WorkResult work(Simulation simulation, DeviceVoiceCommand command, MapElement device);
/**
* 根据分析出的数据查找对应的设备
* @param simulation
* @param matchCommandDescribe
* @return
*/
Optional<? extends MapNamedElement> findDevice(Simulation simulation, CommandParse commandParse, OperateConfigData configData);
/**
* 执行对应的操作
* @param simulation
* @param command
* @param device
* @return
*/
void work(Simulation simulation, DeviceVoiceCommand command, MapElement device);
MapElement.DeviceType deviceType();
}

View File

@ -3,6 +3,8 @@ package club.joylink.rtss.simulation.cbtc.command.voice.work;
import club.joylink.rtss.exception.BusinessExceptionAssertEnum;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.command.voice.analyse.VoiceCommandAnalyse;
import club.joylink.rtss.simulation.cbtc.command.voice.vo.CommandParse;
import club.joylink.rtss.simulation.cbtc.command.voice.vo.ParseDetail;
import club.joylink.rtss.simulation.cbtc.command.voice.vo.WorkResult;
import club.joylink.rtss.simulation.cbtc.command.voice.vo.DeviceVoiceCommand;
import club.joylink.rtss.simulation.cbtc.data.map.MapElement;
@ -31,12 +33,18 @@ public class VoiceCommandAnalyseWork {
return deviceWork;
}
/**
* 分析语音指令的描述并返回查找对应的设备
* @param simulation
* @param command
* @return
*/
public Optional<MapNamedElement> analyse(Simulation simulation, DeviceVoiceCommand command) {
IDeviceWork deviceWork = this.findDeviceWork(command.getDeviceType());
List<String> findDeviceNames = this.commandAnalyse.parseCommandDescribe(command);
command.setMatchCommandDescribe(Joiner.on(",").join(findDeviceNames));
Optional<MapNamedElement> optional = deviceWork.findDevice(simulation,findDeviceNames);
return optional;
CommandParse commandParse = this.commandAnalyse.parseCommandDescribe(simulation,command);
// command.setMatchCommandDescribe(Joiner.on(",").join(findDeviceNames));
Optional<? extends MapNamedElement> optional = deviceWork.findDevice(simulation,commandParse,command.getOperateConfigData());
return (Optional<MapNamedElement>) optional;
}
public WorkResult work(Simulation simulation, DeviceVoiceCommand command, MapNamedElement device){

View File

@ -0,0 +1,71 @@
package club.joylink.rtss.simulation.cbtc.command.voice.work.device;
import club.joylink.rtss.simulation.cbtc.ATS.service.AtsStandService;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.command.voice.analyse.VoiceCommandAnalyse;
import club.joylink.rtss.simulation.cbtc.command.voice.operate.OperateEnum;
import club.joylink.rtss.simulation.cbtc.command.voice.vo.CommandParse;
import club.joylink.rtss.simulation.cbtc.command.voice.vo.ParseDetail;
import club.joylink.rtss.simulation.cbtc.command.voice.vo.DeviceVoiceCommand;
import club.joylink.rtss.simulation.cbtc.command.voice.vo.OperateConfigData;
import club.joylink.rtss.simulation.cbtc.command.voice.work.IDeviceWork;
import club.joylink.rtss.simulation.cbtc.data.map.*;
import club.joylink.rtss.util.PinYinUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.similarity.JaroWinklerSimilarity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
@Component
public class StandWork implements IDeviceWork {
@Autowired
private AtsStandService atsStandService;
private String findStationCode(Simulation simulation, CommandParse commandParse){
List<ParseDetail> findCommandParse = commandParse.findNotNatureDetail(VoiceCommandAnalyse.DESCRIBE_NATURE);
JaroWinklerSimilarity similarity = new JaroWinklerSimilarity();
Map<Double,String> similarityMaper = new HashMap<>();
for (Station station : simulation.getRepository().getStationList()) {
String stationName = station.getName();
String pinYinStation = PinYinUtil.toPinYinSplitBlankSpace(stationName);
for (ParseDetail cp : findCommandParse) {
double scope = similarity.apply(pinYinStation,cp.getName());
similarityMaper.put(scope,station.getCode());
}
}
if(similarityMaper.isEmpty()){
return null;
}
double max = similarityMaper.keySet().stream().mapToDouble(d->d).max().getAsDouble();
return similarityMaper.get(max);
}
@Override
public Optional<? extends MapNamedElement> findDevice(Simulation simulation, CommandParse commandParse, OperateConfigData configData) {
String stationCode = this.findStationCode(simulation,commandParse);
if(StringUtils.isEmpty(stationCode)){
return Optional.empty();
}
OperateEnum configOperateEnum = configData.getOperate();
final boolean isRight = (configOperateEnum == OperateEnum.STAND_DOWN_HOLD_TRAIN || configOperateEnum == OperateEnum.STAND_CANCEL_DOWN_HOLD_TRAIN) ? false : true;
Optional<Stand> stand = simulation.getRepository().getStandList().stream().filter(d->d.isRight() == isRight && StringUtils.equalsIgnoreCase(d.getStation().getCode(),stationCode)).findFirst();
return stand;
}
@Override
public void work(Simulation simulation, DeviceVoiceCommand command, MapElement device) {
command.getOperateConfigData().getOperate().handle(simulation,this.atsStandService,device);
}
@Override
public MapElement.DeviceType deviceType() {
return MapElement.DeviceType.STAND;
}
}

View File

@ -2,7 +2,9 @@ package club.joylink.rtss.simulation.cbtc.command.voice.work.device;
import club.joylink.rtss.simulation.cbtc.CI.device.CiSwitchControlService;
import club.joylink.rtss.simulation.cbtc.Simulation;
import club.joylink.rtss.simulation.cbtc.command.voice.vo.WorkResult;
import club.joylink.rtss.simulation.cbtc.command.voice.vo.CommandParse;
import club.joylink.rtss.simulation.cbtc.command.voice.vo.ParseDetail;
import club.joylink.rtss.simulation.cbtc.command.voice.vo.OperateConfigData;
import club.joylink.rtss.simulation.cbtc.command.voice.vo.DeviceVoiceCommand;
import club.joylink.rtss.simulation.cbtc.command.voice.work.IDeviceWork;
import club.joylink.rtss.simulation.cbtc.data.map.MapElement;
@ -24,13 +26,13 @@ public class SwitchWork implements IDeviceWork {
private CiSwitchControlService ciSwitchControlService;
@Override
public Optional<MapNamedElement> findDevice(Simulation simulation, List<String> matchCommandDescribe) {
public Optional<MapNamedElement> findDevice(Simulation simulation, CommandParse commandParse, OperateConfigData configData) {
JaroWinklerSimilarity similarity = new JaroWinklerSimilarity();
Map<Double,String> similarityMaper = new HashMap<>();
for (Switch aSwitch : simulation.getRepository().getSwitchList()) {
String switchName = aSwitch.getName();
for (String findDeviceName : matchCommandDescribe) {
double scope = similarity.apply(switchName.toUpperCase(),findDeviceName);
for (ParseDetail cp : commandParse.getDetail()) {
double scope = similarity.apply(switchName.toUpperCase(),cp.getName());
similarityMaper.put(scope,aSwitch.getCode());
}
}
@ -45,9 +47,9 @@ public class SwitchWork implements IDeviceWork {
}
@Override
public WorkResult work(Simulation simulation, DeviceVoiceCommand command, MapElement device) {
public void work(Simulation simulation, DeviceVoiceCommand command, MapElement device) {
command.getOperateConfigData().getOperate().handle(simulation,this.ciSwitchControlService,device);
return null;
}
@Override

View File

@ -1,11 +1,14 @@
package club.joylink.rtss.util;
import com.google.common.base.Splitter;
import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
import java.util.List;
public class PinYinUtil {
private final static HanyuPinyinOutputFormat PIN_YIN_FORMAT = new HanyuPinyinOutputFormat();
@ -37,6 +40,11 @@ public class PinYinUtil {
}
return result;
}
public static List<String> toPinyinList(String sourceMsg){
String tmpPinyinStr = toPinYinSplitBlankSpace(sourceMsg);
return Splitter.onPattern("\\s").omitEmptyStrings().splitToList(tmpPinyinStr);
}
public static String toPinYinSplitBlankSpace(String sourceMsg){
StringBuilder sb = new StringBuilder();
for(char c : sourceMsg.toCharArray()){

View File

@ -16,7 +16,6 @@ import org.springframework.util.StringUtils;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
@ -73,14 +72,20 @@ public class VoiceConfigVO implements Serializable {
VoiceDeviceConfig vc = new VoiceDeviceConfig();
if(Objects.nonNull(this.wakeUpKw)){
if(this.handleType == HandleType.PINYIN){
this.wakeUpKw.setTranslateMatch(PinYinUtil.toPinYins(this.wakeUpKw.getSourceMatch()));
this.wakeUpKw.setTranslateActionMatch(PinYinUtil.toPinYins(this.wakeUpKw.getActionMatch()));
}
vc.setWakeUpKw(JsonUtils.writeValueAsString(this.wakeUpKw));
}
if(!CollectionUtils.isEmpty(this.config)){
for (OperateConfigData configData : this.config) {
if(this.handleType == HandleType.PINYIN){
configData.setTranslateMatch(PinYinUtil.toPinYins(configData.getSourceMatch()));
configData.setTranslateActionMatch(PinYinUtil.toPinYins(configData.getActionMatch()));
if(ArrayUtils.isNotEmpty(configData.getDescribeKW())){
configData.setTranslateDescribeKW(PinYinUtil.toPinYins(configData.getDescribeKW()));
}
if(ArrayUtils.isNotEmpty(configData.getNatureKW())){
configData.setTranslateNatureKW(PinYinUtil.toPinYins(configData.getNatureKW()));
}
}
}
vc.setConfig(JsonUtils.writeValueAsString(this.config));

View File

@ -1,27 +1,37 @@
package club.joylink.rtss.services.util;
import club.joylink.rtss.util.PinYinUtil;
import org.ansj.domain.Result;
import org.ansj.domain.Term;
import org.ansj.library.DicLibrary;
import org.ansj.splitWord.analysis.DicAnalysis;
import org.nlpcn.commons.lang.tire.domain.Forest;
public class SplitWordTest {
public static void main(String[] args) throws Exception {
DicLibrary.insert(DicLibrary.DEFAULT, "dao cha", DicLibrary.DEFAULT_NATURE, 1);
DicLibrary.insert(DicLibrary.DEFAULT, "ding wei", DicLibrary.DEFAULT_NATURE, 1);
DicLibrary.insert(DicLibrary.DEFAULT, "fan wei", DicLibrary.DEFAULT_NATURE, 1);
DicLibrary.insert(DicLibrary.DEFAULT, "ban li", DicLibrary.DEFAULT_NATURE, 1);
// print("1234asdfa");
// print("BAN LI|p0707|daochadingwei|");
print("BAN LI p0707 dao cha ding wei");
// DicLibrary.insert(DicLibrary.DEFAULT, "dao cha", DicLibrary.DEFAULT_NATURE, 1);
// DicLibrary.insert(DicLibrary.DEFAULT, "ding wei", DicLibrary.DEFAULT_NATURE, 1);
// DicLibrary.insert(DicLibrary.DEFAULT, "fan wei", DicLibrary.DEFAULT_NATURE, 1);
// DicLibrary.insert(DicLibrary.DEFAULT, "ban li", DicLibrary.DEFAULT_NATURE, 1);
// DicLibrary.put("user",null);
// DicLibrary.put("user", "user", new Forest());
// DicLibrary.insert("user", PinYinUtil.toPinYinSplitBlankSpace("车险").toLowerCase(),"user",1000);
DicLibrary.insert(DicLibrary.DEFAULT, "zhan tai", DicLibrary.DEFAULT_NATURE, 1);
DicLibrary.insert(DicLibrary.DEFAULT, "zhan", "xxxws", 1);
DicLibrary.insert(DicLibrary.DEFAULT, "zhan", "user", 1);
DicLibrary.insert(DicLibrary.DEFAULT, "shang xing", DicLibrary.DEFAULT_NATURE, 1);
DicLibrary.insert(DicLibrary.DEFAULT, "kou che", DicLibrary.DEFAULT_NATURE, 1);
String source = "车险 车站01上行站台扣车";
String pinyin = PinYinUtil.toPinYinSplitBlankSpace(source);
print(pinyin);
}
private static void print(String s) throws Exception {
// print(BaseAnalysis.parse(s));
// print(ToAnalysis.parse(s));
// print(IndexAnalysis.parse(s));
print(DicAnalysis.parse(s));
print(DicAnalysis.parse(s,DicLibrary.get("user")));
// print(NlpAnalysis.parse(s));
// print(DicAnalysis.parse(s));
}

View File

@ -95,4 +95,15 @@ public class SimulationVoiceTest {
System.out.println(result);
}
}
@Test
public void newTestStand(){
LoginUserInfoVO userInfoVO = this.getInfo();
String simKey = simulationService.createSimulation(10642L,userInfoVO);
Simulation simulation = (Simulation)this.simulationManager.getById(simKey);
List<WorkResult> results = this.commandService.voiceCommand(simulation,"办理车站十上行站台扣车");
// List<WorkResult> results = this.commandService.voiceCommand(simulation,"办理车站1上行站台扣车");
for (WorkResult result : results) {
System.out.println(result);
}
}
}

View File

@ -50,19 +50,45 @@ public class VoiceDataManageTest {
configVO.setDeviceType(MapElement.DeviceType.SWITCH);
configVO.setMapId(50L);
VoiceConfigData config = new VoiceConfigData();
config.setSourceMatch(new String[]{"道岔"});
config.setActionMatch(new String[]{"道岔"});
configVO.setWakeUpKw(config);
List<OperateConfigData> configDataList = Lists.newArrayList();
OperateConfigData configData = new OperateConfigData(OperateEnum.SWITCH_DINGWEI);
configData.setSourceMatch(new String[]{"定位"});
configData.setActionMatch(new String[]{"定位"});
configDataList.add(configData);
configData = new OperateConfigData(OperateEnum.SWITCH_FANWEI);
configData.setSourceMatch(new String[]{"反位"});
configData.setActionMatch(new String[]{"反位"});
configDataList.add(configData);
configVO.setConfig(configDataList);
this.dataService.saveOrUpdate(configVO,userInfoVO);
}
@Test
// @Rollback
public void insertDataStand(){
LoginUserInfoVO userInfoVO = this.getInfo();
VoiceConfigVO configVO = new VoiceConfigVO();
configVO.setId(11L);
configVO.setHandleType(HandleType.PINYIN);
configVO.setDescribe("测试站台");
configVO.setDeviceType(MapElement.DeviceType.STAND);
configVO.setMapId(63L);
VoiceConfigData config = new VoiceConfigData();
config.setActionMatch(new String[]{"站台"});
configVO.setWakeUpKw(config);
List<OperateConfigData> configDataList = Lists.newArrayList();
OperateConfigData configData = new OperateConfigData(OperateEnum.STAND_UP_HOLD_TRAIN);
configData.setActionMatch(new String[]{"扣车"});
configData.setNatureKW(new String[]{"上行",""});
// configData.setDescribeKW(new String[]{""});
configDataList.add(configData);
configData = new OperateConfigData(OperateEnum.STAND_CANCEL_UP_HOLD_TRAIN);
configData.setActionMatch(new String[]{"取消扣车","取消"});
configData.setNatureKW(new String[]{"上行",""});
// configData.setDescribeKW(new String[]{""});
configDataList.add(configData);
configVO.setConfig(configDataList);
this.dataService.saveOrUpdate(configVO,userInfoVO);
}
@Test
public void findData(){
VoiceConfigVO vo1 = this.dataService.byId(7L);