/** * Created by Tony on 2017/6/21. */ let executeObj = { calculation : null, ration: null, feeRate: null, at: function(ID) { let me = executeObj, rst = 0; rst = me.calculation.compileAssistantObj[ID].unitFee; rst = parseFloat(rst); return rst; }, base: function(calcBaseName) { let me = executeObj, rst = 0, base = getRationCalcBase(calcBaseName); if (base != null) { let price = 0, tmpSum = 0; for (let glj of me.ration.data.gljList) { if (base.gljTypes.indexOf(glj.type) >= 0) { if (base.calcType == baseCalc){ price = glj["basePrice"];} else if (base.calcType == adjustCalc){price = glj["adjustPrice"];} else if (base.calcType == budgetCalc){price = glj["marketPrice"];} else if (base.calcType == diffCalc){price = glj["marketPrice"] - glj["adjustPrice"];}; }; tmpSum = tmpSum + glj["quantity"] * price; glj = null; }; rst = tmpSum; }; return rst; }, fee: function(feeID) { let me = executeObj, rst = 0; if (me.compiledFeeRateFile["fee_" + feeID]) rst = me.compiledFeeRateFile["fee_" + feeID].rate; return rst; }, factor: function(factorCode) { let me = executeObj; let rst = 0.89; //暂时固定输出,测试用 return rst; } }; class Calculation { init(calcTemplate, feeRate){ let me = this; me.calcTemplate = calcTemplate; me.feeRate = feeRate; me.hasCompiled = false; }; compile(){ let me = this; me.hasCompiled = false; me.errs = []; let private_extract_ID = function(str, idx){ let rst = '', lBracket = 0, rBracket = 0, firstIdx = idx, lastIdx = 0; for (let i = idx; i < str.length; i++) { if (str[i] === '(') { lBracket++; if (lBracket == 1) firstIdx = i + 1; } if (str[i] === ')') { rBracket++; if (lBracket == rBracket) { lastIdx = i - 1; if (lastIdx > firstIdx) { if (str[firstIdx] === "'") firstIdx++; if (str[lastIdx] !== "'") lastIdx++; if (lastIdx > firstIdx) { rst = str.slice(firstIdx, lastIdx); } } break; } } } return rst; }; let private_parse_ref = function(item, itemIdx){ let idx = item.expression.indexOf('@(', 0); while (idx >= 0) { let ID = private_extract_ID(item.expression, idx); if (ID.length > 0) { let subItem = me.compileAssistantObj[ID]; if (subItem) { if (subItem.ID !== item.ID) { private_parse_ref(subItem, me.compileAssistantObj[ID + "_idx"]); } else { me.errs.push("There exists the self refer ID: " + ID); } } else { me.errs.push("There exists the invalid ID by which could not find the item: " + ID); console.log('invalid ID: ' + ID); } } idx = item.expression.indexOf('@(', idx + ID.length + 3); } if (me.calcTemplate.compiledSeq.indexOf(itemIdx) < 0) { me.calcTemplate.compiledSeq.push(itemIdx); } }; let private_setup_seq = function(item, itemIdx){ if (me.calcTemplate.compiledSeq.indexOf(itemIdx) < 0) { private_parse_ref(item, itemIdx); } }; let private_compile_items = function() { for (let idx of me.calcTemplate.compiledSeq) { let item = me.calcTemplate.calcItems[idx]; item.compiledExpr = item.expression.split('@(').join('$CE.at('); item.compiledExpr = item.compiledExpr.split('base(').join('$CE.base('); item.compiledExpr = item.compiledExpr.split('fee(').join('$CE.fee('); item.compiledExpr = item.compiledExpr.split('factor(').join('$CE.factor('); } }; let private_comile_feeFile = function() { if (me.feeRate) { me.compiledFee = {}; for (let fee of me.feeRate) { me.compiledFee["fee_" + fee.ID] = fee; } } }; if (me.calcTemplate && me.calcTemplate.calcItems && me.calcTemplate.calcItems.length > 0) { me.calcTemplate.compiledSeq = []; me.compileAssistantObj = {}; //1. first round -> prepare private_comile_feeFile(); for (let i = 0; i < me.calcTemplate.calcItems.length; i++) { let item = me.calcTemplate.calcItems[i]; me.compileAssistantObj[item.ID] = item; me.compileAssistantObj[item.ID + "_idx"] = i; } //2. second round -> go! for (let i = 0; i < me.calcTemplate.calcItems.length; i++) { private_setup_seq(me.calcTemplate.calcItems[i], i); } if (me.errs.length == 0) { private_compile_items(); if (me.errs.length == 0) me.hasCompiled = true; } else { console.log('errors: ' + me.errs.toString()); } } }; calculate($RATION){ // 参数$RATION也可以是清单 let me = this; if ($RATION && me.hasCompiled) { let $CE = executeObj; $CE.ration = $RATION; $CE.calculation = me; $CE.feeRate = me.feeRate; $CE.compiledFeeRateFile = me.compiledFee; if (!$RATION.fees) { $RATION.fees = []; $RATION.feesIndex = {}; }; for (let idx of me.calcTemplate.compiledSeq) { let calcItem = me.calcTemplate.calcItems[idx]; // 这两项用于界面显示。 calcItem.unitFee = eval(calcItem.compiledExpr); // AAAAA 如果eval()对清单树有影响,就换成小麦的Expression对象再试 calcItem.totalFee = calcItem.unitFee * 3; // AAAAA 测试值,因目前定额无数量(保存不上) $RATION.data.Quantity // 费用同步到定额 // 引入小麦的字段检测后,快速切换定额出现计算卡顿现象,过多的循环造成。这里把她的代码拆出来,减少微循环。 if (!$RATION.feesIndex[calcItem.type]){ calcFees.addFee($RATION, calcItem.type); }; $RATION.feesIndex[calcItem.type].unitFee = calcItem.unitFee; $RATION.feesIndex[calcItem.type].totalFee = calcItem.totalFee; } } } } //module.exports = new calculation();