unit ChainF;
//*******************************************************
// Example program demonstrating a hash table with
// chaining.
//*******************************************************
// Copyright (C) 1998 John Wiley & Sons, Inc.
// All rights reserved. See additional copyright
// information in Readme.txt.
//*******************************************************

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Menus, StdCtrls,
  ChainC;

type
  TChainForm = class(TForm)
    Frame2: TGroupBox;
    Label1_0: TLabel;
    NewItemText: TEdit;
    CmdAdd: TButton;
    CmdFind: TButton;
    Frame3: TGroupBox;
    Label1_6: TLabel;
    Label1_2: TLabel;
    NumItemsText: TEdit;
    MaxValueText: TEdit;
    CmdCreateItems: TButton;
    Frame1: TGroupBox;
    Label1_3: TLabel;
    SortListsCheck: TCheckBox;
    CmdCreateTable: TButton;
    TableSizeText: TEdit;
    StatusLabel: TLabel;
    MainMenu1: TMainMenu;
    mnuFile: TMenuItem;
    mnuFileExit: TMenuItem;
    mnuHelp: TMenuItem;
    mnuHelpAbout: TMenuItem;
    TableScrollBox: TScrollBox;
    TableLabel: TLabel;
    CmdRemove: TButton;
    procedure FormCreate(Sender: TObject);
    procedure mnuFileExitClick(Sender: TObject);
    procedure mnuHelpAboutClick(Sender: TObject);
    procedure CmdCreateTableClick(Sender: TObject);
    procedure CmdCreateItemsClick(Sender: TObject);
    procedure CmdAddClick(Sender: TObject);
    procedure CmdFindClick(Sender: TObject);
    procedure CmdRemoveClick(Sender: TObject);
    procedure DisplayStatus(msg : String; probes : Integer);
    procedure ComputeAverageProbe(var ave_succ, ave_unsucc : Single);
    procedure TableSizeTextChange(Sender: TObject);
    procedure NewItemTextChange(Sender: TObject);
    procedure FormResize(Sender: TObject);
  private
    { Private declarations }
    MaxValue  : TTableData;
    HashTable : TChainingHashTable;
  public
    { Public declarations }
    destructor Destroy; override;
  end;

var
  ChainForm: TChainForm;

implementation

{$R *.DFM}

// Create the hash table.
procedure TChainForm.FormCreate(Sender: TObject);
begin
    Randomize;

    HashTable := TChainingHashTable.Create;
end;

// Free the hash table.
destructor TChainForm.Destroy;
begin
    HashTable.Free;
    inherited Destroy;
end;

procedure TChainForm.mnuFileExitClick(Sender: TObject);
begin
    Close;
end;

procedure TChainForm.mnuHelpAboutClick(Sender: TObject);
const
    CRCR = #13#10#13#10;
    CR = #13#10;
begin


    MessageDlg(
        'Niniejszy program demonstruje łańcuchowanie jako technikę implementacji' + CR +
        'tablic rozproszonych' + CRCR +
        'W sekcji "Tworzenie tablicy" podaj liczbę list biorących początek w tablicy,' + CR +
        'zaznaczenie pola "Listy posortowane" spowoduje utrzymywanie posortowanej' +CR +
        'postaci list po dodaniu i usunięciu elementu' +CRCR+
        'W sekcji "Generowanie elementów" podaj liczbę generowanych losowo elementów' +CR+
        'oraz maksymalną wartość elementu' +CRCR+
        'Sekcja "Szukanie" służy do wyszukiwania, dodawania i usuwania elementów'
        , mtInformation, [mbOK], 0);




end;

// Create a new hash table.
procedure TChainForm.CmdCreateTableClick(Sender: TObject);
begin
    Screen.Cursor := crHourGlass;

    // This makes the HashTable create the lists.
    HashTable.CreateTable(StrToInt(TableSizeText.Text),
        SortListsCheck.Checked);

    MaxValue := 1;
    StatusLabel.Caption := 'Utworzono tablicę.';
    CmdCreateItems.Enabled := True;
    TableLabel.Caption := HashTable.TextRepresentation(-1);
    Screen.Cursor := crDefault;
end;

// Add random items to the hash table.
procedure TChainForm.CmdCreateItemsClick(Sender: TObject);
var
    num, created, probes : Integer;
    value, max_value     : TTableData;
begin
    max_value := StrToInt(MaxValueText.Text);
    num := StrToInt(NumItemsText.Text);
    if (max_value < num) then
    begin
        ShowMessage('Zbyt mała wartość maksymalna.');
        exit;
    end;

    Screen.Cursor := crHourGlass;
    created := 0; // The number we have created.
    while (created < num) do
    begin
        value := Trunc(Random(max_value) + 1);
        if (value > MaxValue) then MaxValue := value;
        if (HashTable.InsertItem(value, probes) =
            chInserted) then
                created := created + 1;
    end;
    DisplayStatus('Wykonano.', probes);

    TableLabel.Caption := HashTable.TextRepresentation(-1);
    Screen.Cursor := crDefault;
end;

// Add an item to the hash table.
procedure TChainForm.CmdAddClick(Sender: TObject);
var
    probes : Integer;
    value  : TTableData;
    status : TChainReturnValue;
begin
    Screen.Cursor := crHourGlass;

    value := StrToInt(NewItemText.Text);
    if (value > MaxValue) then MaxValue := value;

    // Insert the item.
    status := HashTable.InsertItem(value, probes);
    case status of
        chFound:
            DisplayStatus('Element o tym kluczu już istnieje.', probes);
        chInserted:
            DisplayStatus('Dodano.', probes);
    end;

    TableLabel.Caption := HashTable.TextRepresentation(value);
    Screen.Cursor := crDefault;
end;

// Find an item in the hash table.
procedure TChainForm.CmdFindClick(Sender: TObject);
var
    value  : TTableData;
    probes : Integer;
    status : TChainReturnValue;
begin
    Screen.Cursor := crHourGlass;

    value := StrToInt(NewItemText.Text);
    if (value > MaxValue) then MaxValue := value;

    status := HashTable.LocateItem(value, probes);
    case status of
        chNotFound:
            DisplayStatus('Nie znaleziono.', probes);
        chFound:
            DisplayStatus('Znaleziono.', probes);
    end;

    TableLabel.Caption := HashTable.TextRepresentation(value);
    Screen.Cursor := crDefault;
end;

// Find an item in the hash table.
procedure TChainForm.CmdRemoveClick(Sender: TObject);
var
    value  : TTableData;
    probes : Integer;
    status : TChainReturnValue;
begin
    Screen.Cursor := crHourGlass;

    value := StrToInt(NewItemText.Text);
    if (value > MaxValue) then MaxValue := value;

    status := HashTable.RemoveItem(value, probes);
    case status of
        chNotFound:
            DisplayStatus('Nie znaleziono.', probes);
        chFound:
            DisplayStatus('Usunięto.', probes);
    end;

    TableLabel.Caption := HashTable.TextRepresentation(value);
    Screen.Cursor := crDefault;
end;

// Display a status message.
procedure TChainForm.DisplayStatus(msg : String; probes : Integer);
const
    CR = #13#10;
var
    ave_succ, ave_unsucc : single;
begin
    ComputeAverageProbe(ave_succ, ave_unsucc);
    StatusLabel.Caption := msg + CR +
        Format('Ta próba: %d.', [probes]) + CR +
        Format('Średnio pomyślnych prób: %.2f.', [ave_succ]) + CR +
        Format('Średnio niepomyślnych prób: %.2f.', [ave_unsucc]);
end;

// Compute the average lengths of probe sequences.
procedure TChainForm.ComputeAverageProbe(var ave_succ, ave_unsucc : Single);
var
    status                         : TChainReturnValue;
    trial, probes                  : Integer;
    succ_searches, succ_probes     : Integer;
    unsucc_searches, unsucc_probes : Integer;
begin
    succ_searches := 0;
    succ_probes := 0;
    unsucc_searches := 0;
    unsucc_probes := 0;
    for trial := 1 to MaxValue do
    begin
        status := HashTable.LocateItem(trial, probes);
        if (status = chFound) then
        begin
            succ_searches := succ_searches + 1;
            succ_probes := succ_probes + probes;
        end else begin
            unsucc_searches := unsucc_searches + 1;
            unsucc_probes := unsucc_probes + probes;
        end;
    end;

    if (succ_searches > 0) then
        ave_succ := succ_probes / succ_searches
    else
        ave_succ := 0;
    if (unsucc_searches > 0) then
        ave_unsucc := unsucc_probes / unsucc_searches
    else
        ave_unsucc := 0;
end;

procedure TChainForm.TableSizeTextChange(Sender: TObject);
begin
    CmdCreateTable.Enabled :=
        (TableSizeText.Text <> '');
end;

procedure TChainForm.NewItemTextChange(Sender: TObject);
begin
    CmdAdd.Enabled := (NewItemText.Text <> '');
    CmdFind.Enabled := CmdAdd.Enabled;
    CmdRemove.Enabled := CmdAdd.Enabled;
end;

// Make the scroll box as wide as possible.
procedure TChainForm.FormResize(Sender: TObject);
var
    wid : Integer;
begin
    wid := ClientWidth - TableScrollBox.Left;
    if (wid < 50) then wid := 50;
    TableScrollBox.Width := wid;
end;


end.
