twzydn20000928 1 жил өмнө
parent
commit
c84031d938

+ 7 - 5
pdaaphm-admin/src/main/java/com/pdaaphm/biz/domain/AlgorithmIoField.java

@@ -1,9 +1,5 @@
 package com.pdaaphm.biz.domain;
-
-import com.pdaaphm.common.annotation.DataSource;
 import lombok.Data;
-import org.apache.commons.lang3.builder.ToStringBuilder;
-import org.apache.commons.lang3.builder.ToStringStyle;
 import com.pdaaphm.common.annotation.Excel;
 import com.pdaaphm.common.core.domain.BaseEntity;
 
@@ -11,12 +7,14 @@ import com.pdaaphm.common.core.domain.BaseEntity;
  * 算法输入输出字段对象 t_algorithm_io_field
  *
  * @author xlk
- * @date 2023-07-26
+ * @date 2023-08-17
  */
 @Data
 public class AlgorithmIoField extends BaseEntity
 {
     private static final long serialVersionUID = 1L;
+    public static String inputCode = "1";
+    public static String outputCode = "2";
 
     /** 编号 */
     private Long id;
@@ -40,4 +38,8 @@ public class AlgorithmIoField extends BaseEntity
     /** 算法子类型名称 */
     @Excel(name = "算法子类型名称")
     private String algoSubName;
+
+    /** matlab文件独有的输入输入路径 */
+    @Excel(name = "matlab文件独有的输入输入路径")
+    private String matlabIoPath;
 }

+ 2 - 0
pdaaphm-admin/src/main/java/com/pdaaphm/biz/domain/AlgorithmSubType.java

@@ -14,6 +14,8 @@ import com.pdaaphm.common.core.domain.BaseEntity;
 public class AlgorithmSubType extends BaseEntity
 {
     private static final long serialVersionUID = 1L;
+    public static String pythonCode = "1";
+    public static String matlabCode = "2";
 
     /** 编号 */
     private Long id;

+ 3 - 2
pdaaphm-admin/src/main/java/com/pdaaphm/biz/factory/AlgorithmFactory.java

@@ -1,5 +1,6 @@
 package com.pdaaphm.biz.factory;
 
+import com.pdaaphm.biz.domain.AlgorithmSubType;
 import com.pdaaphm.biz.service.RunAlgorithmService;
 import com.pdaaphm.biz.service.impl.RunMatlabImpl;
 import com.pdaaphm.biz.service.impl.RunPythonImpl;
@@ -14,9 +15,9 @@ public class AlgorithmFactory {
     private RunPythonImpl runPythonImpl;
 
     public RunAlgorithmService createRun(String type) {
-        if ("1".equals(type)) {
+        if (AlgorithmSubType.pythonCode.equals(type)) {
             return runPythonImpl;
-        } else if ("2".equals(type)) {
+        } else if (AlgorithmSubType.matlabCode.equals(type)) {
             return runMatlabImpl;
         } else {
             return null;

+ 8 - 1
pdaaphm-admin/src/main/java/com/pdaaphm/biz/mapper/AlgorithmIoFieldMapper.java

@@ -63,5 +63,12 @@ public interface AlgorithmIoFieldMapper
      */
     public int deleteAlgorithmIoFieldByIds(Long[] ids);
 
-    List<SubAlgorithmDTO> getIoSubList(@Param("subTypeId") Long subTypeId,@Param("algoId") Long algoId);
+    public List<SubAlgorithmDTO> getIoSubList(@Param("subTypeId") Long subTypeId,@Param("algoId") Long algoId);
+
+    /**
+     * 根据算法id查询MatlabIoPath,Type和Index,以构建matlab完整绝对路径
+     * @param id
+     * @return
+     */
+    public List<Map> selectMatlabIoPathTypeIndexByAlgoId(Long id);
 }

+ 3 - 2
pdaaphm-admin/src/main/java/com/pdaaphm/biz/service/impl/AlgorithmServiceImpl.java

@@ -7,6 +7,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
+import com.pdaaphm.biz.domain.AlgorithmIoField;
 import com.pdaaphm.biz.domain.AlgorithmSubType;
 import com.pdaaphm.biz.domain.SubAlgorithm;
 import com.pdaaphm.biz.dto.AlgorithmDTO;
@@ -169,7 +170,7 @@ public class AlgorithmServiceImpl implements IAlgorithmService
     @Override
     public List<Map> getOption() { return algorithmMapper.getOption(); }
 
-    @Async
+//    @Async
     @Override
     public void runAlgorithms(Long id) throws IOException {
         algorithmMapper.updateStatusById(id, Algorithm.runningCode);
@@ -188,7 +189,7 @@ public class AlgorithmServiceImpl implements IAlgorithmService
         String prefix2 = PadaphmConfig.getResultPath();
         int j = 1;
         for (int i = 0; i < list.size(); i++) {
-            if ("1".equals(list.get(i).get("type"))) {
+            if (AlgorithmIoField.inputCode.equals(list.get(i).get("type"))) {
                 String s = (String)list.get(i).get("path");
                 if (s.startsWith("/profile")) {
                     s = s.replace("/profile", prefix);

+ 175 - 3
pdaaphm-admin/src/main/java/com/pdaaphm/biz/service/impl/RunMatlabImpl.java

@@ -1,32 +1,203 @@
 package com.pdaaphm.biz.service.impl;
 
+import com.pdaaphm.biz.domain.AlgorithmIoField;
 import com.pdaaphm.biz.domain.BaseResponse;
+import com.pdaaphm.biz.domain.File;
+import com.pdaaphm.biz.domain.SubAlgorithm;
 import com.pdaaphm.biz.dto.RequestDTO;
+import com.pdaaphm.biz.mapper.AlgorithmIoFieldMapper;
+import com.pdaaphm.biz.mapper.FileMapper;
+import com.pdaaphm.biz.mapper.SubAlgorithmMapper;
 import com.pdaaphm.biz.service.RunAlgorithmService;
+import com.pdaaphm.common.config.PadaphmConfig;
+import com.pdaaphm.common.utils.DateUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.io.IOException;
-import java.util.List;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.util.*;
 import java.io.IOException;
 
 @Service
 public class RunMatlabImpl implements RunAlgorithmService {
+
+    @Autowired
+    private FileMapper fileMapper;
+
+    @Autowired
+    private SubAlgorithmMapper subAlgorithmMapper;
+
+    @Autowired
+    private AlgorithmIoFieldMapper algorithmIoFieldMapper;
+
+    private final Logger logger = LoggerFactory.getLogger(this.getClass());
+
     @Override
     public BaseResponse runAlgorithm(Long id, String url, RequestDTO requestDto) {
+
+        //初始化res
         BaseResponse res = new BaseResponse();
         res.setCode(200);
 
+        //把文件从inputPath文件系统copy到matlab要求的输入位置matlabInputPath,记录matlab的输出文件位置到matlabOutputPathList
+
+        List<String> doctList = requestDto.getDocList();
+        //docList的映射指针
+        int p = 0;
+        List<Map> matlabIoMapList = algorithmIoFieldMapper.selectMatlabIoPathTypeIndexByAlgoId(id);
+        List<String> matlabOutputPathList = new LinkedList<>();
+        for (Map matlabIoMap : matlabIoMapList) {
+            if (AlgorithmIoField.inputCode.equals(matlabIoMap.get("type"))) {
+                String matlabInputPathWithNoFileType = matlabIoMap.get("matlab_io_path") + "\\input" + matlabIoMap.get("index");
+                String inputPath = doctList.get(p);
+                p++;
+                int index = inputPath.lastIndexOf('.');
+                String extension = inputPath.substring(index + 1);
+                String matlabInputPath = matlabInputPathWithNoFileType + '.' + extension;
+                try {
+                    copyFile(inputPath, matlabInputPath);
+                } catch (IOException e) {
+                    throw new RuntimeException(e);
+                }
+            } else {
+                String matlabOutputPathWithNoFileType = matlabIoMap.get("matlab_io_path") + "\\output" + matlabIoMap.get("index");
+                matlabOutputPathList.add(matlabOutputPathWithNoFileType);
+            }
+        }
+
+        //run matlab exe
+//        runMatExe(url);
+
+        //将matlab输出的文件从matlabOutputPathList里copy到文件系统outputPath
+
+        List<String> resultList = requestDto.getResultList();
+        //resultList的映射指针
+        int q = 0;
+        for (String matlabOutputPath : matlabOutputPathList) {
+            int index = matlabOutputPath.lastIndexOf("\\");
+            String dir = matlabOutputPath.substring(0, index);
+            String prefixName = matlabOutputPath.substring(index + 1);
+            Map<String,String> map = getFinalNameAndPath(dir,prefixName);
+            String outputPath = map.get("path");
+            try {
+                copyFile(matlabOutputPath, outputPath);
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+            q++;
+        }
+
+
+        // save result path to subAlgorithm
+        List<Map> subAlgorithmOutputList = subAlgorithmMapper.selectSubAlgorithmOutputList(id);
+        if (resultList == null) {
+            return res.error("算法未配置输出");
+        }
+        for (int i = 0; i < resultList.size(); i++) {
+            String resultPath = resultList.get(i);
+            Map subAlgorithmOutput = subAlgorithmOutputList.get(i);
+            int lastIndex = resultPath.lastIndexOf("/");
+            String dirs = resultPath.substring(0, lastIndex);
+            String prefixName = resultPath.substring(lastIndex + 1);
+            Map<String, String> map = getFinalNameAndPath(dirs, prefixName);
+            if (map != null) {
+                String prefix = PadaphmConfig.getResultPath();
+                String s = map.get("path");
+                if (s.startsWith(prefix)) {
+                    s = s.replace(prefix, "/resultPath");
+                    map.put("path", s);
+                }
+                File resultFile = new File();
+                resultFile.setName(map.get("name"));
+                resultFile.setPath(map.get("path"));
+                resultFile.setType(File.ouputFlag);
+                resultFile.setCreateTime(DateUtils.getNowDate());
+                Long fileId = fileMapper.selectOutputFile(id);
+                if (fileId == null) {
+                    fileMapper.insertFile(resultFile);
+                } else {
+                    resultFile.setId(fileId);
+                    fileMapper.updateFile(resultFile);
+                }
+                SubAlgorithm subAlgorithm = new SubAlgorithm();
+                subAlgorithm.setId((Long) subAlgorithmOutput.get("id"));
+                subAlgorithm.setAlgorithmId((Long) subAlgorithmOutput.get("algorithm_id"));
+                subAlgorithm.setFieldId((Long) subAlgorithmOutput.get("field_id"));
+                subAlgorithm.setUploadId(resultFile.getId());
+                subAlgorithm.setCreateTime(DateUtils.getNowDate());
+                subAlgorithmMapper.updateSubAlgorithm(subAlgorithm);
+            } else {
+                logger.error("输出文件未生成!");
+                // todo 对程序结果产生负面影响的分子,应反馈给前端
+                // update algorithm
+            }
+        }
         return null;
     }
 
+    // todo return type is Map<String,String>
+    public Map getFinalNameAndPath(String dirs, String prefixName) {
+        // 指定目录路径
+        java.io.File directory = new java.io.File(dirs);
+
+        // 使用FilenameFilter筛选与已知文件名开头的文件
+        String[] matchingFiles = directory.list((dir, name) -> name.startsWith(prefixName));
+
+        Map<String, String> map = new HashMap<>();
+
+        if (matchingFiles != null && matchingFiles.length == 1) {
+            System.out.println("找到匹配的文件:");
+            map.put("name", matchingFiles[0]);
+            map.put("path", dirs + '/' + matchingFiles[0]);
+            return map;
+        } else if (matchingFiles != null && matchingFiles.length > 1) {
+            // todo 工程内禁止使用System.out.print 日志统一使用log
+            logger.error("找到多个匹配的文件,这不应该发生。");
+            return null;
+        } else {
+            // todo 工程内禁止使用System.out.print 日志统一使用log
+            logger.error("没有找到匹配的文件。");
+            return null;
+        }
+    }
+
+    /**
+     * copy file
+     */
+    public void copyFile(String sourcePathStr, String destinationPathStr) throws IOException {
+        Path sourcePath = Paths.get(sourcePathStr);
+        Path destinationPath = Paths.get(destinationPathStr);
+        Files.copy(sourcePath, destinationPath, StandardCopyOption.REPLACE_EXISTING);
+    }
 
     /**
      * this is a demo
      */
-    public static void main(String[] args) {
+    public void runMatExe(String url) {
+        try {
+            // 指定要执行的外部程序和参数
+            ProcessBuilder processBuilder = new ProcessBuilder(url);
+            // 启动外部程序
+            Process process = processBuilder.start();
+            // 等待外部程序执行完成
+            int exitCode = process.waitFor();
+            System.out.println("外部程序执行完成,退出码:" + exitCode);
+        } catch (IOException | InterruptedException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public static void main(String args[]) {
+        String url = "D:\\pdaaphm\\matlabexe\\GWO_SVM_exmp2.exe";
         try {
             // 指定要执行的外部程序和参数
-            ProcessBuilder processBuilder = new ProcessBuilder("C:\\soft\\Program Files (x86)\\Tencent\\WeDoc\\WeChat Files\\Allen_AL\\FileStorage\\File\\2023-08\\fuliye\\for_redistribution_files_only\\fuliye.exe");
+            ProcessBuilder processBuilder = new ProcessBuilder(url);
             // 启动外部程序
             Process process = processBuilder.start();
             // 等待外部程序执行完成
@@ -35,5 +206,6 @@ public class RunMatlabImpl implements RunAlgorithmService {
         } catch (IOException | InterruptedException e) {
             e.printStackTrace();
         }
+        return;
     }
 }

+ 2 - 0
pdaaphm-admin/src/main/resources/mapper/algoManager/AlgorithmMapper.xml

@@ -127,6 +127,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                 LEFT JOIN t_file tf ON tf.id = tsa.upload_id
         WHERE
             ta.id = #{id}
+        ORDER BY
+            taf.`index`
     </select>
 
     <update id="updateStartTimeById" parameterType="map">

+ 21 - 1
pdaaphm-admin/src/main/resources/mapper/conf/AlgorithmIoFieldMapper.xml

@@ -10,6 +10,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="type"    column="type"    />
         <result property="name"    column="name"    />
         <result property="index"    column="index"    />
+        <result property="matlabIoPath"    column="matlab_io_path"    />
         <result property="createBy"    column="create_by"    />
         <result property="createTime"    column="create_time"    />
         <result property="updateBy"    column="update_by"    />
@@ -19,7 +20,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </resultMap>
 
     <sql id="selectAlgorithmIoFieldVo">
-        select io.id, io.algorithm_sub_id, io.`type`, io.`name`, io.`index`, io.create_by, io.create_time, io.update_by, io.update_time, io.remark, sub.name as sub_name from t_algorithm_io_field as io left join t_algorithm_sub_type as sub on io.algorithm_sub_id = sub.id
+        select io.id, io.algorithm_sub_id, io.`type`, io.`name`, io.`index`,io.matlab_io_path ,io.create_by, io.create_time, io.update_by, io.update_time, io.remark, sub.name as sub_name from t_algorithm_io_field as io left join t_algorithm_sub_type as sub on io.algorithm_sub_id = sub.id
     </sql>
 
     <select id="selectAlgorithmIoFieldList" parameterType="AlgorithmIoField" resultMap="AlgorithmIoFieldResult">
@@ -29,6 +30,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="type != null  and type != ''"> and `type` = #{type}</if>
             <if test="name != null  and name != ''"> and `name` like concat('%', #{name}, '%')</if>
             <if test="index != null "> and `index` = #{index}</if>
+            <if test="matlabIoPath != null  and matlabIoPath != ''"> and matlab_io_path = #{matlabIoPath}</if>
         </where>
     </select>
 
@@ -44,6 +46,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="type != null">`type`,</if>
             <if test="name != null">`name`,</if>
             <if test="index != null">`index`,</if>
+            <if test="matlabIoPath != null">matlab_io_path,</if>
             <if test="createBy != null">create_by,</if>
             <if test="createTime != null">create_time,</if>
             <if test="updateBy != null">update_by,</if>
@@ -55,6 +58,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="type != null">#{type},</if>
             <if test="name != null">#{name},</if>
             <if test="index != null">#{index},</if>
+            <if test="matlabIoPath != null">#{matlabIoPath},</if>
             <if test="createBy != null">#{createBy},</if>
             <if test="createTime != null">#{createTime},</if>
             <if test="updateBy != null">#{updateBy},</if>
@@ -70,6 +74,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="type != null">`type` = #{type},</if>
             <if test="name != null">`name` = #{name},</if>
             <if test="index != null">`index` = #{index},</if>
+            <if test="matlabIoPath != null">matlab_io_path = #{matlabIoPath},</if>
             <if test="createBy != null">create_by = #{createBy},</if>
             <if test="createTime != null">create_time = #{createTime},</if>
             <if test="updateBy != null">update_by = #{updateBy},</if>
@@ -135,4 +140,19 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         WHERE
             io.algorithm_sub_id = #{subTypeId}
     </select>
+
+    <select id="selectMatlabIoPathTypeIndexByAlgoId" resultType="map">
+        SELECT
+            io.matlab_io_path,
+            io.type,
+            io.`index`
+        FROM
+            t_algorithm_io_field io
+                JOIN t_algorithm_sub_type ast ON ast.id = io.algorithm_sub_id
+                JOIN t_algorithm a ON a.sub_type_id = ast.id
+        WHERE
+            a.id = #{id}
+        ORDER BY
+            io.`index`
+    </select>
 </mapper>

+ 8 - 3
pdaaphm-ui/src/views/conf/field/index.vue

@@ -166,7 +166,10 @@
           <el-input v-model="form.name" placeholder="请输入名称" />
         </el-form-item>
         <el-form-item label="排序" prop="index">
-          <el-input v-model="form.index" placeholder="请输入排序" />
+          <el-input-number v-model="form.index" :min="1" :max="100" />
+        </el-form-item>
+        <el-form-item label="matlab文件路径" prop="matlabIoPath">
+          <el-input v-model="form.matlabIoPath" placeholder="请输入matlab文件路径" />
         </el-form-item>
         <el-form-item label="备注" prop="remark">
           <el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
@@ -217,7 +220,8 @@ export default {
         index: null,
       },
       // 表单参数
-      form: {},
+      form: { 
+      },
       // 表单校验
       rules: {
         algorithmSubId: [
@@ -259,7 +263,8 @@ export default {
         createTime: null,
         updateBy: null,
         updateTime: null,
-        remark: null
+        remark: null,
+        matlabIoPath: null,
       };
       this.resetForm("form");
     },

+ 16 - 5
pdaaphm-ui/src/views/conf/subType/index.vue

@@ -123,7 +123,7 @@
     <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
       <el-form ref="form" :model="form" :rules="rules" label-width="80px">
         <el-form-item label="类型" prop="type">
-          <el-select v-model="form.type" placeholder="请选择类型">
+          <el-select v-model="form.type" clearable placeholder="请选择类型">
             <el-option
               v-for="dict in dict.type.algorithm_type"
               :key="dict.value"
@@ -136,11 +136,23 @@
           <el-input v-model="form.name" placeholder="请输入算法子名称" />
         </el-form-item>
         <el-form-item label="算法url" prop="url">
-          <el-input v-model="form.url" placeholder="请输入算法url" />
+          <el-input v-model="form.url" placeholder="请输入算法url/matlab的exe路径" />
         </el-form-item>
         <el-form-item label="算法运行类型" prop="runType">
-          <el-input v-model="form.runType" placeholder="请输入算法运行类型" />
+          <el-select v-model="form.runType" clearable placeholder="请输入算法运行类型">
+            <el-option
+              v-for="dict in dict.type.run_type"
+                :key="dict.value"
+                :label="dict.label"
+                :value="dict.value"
+            ></el-option>
+          </el-select>
         </el-form-item>
+        <!-- <template v-if="form.runType == 2">
+          <el-form-item label="matlab文件路径" prop="matlabIoPath">
+            <el-input v-model="form.matlabIoPath" placeholder="请输入matlab文件路径" />
+          </el-form-item>
+        </template> -->
         <el-form-item label="备注" prop="remark">
           <el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
         </el-form-item>
@@ -158,7 +170,7 @@ import { listSubType, getSubType, delSubType, addSubType, updateSubType } from "
 
 export default {
   name: "SubType",
-  dicts: ['algorithm_type'],
+  dicts: ['algorithm_type','run_type'],
   data() {
     return {
       // 遮罩层
@@ -186,7 +198,6 @@ export default {
         type: null,
         name: null,
         url: null,
-        runType: null,
       },
       // 表单参数
       form: {},