albertshaw лет назад: 8
Родитель
Сommit
86f2debd65

Разница между файлами не показана из-за своего большого размера
+ 0 - 2
schema/2017-06-12.sql


+ 7 - 1
schema/2017-06-20.sql

@@ -3,4 +3,10 @@ alter TABLE `achievement`
   COMMENT '成熟度资料--图片URL';
   
 alter table `demand`
-modify column `picture_url` longtext null comment '需求文件--图片URL';
+modify column `picture_url` longtext null comment '需求文件--图片URL';
+
+CREATE TABLE `sys_dict` (
+  `id` varchar(36) NOT NULL,
+  `value` varchar(64) DEFAULT NULL,
+  PRIMARY KEY (`id`)
+);

Разница между файлами не показана из-за своего большого размера
+ 1 - 0
schema/html_fragment.sql


+ 1 - 0
schema/sys_dict.sql

@@ -0,0 +1 @@
+INSERT INTO `sys_dict` (`id`, `value`) VALUES ('government_loan_ror', '3.06');

+ 17 - 0
src/main/java/com/goafanti/common/dao/SysDictMapper.java

@@ -0,0 +1,17 @@
+package com.goafanti.common.dao;
+
+import com.goafanti.common.model.SysDict;
+
+public interface SysDictMapper {
+    int deleteByPrimaryKey(String id);
+
+    int insert(SysDict record);
+
+    int insertSelective(SysDict record);
+
+    SysDict selectByPrimaryKey(String id);
+
+    int updateByPrimaryKeySelective(SysDict record);
+
+    int updateByPrimaryKey(SysDict record);
+}

+ 58 - 0
src/main/java/com/goafanti/common/mapper/SysDictMapper.xml

@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.goafanti.common.dao.SysDictMapper">
+  <resultMap id="BaseResultMap" type="com.goafanti.common.model.SysDict">
+    <id column="id" jdbcType="VARCHAR" property="id" />
+    <result column="value" jdbcType="VARCHAR" property="value" />
+  </resultMap>
+  <sql id="Base_Column_List">
+    id, value
+  </sql>
+  <select id="selectByPrimaryKey" parameterType="java.lang.String" resultMap="BaseResultMap">
+    select 
+    <include refid="Base_Column_List" />
+    from sys_dict
+    where id = #{id,jdbcType=VARCHAR}
+  </select>
+  <delete id="deleteByPrimaryKey" parameterType="java.lang.String">
+    delete from sys_dict
+    where id = #{id,jdbcType=VARCHAR}
+  </delete>
+  <insert id="insert" parameterType="com.goafanti.common.model.SysDict">
+    insert into sys_dict (id, value)
+    values (#{id,jdbcType=VARCHAR}, #{value,jdbcType=VARCHAR})
+  </insert>
+  <insert id="insertSelective" parameterType="com.goafanti.common.model.SysDict">
+    insert into sys_dict
+    <trim prefix="(" suffix=")" suffixOverrides=",">
+      <if test="id != null">
+        id,
+      </if>
+      <if test="value != null">
+        value,
+      </if>
+    </trim>
+    <trim prefix="values (" suffix=")" suffixOverrides=",">
+      <if test="id != null">
+        #{id,jdbcType=VARCHAR},
+      </if>
+      <if test="value != null">
+        #{value,jdbcType=VARCHAR},
+      </if>
+    </trim>
+  </insert>
+  <update id="updateByPrimaryKeySelective" parameterType="com.goafanti.common.model.SysDict">
+    update sys_dict
+    <set>
+      <if test="value != null">
+        value = #{value,jdbcType=VARCHAR},
+      </if>
+    </set>
+    where id = #{id,jdbcType=VARCHAR}
+  </update>
+  <update id="updateByPrimaryKey" parameterType="com.goafanti.common.model.SysDict">
+    update sys_dict
+    set value = #{value,jdbcType=VARCHAR}
+    where id = #{id,jdbcType=VARCHAR}
+  </update>
+</mapper>

+ 23 - 0
src/main/java/com/goafanti/common/model/SysDict.java

@@ -0,0 +1,23 @@
+package com.goafanti.common.model;
+
+public class SysDict {
+    private String id;
+
+    private String value;
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(String value) {
+        this.value = value;
+    }
+}

+ 29 - 0
src/main/java/com/goafanti/common/service/SysDictService.java

@@ -0,0 +1,29 @@
+package com.goafanti.common.service;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.stereotype.Service;
+
+import com.goafanti.common.dao.SysDictMapper;
+import com.goafanti.common.utils.LoggerUtils;
+@Service
+public class SysDictService {
+	@Autowired
+	SysDictMapper		sysDictMapper;
+	
+	private static final Logger	logger	= LoggerFactory.getLogger(SysDictService.class);
+	
+	@Cacheable(value = "SysDictCache", key = "'SysDict:'+#id")
+	public String getValue(String id){
+		LoggerUtils.debug(logger, "缓存字典:[%s]", id);
+		return sysDictMapper.selectByPrimaryKey(id).getValue();
+	}
+	
+	@CacheEvict(value = "SysDictCache", key = "'SysDict:'+#id")
+	public void clear(String id) {
+		LoggerUtils.debug(logger, "清除字典缓存:[%s]", id);
+	}
+}

+ 10 - 10
src/main/java/com/goafanti/evaluation/bo/Step3.java

@@ -5,43 +5,43 @@ import javax.validation.constraints.NotNull;
 
 public class Step3 {
 	@NotNull
-	@Max(value = 7)
+	@Max(value = 6)
 	private Integer	progressiveness;
 	
 	@NotNull
-	@Max(value = 7)
+	@Max(value = 6)
 	private Integer	innovativeness;
 	
 	@NotNull
-	@Max(value = 7)
+	@Max(value = 6)
 	private Integer	ripeness;
 	
 	@NotNull
-	@Max(value = 7)
+	@Max(value = 6)
 	private Integer	alternatives;
 	
 	@NotNull
-	@Max(value = 7)
+	@Max(value = 6)
 	private Integer	defensive;
 	
 	@NotNull
-	@Max(value = 7)
+	@Max(value = 6)
 	private Integer	prospect;
 	
 	@NotNull
-	@Max(value = 7)
+	@Max(value = 6)
 	private Integer	supplyAndDemand;
 	
 	@NotNull
-	@Max(value = 7)
+	@Max(value = 6)
 	private Integer	rangeOfApplication;
 	
 	@NotNull
-	@Max(value = 7)
+	@Max(value = 6)
 	private Integer	imitable;
 	
 	@NotNull
-	@Max(value = 7)
+	@Max(value = 6)
 	private Integer	profitability;
 
 	public Integer getProgressiveness() {

+ 4 - 2
src/main/java/com/goafanti/evaluation/bo/Step6.java

@@ -1,10 +1,12 @@
 package com.goafanti.evaluation.bo;
 
+import javax.validation.constraints.Max;
 import javax.validation.constraints.NotNull;
 
 public class Step6 {
 	@NotNull
-	private Integer	taxRate;
+	@Max(value = 75)
+	private Integer taxRate;
 
 	public Integer getTaxRate() {
 		return taxRate;
@@ -13,5 +15,5 @@ public class Step6 {
 	public void setTaxRate(Integer taxRate) {
 		this.taxRate = taxRate;
 	}
-	
+
 }

+ 5 - 5
src/main/java/com/goafanti/evaluation/bo/Step7.java

@@ -5,23 +5,23 @@ import javax.validation.constraints.NotNull;
 
 public class Step7 {
 	@NotNull
-	@Max(value = 7)
+	@Max(value = 6)
 	private Integer	political;
 
 	@NotNull
-	@Max(value = 7)
+	@Max(value = 6)
 	private Integer	technical;
 
 	@NotNull
-	@Max(value = 7)
+	@Max(value = 6)
 	private Integer	market;
 
 	@NotNull
-	@Max(value = 7)
+	@Max(value = 6)
 	private Integer	capital;
 
 	@NotNull
-	@Max(value = 7)
+	@Max(value = 6)
 	private Integer	management;
 
 	public Integer getPolitical() {

+ 315 - 28
src/main/java/com/goafanti/evaluation/controller/EvaluationController.java

@@ -4,7 +4,11 @@ import java.math.BigDecimal;
 import java.math.MathContext;
 import java.math.RoundingMode;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import javax.validation.Valid;
 
@@ -24,11 +28,14 @@ import com.alibaba.fastjson.JSONObject;
 import com.goafanti.common.bo.Result;
 import com.goafanti.common.constant.ErrorConstants;
 import com.goafanti.common.controller.BaseApiController;
+import com.goafanti.common.model.DistrictGlossory;
 import com.goafanti.common.model.IndustryCategory;
 import com.goafanti.common.model.ValueEvaluation;
 import com.goafanti.common.service.IndustryCategoryService;
+import com.goafanti.common.service.SysDictService;
 import com.goafanti.common.utils.LoggerUtils;
 import com.goafanti.core.shiro.token.TokenManager;
+import com.goafanti.dataGlossory.service.DistrictGlossoryService;
 import com.goafanti.evaluation.bo.ForecastIncome;
 import com.goafanti.evaluation.bo.Step1;
 import com.goafanti.evaluation.bo.Step2;
@@ -38,6 +45,7 @@ import com.goafanti.evaluation.bo.Step5;
 import com.goafanti.evaluation.bo.Step6;
 import com.goafanti.evaluation.bo.Step7;
 import com.goafanti.evaluation.bo.YearIncome;
+import com.goafanti.evaluation.enums.ProfitRate;
 import com.goafanti.evaluation.service.ValueEvaluationService;
 
 @RestController
@@ -45,12 +53,30 @@ import com.goafanti.evaluation.service.ValueEvaluationService;
 public class EvaluationController extends BaseApiController {
 
 	private static final Logger			logger				= LoggerFactory.getLogger(EvaluationController.class);
-	private static final MathContext	DEFAULT_PRECISION	= new MathContext(3, RoundingMode.HALF_UP);
+	private static final MathContext	DEFAULT_PRECISION	= new MathContext(4, RoundingMode.HALF_UP);
+
+	private static final String			STEP1				= "0";
+	private static final String			STEP2				= "1";
+	private static final String			STEP3				= "2";
+	private static final String			STEP4				= "3";
+	private static final String			STEP5				= "4";
+	private static final String			STEP6				= "5";
+	private static final String			STEP7				= "6";
+	private static final Integer[]		SCORES				= new Integer[] { 100, 80, 60, 40, 20, 0 };
+	private static final Integer[]		DISCOUNT_SCORES		= new Integer[] { 1, 2, 3, 4, 5 };
+	private static final BigDecimal		MIN_RATE			= new BigDecimal(2);
+	private static final BigDecimal		MAX_RATE			= new BigDecimal(6);
+	private static final BigDecimal		HUNDRED				= new BigDecimal(100);
+	private static final BigDecimal		PERCENTAGE			= new BigDecimal(0.01, DEFAULT_PRECISION);
 
 	@Autowired
 	ValueEvaluationService				valueEvaluationService;
 	@Autowired
+	private DistrictGlossoryService		districtGlossoryService;
+	@Autowired
 	private IndustryCategoryService		industryCategoryService;
+	@Autowired
+	private SysDictService				sysDictService;
 
 	@RequestMapping(value = "/create", method = RequestMethod.GET)
 	public Result create() {
@@ -69,9 +95,16 @@ public class EvaluationController extends BaseApiController {
 	}
 
 	@RequestMapping(value = "/info/{id}", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
-	public String info(@PathVariable String id) {
+	public Result info(@PathVariable String id) {
 		Assert.isTrue(StringUtils.isNumeric(id), ErrorConstants.EVALUATE_ID);
-		return valueEvaluationService.getMyEvaluationSteps(Long.valueOf(id));
+		ValueEvaluation ve = valueEvaluationService.getMyEvaluation(Long.valueOf(id));
+		Assert.notNull(ve, ErrorConstants.EVALUATE_ID);
+		Map<String, Object> res = new HashMap<>();
+		res.put("name", ve.getName());
+		res.put("step", ve.getStep());
+		res.put("value", ve.getValue());
+		res.put("steps", JSON.parse(ve.getLog()));
+		return new Result().data(res);
 	}
 
 	@RequestMapping(value = "/remove", method = RequestMethod.POST)
@@ -106,7 +139,7 @@ public class EvaluationController extends BaseApiController {
 		if (handleBindingError(res, bindingResult)) {
 			return res;
 		}
-		updateSteps(data, 2, "1", res, id);
+		updateSteps(data, 2, STEP2, res, id);
 		return res;
 	}
 
@@ -117,7 +150,7 @@ public class EvaluationController extends BaseApiController {
 		if (handleBindingError(res, bindingResult)) {
 			return res;
 		}
-		updateSteps(data, 3, "2", res, id);
+		updateSteps(data, 3, STEP3, res, id);
 		return res;
 	}
 
@@ -140,7 +173,7 @@ public class EvaluationController extends BaseApiController {
 			res.error(buildError(ErrorConstants.EVALUATE_PARAM));
 		}
 		if (res.getError().isEmpty()) {
-			updateSteps(step, 4, "3", res, id);
+			updateSteps(step, 4, STEP4, res, id);
 		}
 		return res;
 	}
@@ -163,7 +196,7 @@ public class EvaluationController extends BaseApiController {
 			res.error(buildError(ErrorConstants.EVALUATE_PARAM));
 		}
 		if (res.getError().isEmpty()) {
-			updateSteps(step, 5, "4", res, id);
+			updateSteps(step, 5, STEP5, res, id);
 		}
 		return res;
 	}
@@ -172,13 +205,13 @@ public class EvaluationController extends BaseApiController {
 	public Result step5Info(@PathVariable String id) {
 		Assert.isTrue(StringUtils.isNumeric(id), ErrorConstants.EVALUATE_ID);
 		Result res = new Result();
-		ValueEvaluation ve = valueEvaluationService.getEvaluation(Long.valueOf(id));
+		ValueEvaluation ve = valueEvaluationService.getMyEvaluation(Long.valueOf(id));
 		try {
 			JSONObject jo = JSON.parseObject(ve.getLog());
-			Step4 step4 = ((JSON) jo.get("3")).toJavaObject(Step4.class);
+			Step4 step4 = ((JSON) jo.get(STEP4)).toJavaObject(Step4.class);
 			if (step4.getHasIncome().equals(2)) {
-				Step1 step1 = ((JSON) jo.get("0")).toJavaObject(Step1.class);
-				res.data(getPredicateIncome(step4.getIncomes(), getIndustryCategoryValue(step1)));
+				Step1 step1 = ((JSON) jo.get(STEP1)).toJavaObject(Step1.class);
+				res.data(calcForecastIncome(step4.getIncomes(), getIndustryCategoryValue(step1)));
 			}
 		} catch (Exception e) {
 			res.error(buildError(ErrorConstants.EVALUATE_PARAM));
@@ -193,7 +226,7 @@ public class EvaluationController extends BaseApiController {
 		if (handleBindingError(res, bindingResult)) {
 			return res;
 		}
-		updateSteps(data, 6, "5", res, id);
+		updateSteps(data, 6, STEP6, res, id);
 		return res;
 	}
 
@@ -204,12 +237,256 @@ public class EvaluationController extends BaseApiController {
 		if (handleBindingError(res, bindingResult)) {
 			return res;
 		}
-		updateSteps(data, 7, "6", res, id);
+		updateSteps(data, 7, STEP7, res, id);
 		return res;
 	}
 
+	@RequestMapping(value = "/calc/{id}", method = RequestMethod.GET)
+	public Result calc(@PathVariable String id) {
+		Assert.isTrue(StringUtils.isNumeric(id), ErrorConstants.EVALUATE_ID);
+		Result res = new Result();
+		ValueEvaluation ve = valueEvaluationService.getMyEvaluation(Long.valueOf(id));
+		if (ve == null || ve.getStep() < 7) {
+			res.error(buildError(ErrorConstants.EVALUATE_ID));
+		} else {
+			Long value = calcValue(ve, new HashMap<>());
+			res.data(value);
+			ValueEvaluation upt = new ValueEvaluation();
+			upt.setId(ve.getId());
+			upt.setValue(value);
+			valueEvaluationService.update(upt);
+		}
+		return res;
+	}
+
+	@RequestMapping(value = "/report/{id}", method = RequestMethod.GET)
+	public Result report(@PathVariable String id) {
+		Assert.isTrue(StringUtils.isNumeric(id), ErrorConstants.EVALUATE_ID);
+		Result res = new Result();
+		ValueEvaluation ve = valueEvaluationService.getMyEvaluation(Long.valueOf(id));
+		if (ve == null || ve.getStep() < 7) {
+			res.error(buildError(ErrorConstants.EVALUATE_ID));
+		} else {
+			Map<String, Object> map = new HashMap<>();
+			calcValue(ve, map);
+			res.data(map);
+		}
+		return res;
+	}
+
+	private Long calcValue(ValueEvaluation ve, Map<String, Object> result) {
+		JSONObject log = JSON.parseObject(ve.getLog());
+		Step1 step1 = ((JSON) log.get(STEP1)).toJavaObject(Step1.class);
+		Step2 step2 = ((JSON) log.get(STEP2)).toJavaObject(Step2.class);
+		Step3 step3 = ((JSON) log.get(STEP3)).toJavaObject(Step3.class);
+		Step5 step5 = ((JSON) log.get(STEP5)).toJavaObject(Step5.class);
+		Step6 step6 = ((JSON) log.get(STEP6)).toJavaObject(Step6.class);
+		Step7 step7 = ((JSON) log.get(STEP7)).toJavaObject(Step7.class);
+		Integer timeLeft = step1.getTimeLeft();
+		timeLeft = timeLeft < 3 ? 3 : timeLeft > 10 ? 10 : timeLeft; // 剩余经济寿命最低3,最大10年
+		Map<Integer, IndustryCategory> subs = getIndustryCates(step1.getIndustry());
+
+		Map<Integer, DistrictGlossory> provinces = getProvinces();
+
+		result.put("subIndustries", Stream.of(step1.getSubIndustry().split(",")).map(it -> {
+			return subs.get(Integer.valueOf(it)).getName();
+		}).collect(Collectors.joining(",")));
+
+		result.put("transferArea", Stream.of(step1.getTransferArea().split(",")).map(it -> {
+			return it.equals("0") ? "中国全境" : provinces.get(Integer.valueOf(it)).getName();
+		}).collect(Collectors.joining(",")));
+
+		result.put("industry", industryCategoryService.list(0).stream().filter(it -> {
+			return it.getId().equals(step1.getIndustry());
+		}).findFirst().get().getName());
+
+		BigDecimal industryAverageRate = getIndustryCategoryValue(step1, subs);
+		List<Long> userForecast = step5.getForecastIncomes().stream().map(fc -> {
+			return fc.getIncome();
+		}).collect(Collectors.toList());
+		List<Long> sysForecast = calcSysForecast(userForecast, industryAverageRate, timeLeft);
+		List<Long> measuredForecast = calcMeasuredForecast(userForecast, sysForecast);
+
+		Map<String, Integer> profitScores = getProfitScores(step2, step3);
+		Map<String, Integer> discountRates = getDiscountRates(step7);
+
+		BigDecimal profitRate = calcProfitRate(profitScores, step1.getIndustry());
+
+		BigDecimal governmentLoanRoR = new BigDecimal(sysDictService.getValue("government_loan_ror"),
+				MathContext.DECIMAL32);
+		BigDecimal taxRate = new BigDecimal(step6.getTaxRate());
+
+		BigDecimal discountRate = calcDiscountRate(discountRates, taxRate, governmentLoanRoR);
+
+		result.put("userForecast", userForecast);
+		result.put("sysForecast", sysForecast);
+		result.put("measuredForecast", measuredForecast);
+		result.put("profitRate", profitRate);
+		result.put("governmentLoanRoR", governmentLoanRoR);
+		result.put("industryAverageRate", industryAverageRate);
+		result.put("discountRate", discountRate);
+		result.put("benchmarkDate", step1.getBenchmarkDate());
+		result.put("timeLeft", timeLeft);
+		result.put("name", step1.getName());
+		Long value = calcTotal(measuredForecast, profitRate, discountRate, result);
+		result.put("value", value);
+		result.put("log", log);
+		return value;
+	}
+
+	private Long calcTotal(List<Long> measuredForecast, BigDecimal profitRate, BigDecimal discountRate,
+			Map<String, Object> result) {
+		List<Long> profitList = new ArrayList<>();
+		BigDecimal total = BigDecimal.ZERO;
+		BigDecimal incomeDiscount = BigDecimal.ZERO;
+		double discountTerm = 0.5;
+		int index = 0;
+		BigDecimal discountFactor = BigDecimal.ZERO;
+		for (Long val : measuredForecast) {
+			incomeDiscount = new BigDecimal(val).multiply(profitRate);
+			profitList.add(incomeDiscount.longValue());
+			discountFactor = BigDecimal.ONE.divide(BigDecimal.ONE.add(discountRate), 4, RoundingMode.FLOOR);
+			discountTerm += index;
+			double pow = Math.pow(discountFactor.doubleValue(), discountTerm);
+			total = total.add(incomeDiscount.multiply(new BigDecimal(pow)));
+			index++;
+		}
+		result.put("profitList", profitList); // 收入分成额
+		return total.longValue();
+	}
+
+	private BigDecimal calcDiscountRate(Map<String, Integer> discountRates, BigDecimal taxRate,
+			BigDecimal governmentLoanRoR) {
+		BigDecimal discountRate = new BigDecimal(discountRates.get("capital"))
+				.add(new BigDecimal(discountRates.get("management"))).add(new BigDecimal(discountRates.get("market")))
+				.add(new BigDecimal(discountRates.get("political")))
+				.add(new BigDecimal(discountRates.get("technical")));
+		discountRate = discountRate.add(governmentLoanRoR).divide(HUNDRED.subtract(taxRate), 4, RoundingMode.FLOOR);
+		double rate = discountRate.doubleValue();
+		rate = rate > 0.3 ? 0.3 : rate < 0.17 ? 0.17 : rate;
+		discountRate = new BigDecimal(rate, DEFAULT_PRECISION);
+		return discountRate;
+	}
+
+	private Map<String, Integer> getDiscountRates(Step7 step7) {
+		Map<String, Integer> profitScores = new HashMap<>();
+		profitScores.put("capital", getDiscountScore(step7.getCapital()));// 资金风险
+		profitScores.put("management", getDiscountScore(step7.getManagement()));// 管理风险
+		profitScores.put("market", getDiscountScore(step7.getMarket()));// 市场风险
+		profitScores.put("political", getDiscountScore(step7.getPolitical()));// 政策风险
+		profitScores.put("technical", getDiscountScore(step7.getTechnical()));// 技术风险
+		return profitScores;
+	}
+
+	private BigDecimal calcProfitRate(Map<String, Integer> profitScores, Integer industry) {
+		BigDecimal legalFactor = new BigDecimal(0.2, DEFAULT_PRECISION);
+		BigDecimal techFactor = new BigDecimal(0.6, DEFAULT_PRECISION);
+		BigDecimal fundFactor = legalFactor;
+
+		BigDecimal profitRate = new BigDecimal(profitScores.get("confidentiality")).multiply(legalFactor)
+				.multiply(new BigDecimal(0.4, DEFAULT_PRECISION));
+		profitRate = profitRate.add(new BigDecimal(profitScores.get("legalStatus")).multiply(legalFactor)
+				.multiply(new BigDecimal(0.3, DEFAULT_PRECISION)));
+		profitRate = profitRate.add(new BigDecimal(profitScores.get("decidability")).multiply(legalFactor)
+				.multiply(new BigDecimal(0.3, DEFAULT_PRECISION)));
+		profitRate = profitRate.add(new BigDecimal(profitScores.get("prospect")).multiply(techFactor)
+				.multiply(new BigDecimal(0.1, DEFAULT_PRECISION)));
+		profitRate = profitRate.add(new BigDecimal(profitScores.get("alternatives")).multiply(techFactor)
+				.multiply(new BigDecimal(0.2, DEFAULT_PRECISION)));
+		profitRate = profitRate.add(new BigDecimal(profitScores.get("progressiveness")).multiply(techFactor)
+				.multiply(new BigDecimal(0.2, DEFAULT_PRECISION)));
+		profitRate = profitRate.add(new BigDecimal(profitScores.get("innovativeness")).multiply(techFactor)
+				.multiply(new BigDecimal(0.1, DEFAULT_PRECISION)));
+		profitRate = profitRate.add(new BigDecimal(profitScores.get("ripeness")).multiply(techFactor)
+				.multiply(new BigDecimal(0.2, DEFAULT_PRECISION)));
+		profitRate = profitRate.add(new BigDecimal(profitScores.get("rangeOfApplication")).multiply(techFactor)
+				.multiply(new BigDecimal(0.1, DEFAULT_PRECISION)));
+		profitRate = profitRate.add(new BigDecimal(profitScores.get("defensive")).multiply(techFactor)
+				.multiply(new BigDecimal(0.1, DEFAULT_PRECISION)));
+		profitRate = profitRate.add(new BigDecimal(profitScores.get("supplyAndDemand")).multiply(fundFactor)
+				.multiply(new BigDecimal(0.6, DEFAULT_PRECISION)));
+		profitRate = profitRate.add(new BigDecimal(profitScores.get("profitability")).multiply(fundFactor)
+				.multiply(new BigDecimal(0.4, DEFAULT_PRECISION)));
+
+		BigDecimal minRate = MIN_RATE;
+		BigDecimal maxRate = MAX_RATE;
+		if (ProfitRate.containsType(industry)) {
+			ProfitRate pr = ProfitRate.getProfitRate(industry);
+			minRate = new BigDecimal(pr.getMinRate());
+			maxRate = new BigDecimal(pr.getMaxRate());
+		}
+
+		profitRate = maxRate.subtract(minRate).multiply(profitRate.multiply(PERCENTAGE)).add(minRate)
+				.multiply(PERCENTAGE).setScale(4, RoundingMode.FLOOR);
+
+		return profitRate;
+	}
+
+	private Map<String, Integer> getProfitScores(Step2 step2, Step3 step3) {
+		// 法律因素权重 20%
+		Map<String, Integer> profitScores = new HashMap<>();
+		profitScores.put("legalStatus", getScore(step2.getLegalStatus()));// 法律状态
+		profitScores.put("confidentiality", getScore(step2.getConfidentiality()));// 保密性
+		profitScores.put("decidability", getScore(step2.getDecidability()));// 侵权可判定性
+		// 技术因素权重 60%
+		profitScores.put("prospect", getScore(step3.getProspect()));// 领域前景
+		profitScores.put("alternatives", getScore(step3.getAlternatives()));// 可替代性
+		profitScores.put("progressiveness", getScore(step3.getProgressiveness()));// 先进性
+		profitScores.put("innovativeness", getScore(step3.getInnovativeness()));// 创新性
+		profitScores.put("ripeness", getScore(step3.getRipeness()));// 成熟度
+		profitScores.put("rangeOfApplication", getScore(step3.getRangeOfApplication()));// 应用范围
+		profitScores.put("defensive", getScore(step3.getDefensive()));// 应用范围
+		// 经济因素 20%
+		profitScores.put("supplyAndDemand", getScore(step3.getSupplyAndDemand()));// 供求关系
+		profitScores.put("profitability", getScore(step3.getProfitability()));// 独立获利能力
+
+		return profitScores;
+	}
+
+	private Integer getScore(int option) {
+		int idx = option - 1;
+		idx = idx < 0 ? 0 : idx >= SCORES.length ? SCORES.length - 1 : idx;
+		return SCORES[idx];
+	}
+
+	private Integer getDiscountScore(int option) {
+		int idx = option - 1;
+		idx = idx < 0 ? 0 : idx >= DISCOUNT_SCORES.length ? DISCOUNT_SCORES.length - 1 : idx;
+		return DISCOUNT_SCORES[idx];
+	}
+
+	private List<Long> calcSysForecast(List<Long> userForecast, BigDecimal industryAverageRate, Integer timeLeft) {
+		List<Long> sysForecast = new ArrayList<>();
+		BigDecimal rate = BigDecimal.ONE;
+		BigDecimal lastYear = BigDecimal.ZERO;
+		BigDecimal step = new BigDecimal(0.1, DEFAULT_PRECISION);
+		industryAverageRate = industryAverageRate.multiply(PERCENTAGE);
+		for (int i = 0; i < timeLeft; i++) {
+			if (i == 0) {
+				lastYear = new BigDecimal(userForecast.get(0)).multiply(new BigDecimal(0.9, DEFAULT_PRECISION));
+			} else if (i < 6) {
+				lastYear = lastYear.multiply(BigDecimal.ONE
+						.add(industryAverageRate.multiply(rate.subtract(step.multiply(new BigDecimal(i))))));
+			}
+			sysForecast.add(lastYear.longValue());
+		}
+		return sysForecast;
+	}
+
+	private List<Long> calcMeasuredForecast(List<Long> userForecast, List<Long> sysForecast) {
+		List<Long> measuredForecast = new ArrayList<>();
+		for (int i = 0; i < sysForecast.size(); i++) {
+			if (i < userForecast.size()) {
+				measuredForecast.add((userForecast.get(i) + sysForecast.get(i)) >> 1);
+			} else {
+				measuredForecast.add(sysForecast.get(i));
+			}
+		}
+		return measuredForecast;
+	}
+
 	private void updateSteps(Object step, Integer nextStep, String key, Result res, String id) {
-		ValueEvaluation ve = valueEvaluationService.getEvaluation(Long.valueOf(id));
+		ValueEvaluation ve = valueEvaluationService.getMyEvaluation(Long.valueOf(id));
 		Assert.notNull(ve, ErrorConstants.EVALUATE_ID);
 		ve.setStep(Math.max(nextStep, ve.getStep()));
 		if (nextStep == 1) {
@@ -233,25 +510,35 @@ public class EvaluationController extends BaseApiController {
 	}
 
 	private BigDecimal getIndustryCategoryValue(Step1 step1) {
-		List<IndustryCategory> cates = industryCategoryService.list(step1.getIndustry());
-		String[] subs = step1.getSubIndustry().split(",");
-		Integer[] subIds = new Integer[subs.length];
-		for (int i = 0; i < subs.length; i++) {
-			subIds[i] = Integer.valueOf(subs[i]);
-		}
+		return getIndustryCategoryValue(step1, getIndustryCates(step1.getIndustry()));
+	}
+
+	private Map<Integer, IndustryCategory> getIndustryCates(Integer pid) {
+		return industryCategoryService.list(pid).stream()
+				.collect(Collectors.toMap(IndustryCategory::getId, (it) -> it));
+	}
+
+	private Map<Integer, DistrictGlossory> getProvinces() {
+		return districtGlossoryService.list(0).stream().collect(Collectors.toMap(DistrictGlossory::getId, (it) -> it));
+	}
+
+	private BigDecimal getIndustryCategoryValue(Step1 step1, Map<Integer, IndustryCategory> cates) {
+		List<Integer> subIds = Stream.of(step1.getSubIndustry().split(",")).map(it -> {
+			return Integer.valueOf(it);
+		}).collect(Collectors.toList());
 		BigDecimal average = BigDecimal.ZERO;
-		for (IndustryCategory ic : cates) {
-			for (int i = 0; i < subIds.length; i++) {
-				if (ic.getId().equals(subIds[i])) {
-					average = average.add(ic.getValue());
-				}
+		int count = 0;
+		for (Integer id : subIds) {
+			if (cates.containsKey(id)) {
+				average = average.add(cates.get(id).getValue());
+				count++;
 			}
 		}
-		return average.divide(new BigDecimal(3), 2, RoundingMode.HALF_UP);
+		return average.divide(new BigDecimal(count == 0 ? 1 : count), 2, RoundingMode.HALF_UP);
 	}
 
-	private Long[] getPredicateIncome(List<YearIncome> incomes, BigDecimal growth) {
-		BigDecimal useGrowth = growth.divide(new BigDecimal(100), 2, RoundingMode.CEILING);
+	private Long[] calcForecastIncome(List<YearIncome> incomes, BigDecimal growth) {
+		BigDecimal useGrowth = growth.multiply(PERCENTAGE);
 		BigDecimal base = new BigDecimal(incomes.get(0).getIncome());
 		if (!incomes.get(1).getIncome().equals(0)) {
 			useGrowth = base.divide(new BigDecimal(incomes.get(1).getIncome()), 2, RoundingMode.CEILING)

+ 81 - 0
src/main/java/com/goafanti/evaluation/enums/ProfitRate.java

@@ -0,0 +1,81 @@
+package com.goafanti.evaluation.enums;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public enum ProfitRate {
+	CJ(1, "采掘", 2, 6),
+	HG(2, "化工", 2, 3.5),
+	GT(3, "钢铁", 2, 6),
+	JZCL(4, "建筑材料", 2, 6),
+	JZZS(5, "建筑装饰", 2, 6),
+	DQSB(6, "电气设备", 3, 4.5),
+	JXSB(7, "机械设备", 1.5, 3),
+	GFJG(8, "国防军工", 2, 6),
+	QC(9, "汽车", 2, 6),
+	JYDQ(10, "家用电器", 1, 2.5),
+	FZFZ(11, "纺织服装", 1, 2.5),
+	QGZZ(12, "轻工制造", 2, 6),
+	SYMY(13, "商业贸易", 1, 2.5),
+	NLMY(14, "农林牧渔", 2, 6),
+	SPYL(15, "食品饮料", 1, 2.5),
+	XXFW(16, "休闲服务", 1, 2.5),
+	YYSW(17, "医药生物", 2.5, 4),
+	GGSY(18, "公用事业", 2, 6),
+	JTYS(19, "交通运输", 2, 6),
+	FDC(20, "房地产", 2, 6),
+	DZ(21, "电子", 7, 10),
+	JSJ(22, "计算机", 4, 5.5),
+	CM(23, "传媒", 2, 6),
+	TX(24, "通信", 2, 6),
+	YH(25, "银行", 2, 6);
+
+	private Integer							id;
+	private String							desc;
+	private double							minRate;
+	private double							maxRate;
+
+	private static Map<Integer, ProfitRate>	map	= new HashMap<Integer, ProfitRate>();
+
+	private ProfitRate(Integer id, String desc, double minRate, double maxRate) {
+		this.id = id;
+		this.desc = desc;
+		this.minRate = minRate;
+		this.maxRate = maxRate;
+	}
+
+	static {
+		for (ProfitRate value : ProfitRate.values()) {
+			map.put(value.getId(), value);
+		}
+	}
+
+	public static ProfitRate getProfitRate(Integer code) {
+		return map.get(code);
+	}
+
+	public static String getFieldDesc(Integer code) {
+		return containsType(code) ? getProfitRate(code).getDesc() : "";
+	}
+
+	public static boolean containsType(Integer code) {
+		return map.containsKey(code);
+	}
+
+	public Integer getId() {
+		return id;
+	}
+
+	public String getDesc() {
+		return desc;
+	}
+
+	public double getMinRate() {
+		return minRate;
+	}
+
+	public double getMaxRate() {
+		return maxRate;
+	}
+
+}

+ 1 - 9
src/main/java/com/goafanti/evaluation/service/ValueEvaluationService.java

@@ -33,21 +33,13 @@ public class ValueEvaluationService extends BaseMybatisDao<ValueEvaluationMapper
 		return valueEvaluationMapper.updateByPrimaryKeySelective(ve);
 	}
 
-	public ValueEvaluation getEvaluation(Long id) {
+	public ValueEvaluation getMyEvaluation(Long id) {
 		Map<String, Object> params = new HashMap<>();
 		params.put("uid", TokenManager.getUserId());
 		params.put("id", id);
 		return valueEvaluationMapper.selectByPrimaryKeyAndUser(params);
 	}
 
-	public String getMyEvaluationSteps(Long id) {
-		Map<String, Object> params = new HashMap<>();
-		params.put("uid", TokenManager.getUserId());
-		params.put("id", id);
-		ValueEvaluation ve = valueEvaluationMapper.selectByPrimaryKeyAndUser(params);
-		return ve == null ? "{}" : ve.getLog();
-	}
-
 	public int deleteMySteps(List<Long> ids) {
 		Map<String, Object> params = new HashMap<>();
 		params.put("uid", TokenManager.getUserId());