123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- unit FormulaCalc;
- interface
- uses
- sdIDTree, ZhAPI, Math;
- const
- ArithmeticCharSet: set of Char = ['0'..'9', '.', '(','[','{', ')',']','}', '+','-','*','/','^', '%', '='];
- ExprsBaseCharSet: set of Char = ['h', 't', 'j', 'b', 'q', 'w', 'c', 'k', 'g', 'y', 'f', 'l'];
- ExprsExceptCharSet: set of Char = ['h', 't', 'j', 'k', 'g', 'y', 'f', 'c', 'l'];
- type
- TOnGetValueEvent = function (const ACardinalNum: string): Double of object;
- TFormulaCalc = class
- private
- FTree: TsdIDTree;
- FDisplayText: string;
- FRecordText: string;
- FIndexRange: Integer;
- FOnGetValue: TOnGetValueEvent;
- FPhaseIndex: Integer;
- function GetIndexID(AKeyID: Integer): Integer;
- function GetKeyID(AIndexID: Integer): Integer;
- procedure ResetDisplayText;
- procedure ResetRecordText;
- function GetCalcText: string;
- function GetValue: Double;
- function DoOnGetValue(const ACardinalNum: string): Double;
- procedure SetIndexRange(ANodeID: Integer);
- public
- constructor Create(ATree: TsdIDTree);
- destructor Destroy; override;
- property DisplayText: string read FDisplayText;
- property RecordText: string read FRecordText;
- property Value: Double read GetValue;
- procedure SetDisplayText(const AText: string; AIndexRange: Integer);
- procedure SetRecordText(const AText: string);
- property PhaseIndex: Integer read FPhaseIndex write FPhaseIndex;
- property OnGetValue: TOnGetValueEvent read FOnGetValue write FOnGetValue;
- end;
- TPayFormula = class
- private
- FProjectData: TObject;
- FDisplayText: string;
- FStartedPrice: Double;
- // 签约合同价
- function ContractPrice: Double;
- // 开工预付款
- function StartedSubsist: Double;
- // 材料预付款
- function MaterialSubsist: Double;
- // 本期本阶段结算价
- function StageSettlement: Double;
- // 100/200/.../900章本期完成计量
- function ChapterStageGather(AChapter: Integer): Double;
- function GetCalcText: string;
- function GetValue: Double;
- public
- constructor Create(AProjectData: TObject);
- destructor Destroy; override;
- function Calculate(const ADisplayText: string; AStartedPrice: Double = 0): Double;
- end;
- implementation
- uses
- SysUtils, ProjectData, PhaseData, UtilMethods;
- { TFormulaCalc }
- constructor TFormulaCalc.Create(ATree: TsdIDTree);
- begin
- FTree := ATree;
- end;
- destructor TFormulaCalc.Destroy;
- begin
- inherited;
- end;
- function TFormulaCalc.DoOnGetValue(const ACardinalNum: string): Double;
- begin
- Result := 0;
- if Assigned(FOnGetValue) then
- Result := FOnGetValue(ACardinalNum);
- end;
- function TFormulaCalc.GetCalcText: string;
- var
- iPos, iCharIndex: Integer;
- sNode: string;
- begin
- Result := FRecordText;
- iPos := Pos('@', Result);
- while iPos > 0 do
- begin
- sNode:= '';
- for iCharIndex := iPos + 1 to Length(Result) do
- begin
- if Result[iCharIndex] in ['0'..'9', 'a'..'d', 'A'..'D'] then
- sNode := sNode + Result[iCharIndex]
- else
- Break;
- end;
- Result := StringReplace(Result, '@'+sNode, FloatToStr(DoOnGetValue(sNode)), [rfReplaceAll, rfIgnoreCase]);
- iPos := Pos('@', Result);
- end;
- end;
- function TFormulaCalc.GetIndexID(AKeyID: Integer): Integer;
- begin
- with FTree do
- Result := IndexOf(FindNode(AKeyID));
- end;
- function TFormulaCalc.GetKeyID(AIndexID: Integer): Integer;
- begin
- if AIndexID > -1 then
- Result := FTree.Items[AIndexID].ID
- else
- Result := -1;
- end;
- function TFormulaCalc.GetValue: Double;
- begin
- Result := EvaluateExprs(GetCalcText);
- end;
- procedure TFormulaCalc.ResetDisplayText;
- var
- iCharIndex, iLength: Integer;
- sChar, sID, sFormula: string;
- begin
- iCharIndex := 1;
- iLength := Length(FRecordText);
- sFormula := '';
- while iCharIndex <= iLength do
- begin
- if FRecordText[iCharIndex] = '@' then
- begin
- Inc(iCharIndex);
- if FRecordText[iCharIndex] in ['A'..'D', 'a'..'d'] then
- begin
- sChar := FRecordText[iCharIndex];
- Inc(iCharIndex);
- sID := '';
- while (FRecordText[iCharIndex] in ['0'..'9']) and (iCharIndex <= iLength) do
- begin
- sID := sID + FRecordText[iCharIndex];
- Inc(iCharIndex);
- end;
- if GetIndexID(StrToIntDef(sID, -1)) > -1 then
- sFormula := sFormula + sChar + IntToStr(GetIndexID(StrToIntDef(sID, -1)) + 1);
- end;
- end
- else if FRecordText[iCharIndex] in ['0'..'9', '.', '(','[','{', ')',']','}', '+','-','*','/','^', '%', '='] then
- begin
- sFormula := sFormula + FRecordText[iCharIndex];
- Inc(iCharIndex);
- end;
- end;
- FDisplayText := sFormula;
- end;
- procedure TFormulaCalc.ResetRecordText;
- var
- iCharIndex, iLength: Integer;
- sChar, sID, sFormula: string;
- begin
- iCharIndex := 1;
- iLength := Length(FDisplayText);
- sFormula := '';
- while iCharIndex <= iLength do
- begin
- if FDisplayText[iCharIndex] in ['A'..'D', 'a'..'d'] then
- begin
- sChar := FDisplayText[iCharIndex];
- Inc(iCharIndex);
- sID := '';
- while FDisplayText[iCharIndex] in ['0'..'9'] do
- begin
- sID := sID + FDisplayText[iCharIndex];
- Inc(iCharIndex);
- end;
- if FDisplayText[iCharIndex] in ['.', '%'] then
- Raise Exception.Create('表达式非法' + FDisplayText + '!')
- else if StrToIntDef(sID, -1) > FIndexRange then
- Raise Exception.Create('表达式仅可以引用前项清单!')
- else if GetKeyID(StrToIntDef(sID, -1) - 1) = -1 then
- Raise Exception.Create('表达式非法' + FDisplayText + '!')
- else
- sFormula := sFormula + '@' + sChar + IntToStr(GetKeyID(StrToIntDef(sID, -1) - 1));
- end
- else if FDisplayText[iCharIndex] in ['0'..'9', '.', '(','[','{', ')',']','}', '+','-','*','/','^', '%', '='] then
- begin
- sFormula := sFormula + FDisplayText[iCharIndex];
- Inc(iCharIndex);
- end;
- end;
- FRecordText := sFormula
- end;
- procedure TFormulaCalc.SetDisplayText(const AText: string; AIndexRange: Integer);
- begin
- SetIndexRange(AIndexRange);
- FDisplayText := AText;
- FRecordText := '';
- ResetRecordText;
- end;
- procedure TFormulaCalc.SetIndexRange(ANodeID: Integer);
- var
- stnNode: TsdIDTreeNode;
- begin
- stnNode := FTree.FindNode(ANodeID);
- while Assigned(stnNode.Parent) do
- stnNode := stnNode.Parent;
- FIndexRange := FTree.IndexOf(stnNode);
- end;
- procedure TFormulaCalc.SetRecordText(const AText: string);
- begin
- FRecordText := AText;
- FDisplayText := '';
- ResetDisplayText;
- end;
- { TPayFormula }
- function TPayFormula.Calculate(const ADisplayText: string; AStartedPrice: Double = 0): Double;
- begin
- FDisplayText := ADisplayText;
- FStartedPrice := AStartedPrice;
- Result := GetValue;
- end;
- function TPayFormula.ChapterStageGather(AChapter: Integer): Double;
- begin
- with TProjectData(FProjectData).PhaseData do
- if Active then
- Result := StageData.ChapterStageGather[AChapter]
- else
- Result := 0;
- end;
- function TPayFormula.ContractPrice: Double;
- begin
- Result := TProjectData(FProjectData).ProjProperties.ContractPrice;
- end;
- constructor TPayFormula.Create(AProjectData: TObject);
- begin
- FProjectData := AProjectData;
- end;
- destructor TPayFormula.Destroy;
- begin
- inherited;
- end;
- function TPayFormula.GetCalcText: string;
- begin
- Result := StringReplace(FDisplayText, 'htj', FloatToStr(ContractPrice), [rfReplaceAll, rfIgnoreCase]);
- Result := StringReplace(Result, 'kgyfk', FloatToStr(StartedSubsist), [rfReplaceAll, rfIgnoreCase]);
- Result := StringReplace(Result, 'clyfk', FloatToStr(MaterialSubsist), [rfReplaceAll, rfIgnoreCase]);
- Result := StringReplace(Result, 'ybbqwc', FloatToStr(ChapterStageGather(1)), [rfReplaceAll, rfIgnoreCase]);
- Result := StringReplace(Result, 'bqwc', FloatToStr(StageSettlement), [rfReplaceAll, rfIgnoreCase]);
- end;
- function TPayFormula.GetValue: Double;
- begin
- Result := TotalPriceRoundTo(EvaluateExprs(GetCalcText));
- end;
- function TPayFormula.MaterialSubsist: Double;
- begin
- Result := TProjectData(FProjectData).ProjProperties.MaterialSubsist;
- end;
- function TPayFormula.StageSettlement: Double;
- begin
- with TProjectData(FProjectData).PhaseData do
- if Active then
- begin
- // 初次达到起扣金额时,bqwc计数值,取累计完成计量-起扣金额
- if FStartedPrice = 0 then
- Result := StageData.StageSettlement[1, 4]
- else
- Result := StageData.StageSettlement[2, 4] - FStartedPrice;
- end
- else
- Result := 0;
- end;
- function TPayFormula.StartedSubsist: Double;
- begin
- Result := TProjectData(FProjectData).ProjProperties.StartedSubsisit;
- end;
- end.
|