Unit HashSelector; { This unit says which symbols we are following. This decision can be based on hashing and/or the use of Canadian data. This is mostly aimed at Realtick where we were required to have multiple instances of the program to cover the entire market. Note that there is only one choce for the entire application. This helps a lot with the monitoring code. It can report which hash values it is watching. } Interface Uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; Type // Values for CanadianDataComboBox.ItemIndex TUseCanada = (ucAllRegardless, ucOnlyCanadian, ucNoCanadian); THashSelectorForm = class(TForm) HashFirstEdit: TEdit; HashCountEdit: TEdit; Label1: TLabel; Label2: TLabel; Label3: TLabel; Label4: TLabel; Label5: TLabel; OkButton: TButton; CancelButton: TButton; CanadianDataComboBox: TComboBox; procedure FormCreate(Sender: TObject); procedure FormShow(Sender: TObject); procedure OkButtonClick(Sender: TObject); private FHashCount, FHashFirst : Integer; FUseCanada : TUseCanada; Procedure VerifyValues; public Property HashCount : Integer Read FHashCount; Property HashFirst : Integer Read FHashFirst; Function FollowSymbol(Const Symbol : String) : Boolean; Function AppDescription(Const Base : String) : String; end; Var HashSelectorForm: THashSelectorForm; Implementation Uses StrUtils; {$R *.dfm} Function THashSelectorForm.AppDescription(Const Base : String) : String; Begin If HashCount = 1 Then Result := Base Else Result := Base + ' H%' + IntToStr(HashCount) + '=' + IntToStr(HashFirst) End; Function THashSelectorForm.FollowSymbol(Const Symbol : String) : Boolean; Function Hash(S : String) : Integer; Var I : Integer; Begin { Hash } // I stole this hash function from SymbolLists.pas in the Windows / // Realtick get stock list program. The unix version is slightly // different, as in the version I use in Windows' hash tables. There's // only so much you can do with stock symbols because they are so short. // The hash table version was optimized for longer strings. Result := 0; For I := 1 To Length(S) Do Begin Result := Result * 9; Result := Result + Ord(S[I]) End; Result := Result And $7fffffff; Result := Result XOr (Result ShR 8) End; { Hash } Function TestHash : Boolean; Begin { TestHash } If HashCount = 1 Then // This is an optimization. We need these tests for the realtick // version, but we expect the DTN version might have only one server. TestHash := True Else TestHash := (Hash(Symbol) Mod HashCount) = HashFirst End; { TestHash } Function TestCanadian : Boolean; Var Suffix : String; WantCanadian, IsCanadian : Boolean; Begin { TestCanadian } If FUseCanada = ucAllRegardless Then TestCanadian := True Else Begin Suffix := RightStr(Symbol, 4); IsCanadian := (Suffix = '.CAT') Or (Suffix = '.CAV'); WantCanadian := FUseCanada = ucOnlyCanadian; TestCanadian := IsCanadian = WantCanadian End End; { TestCanadian } Begin { THashSelectorForm.FollowSymbol } Result := TestHash And TestCanadian End; { THashSelectorForm.FollowSymbol } Procedure THashSelectorForm.VerifyValues; Begin If HashCount < 1 Then FHashCount := 1; If (HashFirst < 0) Or (HashFirst >= HashCount) Then FHashFirst := 0 End; Procedure THashSelectorForm.FormCreate(Sender: TObject); Var I : Integer; Begin FHashCount := 1; FHashFirst := 0; For I := 1 To ParamCount Do If (ParamStr(I) = '--Hash-Count') And (I < ParamCount) Then FHashCount := StrToIntDef(ParamStr(Succ(I)), FHashCount) Else If (ParamStr(I) = '--Hash-First') And (I < ParamCount) Then // Use the same command line names as the overnight program. This is // a little silly since we only cover one hash bucket. First and // only. In practice the overnight stuff worked the same way. FHashFirst := StrToIntDef(ParamStr(Succ(I)), FHashFirst) Else If ParamStr(I) = '--Canada-Only' Then FUseCanada := ucOnlyCanadian Else If ParamStr(I) = '--Exclude-Canada' Then FUseCanada := ucNoCanadian; VerifyValues End; Procedure THashSelectorForm.FormShow(Sender: TObject); Begin HashFirstEdit.Text := IntToStr(HashFirst); HashCountEdit.Text := IntToStr(HashCount); CanadianDataComboBox.ItemIndex := Ord(FUseCanada) End; Procedure THashSelectorForm.OkButtonClick(Sender: TObject); Begin FHashCount := StrToIntDef(HashCountEdit.Text, HashCount); FHashFirst := StrToIntDef(HashFirstEdit.Text, HashFirst); FUseCanada := TUseCanada(CanadianDataComboBox.ItemIndex); VerifyValues End; End.