From 8e6bbfdad518ea55f3fc5ad44ce9a35ee9538e4c Mon Sep 17 00:00:00 2001 From: wangshaoping Date: Sun, 4 Feb 2024 14:05:48 +0800 Subject: [PATCH] update --- .../main/java/io/sc/engine/mv/ModelType.java | 11 ++ .../mv/controller/sc/KsWebController.java | 102 ++++++++++ ...rm.core.initializer.ApplicationInitializer | 1 + .../platform/core/support/NumberIterator.java | 179 ++++++++++++++++++ .../io/sc/platform/data/ItemProcessor.java | 5 + .../java/io/sc/platform/data/ItemReader.java | 10 + .../java/io/sc/platform/data/ItemWriter.java | 10 + .../java/io/sc/platform/data/job/Job.java | 87 +++++++++ .../java/io/sc/platform/data/job/JobStep.java | 122 ++++++++++++ .../wrapper/springboot/MappingWrapper.java | 170 +++++++++++++++++ .../controller/LogViewerWebController.java | 4 +- 11 files changed, 699 insertions(+), 2 deletions(-) create mode 100644 io.sc.engine.mv/src/main/java/io/sc/engine/mv/ModelType.java create mode 100644 io.sc.engine.mv/src/main/java/io/sc/engine/mv/controller/sc/KsWebController.java create mode 100644 io.sc.engine.mv/src/main/resources/META-INF/services/io.sc.platform.core.initializer.ApplicationInitializer create mode 100644 io.sc.platform.core/src/main/java/io/sc/platform/core/support/NumberIterator.java create mode 100644 io.sc.platform.data/src/main/java/io/sc/platform/data/ItemProcessor.java create mode 100644 io.sc.platform.data/src/main/java/io/sc/platform/data/ItemReader.java create mode 100644 io.sc.platform.data/src/main/java/io/sc/platform/data/ItemWriter.java create mode 100644 io.sc.platform.data/src/main/java/io/sc/platform/data/job/Job.java create mode 100644 io.sc.platform.data/src/main/java/io/sc/platform/data/job/JobStep.java create mode 100644 io.sc.platform.developer/src/main/java/io/sc/platform/developer/wrapper/springboot/MappingWrapper.java diff --git a/io.sc.engine.mv/src/main/java/io/sc/engine/mv/ModelType.java b/io.sc.engine.mv/src/main/java/io/sc/engine/mv/ModelType.java new file mode 100644 index 00000000..6bdadc7b --- /dev/null +++ b/io.sc.engine.mv/src/main/java/io/sc/engine/mv/ModelType.java @@ -0,0 +1,11 @@ +package io.sc.engine.mv; + +/** + * 模型创建类型 + * @author wangshaoping + * + */ +public enum ModelType { + IMPORT_FROM_SCORE_RECORD, //模型从评分记录表中导入 + MANUAL; //手工创建 +} diff --git a/io.sc.engine.mv/src/main/java/io/sc/engine/mv/controller/sc/KsWebController.java b/io.sc.engine.mv/src/main/java/io/sc/engine/mv/controller/sc/KsWebController.java new file mode 100644 index 00000000..a28a0547 --- /dev/null +++ b/io.sc.engine.mv/src/main/java/io/sc/engine/mv/controller/sc/KsWebController.java @@ -0,0 +1,102 @@ +package io.sc.engine.mv.controller.sc; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +import io.sc.engine.mv.jpa.entity.GeneralResultHistory; +import io.sc.engine.mv.jpa.entity.ScKsHistory; +import io.sc.engine.mv.jpa.entity.id.ScKsHistoryId; +import io.sc.engine.mv.jpa.repository.GeneralResultHistoryRepository; +import io.sc.engine.mv.jpa.repository.ScKsHistoryRepository; +import io.sc.engine.mv.sc.echarts.Coordinates; +import io.sc.engine.mv.service.sc.ScKsHistoryService; +import io.sc.engine.mv.vo.ScKsHistoryVo; +import io.sc.platform.core.util.CollectionUtil; +import io.sc.platform.mvc.controller.support.RestCrudController; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataAccessException; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.PreparedStatementCreator; +import org.springframework.jdbc.core.ResultSetExtractor; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.servlet.ModelAndView; + +@Controller +@RequestMapping("/mv/sc/ks") +public class KsWebController extends RestCrudController { + //模型验证结果DAO + @Autowired private GeneralResultHistoryRepository generalResultHistoryRepository; + //jdbc 模板 + @Autowired private JdbcTemplate jdbcTemplate; + + /** + * 查看模型区分能力验证 KS 指标数据UI + * @param modelId 模型标识 + * @param validateDate 验证日期 + * @return UI视图 + */ + @RequestMapping("ksDataView") + public ModelAndView rocDataView( + @RequestParam(name="modelId",required=false) String modelId, + @RequestParam(name="validateDate",required=false) String validateDate + ){ + ModelAndView mv =new ModelAndView("org/wsp/model/validator/view/sc/ksDataView.html"); + mv.addObject("removeNavbar", true); + mv.addObject("modelId", modelId); + mv.addObject("validateDate", validateDate); + mv.addObject("distinctModelIdAndNames", CollectionUtil.arrayList2Map(service.getRepository().findDistinctModelIdAndNames())); + return mv; + } + + /** + * 获取模型区分能力 KS 曲线的 echarts Options + * @param modelId 模型标识 + * @param validateDate 验证日期 + * @return 模型区分能力 KS 曲线的 echarts Options 的 javascript + * @throws Exception 违例 + */ + @RequestMapping("ks.js") + public ModelAndView ks( + @RequestParam("modelId") String modelId, + @RequestParam("validateDate") String validateDate + ) throws Exception{ + ModelAndView mv =new ModelAndView("org/wsp/model/validator/view/sc/echarts/ks.js"); + GeneralResultHistory resultSummary =generalResultHistoryRepository.findByModelIdAndValidateDate(modelId, validateDate); + mv.addObject("resultSummary", resultSummary); + mv.addObject("coordinates",getCoordinates(modelId,validateDate)); + return mv; + } + + /** + * 获取 KS 曲线图中 X,Y1,Y2 坐标集 + * @param modelId 模型标识 + * @param validateDate 验证日期 + * @return ROC 曲线图中 X,Y1,Y2 坐标集 + */ + private Coordinates getCoordinates(final String modelId, final String validateDate){ + return jdbcTemplate.query(new PreparedStatementCreator() { + @Override + public PreparedStatement createPreparedStatement(Connection con) throws SQLException { + String sql ="select FD_SCORE_CUT_OFF_POINT FD_X,FD_Y1,FD_Y2 from MV_SC_KS_HIS where FD_MODEL_ID=? and FD_VALIDATE_DATE=? order by FD_X"; + PreparedStatement ps =con.prepareStatement(sql); + ps.setString(1, modelId); + ps.setString(2, validateDate); + return ps; + } + }, new ResultSetExtractor() { + @Override + public Coordinates extractData(ResultSet rs) throws SQLException, DataAccessException { + Coordinates coordinates =new Coordinates(); + while(rs.next()){ + coordinates.add(rs.getBigDecimal("FD_X"), rs.getBigDecimal("FD_Y1"), rs.getBigDecimal("FD_Y2")); + } + coordinates.setScale("y",2); + return coordinates; + } + }); + } +} diff --git a/io.sc.engine.mv/src/main/resources/META-INF/services/io.sc.platform.core.initializer.ApplicationInitializer b/io.sc.engine.mv/src/main/resources/META-INF/services/io.sc.platform.core.initializer.ApplicationInitializer new file mode 100644 index 00000000..6e13dbe7 --- /dev/null +++ b/io.sc.engine.mv/src/main/resources/META-INF/services/io.sc.platform.core.initializer.ApplicationInitializer @@ -0,0 +1 @@ +io.sc.engine.mv.initializer.ConfigurationInitializer \ No newline at end of file diff --git a/io.sc.platform.core/src/main/java/io/sc/platform/core/support/NumberIterator.java b/io.sc.platform.core/src/main/java/io/sc/platform/core/support/NumberIterator.java new file mode 100644 index 00000000..274bd9f7 --- /dev/null +++ b/io.sc.platform.core/src/main/java/io/sc/platform/core/support/NumberIterator.java @@ -0,0 +1,179 @@ +package io.sc.platform.core.support; + +import java.math.BigDecimal; +import java.math.RoundingMode; + +public class NumberIterator { + private BigDecimal from; //初始值 + private BigDecimal to; //目标值 + private BigDecimal step; //步长 + private BigDecimal current; //当前值 + + private int scale =2; //精度位数 + private RoundingMode roundingMode=RoundingMode.HALF_UP; //四舍五入模式 + + /** + * 默认构造函数 + */ + public NumberIterator(){ + + } + + /** + * 构造函数(精度为2,采用四舍五入模式) + * @param from 起始值 + * @param to 目标值 + * @param step 步长 + */ + public NumberIterator(String from,String to,String step){ + this(from,to,step,2,RoundingMode.HALF_UP); + } + + /** + * 构造函数 + * @param from 起始值 + * @param to 目标值 + * @param step 步长 + * @param scale 精度 + * @param roundingMode 四舍五入模式 + */ + public NumberIterator(String from,String to,String step, int scale,RoundingMode roundingMode){ + this.from =new BigDecimal(from); + this.current =new BigDecimal(from); + this.to =new BigDecimal(to); + this.step =new BigDecimal(step); + this.scale =scale; + this.roundingMode =roundingMode; + } + + /** + * 获取初始值 + * @return 初始值 + */ + public BigDecimal getFrom() { + return from; + } + + /** + * 设置初始值 + * @param from 初始值 + */ + public void setFrom(BigDecimal from) { + this.from = from; + } + + /** + * 获取目标值 + * @return 目标值 + */ + public BigDecimal getTo() { + return to; + } + + /** + * 设置目标值 + * @param to 目标值 + */ + public void setTo(BigDecimal to) { + this.to = to; + } + + /** + * 获取步长 + * @return 步长 + */ + public BigDecimal getStep() { + return step; + } + + /** + * 设置步长 + * @param step 步长 + */ + public void setStep(BigDecimal step) { + this.step = step; + } + + /** + * 获取当前值 + * @return 当前值 + */ + public BigDecimal getCurrent() { + return current; + } + + /** + * 设置当前值 + * @param current 当前值 + */ + public void setCurrent(BigDecimal current) { + this.current = current; + } + + /** + * 获取精度 + * @return 精度 + */ + public int getScale() { + return scale; + } + + /** + * 设置精度 + * @param scale 精度 + */ + public void setScale(int scale) { + this.scale = scale; + } + + /** + * 获取四舍五入模式 + * @return 四舍五入模式 + */ + public RoundingMode getRoundingMode() { + return roundingMode; + } + + /** + * 设置四舍五入模式 + * @param roundingMode 四舍五入模式 + */ + public void setRoundingMode(RoundingMode roundingMode) { + this.roundingMode = roundingMode; + } + + /** + * 获取下一个值 + * @return 下一个值 + */ + public BigDecimal next(){ + BigDecimal result =current; + current =current.add(step); + return result; + } + + /** + * 获取是否还有下一个值 + * @return 是否还有下一个值 + */ + public boolean hasNext(){ + if(step.doubleValue()>0){ + return current.compareTo(to)<=0; + }else{ + return current.compareTo(to)>=0; + } + } + + /** + * 重置 + */ + public void reset(){ + current =from; + } + + @Override + public String toString() { + return "NumberIterator [from=" + from + ", to=" + to + ", step=" + step + ", current=" + current + ", scale=" + + scale + ", roundingMode=" + roundingMode + "]"; + } +} diff --git a/io.sc.platform.data/src/main/java/io/sc/platform/data/ItemProcessor.java b/io.sc.platform.data/src/main/java/io/sc/platform/data/ItemProcessor.java new file mode 100644 index 00000000..5def2e59 --- /dev/null +++ b/io.sc.platform.data/src/main/java/io/sc/platform/data/ItemProcessor.java @@ -0,0 +1,5 @@ +package io.sc.platform.data; + +public interface ItemProcessor { + public T process(S item) throws Exception; +} diff --git a/io.sc.platform.data/src/main/java/io/sc/platform/data/ItemReader.java b/io.sc.platform.data/src/main/java/io/sc/platform/data/ItemReader.java new file mode 100644 index 00000000..59f035cf --- /dev/null +++ b/io.sc.platform.data/src/main/java/io/sc/platform/data/ItemReader.java @@ -0,0 +1,10 @@ +package io.sc.platform.data; + +import java.io.Closeable; +import java.io.IOException; + +public interface ItemReader extends Closeable { + public void init() throws IOException; + public boolean hasNext() throws IOException; + public T read() throws IOException; +} diff --git a/io.sc.platform.data/src/main/java/io/sc/platform/data/ItemWriter.java b/io.sc.platform.data/src/main/java/io/sc/platform/data/ItemWriter.java new file mode 100644 index 00000000..593dc6fe --- /dev/null +++ b/io.sc.platform.data/src/main/java/io/sc/platform/data/ItemWriter.java @@ -0,0 +1,10 @@ +package io.sc.platform.data; + +import java.io.Closeable; +import java.io.IOException; +import java.util.List; + +public interface ItemWriter extends Closeable { + public void init() throws IOException; + public void write(List items) throws IOException; +} diff --git a/io.sc.platform.data/src/main/java/io/sc/platform/data/job/Job.java b/io.sc.platform.data/src/main/java/io/sc/platform/data/job/Job.java new file mode 100644 index 00000000..548e3193 --- /dev/null +++ b/io.sc.platform.data/src/main/java/io/sc/platform/data/job/Job.java @@ -0,0 +1,87 @@ +package io.sc.platform.data.job; + +import io.sc.platform.data.csv.RecordMapper; +import io.sc.platform.data.csv.CsvItemProcessor; +import io.sc.platform.data.csv.CsvItemReader; +import io.sc.platform.data.csv.CsvItemWriter; + +import java.util.ArrayList; +import java.util.List; + +public class Job { + private String name; + private List steps =new ArrayList<>(); + private boolean async; + + public Job(String name){ + this.name =name; + } + + public Job name(String name){ + this.name =name; + return this; + } + + public Job addStep(JobStep step){ + this.steps.add(step); + return this; + } + + public Job async(boolean async){ + this.async =async; + return this; + } + + public void execute() throws Exception{ + if(steps!=null && !steps.isEmpty()){ + for(JobStep step : steps){ + step.execute(); + } + } + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getSteps() { + return steps; + } + + public void setSteps(List steps) { + this.steps = steps; + } + + public boolean isAsync() { + return async; + } + + public void setAsync(boolean async) { + this.async = async; + } + + public static void main(String[] args) throws Exception { + RecordMapper mapper =new RecordMapper(); + mapper.addMapping("CUSTOMER_ID",0); + mapper.addMapping("SCORE",1); + mapper.addMapping("LEVEL",2); + mapper.addMapping("IS_DEFAULT",3); + CsvItemReader reader =new CsvItemReader(mapper); + reader.setResourceUrl("classpath:/泰隆银行_信用卡_工薪模型_验证样本.csv"); + reader.setSkipLines(1); + reader.setSplitChar(","); + CsvItemProcessor processor =new CsvItemProcessor(); + CsvItemWriter writer =new CsvItemWriter(); + + JobStep step =new JobStep("step"); + step.reader(reader); + step.processor(processor); + step.writer(writer); + + new Job("csv job").addStep(step).execute(); + } +} diff --git a/io.sc.platform.data/src/main/java/io/sc/platform/data/job/JobStep.java b/io.sc.platform.data/src/main/java/io/sc/platform/data/job/JobStep.java new file mode 100644 index 00000000..35bec34d --- /dev/null +++ b/io.sc.platform.data/src/main/java/io/sc/platform/data/job/JobStep.java @@ -0,0 +1,122 @@ +package io.sc.platform.data.job; + +import io.sc.platform.data.ItemProcessor; +import io.sc.platform.data.ItemReader; +import io.sc.platform.data.ItemWriter; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class JobStep { + public static final int DEFAULT_CHUNK =20; + private String name; + private int chunk =DEFAULT_CHUNK; + private ItemReader reader; + private ItemProcessor processor; + private ItemWriter writer; + + public JobStep(){} + + public JobStep(String name){ + this.name =name; + } + + public JobStep name(String name){ + this.name =name; + return this; + } + + public JobStep chunk(int chunk){ + if(chunk<1){ + this.chunk =DEFAULT_CHUNK; + } + this.chunk =chunk; + return this; + } + + public JobStep reader(ItemReader reader){ + this.reader =reader; + return this; + } + + public JobStep processor(ItemProcessor processor){ + this.processor =processor; + return this; + } + + public JobStep writer(ItemWriter writer){ + this.writer =writer; + return this; + } + + public void execute() throws Exception { + if(reader==null){ + throw new RuntimeException("reader is null"); + } + if(processor==null){ + throw new RuntimeException("processor is null"); + } + if(writer==null){ + throw new RuntimeException("writer is null"); + } + + reader.init(); + writer.init(); + long index =0; + List list =new ArrayList<>(chunk); + while(reader.hasNext()){ + list.add(processor.process(reader.read())); + if(index%chunk==chunk-1) { + writer.write(list); + list.clear(); + } + index++; + } + if(list.size()>0) { + writer.write(list); + } + reader.close(); + writer.close(); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getChunk() { + return chunk; + } + + public void setChunk(int chunk) { + this.chunk = chunk; + } + + public ItemReader getReader() { + return reader; + } + + public void setReader(ItemReader reader) { + this.reader = reader; + } + + public ItemProcessor getProcessor() { + return processor; + } + + public void setProcessor(ItemProcessor processor) { + this.processor = processor; + } + + public ItemWriter getWriter() { + return writer; + } + + public void setWriter(ItemWriter writer) { + this.writer = writer; + } +} diff --git a/io.sc.platform.developer/src/main/java/io/sc/platform/developer/wrapper/springboot/MappingWrapper.java b/io.sc.platform.developer/src/main/java/io/sc/platform/developer/wrapper/springboot/MappingWrapper.java new file mode 100644 index 00000000..7f78675b --- /dev/null +++ b/io.sc.platform.developer/src/main/java/io/sc/platform/developer/wrapper/springboot/MappingWrapper.java @@ -0,0 +1,170 @@ +package io.sc.platform.developer.wrapper.springboot; + +import io.sc.platform.core.util.StringUtil; +import org.springframework.boot.actuate.web.mappings.HandlerMethodDescription; +import org.springframework.boot.actuate.web.mappings.servlet.RequestMappingConditionsDescription.MediaTypeExpressionDescription; +import org.springframework.boot.actuate.web.mappings.servlet.RequestMappingConditionsDescription.NameValueExpressionDescription; +import org.springframework.web.bind.annotation.RequestMethod; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +public class MappingWrapper { + private String className; + private String methodName; + private String methodDescriptor; + private String httpMethods; + private String patterns; + private String consumes; + private String produces; + private String headers; + private String params; + + public MappingWrapper( + HandlerMethodDescription handler, + Set httpMethods, + Set patterns, + List consumes, + List produces, + List headers, + List params){ + this.className =handler.getClassName(); + this.methodName =handler.getName(); + this.methodDescriptor =handler.getDescriptor(); + this.patterns =StringUtil.combine(",",patterns); + + if(httpMethods!=null && !httpMethods.isEmpty()){ + List list =new ArrayList<>(httpMethods.size()); + for(RequestMethod requestMethod : httpMethods){ + list.add(requestMethod.toString()); + } + this.httpMethods =StringUtil.combine(",",list); + } + if(consumes!=null && !consumes.isEmpty()){ + List list =new ArrayList<>(consumes.size()); + for(MediaTypeExpressionDescription description : consumes){ + list.add(formatMediaTypeExpressionDescription(description)); + } + this.consumes =StringUtil.combine(",",list); + } + if(produces!=null && !produces.isEmpty()){ + List list =new ArrayList<>(produces.size()); + for(MediaTypeExpressionDescription description : produces){ + list.add(formatMediaTypeExpressionDescription(description)); + } + this.produces =StringUtil.combine(",",list); + } + if(headers!=null && !headers.isEmpty()){ + List list =new ArrayList<>(headers.size()); + for(NameValueExpressionDescription description : headers){ + list.add(formatNameValueExpressionDescription(description)); + } + this.headers =StringUtil.combine(",",list); + } + if(params!=null && !params.isEmpty()){ + List list =new ArrayList<>(params.size()); + for(NameValueExpressionDescription description : params){ + list.add(formatNameValueExpressionDescription(description)); + } + this.params =StringUtil.combine(",",list); + } + } + + private String formatMediaTypeExpressionDescription(MediaTypeExpressionDescription description){ + if(description==null){ + return null; + } + if(description.isNegated()){ + return "-" + description.getMediaType(); + }else{ + return "+" + description.getMediaType(); + } + } + + private String formatNameValueExpressionDescription(NameValueExpressionDescription description){ + if(description==null){ + return null; + } + if(description.isNegated()){ + return "-" + description.getName() + "" + description.getValue(); + }else{ + return "-" + description.getName() + "" + description.getValue(); + } + } + + + public String getClassName() { + return className; + } + + public void setClassName(String className) { + this.className = className; + } + + public String getMethodName() { + return methodName; + } + + public void setMethodName(String methodName) { + this.methodName = methodName; + } + + public String getMethodDescriptor() { + return methodDescriptor; + } + + public void setMethodDescriptor(String methodDescriptor) { + this.methodDescriptor = methodDescriptor; + } + + public String getHttpMethods() { + return httpMethods; + } + + public void setHttpMethods(String httpMethods) { + this.httpMethods = httpMethods; + } + + public String getPatterns() { + return patterns; + } + + public void setPatterns(String patterns) { + this.patterns = patterns; + } + + public String getConsumes() { + return consumes; + } + + public void setConsumes(String consumes) { + this.consumes = consumes; + } + + public String getProduces() { + return produces; + } + + public void setProduces(String produces) { + this.produces = produces; + } + + public String getHeaders() { + return headers; + } + + public void setHeaders(String headers) { + this.headers = headers; + } + + public String getParams() { + return params; + } + + public void setParams(String params) { + this.params = params; + } + + +} diff --git a/io.sc.platform.system/src/main/java/io/sc/platform/system/monitor/controller/LogViewerWebController.java b/io.sc.platform.system/src/main/java/io/sc/platform/system/monitor/controller/LogViewerWebController.java index 3fdde0fa..60807b42 100644 --- a/io.sc.platform.system/src/main/java/io/sc/platform/system/monitor/controller/LogViewerWebController.java +++ b/io.sc.platform.system/src/main/java/io/sc/platform/system/monitor/controller/LogViewerWebController.java @@ -73,7 +73,7 @@ public class LogViewerWebController { } } } - return QueryResult.page(result,queryParameter.getJpaPageable()); + return QueryResult.page(result,queryParameter); } return QueryResult.emptyPage(); } @@ -122,7 +122,7 @@ public class LogViewerWebController { } } } - return QueryResult.page(result,queryParameter.getJpaPageable()); + return QueryResult.page(result,queryParameter); } /**