LazStats: Fix crash due to range check error in DescriptiveUnit

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7749 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2020-10-05 21:00:45 +00:00
parent d16c17ff86
commit 2d3368e257
2 changed files with 20 additions and 28 deletions

View File

@ -49,13 +49,7 @@
<DebugInfoType Value="dsDwarf2Set"/> <DebugInfoType Value="dsDwarf2Set"/>
<UseHeaptrc Value="True"/> <UseHeaptrc Value="True"/>
<TrashVariables Value="True"/> <TrashVariables Value="True"/>
<UseExternalDbgSyms Value="True"/>
</Debugging> </Debugging>
<Options>
<Win32>
<GraphicApplication Value="True"/>
</Win32>
</Options>
</Linking> </Linking>
</CompilerOptions> </CompilerOptions>
</Item2> </Item2>

View File

@ -95,7 +95,7 @@ type
private private
function GetReportFrame(APageIndex: Integer): TReportFrame; function GetReportFrame(APageIndex: Integer): TReportFrame;
procedure WriteToReport(Stats: TDescriptiveStats; AVarName: String; AReport: TStrings); procedure WriteToReport(Stats: TDescriptiveStats; AVarName: String; AReport: TStrings);
procedure zScoresToGrid(AColIndex: Integer; const AColsSelected: IntDyneVec; procedure zScoresToGrid(AColIndex: Integer; var AColsSelected: IntDyneVec;
AMean, AStdDev: Double); AMean, AStdDev: Double);
protected protected
@ -380,35 +380,30 @@ end;
procedure TDescriptiveFrm.Compute; procedure TDescriptiveFrm.Compute;
var var
cellString: String;
i, j: Integer; i, j: Integer;
noSelected: Integer; nSelected: Integer;
selected: IntDyneVec = nil; selected: IntDyneVec = nil;
page: TTabSheet; page: TTabSheet;
reportFrame: TReportFrame; reportFrame: TReportFrame;
lReport: TStrings; lReport: TStrings;
lStats: TDescriptiveStats; lStats: TDescriptiveStats;
begin begin
noSelected := SelList.Items.Count; nSelected := SelList.Items.Count;
if noSelected = 0 then if nSelected = 0 then
begin begin
MessageDlg('No variables selected.', mtError, [mbOK], 0); MessageDlg('No variables selected.', mtError, [mbOK], 0);
exit; exit;
end; end;
SetLength(selected, noSelected); SetLength(selected, nSelected);
// Find column index of selected variables // Find column index of selected variables
for i := 0 to noSelected - 1 do for i := 0 to nSelected - 1 do
begin selected[i] := OS3MainFrm.DataGrid.Rows[0].IndexOf(SelList.Items[i]);
cellstring := SelList.Items[i];
for j := 1 to NoVariables do
if cellstring = OS3MainFrm.DataGrid.Cells[j,0] then selected[i] := j;
end;
// Create a tabsheet with ReportFrame for each selected variable (in addition to the built-in one) // Create a tabsheet with ReportFrame for each selected variable (in addition to the built-in one)
if noSelected > PageControl.PageCount then if nSelected > PageControl.PageCount then
begin begin
for i := 1 to noSelected-1 do // we do not create a tab for the first variable - it exists by default for i := 1 to nSelected-1 do // we do not create a tab for the first variable - it exists by default
begin begin
page := TTabSheet.Create(PageControl); page := TTabSheet.Create(PageControl);
page.Parent := PageControl; page.Parent := PageControl;
@ -420,27 +415,28 @@ begin
end; end;
// Remove excess pages from previous session // Remove excess pages from previous session
while PageControl.PageCount > noSelected do while PageControl.PageCount > nSelected do
PageControl.Pages[PageControl.PageCount-1].Free; PageControl.Pages[PageControl.PageCount-1].Free;
// Every tab gets the name of the corresponding variable. // Every tab gets the name of the corresponding variable.
for i := 0 to NoSelected-1 do for i := 0 to nSelected-1 do
PageControl.Pages[i].Caption := OS3MainFrm.DataGrid.Cells[selected[i], 0]; PageControl.Pages[i].Caption := OS3MainFrm.DataGrid.Cells[selected[i], 0];
// // Write report
lReport := TStringList.Create; lReport := TStringList.Create;
if not CaseChk.Checked then if not CaseChk.Checked then
lStats := TDescriptiveStats.Create(OS3MainFrm.DataGrid) lStats := TDescriptiveStats.Create(OS3MainFrm.DataGrid)
else else
lStats := TDescriptiveStats.Create(OS3MainFrm.DataGrid, selected); lStats := TDescriptiveStats.Create(OS3MainFrm.DataGrid, selected);
try try
for i := 0 to noSelected-1 do for i := 0 to nSelected-1 do
begin begin
// Analyze the data and get descriptive stats // Analyze the data and get descriptive stats
lStats.Analyze(selected[i]); lStats.Analyze(selected[i]);
// Store z values, (value - mean) / stdDev, to grid, if needed // Store z values, (value - mean) / stdDev, to grid, if needed
zScoresToGrid(selected[i], selected, lStats.Mean, lStats.StdDev); if zScoresToGridChk.Checked then
zScoresToGrid(selected[i], selected, lStats.Mean, lStats.StdDev);
// Write descriptive stats to report // Write descriptive stats to report
WriteToReport(lStats, trim(OS3MainFrm.DataGrid.Cells[selected[i], 0]), lReport); WriteToReport(lStats, trim(OS3MainFrm.DataGrid.Cells[selected[i], 0]), lReport);
@ -700,7 +696,7 @@ end;
procedure TDescriptiveFrm.zScoresToGrid(AColIndex: Integer; procedure TDescriptiveFrm.zScoresToGrid(AColIndex: Integer;
const AColsSelected: IntDyneVec; AMean, AStdDev: Double); var AColsSelected: IntDyneVec; AMean, AStdDev: Double);
var var
i, idx: Integer; i, idx: Integer;
value, zValue: Double; value, zValue: Double;
@ -725,10 +721,12 @@ begin
begin begin
if CaseChk.Checked then if CaseChk.Checked then
begin begin
if not DataProcs.ValidValue(i, AColsSelected[AColIndex]) then continue; if not DataProcs.GoodRecord(i, Length(AColsSelected), AColsSelected) then continue;
end end
else else
if not DataProcs.GoodRecord(i, Length(AColsSelected), AColsSelected) then continue; begin
if not DataProcs.ValidValue(i, AColIndex) then continue;
end;
value := StrToFloat(OS3MainFrm.DataGrid.Cells[AColIndex, i]); value := StrToFloat(OS3MainFrm.DataGrid.Cells[AColIndex, i]);
zValue := (value - AMean) / AStdDev; zValue := (value - AMean) / AStdDev;