unit UMyUtils;

interface
uses IniFiles,Graphics,jpeg,classes;

function GetCurrentVersion: String;
function RandomRound(const R:Extended):Integer;
procedure MyInputBox(const ACaption, APrompt, ADefault,Invalid: string;
  out ResString:String); overload;
procedure MyInputBox(const ACaption, APrompt, ADefault: string;
  MinVal,MaxVal:Integer; out ResInteger:Integer); overload; 
procedure MyInputBox(const ACaption, APrompt, ADefault: string;
  MinVal,MaxVal:Real; out ResFloat:Real); overload;   
function JPGtoBMP(const FileName:string):Graphics.TBitmap;   
procedure CalcFPS(MeasureIntervalSec:Real);


type TMyIni=class (TIniFile)
  public
    SectionDefault:string;
    ReadStringDefault:string;
    ReadBoolDefault:Boolean;
    ReadFloatDefault:Real;
    ReadIntDefault:Integer;
    ReadColorDefault:Integer;

    constructor Create(const FileName: string);
    
    procedure Read(const Ident, Default: string;
    Out ResString:string); overload;
    procedure Read(const Ident: string;
    Out ResString:string); overload;

    procedure Read(const Ident: string; Default: Integer;
    Out ResInt:Integer); overload;
    procedure Read(const Ident: string;
    Out ResInt:Integer); overload;

    procedure Read(const Ident: string; Default: Real;
    Out ResFloat:Real); overload;
    procedure Read(const Ident: string;
    Out ResFloat:Real); overload;
    
    procedure Read(const Ident: string; Default: Boolean;
    Out ResBool:Boolean); overload;
    procedure Read(const Ident: string;
    Out ResBool:Boolean); overload;

    procedure Write(const Name: string; Value: string); overload;
    procedure Write(const Name: string; Value: Integer); overload;
    procedure Write(const Name: string; Value: Real); overload;
    procedure Write(const Name: string; Value: Boolean); overload;
end;

type TMyStopWatch=class
  public
    Start:Cardinal;
    constructor create;
    function TimeElapsedmilliSecs:Cardinal;
    function TimeElapsedSecs:Real;
    function TimeElapsedmins:Real;
    procedure ResetTimer;
end;

var InformationDump:Cardinal;


  //FPS Calculation
  FPS:Real;
  FPSMeasureCount:Cardinal=0;
  FrameCount:Cardinal=0;
  LastFrameCounts:TList;

  
implementation
uses Types,Windows,SysUtils,Math,Dialogs,UMessageThread,Forms;

constructor TMyStopWatch.Create;
begin
  inherited Create;
  ResetTimer;
end;

procedure TMyStopWatch.ResetTimer;
begin
  Start:=GetTickCount;
end;

function TMyStopWatch.TimeElapsedmilliSecs:Cardinal;
begin
  Result:=GetTickCount-Start;
end;

function TMyStopWatch.TimeElapsedSecs:Real;
begin
  Result:=TimeElapsedmilliSecs/1000;
end;

function TMyStopWatch.TimeElapsedMins:Real;
begin
  Result:=TimeElapsedmilliSecs/60000;
end;

constructor TMyIni.Create(const FileName: string);
begin
  inherited Create(FileName);
  SectionDefault:='';
  ReadStringDefault:='';
  ReadBoolDefault:=false;
  ReadFloatDefault:=NaN;
  ReadIntDefault:=Low(Integer);
end;

procedure TMyIni.Write(const Name: string; Value: string);
begin
  self.WriteString(SectionDefault,Name,Value);
end;

procedure TMyIni.Write(const Name: string; Value: Integer);
begin
  self.WriteInteger(SectionDefault,Name,Value);
end;

procedure TMyIni.Write(const Name: string; Value: Real);
begin
  self.WriteFloat(SectionDefault,Name,Value);
end;

procedure TMyIni.Write(const Name: string; Value: Boolean);
begin
  self.WriteBool(SectionDefault,Name,Value);
end;

procedure TMyIni.Read(const Ident, Default: string; Out ResString:string);
begin
  ResString:=self.ReadString(SectionDefault,Ident,Default);
end;

procedure TMyIni.Read(const Ident: string; Out ResString:string);
begin
  ResString:=self.ReadString(SectionDefault,Ident,ReadStringDefault);
end;

procedure TMyIni.Read(const Ident: string; Default: Integer; Out ResInt:Integer);
begin
  ResInt:=self.ReadInteger(SectionDefault,Ident,Default);
end;

procedure TMyIni.Read(const Ident: string; Out ResInt:Integer);
begin
  ResInt:=self.ReadInteger(SectionDefault,Ident,ReadIntDefault);
end;

procedure TMyIni.Read(const Ident: string; Default: Real; Out ResFloat:Real);
begin
  ResFloat:=self.ReadFloat(SectionDefault,Ident,Default);
end;

procedure TMyIni.Read(const Ident: string; Out ResFloat:Real);
begin
  ResFloat:=self.ReadFloat(SectionDefault,Ident,ReadFloatDefault);
end;

procedure TMyIni.Read(const Ident: string; Default: Boolean; Out ResBool:Boolean);
begin
  ResBool:=self.ReadBool(SectionDefault,Ident,Default);
end;

procedure TMyIni.Read(const Ident: string; Out ResBool:Boolean);
begin
  ResBool:=self.ReadBool(SectionDefault,Ident,ReadBoolDefault);
end;


procedure MyInputBox(const ACaption, APrompt, ADefault: string;
  MinVal,MaxVal:Real; out ResFloat:Real);
var Error:Boolean; S1:String;
begin
  repeat
    try
      Error:=false;
      S1:=InputBox(ACaption,APrompt,ADefault);
      ResFloat:=Strtofloat(S1);
    except
      Error:=true;
    end;
    if Error then
    MessageOut('An unknown error occured. Please check if "'+S1+
    '" is a valid floating point number',
    'Invalid value') else if (ResFloat>MaxVal) or (ResFloat<MinVal) then
    MessageOut('Must be true: '+FloatToStr(MinVal)+'<=X<='+FloatToStr(MaxVal),
    'Invalid value');
    if Application.Terminated then Break;
  until (ResFloat<=MaxVal) and (ResFloat>=MinVal) and not Error;
end;

procedure MyInputBox(const ACaption, APrompt, ADefault: string;
  MinVal,MaxVal:Integer; out ResInteger:Integer);
var Error:Boolean; S1:String;
begin
  repeat
    try  
      Error:=false;
      S1:=InputBox(ACaption,APrompt,ADefault);
      ResInteger:=Strtoint(S1);
    except
      Error:=true;
    end;
    if Error then
    MessageOut('An unknown error occured. Please check if "'+S1+
    '" is a valid integer number',
    'Invalid value') else
    if (ResInteger>MaxVal) or (ResInteger<MinVal) then
    MessageOut('Must be true: '+IntToStr(MinVal)+'<=X<='+IntToStr(MaxVal),
    'Invalid value');
    if Application.Terminated then Break;
  until (ResInteger<=MaxVal) and (ResInteger>=MinVal) and not Error;
end;

function JPGtoBMP(const FileName:string):Graphics.TBitmap;
var jpg1:TJPEGImage;
begin
  Result:=Graphics.TBitmap.Create;
  jpg1:=TJPEGImage.Create;
  jpg1.LoadFromFile(FileName);
  Result.Assign(jpg1);
end;

procedure CalcFPS(MeasureIntervalSec:Real);
Var P1:PCardinal; C1:Integer;
begin
  if not assigned(LastFrameCounts) then
  LastFrameCounts:=TList.create;
  Inc(FPSMeasureCount);
  if FrameCount<>0 then begin
    New(P1);
    P1^:=FrameCount;
    LastFrameCounts.Add(P1);
    FrameCount:=0;
    while LastFrameCounts.Count>Round(5/MeasureIntervalSec) do begin
      P1:=LastFrameCounts[0];
      Dispose(P1);
      LastFrameCounts.Delete(0);
    end;
  end;
  FPS:=0;
  for C1:=0 to LastFrameCounts.Count-1 do begin
    P1:=LastFrameCounts[C1];
    FPS:=FPS+P1^;
  end;
  FPS:=FPS/LastFrameCounts.Count/MeasureIntervalSec;
end;

procedure MyInputBox(const ACaption, APrompt, ADefault,Invalid: string;
  out ResString:String);
begin
  repeat
    try
      ResString:=InputBox(ACaption,APrompt,ADefault);
    except
      ResString:=Invalid;
    end;
    if ResString=Invalid then
    MessageOut('An unknown error occured.',
    'Invalid value');   
    if Application.Terminated then Break;
  until ResString<>Invalid;
end;

function GetCurrentVersion: String;
var
  VerInfoSize: DWORD;
  VerInfo: Pointer;
  VerValueSize: DWORD;
  VerValue: PVSFixedFileInfo;
  Dummy: DWORD;
begin
  VerInfoSize := GetFileVersionInfoSize(PChar(ParamStr(0)), Dummy);
  GetMem(VerInfo, VerInfoSize);
  GetFileVersionInfo(PChar(ParamStr(0)), 0, VerInfoSize, VerInfo);
  VerQueryValue(VerInfo, '\', Pointer(VerValue), VerValueSize);
  with VerValue^ do begin
    Result := 'Version '+IntToStr(dwFileVersionMS shr 16);
    Result := Result + '.' + IntToStr(dwFileVersionMS and $FFFF);
    Result := Result + '.' + IntToStr(dwFileVersionLS shr 16);
  end;
  FreeMem(VerInfo, VerInfoSize);
end;



function RandomRound(const R:Extended):Integer;
begin
  Result:=Floor(R);
  if Random>Frac(R) then Inc(Result);
end;

end.
