diff --git a/pom.xml b/pom.xml index 4f9c38c..f0c2dd9 100644 --- a/pom.xml +++ b/pom.xml @@ -261,6 +261,18 @@ 9.1.22 + + + com.kennycason + kumo-core + 1.28 + + + com.kennycason + kumo-tokenizers + 1.28 + + diff --git a/src/main/java/com/sztzjy/marketing/config/Constant.java b/src/main/java/com/sztzjy/marketing/config/Constant.java index 31181ed..ffa0431 100644 --- a/src/main/java/com/sztzjy/marketing/config/Constant.java +++ b/src/main/java/com/sztzjy/marketing/config/Constant.java @@ -29,6 +29,7 @@ public class Constant { public static final String FILTEROUTSTATIS_TWO= "纳入"; public static final String FILTEROUTSTATIS_THREE= "4"; public static final String FILTEROUTSTATIS_FOUR= "2"; + public static final String FILTEROUTSTATIS_fIVE_ON= "5"; public static final String FILTEROUTSTATIS_FIVE= "5000"; public static final String FILTEROUTSTATIS_SIX= "3"; public static final String FILTEROUTSTATIS_SEVEN= "1000"; diff --git a/src/main/java/com/sztzjy/marketing/controller/stu/DownloadDataController.java b/src/main/java/com/sztzjy/marketing/controller/stu/DownloadDataController.java index 5599c92..833ce8a 100644 --- a/src/main/java/com/sztzjy/marketing/controller/stu/DownloadDataController.java +++ b/src/main/java/com/sztzjy/marketing/controller/stu/DownloadDataController.java @@ -1,15 +1,19 @@ package com.sztzjy.marketing.controller.stu; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.RandomUtil; import com.sztzjy.marketing.annotation.AnonymousAccess; +import com.sztzjy.marketing.entity.dto.StuWordCreateDto; +import com.sztzjy.marketing.util.TagWordCloudService; import com.sztzjy.marketing.util.file.IFileUtil; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; 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.RestController; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletResponse; +import java.io.IOException; /** * @author 17803 @@ -25,6 +29,9 @@ public class DownloadDataController { @Autowired private IFileUtil iFileUtil; + @Value("${file.path}") + private String filePath; + @AnonymousAccess @ApiOperation("RFM分析方法下载数据") @@ -107,6 +114,22 @@ public class DownloadDataController { } + @AnonymousAccess + @ApiOperation("情感分析/文本挖掘词云生成") + @PostMapping("/wordCreateByAna") + public void wordCreateByAna(@RequestBody StuWordCreateDto stuWordCreateDto) throws IOException { + + TagWordCloudService tagWordCloudService = new TagWordCloudService(); + + //1成图片路径,2.图云背景图片 + String url = filePath+"/word/" + IdUtil.simpleUUID()+"."+"png"; + + + tagWordCloudService.generate(url,filePath+"/1.png",stuWordCreateDto.getContext()); + + + } + diff --git a/src/main/java/com/sztzjy/marketing/controller/stu/UserBehaviorProfilingByRFM.java b/src/main/java/com/sztzjy/marketing/controller/stu/UserBehaviorProfilingByRFM.java index 1ccaf1a..86fe5fb 100644 --- a/src/main/java/com/sztzjy/marketing/controller/stu/UserBehaviorProfilingByRFM.java +++ b/src/main/java/com/sztzjy/marketing/controller/stu/UserBehaviorProfilingByRFM.java @@ -50,6 +50,19 @@ public class UserBehaviorProfilingByRFM { + @AnonymousAccess + @ApiOperation("第四步:按价值打分") + @PostMapping("/scoreByValue") + public ResultEntity scoreByValue(@RequestBody StuMachineLearning stuMachineLearning) { + + return userBehaviorProfilingByRFMService.scoreByValue(stuMachineLearning); + + } + + + + + } diff --git a/src/main/java/com/sztzjy/marketing/entity/dto/StuWordCreateDto.java b/src/main/java/com/sztzjy/marketing/entity/dto/StuWordCreateDto.java new file mode 100644 index 0000000..e9d5ca4 --- /dev/null +++ b/src/main/java/com/sztzjy/marketing/entity/dto/StuWordCreateDto.java @@ -0,0 +1,16 @@ +package com.sztzjy.marketing.entity.dto; + +import lombok.Data; + +/** + * @author 17803 + * @date 2024-06-21 14:21 + */ + +@Data +public class StuWordCreateDto { + + private String context; + private String userId; + +} diff --git a/src/main/java/com/sztzjy/marketing/service/UserBehaviorProfilingByRfmService.java b/src/main/java/com/sztzjy/marketing/service/UserBehaviorProfilingByRfmService.java index 5d8f744..f384ebe 100644 --- a/src/main/java/com/sztzjy/marketing/service/UserBehaviorProfilingByRfmService.java +++ b/src/main/java/com/sztzjy/marketing/service/UserBehaviorProfilingByRfmService.java @@ -23,4 +23,12 @@ public interface UserBehaviorProfilingByRfmService { */ ResultEntity calculateRfm(StuMachineLearning stuMachineLearning); + + /** + * 按价值打分 + * @param stuMachineLearning + * @return + */ + + ResultEntity scoreByValue(StuMachineLearning stuMachineLearning); } diff --git a/src/main/java/com/sztzjy/marketing/service/UserBehaviorProfilingByRfmServiceImpl.java b/src/main/java/com/sztzjy/marketing/service/UserBehaviorProfilingByRfmServiceImpl.java index c4488e7..800d11e 100644 --- a/src/main/java/com/sztzjy/marketing/service/UserBehaviorProfilingByRfmServiceImpl.java +++ b/src/main/java/com/sztzjy/marketing/service/UserBehaviorProfilingByRfmServiceImpl.java @@ -105,6 +105,15 @@ public class UserBehaviorProfilingByRfmServiceImpl implements UserBehaviorProfil //判断结果是否正确 StuBehaviorProfilingDTO behaviorProfilingDTO = checkAnswerByTwoSub(learning); + + return selectRfmInfo(learning,behaviorProfilingDTO); + + } + + + + + private ResultEntity selectRfmInfo(StuMachineLearning learning, StuBehaviorProfilingDTO behaviorProfilingDTO) { //查询是否提交,已提交不做任何修改,未提交校验结果并保存,修改对应提交状态 StuMachineLearningExample machineLearningExample = new StuMachineLearningExample(); @@ -153,10 +162,100 @@ public class UserBehaviorProfilingByRfmServiceImpl implements UserBehaviorProfil } } + /** + * 第四步:按价值打分 + * @param stuMachineLearning + * @return + */ + + @Override + public ResultEntity scoreByValue(StuMachineLearning stuMachineLearning) { + + + //判断结果是否正确 + StuBehaviorProfilingDTO behaviorProfilingDTO = checkAnswerByFourSub(stuMachineLearning); + + //同意查询用户数据 + return selectRfmInfo(stuMachineLearning,behaviorProfilingDTO); + } + + private StuBehaviorProfilingDTO checkAnswerByFourSub(StuMachineLearning learning) { + //用来存储错误字段和正确答案 + // 使用 fastjson 将 JSON 字符串转换回 Map + Map map = JSON.parseObject(learning.getErrorField(), HashMap.class); + + + //错误次数 + int count = 0; + + + if (!Constant.FILTEROUTSTATIS_THREE.equals(learning.getStepFiveB())){ + count ++; + + map.put("stepFiveB",Constant.FILTEROUTSTATIS_THREE); + } + + if (!Constant.FILTEROUTSTATIS_FOUR.equals(learning.getStepFiveC())){ + count ++; + map.put("stepFiveC",Constant.FILTEROUTSTATIS_FOUR); + } + + if (!Constant.FILTEROUTSTATIS_THREE.equals(learning.getStepFiveD())){ + count ++; + map.put("stepFiveD",Constant.FILTEROUTSTATIS_THREE); + } + if (!Constant.FILTEROUTSTATIS_fIVE_ON.equals(learning.getStepSixA())){ + count ++; + map.put("stepSixA",Constant.FILTEROUTSTATIS_fIVE_ON); + } + + if (!Constant.FILTEROUTSTATIS_FOUR.equals(learning.getStepSixB())){ + count ++; + map.put("stepSixB",Constant.FILTEROUTSTATIS_FOUR); + } + + if (!Constant.FILTEROUTSTATIS_FOUR.equals(learning.getStepSixC())){ + count ++; + map.put("stepSixC",Constant.FILTEROUTSTATIS_FOUR); + } + + + + + if (!Constant.FILTEROUTSTATIS_fIVE_ON.equals(learning.getStepSixD())){ + count ++; + map.put("stepSixD",Constant.FILTEROUTSTATIS_fIVE_ON); + } + if (!Constant.FILTEROUTSTATIS_EIGHT.equals(learning.getStepSevenA())){ + count ++; + map.put("stepSevenA",Constant.FILTEROUTSTATIS_EIGHT); + } + if (!Constant.FILTEROUTSTATIS_EIGHT.equals(learning.getStepSevenB())){ + count ++; + map.put("stepSevenB",Constant.FILTEROUTSTATIS_EIGHT); + } + + + Integer number = 9 - count; + + //获取上一次得分 + + Integer sum = learning.getSuccessNumber() + number; + + + //拼接上一次错误字段 + learning.getErrorField(); + + + StuBehaviorProfilingDTO stuBehaviorProfilingDTO = StuBehaviorProfilingDTO.builder().map(map).count(sum).build(); + + return stuBehaviorProfilingDTO; + + } //第一步:筛选出统计样本结果校验 diff --git a/src/main/java/com/sztzjy/marketing/util/TagWordCloudService.java b/src/main/java/com/sztzjy/marketing/util/TagWordCloudService.java new file mode 100644 index 0000000..c13505f --- /dev/null +++ b/src/main/java/com/sztzjy/marketing/util/TagWordCloudService.java @@ -0,0 +1,114 @@ +package com.sztzjy.marketing.util; + +import com.kennycason.kumo.CollisionMode; +import com.kennycason.kumo.WordCloud; +import com.kennycason.kumo.WordFrequency; +import com.kennycason.kumo.bg.CircleBackground; +import com.kennycason.kumo.bg.PixelBoundaryBackground; +import com.kennycason.kumo.font.KumoFont; +import com.kennycason.kumo.font.scale.SqrtFontScalar; +import com.kennycason.kumo.image.AngleGenerator; +import com.kennycason.kumo.nlp.FrequencyAnalyzer; +import com.kennycason.kumo.nlp.tokenizers.ChineseWordTokenizer; +import com.kennycason.kumo.palette.ColorPalette; + +import java.awt.*; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.List; + +import static cn.hutool.core.io.FileUtil.getInputStream; + +public class TagWordCloudService { + + // 照片纵横比 + private double ratio = 1; + // 获取词云图片 + // wordFile:单词及其频率文件路径 + // pngOutputPath:图片输出路径,应该以.png结尾 + // shapePicPath:词云形状图片路径,其背景应为透明背景,格式为png + public void generate(String pngOutputPath, String shapePicPath,String context) throws IOException { +// final FrequencyAnalyzer frequencyAnalyzer = new FrequencyAnalyzer(); + // 共检索多少个词 +// frequencyAnalyzer.setWordFrequenciesToReturn(1000); + // 单词最短长度,一个汉字和一个英文字符都是1 +// frequencyAnalyzer.setMinWordLength(2); +// frequencyAnalyzer.setStopWords(loadStopWords()); + // 设置中文支持,另一种加载方式不用设置 +// frequencyAnalyzer.setWordTokenizer(new ChineseWordTokenizer()); +// final List wordFrequencies; +// // 加载词云有两种方式,一种是在txt文件中统计词出现的个数,另一种是直接给出每个词出现的次数,这里使用第二种 +// // 文件格式如下 +//// 100: frog +//// 94: dog +//// 43: cog +//// 20: bog +// FrequencyFileLoader frequencyFileLoader = new FrequencyFileLoader(); +// File file = new File(wordFile); +// wordFrequencies = frequencyFileLoader.load(file); + // 可以直接从文件中读取 + FrequencyAnalyzer frequencyAnalyzer = new FrequencyAnalyzer(); + frequencyAnalyzer.setWordFrequenciesToReturn(600); + frequencyAnalyzer.setMinWordLength(2); + frequencyAnalyzer.setWordTokenizer(new ChineseWordTokenizer()); + InputStream inputStream = null; + List wordFrequencies = null; + + try { + inputStream = new ByteArrayInputStream(context.getBytes(StandardCharsets.UTF_8)); + wordFrequencies = frequencyAnalyzer.load(inputStream); + + }catch (Exception e) { + e.printStackTrace(); + }finally { + if (inputStream != null) { + try { + inputStream.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + +// final Dimension dimension = new Dimension(600, 600); +// final WordCloud wordCloud = new WordCloud(dimension, CollisionMode.PIXEL_PERFECT); +// wordCloud.setPadding(2); +// wordCloud.setBackground(new CircleBackground(300)); + // wordCloud.setColorPalette(new ColorPalette(new Color(0x4055F1), new Color(0x408DF1), new Color(0x40AAF1), new Color(0x40C5F1), new Color(0x40D3F1), new Color(0xFFFFFF))); +// wordCloud.setFontScalar(new SqrtFontScalar(10, 40)); + + + // 生成图片的像素大小 + //设置图片分辨率 + Dimension dimension = new Dimension(600, 600); +// final Dimension dimension = new Dimension(1024, (int)(1024*ratio)); + final WordCloud wordCloud = new WordCloud(dimension, CollisionMode.PIXEL_PERFECT); + // 调节词云的稀疏程度,越高越稀疏 + wordCloud.setPadding(2); + +// //设置背景色 + wordCloud.setBackgroundColor(new Color(255,255,255)); + //设置背景图片 + //wordCloud.setBackground(new PixelBoundaryBackground(shapePicPath)); +// wordCloud.setBackground(new CircleBackground(300)); + wordCloud.setBackground(new CircleBackground(300)); + + // 颜色模板,不同频率的颜色会不同 + wordCloud.setColorPalette(new ColorPalette(new Color(0x4055F1), new Color(0x408DF1), new Color(0x40AAF1), new Color(0x40C5F1), new Color(0x40D3F1), new Color(0xFFFFFF))); + // 设置字体 + Font font = new Font("楷体", 0, 25); + wordCloud.setKumoFont(new KumoFont(font)); + // 设置偏转角,角度为0时,字体都是水平的 +// wordCloud.setAngleGenerator(new AngleGenerator(0, 90, 9)); + wordCloud.setAngleGenerator(new AngleGenerator(0)); + // 字体的大小范围,最小是多少,最大是多少 + wordCloud.setFontScalar(new SqrtFontScalar(10, 40)); + + wordCloud.build(wordFrequencies); + wordCloud.writeToFile(pngOutputPath); + + + } +}