#获取课程的听力时长和短句数
##接口 遍历文件夹下所有的excel,获得课的短句数,视频的长度,音频的长度: 访问例子:192.168.0.111:8090/single/config/number 访问方式:GET 访问参数:无 根据数据表中的课程id,来获得课中的短句数和听力时长: 访问例子:192.168.0.111:8090/single/config/number/two 访问方式:GET 访问参数:无 通过excel的id得到课中"单词释意"的值 访问例子:192.168.0.111:8090/single//run/words/{lessonId} 访问方式:GET 访问参数:lessonId 课程的id,String类型
1.短句数是excel表中“图片英文”的字段数:在解析excel时,遍历excel中的每一个sheet页和每一个sheet页下面的所有包含“图片英文”的字段,为了避免计算重复的短句数,在得到所有的“图片英文”的值后,将这些值存放到HashSet集合中,最后得到集合的大小为该课程的短句数; //获取excel中短句数的方法 public static Integer count(Map> map, File file, String catalogId) { int count = 0; Set djSet = new HashSet<>(); for (Map.Entry> entity : map.entrySet()) { Table table = entity.getValue();
Map<Integer, String> djColumn = table.column("图片英文");
for (Map.Entry<Integer, String> djEntity : djColumn.entrySet()) {
String djName = djEntity.getValue();
djSet.add(djName);
}
}
count = djSet.size();
if (count == 0) {
logger.error("课中没有短句! 课的名字为:[{}], 课的id是:[{}], 课中短句书为:[{}]", file.getName(), catalogId, count);
} else {
logger.info("课中有短句!课的名字为:[{}], 课的id是:[{}], 课中短句书为:[{}]", file.getName(), catalogId, count);
}
return count;
}
2.课程中的听力时长为excel表中视频的长度+音频的长度:在VideoDuration类countVideoDuration方法中,遍历excel表中所有的sheet页和sheet页下所有的包含“视频”的字段,得到map集合,遍历该集合,得到每个视频的名称,通过调用rms资源管理平台提供的接口,定义FileEntity对象,给对象赋值资源类型restType、资源搜索目录dataMayKey、资源名称resName、资源前缀prefix,调用接口中的downLoadResource方法,得到FileEntity对象,并获得视频时长,将所有的视频时长加在一起,就可以得到该excel的视频总时长; //跑书的时候计算出书中所有音频的时长 public static Long countAudioDuration(Map> bookMap) { Long totalDuration = 0L; for (Map.Entry> entity : bookMap.entrySet()) { Table table = entity.getValue(); //遍历sheet页,得到每页的table Set columnKeySet = table.columnKeySet(); //table中,获得列的集合
for (String column : columnKeySet) { //遍历列的集合,得到每一个列的名称
if (column.contains("音频")) {
Map<Integer, String> columnMap = table.column(column);
for (Map.Entry<Integer, String> entries : columnMap.entrySet()) {
String audioName = entries.getValue();
FileEntity fileEntity = new FileEntity(); //创建FileEntity对象
fileEntity.setResType("audio"); //设置资源类型
fileEntity.setDataMapKey("default"); //设置资源映射
fileEntity.setResName(audioName); //设置资源前缀
fileEntity.setPrefix("audio"); // 设置前缀
FileEntity audioFileEntity = rmiClient.downLoadResource(fileEntity);
if (audioFileEntity != null) {
String audioDuration = audioFileEntity.getDuration();
//计算音频的总时长
if (StringUtils.isNotBlank(audioDuration)) {
Long audioLong = Long.valueOf(audioDuration);
totalDuration += audioLong;
} else {
totalDuration += 0L;
}
} else {
logger.error("资源管理平台上没有找到[{}]的音频", audioName);
}
}
}
}
}
logger.info("音频总时长为:[{}]", totalDuration);
return totalDuration;
}
3.类似,在AudioDuration类中countAudioDuration方法,在遍历excel表的时候,获得表中所有sheet页中包含“音频”字段的map集合,遍历集合,获得每个音频的name值,调用rms资源管理项目中提供的接口,获得每个音频的时长,将所有的音频时长统计加在一起,就可以得到该excel的音频总时长;
4.将得到的音频总时长和视频总时长相加,得到的就是该课的听力时长;
5.配置第二数据源,将课程的听力时长和课程的短句数保存到数据库中,在向数据库保存的操作中,由于需要保存的数据库与jpa框架配置的数据库不是同一个数据库,在向数据库保存的时需要使用第二数据源完成数据的更新和保存操作;在cn.boxfish.onekey.count.jpa.DataSourceConfig类中,通过注解的方式定义第一数据源“primaryDataSource”和第二数据源“secondaryDataSource”,在spring boot的配置文件中,指定两个数据源连接不同的数据库; //定义多数据源 @Configuration @EnableConfigurationProperties @EnableAutoConfiguration public class DataSourceConfig {
@Bean(name = "primaryDataSource")
@Primary
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "secondaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.secondary")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
}
//在配置文件中,为不同的数据源指定不同的数据库 spring: profiles: development datasource: primary: url: jdbc:mysql://192.168.0.100:3306/bebase?useUnicode=true&characterEncoding=utf8 username: bebase password: boxfish secondary: url: jdbc:mysql://192.168.0.100:3306/statistic?useUnicode=true&characterEncoding=utf8 username: bebase password: boxfish
在CountDao类中完成对数据的更新和保存,在使用之前,先指定使用第二数据源,在对数据的操作的时候,不能再使用jpa框架提供的方法,在对数据的保存中,采用的DBUtils完成对数据库的更新和保存; //第二数据源的使用 @Named public class CountDao { QueryRunner queryRunner = new QueryRunner(); private final Logger logger = LoggerFactory.getLogger(CountDao.class);
@Inject
@Resource(name = "secondaryDataSource")
DataSource dataSource;
//更新数据库中的听力时长和短句数
public void updateLessonVersion(Integer clauseSize, Long listeningDuration, String lessonId) {
try (Connection conn = dataSource.getConnection()) {
String sql = "UPDATE nlp_lesson_version lv SET lv.phrase_count = ? ,lv.listening_duration = ? WHERE lv.lesson_id = ? ";
queryRunner.update(conn, sql, clauseSize, listeningDuration, lessonId);
} catch (SQLException e) {
logger.error("更新数据库出现异常:[{}}", e);
e.printStackTrace();
}
}
//根据课程ID查询对象
public List<LessonVersion> findEntityByLessonId(String lessonId) {
try (Connection conn = dataSource.getConnection()) {
List<LessonVersion> list = new ArrayList<>();
String sql = "SELECT id ,lesson_id AS lessonId ,phrase_count AS clauseCount ,listening_duration listeningDuration FROM nlp_lesson_version WHERE lesson_id = ? ";
Map<Integer, LessonVersion> result = queryRunner.query(conn, sql, new BeanMapHandler<Integer, LessonVersion>(LessonVersion.class), lessonId);
for (Map.Entry<Integer, LessonVersion> entity : result.entrySet()) {
LessonVersion lessonVersion = entity.getValue();
if (lessonVersion != null) {
list.add(lessonVersion);
}
}
return list;
} catch (SQLException e) {
logger.error("查询数据库出现异常:[{}}", e);
e.printStackTrace();
}
return null;
}
}
6.在跑课的代码中,每跑一课需要计算出课程的短句数和听力时长,在跑课代码中,调用获得短句数、音频时长和视频时长的方法,将获得的短句数和听力时长传入到nlp接口中,增加nlp接口中的参数,调用nlp接口中的方法,完成数据的保存操作; //跑课时获得听力时长的短句书,调用nlp保存 //获得课的短句数 Integer phraseCount = CalculCount.count(workbook, excel.toFile(), index.getId()); //获得课中音频时长 Long audioDuration = AudioDuration.countAudioDuration(workbook); //获得课中视频时长 Long videoDuration = VideoDuration.countVideoDuration(workbook); //听力时长 Long listeningDuration = audioDuration + videoDuration; // 校验课程是否已经跑目录 checkCourse(index.getId()); log.info("NLP数据获取-学生版: id:[{}]", index.getId()); try { nlpHandler.saveNlpArticle(index.getId(), "student",phraseCount,listeningDuration); } catch (Exception e) { log.error("NLP数据获取出错-学生版: id:[{}],错误:{{}}", index.getId(), e); }
//nlp接口中增加听力时长和短句数的参数
public void saveNlpArticle(String lessonId, String type,Integer phraseCount,Long listeningDuration){
restTemplate.postForEntity(
nlpUrl.replace("::lessonId",lessonId)
.replace("::type",type)
.replace("::phraseCount",String.valueOf(phraseCount))
.replace("::listeningDuration",String.valueOf(listeningDuration)),
null,Object.class);
}
7.提供"单词释义"接口,根据课程id得到课程中所有"单词释义"的值,在类cn.boxfish.onekey.count.CountController方法下 //获得单词释义的所有值 public static Set getValues(Map> map, File file) { Set valueSet = new HashSet<>(); for (Map.Entry> entity : map.entrySet()) { Table table = entity.getValue(); Map column = table.column("单词释义"); //判断excel中是否有"单词释义" if (column.isEmpty()) { logger.error("课[{}]中[{}]sheet页没有单词释义!", file.getName(),entity.getKey()); return valueSet; } for (Map.Entry entry : column.entrySet()) { valueSet.add(entry.getValue()); } logger.info("课[{}]中[{}]sheet页有单词释义!", file.getName(),entity.getKey()); } return valueSet; }