unit HAScores;
//---------------------------------------------------------------------------
// Hasteroids - High Scores implementation v1.0
//---------------------------------------------------------------------------
// Important Notice:
//
// If you modify/use this code or one of its parts either in original or
// modified form, you must comply with Mozilla Public License v1.1,
// specifically section 3, "Distribution Obligations". Failure to do so will
// result in the license breach, which will be resolved in the court.
// Remember that violating author's rights is considered a serious crime in
// many countries. Thank you!
//
// !! Please *read* Mozilla Public License 1.1 document located at:
//  http://www.mozilla.org/MPL/
//---------------------------------------------------------------------------
// The contents of this file are subject to the Mozilla Public License
// Version 1.1 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://www.mozilla.org/MPL/
//
// Software distributed under the License is distributed on an "AS IS"
// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
// License for the specific language governing rights and limitations
// under the License.
//
// The Original Code is HAScores.pas.
//
// The Initial Developer of the Original Code is M. Sc. Yuriy Kotsarenko.
// Portions created by M. Sc. Yuriy Kotsarenko are Copyright (C) 2007,
// M. Sc. Yuriy Kotsarenko. All Rights Reserved.
//---------------------------------------------------------------------------
interface

//---------------------------------------------------------------------------
uses
 Types, Classes, SysUtils, AsphyreDb, StreamUtils;

//---------------------------------------------------------------------------
type
 THighScore = class(TCollectionItem)
 private
  FScore: Integer;
  FPlayer: string;
 public
  property Player: string read FPlayer write FPlayer;
  property Score: Integer read FScore write FScore;
 end;

//---------------------------------------------------------------------------
 THighScores = class(TCollection)
 private
  function GetItem(Index: Integer): THighScore;
  procedure SetItem(Index: Integer; const Value: THighScore);
 public
  property Items[Index: Integer]: THighScore read GetItem write SetItem; default;

  function Add(): THighScore;
  function AddItem(Item: THighScore; Index: Integer): THighScore;
  function Insert(Index: Integer): THighScore;
  procedure Exchange(Item1, Item2: Integer);

  procedure Sort();

  procedure LoadFromVTDb(Key: string; Archive: TASDb);
  procedure SaveToVTDB(Key: string; Archive: TASDb);

  constructor Create();
 end;

//---------------------------------------------------------------------------
implementation

//---------------------------------------------------------------------------
constructor THighScores.Create();
begin
 inherited Create(THighScore);
end;

//---------------------------------------------------------------------------
function THighScores.GetItem(Index: Integer): THighScore;
begin
 Result:= THighScore(inherited GetItem(Index));
end;

//---------------------------------------------------------------------------
procedure THighScores.SetItem(Index: Integer; const Value: THighScore);
begin
 inherited SetItem(Index, Value);
end;

//---------------------------------------------------------------------------
function THighScores.Add(): THighScore;
begin
 Result:= THighScore(inherited Add());
end;

//---------------------------------------------------------------------------
function THighScores.AddItem(Item: THighScore; Index: Integer): THighScore;
begin
 if (Item = nil) then Result:= THighScore.Create(Self)
  else Result:= Item;

 if (Assigned(Result)) then
  begin
   Result.Collection:= Self;
   if (Index < 0) then Index:= Count - 1;
   Result.Index:= Index;
  end;
end;

//---------------------------------------------------------------------------
function THighScores.Insert(Index: Integer): THighScore;
begin
 Result:= AddItem(nil, Index);
end;

//---------------------------------------------------------------------------
procedure THighScores.Exchange(Item1, Item2: Integer);
var
 Aux: THighScore;
begin
 Aux:= Items[Item1];
 Items[Item1]:= Items[Item2];
 Items[Item2]:= Aux;
end;

//---------------------------------------------------------------------------
procedure THighScores.Sort();
var
 i, j: Integer;
begin
// Simple Bubble-sort
 for j:= 0 to Count - 1 do
  for i:= 0 to Count - 2 do
   if (Items[i].Score < Items[i + 1].Score) then
    Items[i].Index:= Items[i].Index + 1;
end;

//---------------------------------------------------------------------------
procedure THighScores.LoadFromVTDb(Key: string; Archive: TASDb);
var
 Stream: TStream;
 ItemCount, i: Integer;
 NewItem: THighScore;
begin
 Clear();

 // attempt to initialize ASDb
 if (not Archive.UpdateOnce()) then Exit;

 Stream:= TMemoryStream.Create();

 // attempt to read from vtdb archive
 if (not Archive.ReadStream(Key, Stream)) then
  begin
   Stream.Free();
   Exit;
  end;

 Stream.Seek(0, soFromBeginning);
 try
  // retreive item count
  ItemCount:= StreamGetLongint(Stream);

  // retreive individual items
  for i:= 0 to ItemCount - 1 do
   begin
    NewItem:= Add();
    NewItem.Player:= StreamGetSimpleAnsiString(Stream);
    NewItem.Score:= StreamGetLongint(Stream);
   end;
 except
 end;

 Stream.Free();
 Sort();
end;

//---------------------------------------------------------------------------
procedure THighScores.SaveToVTDB(Key: string; Archive: TASDb);
var
 Stream: TStream;
 i: Integer;
begin
 // attempt to initialize VTDb
 if (not Archive.UpdateOnce()) then Exit;

 Stream:= TMemoryStream.Create();

 // item count
 StreamPutLongint(Stream, Count);

 // individual items
 for i:= 0 to Count - 1 do
  begin
   StreamPutSimpleAnsiString(Stream, Items[i].Player);
   StreamPutLongint(Stream, Items[i].Score);
  end;

 // save to vtdb archive
 Stream.Seek(0, soFromBeginning);
 Archive.WriteStream(Key, Stream, recUnknown);

 // release the stream
 Stream.Free();
end;

//---------------------------------------------------------------------------
end.
