unit u_timeseries; {$mode objfpc}{$H+} interface uses Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, Grids, ExtCtrls, TAGraph, TASeries, fpjson, u_norms, u_api; type { TTimeSeriesForm } TTimeSeriesForm = class(TForm) btnClose: TButton; cboCompetence: TComboBox; Label1: TLabel; StringGrid1: TStringGrid; Chart1: TChart; Splitter1: TSplitter; procedure btnCloseClick(Sender: TObject); procedure cboCompetenceChange(Sender: TObject); private FUserID: string; FSession: string; FProfiles: TJSONArray; FGroupName: string; FLineSeries: TLineSeries; FData: array of record ProfilID: string; Name: string; Values: array[1..6] of Integer; end; procedure LoadData; procedure UpdateGrid; procedure UpdateChart; public constructor Create(AOwner: TComponent; const UserID, Session: string; const GroupName: string; Profiles: TJSONArray); reintroduce; end; implementation {$R *.lfm} constructor TTimeSeriesForm.Create(AOwner: TComponent; const UserID, Session: string; const GroupName: string; Profiles: TJSONArray); var i: Integer; TopPanel: TPanel; begin inherited Create(AOwner); FUserID := UserID; FSession := Session; FGroupName := GroupName; FProfiles := Profiles; Caption := 'Zeitreihe - ' + GroupName; Width := 1000; Height := 700; Position := poScreenCenter; // Oberes Panel für ComboBox TopPanel := TPanel.Create(Self); TopPanel.Parent := Self; TopPanel.SetBounds(0, 0, 1000, 45); TopPanel.Align := alTop; TopPanel.Height := 45; TopPanel.BevelOuter := bvNone; // Label Label1 := TLabel.Create(TopPanel); Label1.Parent := TopPanel; Label1.SetBounds(12, 14, 66, 13); Label1.Caption := 'Kompetenz:'; // ComboBox cboCompetence := TComboBox.Create(TopPanel); cboCompetence.Parent := TopPanel; cboCompetence.SetBounds(90, 10, 250, 21); cboCompetence.Style := csDropDownList; cboCompetence.DropDownCount := 6; for i := 1 to 6 do cboCompetence.Items.Add(KOMPETENZEN[i]); cboCompetence.ItemIndex := 0; cboCompetence.OnChange := @cboCompetenceChange; // Chart Chart1 := TChart.Create(Self); Chart1.Parent := Self; Chart1.SetBounds(0, 45, 1000, 250); Chart1.Align := alTop; Chart1.Title.Text.Text := 'Zeitreihe - ' + GroupName; Chart1.LeftAxis.Title.Caption := 'Wert (1-5)'; Chart1.BottomAxis.Title.Caption := 'Profile (Nr.)'; FLineSeries := TLineSeries.Create(Chart1); FLineSeries.SeriesColor := clBlue; FLineSeries.LinePen.Width := 2; FLineSeries.ShowPoints := True; FLineSeries.Pointer.Brush.Color := clBlue; Chart1.AddSeries(FLineSeries); // Splitter Splitter1 := TSplitter.Create(Self); Splitter1.Parent := Self; Splitter1.SetBounds(0, 295, 1000, 5); Splitter1.Align := alTop; // StringGrid StringGrid1 := TStringGrid.Create(Self); StringGrid1.Parent := Self; StringGrid1.SetBounds(0, 300, 1000, 350); StringGrid1.Anchors := [akLeft, akTop, akRight, akBottom]; StringGrid1.FixedCols := 1; StringGrid1.FixedRows := 1; StringGrid1.Options := StringGrid1.Options + [goRowSelect]; StringGrid1.DefaultRowHeight := 22; StringGrid1.ColCount := 8; StringGrid1.ScrollBars := ssAutoBoth; // Spaltenbreiten StringGrid1.ColWidths[0] := 40; StringGrid1.ColWidths[1] := 180; for i := 2 to 7 do StringGrid1.ColWidths[i] := 90; // Kopfzeile StringGrid1.Cells[0, 0] := 'Nr.'; StringGrid1.Cells[1, 0] := 'Name'; StringGrid1.Cells[2, 0] := KOMPETENZEN[1]; StringGrid1.Cells[3, 0] := KOMPETENZEN[2]; StringGrid1.Cells[4, 0] := KOMPETENZEN[3]; StringGrid1.Cells[5, 0] := KOMPETENZEN[4]; StringGrid1.Cells[6, 0] := KOMPETENZEN[5]; StringGrid1.Cells[7, 0] := KOMPETENZEN[6]; // Button btnClose := TButton.Create(Self); btnClose.Parent := Self; btnClose.SetBounds(450, 660, 100, 30); btnClose.Caption := 'Schließen'; btnClose.OnClick := @btnCloseClick; // Daten laden LoadData; end; procedure TTimeSeriesForm.LoadData; var i, j, k: Integer; Profile: TJSONObject; Items: array[1..36] of Integer; Sums: array[1..6] of Integer; Values: array[1..6] of Integer; begin SetLength(FData, FProfiles.Count); for i := 0 to FProfiles.Count - 1 do begin Profile := TJSONObject(FProfiles.Objects[i]); FData[i].ProfilID := Profile.Get('profilID', ''); FData[i].Name := Profile.Get('name', ''); for j := 1 to 36 do Items[j] := Profile.Get('item' + IntToStr(j), 2); // Summen berechnen Sums[1] := 0; for j := 1 to 10 do Sums[1] := Sums[1] + Items[j]; Sums[2] := 0; for j := 11 to 20 do Sums[2] := Sums[2] + Items[j]; Sums[3] := 0; for j := 21 to 28 do Sums[3] := Sums[3] + Items[j]; Sums[3] := Sums[3] + Items[9] + Items[10]; Sums[4] := 0; for j := 29 to 36 do Sums[4] := Sums[4] + Items[j]; Sums[5] := Items[1] + Items[2] + Items[6] + Items[7] + Items[8] + Items[9] + Items[10] + Items[12] + Items[13] + Items[14] + Items[15]; Sums[6] := Items[3] + Items[4] + Items[5] + Items[9] + Items[10] + Items[11] + Items[17] + Items[18]; // Profilwerte (0-4) dann umwandeln in 1-5 for k := 1 to 6 do begin Values[k] := 4; for j := 1 to 5 do if Sums[k] < NORM_SE_HS[k, j] then begin Values[k] := j - 1; Break; end; end; for k := 1 to 6 do FData[i].Values[k] := Values[k] + 1; end; // Tabelle füllen StringGrid1.RowCount := Length(FData) + 1; for i := 0 to Length(FData) - 1 do begin StringGrid1.Cells[0, i + 1] := IntToStr(i + 1); StringGrid1.Cells[1, i + 1] := FData[i].Name; for k := 1 to 6 do StringGrid1.Cells[k + 1, i + 1] := IntToStr(FData[i].Values[k]); end; UpdateGrid; UpdateChart; end; procedure TTimeSeriesForm.UpdateGrid; var k: Integer; compIdx: Integer; begin compIdx := cboCompetence.ItemIndex + 1; // Kopfzeile aktualisieren (markierte Kompetenz) for k := 1 to 6 do begin if k = compIdx then StringGrid1.Cells[k + 1, 0] := '>>> ' + KOMPETENZEN[k] + ' <<<' else StringGrid1.Cells[k + 1, 0] := KOMPETENZEN[k]; end; StringGrid1.Refresh; end; procedure TTimeSeriesForm.UpdateChart; var i: Integer; compIdx: Integer; begin compIdx := cboCompetence.ItemIndex + 1; FLineSeries.Clear; for i := 0 to Length(FData) - 1 do FLineSeries.AddXY(i + 1, FData[i].Values[compIdx]); Chart1.Invalidate; end; procedure TTimeSeriesForm.cboCompetenceChange(Sender: TObject); begin UpdateGrid; UpdateChart; end; procedure TTimeSeriesForm.btnCloseClick(Sender: TObject); begin Close; end; end.