SRL Archive - SRL Suggestions

Progress.simba


Daniel

2012-01-08 12:05:54

Hello all! :)

I present to you my Progress Report include! Taken from the source header:
The Progress Report Form include allows the execution of periodic script reports specified by the user/scripter in a separate window. This include allows the runtime of a periodic updating form as-well as script execution simultaneously.


Basically it allows a periodic progress report displayed in a separate form, running alongside your script, in the same script! This eliminates the need to paint on the SMART canvas once and for all and the slow/lagginess that induces! This uses form execution methods that haven't been done (from what I can tell) before in Simba or SCAR. Simply put, it;s somewhat multi-threaded :) (well, event-driven really if you want to get technical :p)

I got the idea from somebody around here that said it was "impossible" and "very hard to do" whilst reading a couple of hours ago. :)

It's pretty easy to use! Even look at the following script!

program ProgessTest;

{$i SRL\SRL.simba}
{$i SRL\SRL\Misc\Progress.simba}

var
I: Integer;

procedure ProgressReport;
begin
Progress_Clear;

Progress_Writeln(' /----------------------------------------------------------\');
Progress_Writeln('| Progress Report by Daniel |');
Progress_Writeln('| |');
Progress_Writeln('| We are currently up to number: ' + IntToStr(I) + ' |');
Progress_Writeln(' \----------------------------------------------------------/');
end;

begin
Progress_ScriptName := 'Daniels Test Script!'; // Probably the most important bit of this setup!
Progress_Setup; // Set's up the progress report with default form size (W:650, H: 350). Called ONCE
Progress_LoadBackgroundFromFile(ScriptPath + 'bgprogresstest.bmp'); // Let's have a nice background, shall we? :)

Progress_ChangeInterval(5000); // Update the progress report every 5 seconds
OnProgressUpdate := @ProgressReport; // The procedure to run when above time interval passes.

Progress_Show; // Actually displays the progress report form.

for I := 0 to 20 do // Do whatever code here.
begin // In this case, it's a for..loop.
Writeln(I); { You will notice that ProgessReport() should get called at the same time this is running! }
Wait(500); // Let's not spam shall we. :)
end;

Progress_Close; // Closes the form. Not really necessary if its at the end of the script.
Progress_Unload; // Frees everything to do with the form from memory! Just as above, it isn't really necessary if it's at the end of the script.
end.

Pretty easy, eh? Everything to do with this (except one, the OnProgressUpdate) has a prefix of Progress_, and the names are pretty easy too! So you can't get confused by it :)

Also, here's the actual include (place it in /SRL/SRL/Misc/Progress.simba):

(*
Progress Report Form by Daniel
======

The Progress Report Form include allows the execution of periodic script reports
specified by the user/scripter in a separate window. This include allows the
runtime of a periodic updating form as-well as script execution simultaneously.

If you (the scripter/user) leave everything the

.. contents::


*)

const
DEFAULT_INTERVAL = 300000; { Default timer interval (in milliseconds),
default-untouched is 5 minutes. }

// Theses are just some silly variables you don't need to know :D
var
PF_ProgressForm: TForm;
PF_ProgressForm_Text: TMemo;
PF_ProgressForm_Background: TImage;
PF_ProgressForm_Updater: TTimer;
PF_ProgressClose: Boolean;

(*
OnProgressUpdate
~~~~~~~~~~~

.. code-block:: pascal

var OnProgressUpdate: procedure;

This here is what defines what method the Progress Report Form should call when
the period for an update is due. All you have to do is link it to a procedure
(with no parametres! If you don't know what that is, then don't worry!) See the
example below on how to link a procedure (note the '@' symbol).

.. note::

Author: Daniel
Date Added: 9/01/2012

Example:

.. code-block:: pascal

procedure ProgressReport;
begin
end;

begin
OnProgressUpdate := @ProgressReport;
end.
*)
OnProgressUpdate: procedure;

(*
Progress_ScriptName
~~~~~~~~~~~

.. code-block:: pascal

var Progress_ScriptName: String;

What is the name of your script? This is used if you don't want to change the
title of the form later on.

E.g, if you set it to "Daniels Guild Miner", then the title of the Progress
Report Form will be "Daniels Guild Miner - Progress Report".

.. note::

Author: Daniel
Date Added: 9/01/2012

Example:

.. code-block:: pascal

begin
Progress_ScriptName := 'Daniels Guild Miner';
end.
*)
Progress_ScriptName: String;

procedure ThreadSafeCallNoParams(const ProcName: String); forward;

(*
Rect
~~~~~~~~~~~

.. code-block:: pascal

function Rect(const Left, Top, Right, Bottom: Integer): TRect;

Similar to the Point() and IntToBox() methods. Converts the split up values of
a TRect into a TRect type.

.. note::

Author: Daniel
Date Added: 9/01/2012

Example:

.. code-block:: pascal

var
NewRect: TRect;
begin
NewRect := Rect(0, 0, 300, 300);
end.
*)
function Rect(const Left, Top, Right, Bottom: Integer): TRect;
begin
// with..do statements are bad here
Result.Left := Left;
Result.Top := Top;
Result.Right := Right;
Result.Bottom := Bottom;
end;

(*
Progress_SetupEx
~~~~~~~~~~~

.. code-block:: pascal

procedure Progress_SetupEx(const Bounds: TRect);

Set's up the Progress Report Form with scripter specified dimensions. This is
useful if the scripter wants to add a larger background image, or wants to display
more text on the screen.

NOTE: You MUST call a setup procedure BEFORE you display the form.

.. note::

Author: Daniel
Date Added: 9/01/2012

Example:

.. code-block:: pascal

begin
Progress_SetupEx(Rect(0, 0, 300, 300));
end.
*)
procedure Progress_SetupEx(const Bounds: TRect);
var
Params: TVariantArray;
begin
if(Assigned(PF_ProgressForm)) then
Exit;

Params := [Bounds.Left, Bounds.Top, Bounds.Right, Bounds.Bottom];
ThreadSafeCall('UnsafeSetupProgress', Params);
end;

(*
Progress_Setup
~~~~~~~~~~~

.. code-block:: pascal

procedure Progress_Setup;

Set's up the Progress Report Form with default dimensions of 650x350. This is
suitable for most applications. Use Progress_SetupEx() for a much more customisable
setup.

NOTE: You MUST call a setup procedure BEFORE you display the form.

.. note::

Author: Daniel
Date Added: 9/01/2012

Example:

.. code-block:: pascal

begin
Progress_Setup;
end.
*)
procedure Progress_Setup;
begin
Progress_SetupEx(Rect(0, 0, 650, 350));
end;

(*
Progress_Show
~~~~~~~~~~~

.. code-block:: pascal

procedure Progress_Show;

Displays the Progress Report Form.

NOTE: You MUST call a setup procedure BEFORE you display the form.

.. note::

Author: Daniel
Date Added: 9/01/2012

Example:

.. code-block:: pascal

begin
Progress_Show;
end.
*)
procedure Progress_Show;
begin
if(not(Assigned(PF_ProgressForm))) then
Exit;

PF_ProgressClose := False;
ThreadSafeCallNoParams('UnsafeShowProgress');
end;

(*
Progress_Close
~~~~~~~~~~~

.. code-block:: pascal

procedure Progress_Close;

Hides/closes the Progress Report Form.

.. note::

Author: Daniel
Date Added: 9/01/2012

Example:

.. code-block:: pascal

begin
Progress_Close;
end.
*)
procedure Progress_Close;
begin
if(not(Assigned(PF_ProgressForm))) then
Exit;

PF_ProgressClose := True;
ThreadSafeCallNoParams('UnSafeCloseProgress');
end;

(*
Progress_Unload
~~~~~~~~~~~

.. code-block:: pascal

procedure Progress_Unload;

Reverses the effect of SetupEx or Setup. Basically it closes the form (if it's open)
and free's a tiny little bit of RAM. Generally the scripter should not need to call
this. This is automatically run when upon script termination/completeion.

.. note::

Author: Daniel
Date Added: 9/01/2012

Example:

.. code-block:: pascal

begin
Progress_Unload;
end.
*)
procedure Progress_Unload;
begin
if(not(Assigned(PF_ProgressForm))) then
Exit;

if(not(PF_ProgressClose)) then
Progress_Close;

ThreadSafeCallNoParams('UnsafeUnloadProgress');
end;

(*
Progress_ChangeInterval
~~~~~~~~~~~

.. code-block:: pascal

procedure Progress_ChangeInterval(const NewInterval: Cardinal);

Changes the interval between the periodic updates of calling the Progress Report
procedure (in milliseconds, so 1000 is the equivalent of 1 second).

.. note::

Author: Daniel
Date Added: 9/01/2012

Example:

.. code-block:: pascal

begin
Progress_ChangeInterval(5000); // It is now updating every 5 seconds
end.
*)
procedure Progress_ChangeInterval(const NewInterval: Cardinal);
var
Params: TVariantArray;
begin
Params := [NewInterval];
ThreadSafeCall('UnsafeChangeInterval', Params);
end;

(*
Progress_LoadBackgroundFromFile
~~~~~~~~~~~

.. code-block:: pascal

function Progress_LoadBackgroundFromFile(const FileName: AnsiString): Boolean;

Load's a background image from an external bitmap file. Returns True if the background
was successfully set. The image will automatically stretch to the width
and height of the form.

NOTE: It MUST be an image stored as a Windows Bitmap (*.bmp).

.. note::

Author: Daniel
Date Added: 9/01/2012

Example:

.. code-block:: pascal

begin
Progress_LoadBackgroundFromFile(ScriptPath + 'background.bmp');
end.
*)
function Progress_LoadBackgroundFromFile(const FileName: AnsiString): Boolean;
begin
Result := Lowercase(ExtractFileExt(FileName)) = '.bmp';
if(not(Result)) then
Exit;

PF_ProgressForm_Background.Picture.Bitmap.LoadFromFile(FileName);
end;


(*
Progress_LoadBackground
~~~~~~~~~~~

.. code-block:: pascal

function Progress_LoadBackground(const I: Integer): Boolean;

Load's a background image from a bitmap file loaded by Simba. Returns True if the background
was successfully set. The image will automatically stretch to the width and height
of the form.

.. note::

Author: Daniel
Date Added: 9/01/2012

Example:

.. code-block:: pascal

var
Bmp: Integer;

begin
Bmp := BitmapFromString(650, 350, '...');
Progress_LoadBackground(Bmp);
end.
*)
function Progress_LoadBackground(const I: Integer): Boolean;
var
tempMufasaBitmap: TMufasaBitmap;
begin
if(not(Assigned(PF_ProgressForm))) then
Exit;

tempMufasaBitmap := GetMufasaBitmap(I);
Result := Assigned(tempMufasaBitmap);
if(not(Result)) then
Exit;

PF_ProgressForm_Background.Picture.Assign(tempMufasaBitmap.ToTBitmap);

tempMufasaBitmap.Free;
tempMufasaBitmap := nil;
end;

(*
Progress_WriteLn
~~~~~~~~~~~

.. code-block:: pascal

function Progress_WriteLn(const V: Variant): Integer;

Send's text to the Progress Report Form to be displayed. Similar to Simba's
Writeln, except it doesn't support automatically displaying arrays. Returns
the line number which the text was printed on.

.. note::

Author: Daniel
Date Added: 9/01/2012

Example:

.. code-block:: pascal

begin
Progress_WriteLn('Progress Report for Daniel''s Guild Miner: ');
end.
*)
function Progress_WriteLn(const V: Variant): Integer;
begin
if(not(Assigned(PF_ProgressForm))) then
Exit;

Result := PF_ProgressForm_Text.Lines.Add(V);

// Compensate for those "one-liner" progress report forms.
if(PF_ProgressForm.Height < 78) then
PF_ProgressForm_Text.SelStart := Length(PF_ProgressForm_Text.Text) - 1;
end;

(*
Progress_ModifyLine
~~~~~~~~~~~

.. code-block:: pascal

function Progress_ModifyLine(const V: Variant; const Line: Integer): Boolean;

Replaces a line's text with V. Line is the line number (can be retrieved from
the above mentioned methiod, Progress_Writeln.

.. note::

Author: Daniel
Date Added: 9/01/2012

Example:

.. code-block:: pascal

begin
Progress_ModifyLine('I am replacing the first line!', 0);
end.
*)
function Progress_ModifyLine(const V: Variant; const Line: Integer): Boolean;
begin
if(not(Assigned(PF_ProgressForm))) then
Exit;

Result := Line < (PF_ProgressForm_Text.Lines.Count);
if(not(Result)) then
Exit;

PF_ProgressForm_Text.Lines.Strings[Line] := V;
end;

(*
Progress_Clear
~~~~~~~~~~~

.. code-block:: pascal

procedure Progress_Clear;

Erases the entire contents of the text box on the Progress Report Form. Similar
to Simba's ClearDebug().

.. note::

Author: Daniel
Date Added: 9/01/2012

Example:

.. code-block:: pascal

begin
Progress_Clear;
end.
*)
procedure Progress_Clear;
begin
if(not(Assigned(PF_ProgressForm))) then
Exit;

PF_ProgressForm_Text.Lines.Clear;
end;

(*
Progress_ChangeCaption
~~~~~~~~~~~

.. code-block:: pascal

procedure Progress_ChangeCaption(const NewCaption: String);

Changes the title of the Progress Report Form to NewCaption.

.. note::

Author: Daniel
Date Added: 9/01/2012

Example:

.. code-block:: pascal

begin
Progress_ChangeCaption('This is the new title!');
end.
*)
procedure Progress_ChangeCaption(const NewCaption: String);
begin
if(not(Assigned(PF_ProgressForm))) then
Exit;

PF_ProgressForm.Caption := NewCaption;
end;

{* ******************************************************************************
DO NOT TOUCH, AND *ESPECIALLY* DO NOT CALL ANY METHODS LISTED BELOW HERE.
THEY ARE NAMED 'UNSAFE' FOR A REASON.

Unless you know what you are doing, DON'T TOUCH!

- Regards, Daniel. =)
****************************************************************************** *}

procedure ThreadSafeCallNoParams(const ProcName: String);
var
Params: TVariantArray;
begin
Params := [];
ThreadSafeCall(ProcName, Params);
end;

procedure PF_OnProgressTimer(Sender: TObject);
begin
if(Sender = PF_ProgressForm_Updater) then
OnProgressUpdate();
end;

procedure PF_ProgressCanClose(Sender: TObject; var CanClose: Boolean);
begin
CanClose := PF_ProgressClose;
end;

procedure UnsafeSetupProgress(const Left, Top, Right, Bottom: Integer);
begin
PF_ProgressForm := TForm.Create(nil);
PF_ProgressForm.SetBounds(Left, Top, Right, Bottom);
PF_ProgressForm.Caption := Progress_ScriptName + ' - Progress Report';
PF_ProgressForm.Position := poMainFormCenter;
PF_ProgressForm.BorderStyle := bsSingle; // Non-resizeable, non-maximisable form. Which is what we want.
PF_ProgressForm.OnCloseQuery := @PF_ProgressCanClose;
PF_ProgressForm.FormStyle := fsStayOnTop;

PF_ProgressForm_Text := TMemo.Create(PF_ProgressForm);
PF_ProgressForm_Text.Parent := PF_ProgressForm;
PF_ProgressForm_Text.SetBounds(Left + 20, Top + 20, Right - 40, Bottom - 40);
PF_ProgressForm_Text.Font.Name := 'Courier New';
PF_ProgressForm_Text.Font.Size := 10;
PF_ProgressForm_Text.ReadOnly := True;
PF_ProgressForm_Text.WordWrap := False;

PF_ProgressForm_Updater := TTimer.Create(PF_ProgressForm);
PF_ProgressForm_Updater.Interval := DEFAULT_INTERVAL;
PF_ProgressForm_Updater.OnTimer := @PF_OnProgressTimer;
{PF_ProgressForm_Updater.Enabled := True; }

PF_ProgressForm_Background := TImage.Create(PF_ProgressForm);
PF_ProgressForm_Background.Parent := PF_ProgressForm;
PF_ProgressForm_Background.SetBounds(Left, Top, Right, Bottom);
PF_ProgressForm_Background.Stretch := True;
PF_ProgressForm_Background.SendToBack;

AddOnTerminate('Progress_Unload');
end;

procedure UnsafeUnloadProgress;
begin
{ Form components }
PF_ProgressForm_Background.Free;
PF_ProgressForm_Background := nil;
PF_ProgressForm_Text.Free;
PF_ProgressForm_Text := nil;
PF_ProgressForm_Updater.Free;
PF_ProgressForm_Updater := nil;

{ The actual form itself }
PF_ProgressForm.Free;
PF_ProgressForm := nil;
end;

procedure UnsafeShowProgress;
begin
PF_ProgressForm.Show;
PF_ProgressForm_Updater.Enabled := True;
end;

procedure UnsafeCloseProgress;
begin
PF_ProgressForm.Close;
PF_ProgressForm_Updater.Enabled := False;
end;

// I did this for a reason. I can't exactly recall if setting the interval
// without destroying the component worked or not.
procedure UnsafeChangeInterval(const NewInterval: Cardinal);
var
WasAlreadyEnabled: Boolean; // Rather self-explanatory...
begin
WasAlreadyEnabled := False;

if(Assigned(PF_ProgressForm_Updater)) then
begin
WasAlreadyEnabled := PF_ProgressForm_Updater.Enabled;

PF_ProgressForm_Updater.Free;
PF_ProgressForm_Updater := nil;
end;

PF_ProgressForm_Updater := TTimer.Create(PF_ProgressForm);
PF_ProgressForm_Updater.OnTimer := @PF_OnProgressTimer;
PF_ProgressForm_Updater.Interval := NewInterval;
PF_ProgressForm_Updater.Enabled := WasAlreadyEnabled;
end(*
Progress Report Form by Daniel
======

The Progress Report Form include allows the execution of periodic script reports
specified by the user/scripter in a separate window. This include allows the
runtime of a periodic updating form as-well as script execution simultaneously.

.. contents::


*)

const
DEFAULT_INTERVAL = 300000; { Default timer interval (in milliseconds),
default-untouched is 5 minutes. }

// Theses are just some silly variables you don't need to know :D
var
PF_ProgressForm: TForm;
PF_ProgressForm_Text: TMemo;
PF_ProgressForm_Background: TImage;
PF_ProgressForm_Updater: TTimer;
PF_ProgressClose: Boolean;

(*
OnProgressUpdate
~~~~~~~~~~~

.. code-block:: pascal

var OnProgressUpdate: procedure;

This here is what defines what method the Progress Report Form should call when
the period for an update is due. All you have to do is link it to a procedure
(with no parametres! If you don't know what that is, then don't worry!) See the
example below on how to link a procedure (note the '@' symbol).

.. note::

Author: Daniel
Date Added: 9/01/2012

Example:

.. code-block:: pascal

procedure ProgressReport;
begin
end;

begin
OnProgressUpdate := @ProgressReport;
end.
*)
OnProgressUpdate: procedure;

(*
Progress_ScriptName
~~~~~~~~~~~

.. code-block:: pascal

var Progress_ScriptName: String;

What is the name of your script? This is used if you don't want to change the
title of the form later on.

E.g, if you set it to "Daniels Guild Miner", then the title of the Progress
Report Form will be "Daniels Guild Miner - Progress Report".

.. note::

Author: Daniel
Date Added: 9/01/2012

Example:

.. code-block:: pascal

begin
Progress_ScriptName := 'Daniels Guild Miner';
end.
*)
Progress_ScriptName: String;

procedure ThreadSafeCallNoParams(const ProcName: String); forward;

(*
Rect
~~~~~~~~~~~

.. code-block:: pascal

function Rect(const Left, Top, Right, Bottom: Integer): TRect;

Similar to the Point() and IntToBox() methods. Converts the split up values of
a TRect into a TRect type.

.. note::

Author: Daniel
Date Added: 9/01/2012

Example:

.. code-block:: pascal

var
NewRect: TRect;
begin
NewRect := Rect(0, 0, 300, 300);
end.
*)
function Rect(const Left, Top, Right, Bottom: Integer): TRect;
begin
// with..do statements are bad here
Result.Left := Left;
Result.Top := Top;
Result.Right := Right;
Result.Bottom := Bottom;
end;

(*
Progress_SetupEx
~~~~~~~~~~~

.. code-block:: pascal

procedure Progress_SetupEx(const Bounds: TRect);

Set's up the Progress Report Form with scripter specified dimensions. This is
useful if the scripter wants to add a larger background image, or wants to display
more text on the screen.

NOTE: You MUST call a setup procedure BEFORE you display the form.

.. note::

Author: Daniel
Date Added: 9/01/2012

Example:

.. code-block:: pascal

begin
Progress_SetupEx(Rect(0, 0, 300, 300));
end.
*)
procedure Progress_SetupEx(const Bounds: TRect);
var
Params: TVariantArray;
begin
if(Assigned(PF_ProgressForm)) then
Exit;

Params := [Bounds.Left, Bounds.Top, Bounds.Right, Bounds.Bottom];
ThreadSafeCall('UnsafeSetupProgress', Params);
end;

(*
Progress_Setup
~~~~~~~~~~~

.. code-block:: pascal

procedure Progress_Setup;

Set's up the Progress Report Form with default dimensions of 650x350. This is
suitable for most applications. Use Progress_SetupEx() for a much more customisable
setup.

NOTE: You MUST call a setup procedure BEFORE you display the form.

.. note::

Author: Daniel
Date Added: 9/01/2012

Example:

.. code-block:: pascal

begin
Progress_Setup;
end.
*)
procedure Progress_Setup;
begin
Progress_SetupEx(Rect(0, 0, 650, 350));
end;

(*
Progress_Show
~~~~~~~~~~~

.. code-block:: pascal

procedure Progress_Show;

Displays the Progress Report Form.

NOTE: You MUST call a setup procedure BEFORE you display the form.

.. note::

Author: Daniel
Date Added: 9/01/2012

Example:

.. code-block:: pascal

begin
Progress_Show;
end.
*)
procedure Progress_Show;
begin
if(not(Assigned(PF_ProgressForm))) then
Exit;

PF_ProgressClose := False;
ThreadSafeCallNoParams('UnsafeShowProgress');
end;

(*
Progress_Close
~~~~~~~~~~~

.. code-block:: pascal

procedure Progress_Close;

Hides/closes the Progress Report Form.

.. note::

Author: Daniel
Date Added: 9/01/2012

Example:

.. code-block:: pascal

begin
Progress_Close;
end.
*)
procedure Progress_Close;
begin
if(not(Assigned(PF_ProgressForm))) then
Exit;

PF_ProgressClose := True;
ThreadSafeCallNoParams('UnSafeCloseProgress');
end;

(*
Progress_Unload
~~~~~~~~~~~

.. code-block:: pascal

procedure Progress_Unload;

Reverses the effect of SetupEx or Setup. Basically it closes the form (if it's open)
and free's a tiny little bit of RAM. Generally the scripter should not need to call
this. This is automatically run when upon script termination/completeion.

.. note::

Author: Daniel
Date Added: 9/01/2012

Example:

.. code-block:: pascal

begin
Progress_Unload;
end.
*)
procedure Progress_Unload;
begin
if(not(Assigned(PF_ProgressForm))) then
Exit;

if(not(PF_ProgressClose)) then
Progress_Close;

ThreadSafeCallNoParams('UnsafeUnloadProgress');
end;

(*
Progress_ChangeInterval
~~~~~~~~~~~

.. code-block:: pascal

procedure Progress_ChangeInterval(const NewInterval: Cardinal);

Changes the interval between the periodic updates of calling the Progress Report
procedure (in milliseconds, so 1000 is the equivalent of 1 second).

.. note::

Author: Daniel
Date Added: 9/01/2012

Example:

.. code-block:: pascal

begin
Progress_ChangeInterval(5000); // It is now updating every 5 seconds
end.
*)
procedure Progress_ChangeInterval(const NewInterval: Cardinal);
var
Params: TVariantArray;
begin
Params := [NewInterval];
ThreadSafeCall('UnsafeChangeInterval', Params);
end;

(*
Progress_LoadBackgroundFromFile
~~~~~~~~~~~

.. code-block:: pascal

function Progress_LoadBackgroundFromFile(const FileName: AnsiString): Boolean;

Load's a background image from an external bitmap file. Returns True if the background
was successfully set.

NOTE: It MUST be an image stored as a Windows Bitmap (*.bmp).

.. note::

Author: Daniel
Date Added: 9/01/2012

Example:

.. code-block:: pascal

begin
Progress_LoadBackgroundFromFile(ScriptPath + 'background.bmp');
end.
*)
function Progress_LoadBackgroundFromFile(const FileName: AnsiString): Boolean;
begin
Result := Lowercase(ExtractFileExt(FileName)) = '.bmp';
if(not(Result)) then
Exit;

PF_ProgressForm_Background.Picture.Bitmap.LoadFromFile(FileName);
end;


(*
Progress_LoadBackground
~~~~~~~~~~~

.. code-block:: pascal

function Progress_LoadBackground(const I: Integer): Boolean;

Load's a background image from a bitmap file loaded by Simba. Returns True if the background
was successfully set.

.. note::

Author: Daniel
Date Added: 9/01/2012

Example:

.. code-block:: pascal

var
Bmp: Integer;

begin
Bmp := BitmapFromString(650, 350, '...');
Progress_LoadBackground(Bmp);
end.
*)
function Progress_LoadBackground(const I: Integer): Boolean;
var
tempMufasaBitmap: TMufasaBitmap;
begin
if(not(Assigned(PF_ProgressForm))) then
Exit;

tempMufasaBitmap := GetMufasaBitmap(I);
Result := Assigned(tempMufasaBitmap);
if(not(Result)) then
Exit;

PF_ProgressForm_Background.Picture.Assign(tempMufasaBitmap.ToTBitmap);

tempMufasaBitmap.Free;
tempMufasaBitmap := nil;
end;

(*
Progress_WriteLn
~~~~~~~~~~~

.. code-block:: pascal

function Progress_WriteLn(const V: Variant): Integer;

Send's text to the Progress Report Form to be displayed. Similar to Simba's
Writeln, except it doesn't support automatically displaying arrays. Returns
the line number which the text was printed on.

.. note::

Author: Daniel
Date Added: 9/01/2012

Example:

.. code-block:: pascal

begin
Progress_WriteLn('Progress Report for Daniel''s Guild Miner: ');
end.
*)
function Progress_WriteLn(const V: Variant): Integer;
begin
if(not(Assigned(PF_ProgressForm))) then
Exit;

Result := PF_ProgressForm_Text.Lines.Add(V);

// Compensate for those "one-liner" progress report forms.
if(PF_ProgressForm.Height < 78) then
PF_ProgressForm_Text.SelStart := Length(PF_ProgressForm_Text.Text) - 1;
end;

(*
Progress_ModifyLine
~~~~~~~~~~~

.. code-block:: pascal

function Progress_ModifyLine(const V: Variant; const Line: Integer): Boolean;

Replaces a line's text with V. Line is the line number (can be retrieved from
the above mentioned methiod, Progress_Writeln.

.. note::

Author: Daniel
Date Added: 9/01/2012

Example:

.. code-block:: pascal

begin
Progress_ModifyLine('I am replacing the first line!', 0);
end.
*)
function Progress_ModifyLine(const V: Variant; const Line: Integer): Boolean;
begin
if(not(Assigned(PF_ProgressForm))) then
Exit;

Result := Line < (PF_ProgressForm_Text.Lines.Count);
if(not(Result)) then
Exit;

PF_ProgressForm_Text.Lines.Strings[Line] := V;
end;

(*
Progress_Clear
~~~~~~~~~~~

.. code-block:: pascal

procedure Progress_Clear;

Erases the entire contents of the text box on the Progress Report Form. Similar
to Simba's ClearDebug().

.. note::

Author: Daniel
Date Added: 9/01/2012

Example:

.. code-block:: pascal

begin
Progress_Clear;
end.
*)
procedure Progress_Clear;
begin
if(not(Assigned(PF_ProgressForm))) then
Exit;

PF_ProgressForm_Text.Lines.Clear;
end;

(*
Progress_ChangeCaption
~~~~~~~~~~~

.. code-block:: pascal

procedure Progress_ChangeCaption(const NewCaption: String);

Changes the title of the Progress Report Form to NewCaption.

.. note::

Author: Daniel
Date Added: 9/01/2012

Example:

.. code-block:: pascal

begin
Progress_ChangeCaption('This is the new title!');
end.
*)
procedure Progress_ChangeCaption(const NewCaption: String);
begin
if(not(Assigned(PF_ProgressForm))) then
Exit;

PF_ProgressForm.Caption := NewCaption;
end;

{* ******************************************************************************
DO NOT TOUCH, AND *ESPECIALLY* DO NOT CALL ANY METHODS LISTED BELOW HERE.
THEY ARE NAMED 'UNSAFE' FOR A REASON.

Unless you know what you are doing, DON'T TOUCH!

- Regards, Daniel. =)
****************************************************************************** *}

procedure ThreadSafeCallNoParams(const ProcName: String);
var
Params: TVariantArray;
begin
Params := [];
ThreadSafeCall(ProcName, Params);
end;

procedure PF_OnProgressTimer(Sender: TObject);
begin
if(Sender = PF_ProgressForm_Updater) then
try
OnProgressUpdate();
except
srl_Warn('PF_OnProgressTimer', 'Unable to call OnProgressUpdate. Exception raised.', warn_AllVersions);
end;
end;

procedure PF_ProgressCanClose(Sender: TObject; var CanClose: Boolean);
begin
CanClose := PF_ProgressClose;
end;

procedure UnsafeSetupProgress(const Left, Top, Right, Bottom: Integer);
begin
PF_ProgressForm := TForm.Create(nil);
PF_ProgressForm.SetBounds(Left, Top, Right, Bottom);
PF_ProgressForm.Caption := Progress_ScriptName + ' - Progress Report';
PF_ProgressForm.Position := poMainFormCenter;
PF_ProgressForm.BorderStyle := bsSingle; // Non-resizeable, non-maximisable form. Which is what we want.
PF_ProgressForm.OnCloseQuery := @PF_ProgressCanClose;
PF_ProgressForm.FormStyle := fsStayOnTop;

PF_ProgressForm_Text := TMemo.Create(PF_ProgressForm);
PF_ProgressForm_Text.Parent := PF_ProgressForm;
PF_ProgressForm_Text.SetBounds(Left + 20, Top + 20, Right - 40, Bottom - 40);
PF_ProgressForm_Text.Font.Name := 'Courier New';
PF_ProgressForm_Text.Font.Size := 10;
PF_ProgressForm_Text.ReadOnly := True;
PF_ProgressForm_Text.WordWrap := False;

PF_ProgressForm_Updater := TTimer.Create(PF_ProgressForm);
PF_ProgressForm_Updater.Interval := DEFAULT_INTERVAL;
PF_ProgressForm_Updater.OnTimer := @PF_OnProgressTimer;
{PF_ProgressForm_Updater.Enabled := True; }

PF_ProgressForm_Background := TImage.Create(PF_ProgressForm);
PF_ProgressForm_Background.Parent := PF_ProgressForm;
PF_ProgressForm_Background.SetBounds(Left, Top, Right, Bottom);
PF_ProgressForm_Background.Stretch := True;
PF_ProgressForm_Background.SendToBack;

AddOnTerminate('Progress_Unload');
end;

procedure UnsafeUnloadProgress;
begin
{ Form components }
PF_ProgressForm_Background.Free;
PF_ProgressForm_Background := nil;
PF_ProgressForm_Text.Free;
PF_ProgressForm_Text := nil;
PF_ProgressForm_Updater.Free;
PF_ProgressForm_Updater := nil;

{ The actual form itself }
PF_ProgressForm.Free;
PF_ProgressForm := nil;
end;

procedure UnsafeShowProgress;
begin
PF_ProgressForm.Show;
PF_ProgressForm_Updater.Enabled := True;
end;

procedure UnsafeCloseProgress;
begin
PF_ProgressForm.Close;
PF_ProgressForm_Updater.Enabled := False;
end;

// I did this for a reason. I can't exactly recall if setting the interval
// without destroying the component worked or not.
procedure UnsafeChangeInterval(const NewInterval: Cardinal);
var
WasAlreadyEnabled: Boolean; // Rather self-explanatory...
begin
WasAlreadyEnabled := False;

if(Assigned(PF_ProgressForm_Updater)) then
begin
WasAlreadyEnabled := PF_ProgressForm_Updater.Enabled;

PF_ProgressForm_Updater.Free;
PF_ProgressForm_Updater := nil;
end;

PF_ProgressForm_Updater := TTimer.Create(PF_ProgressForm);
PF_ProgressForm_Updater.OnTimer := @PF_OnProgressTimer;
PF_ProgressForm_Updater.Interval := NewInterval;
PF_ProgressForm_Updater.Enabled := WasAlreadyEnabled;
end;

And damn you Kyle Undefined! This made me stay awake until 4am (couple of hours after you told me what you did to help you "sleep")! :p

Coh3n

2012-01-08 18:41:06

Sceenshots? :)

Narcle

2012-01-08 19:16:32

Oh sweet I was thinking about seeing if this could even be done lol. I was even thinking like a small form (like a progress bar when torrenting) that you could keep up on screen to see if its still running etc.

mormonman

2012-01-08 20:31:23

I thought about doing something like this, good job. :)

Edit: BTW, who said it was impossible?

Dgby714

2012-01-08 20:44:22

Make sure your OnProgressUpdate call is in a try..except.
There is a chance of getting an exception.
I would say use TCriticalSection, tho idk if we export the class.

Coh3n

2012-01-08 21:01:58

Could this possibly replace the SRL progress report?

Narcle

2012-01-08 21:18:20

From: Coh3n
Could this possibly replace the SRL progress report?


I think we can just add this into reports and add the option to view it with SRL reports as well. So when you call it you can set it to use form/debug (there's already a setting for this, so it won't break anything).

Coh3n

2012-01-08 21:59:42

From: Narcle
I think we can just add this into reports and add the option to view it with SRL reports as well. So when you call it you can set it to use form/debug (there's already a setting for this, so it won't break anything).
But they're different systems are they not? Unless this uses SRL's report functions to display them in a separate window.

Flight

2012-01-08 22:06:59

I'm gonna try this out asap! Very, very nice work, Daniel. :)

Daniel

2012-01-08 22:32:16

From: Dgby714
Make sure your OnProgressUpdate call is in a try..except.
There is a chance of getting an exception.
I would say use TCriticalSection, tho idk if we export the class.

The chance of that would be next to nil, since Simba would throw any interpretation errors beforehand.

From: Narcle
Oh sweet I was thinking about seeing if this could even be done lol. I was even thinking like a small form (like a progress bar when torrenting) that you could keep up on screen to see if its still running etc.

That's what this is :) It's a form which runs alongside your own script, constantly updating at a given interval, which either stays on top of all other windows or is minimised to the bottom. Note, the user cannot close this form by simply pressing the 'X' button.

From: Coh3n
But they're different systems are they not? Unless this uses SRL's report functions to display them in a separate window.

They are different systems. The only dependency this include has is /Core/Simba.simba, which contains the AddOnTerminate method. I don't understand why not just keep it in a separate include? :s

Narcle

2012-01-08 22:37:27

It can be used just like a custom progress report yes? (any number of lines etc.) Then why not add the option in SRL Reports to use the form?

Daniel

2012-01-09 01:02:52

From: Narcle
It can be used just like a custom progress report yes? (any number of lines etc.)

Yes.
From: Narcle
Then why not add the option in SRL Reports to use the form?

Well, I was aiming for its own include for documentation purposes (plus, Reports.simba won't be able to be parsed by Wizzup's doc system anyway). But absolutely, as long as you include Reports.simba after including Progress.simba (this file) then you can :)

EDIT: New reports.simba, also fixed for SRL-5 docs compatibility. Integrates the Progress Report Form.

Additions by me :):
From: Daniel

  • Allow's printing to the Progess Report Form (created by Daniel, resides in
  • ProgressForm.simba).
  • Allow's multiple result types: e.g., ResultType = ResultDebugBox or ResultProgressForm.
  • Removed ResultReport support (obsolete in Simba).



(*
Reports
======

Don't want to write your own progress report procedure? Get it automatically done
in a nice format with these functions!

.. contents::


*)

const
ResultDebugBox = 1;
ResultString = 2;
ResultProgressForm = 4;

{ SRLProgressReport example
[================================]
[ RM Proggie 1.00 ]
[ by Rasta Magician ]
[================================]
[ TimeRunning : 67h, 58m, 34s ]
[ Total Fish : 56788 ]
[ Active Players : 7 ]
[================================]
[ RM Proggie 1.00 ]
[================================]
}

{ SRLPlayerReport - short example
[=======================================================================================]
[ Nick | Active | Worked | Banked | Loc | fishes | Responses | FishType ]
[=======================================================================================]
[ Rasta Magician | True | 20:10:56 | 43 | lumby | 26 | 162 | trout ]
[ Wizzup? | False | 25:25:53 | 83 | draynor | 99 | 190 | shrimps ]
[ WT-Fakawi | True | 11:37:37 | 55 | draynor | 68 | 122 | shrimps ]
[ Hobbit | False | 24:17:35 | 31 | lumby | 14 | 198 | trout ]
[ Nielsie95 | True | 21:04:37 | 24 | draynor | 2 | 192 | shrimps ]
[ ------------------------------------------------------------------------------------- ]
[ ZephyrsFury | False | 06:12:55 | 0 | draynor | 48 | 168 | shrimps ]
[ Boreas | True | 18:52:54 | 77 | lumby | 94 | 144 | trout ]
[ Sumilion | False | 15:39:55 | 70 | draynor | 82 | 137 | shrimps ]
[ The Claw | False | 17:44:36 | 24 | lumby | 9 | 153 | trout ]
[ Tarajunky | False | 14:31:38 | 18 | draynor | 97 | 146 | shrimps ]
[ ------------------------------------------------------------------------------------- ]
[ Ray | False | 27:11:36 | 94 | lumby | 43 | 122 | trout ]
[ Nava2 | False | 99:59:59 | 86145 | guild | 167854 | 9999785 | SHARK ]
[=======================================================================================]
}

{ SRLPlayerReport - long example
[=========================]
[ Rasta Magician ]
[ Active : True ]
[ Worked : 20h 10m 56s ]
[ Banked : 43 ]
[ Location : lumby ]
[ fishes : 26 ]
[ Responses : 162 ]
[ FishType : trout ]
[=========================]
[ Wizzup? ]
[ Active : False ]
[ Worked : 25h 25m 53s ]
[ Banked : 83 ]
[ Location : draynor ]
[ fishes : 99 ]
[ Responses : 190 ]
[ FishType : shrimps ]
[=========================]
}

(*
SRLProgressReport
~~~~~~~~~~~

.. code-block:: pascal

function SRLProgressReport(
ResultType: integer; ScriptName, ScriptAuthor, ScriptVersion: string;
VarNames: TStringArray;
VarValues: TVariantArray
): Variant;

Prints a Standardized Progress Report, with the variables of your choice

Instructions:
..note::
ResultType => ResultDebugBox, ResultString, ResultProgressReport.
VarNames is a TStringArray, and the order has to be the one you'll use in the VarValues Array
e.g. ['bool1', 'bool2', 'int1', 'string1', 'string2', 'extended1']
VarValues the variable with the values corresponding to VarNames
e.g. [bool1, bool2, int1, string1, string2, extended1]

Additions by Daniel:
.. note::
* Allow's printing to the Progess Report Form (created by Daniel, resides in
ProgressForm.simba).
* Allow's multiple result types: e.g., ResultType = ResultDebugBox or ResultProgressForm.
* Removed ResultReport support (obsolete in Simba).

.. note::

Author: Rasta Magician (modified by Daniel)
Date Modified: 9/01/2012

Example:

.. code-block:: pascal

begin
SRLProgressReport(ResultDebugBox or ResultProgressForm, 'ScriptName', 'ScriptAuthor', '1.00',
['TimeRunning', 'Total Fish', 'Active Players'],
[GetTimeRunning, TotalFish, PlayersActive ]);
end.
*)
function SRLProgressReport(
ResultType: integer; ScriptName, ScriptAuthor, ScriptVersion: string;
VarNames: TStringArray;
VarValues: TVariantArray
): Variant;
var
TSA: TStringArray;
s: string;
i, i2, L: integer;
begin
Result := False;

// Better to do this early on - Daniel
if (not (ResultType and ResultDebugBox <> 0)) then
if (not (ResultType and ResultString <> 0)) then
if (not (ResultType and ResultProgressForm <> 0)) then
begin
SRL_Warn('SRLProgressReport', 'Invalid Result Type', warn_AllVersions);
Exit;
end;

if (not (ResultType and ResultString <> 0)) then
Result := '';

if length(VarNames) <> Length(VarValues) then
begin
SRL_Warn('SRLProgressReport',
'VarNames and VarValues must be the same length', warn_AllVersions);
exit;
end;
SetLength(TSA, 3 + Length(VarNames) + 4);

TSA[0] := '=';
TSA[1] := Capitalize(ScriptName) + ' ' + ScriptVersion;
TSA[2] := 'by ' + ScriptAuthor;
TSA[3] := '=';

i2 := 3 + Length(VarNames);

for i := 4 to i2 do
L := Max(L, Length(VarNames[i - 4]));

for i := 4 to i2 do
begin
s := VarValues[i - 4];
TSA[i] := Padr(Capitalize(VarNames[i - 4]), L) + ' : ' + Capitalize(s);
end;

TSA[i2 + 1] := '=';
TSA[i2 + 2] := Capitalize(ScriptName) + ' ' + ScriptVersion;
TSA[i2 + 3] := '=';

i2 := 0;
for i := 0 to High(TSA) do
i2 := Max(i2, Length(TSA[i]));

TSA[0] := Replicate('=', i2);
TSA[3] := Replicate('=', i2);
TSA[High(TSA) - 2] := Replicate('=', i2);
TSA[High(TSA)] := Replicate('=', i2);

TSA[2] := Replicate(' ', round((i2 - Length(TSA[2])) / 2)) + TSA[2];
//centering by ScriptAuthor
TSA[High(TSA) - 1] := Replicate(' ', round((i2 - Length(TSA[High(TSA) - 1])) /
2)) + TSA[High(TSA) - 1];

for i := 0 to High(TSA) do
if (TSA[i][1] = '=') then
begin
if (ResultType and ResultDebugBox <> 0) then
Writeln('[=' + Padr(TSA[i], i2) + '=]');
if (ResultType and ResultString <> 0) then
Result := Result + '[=' + Padr(TSA[i], i2) + '=]' + chr(13);
if (ResultType and ResultProgressForm <> 0) then
Progress_Writeln('[=' + Padr(TSA[i], i2) + '=]');
end
else
begin
if (ResultType and ResultDebugBox <> 0) then
Writeln('[ ' + Padr(TSA[i], i2) + ' ]');
if (ResultType and ResultString <> 0) then
Result := Result + '[ ' + Padr(TSA[i], i2) + ' ]' + chr(13);
if (ResultType and ResultProgressForm <> 0) then
Progress_Writeln('[ ' + Padr(TSA[i], i2) + ' ]');
end;

if (not (ResultType and ResultString <> 0)) then
Result := True;
end;

(*
SRLPlayerReport
~~~~~~~~~~~

.. code-block:: pascal

function SRLPlayerReport(
ResultType, SkillLevel: Integer; LongReport: boolean;
DefaultSettings: TBooleanArray;
VarNames: TStringArray;
PlayerBooleans, PlayerIntegers, PlayerStrings, PlayerExtendeds: TIntegerArray
): Variant;

Description: Prints a Standardized MultiPlayer Report, with the variables of your choice

Instructions:
.. note::

ResultType => ResultDebugBox, ResultString, ResultProgressReport.
SkillLevel => check Players.scar for the index of each level
e.g. for fishing = 17 ; 0 for none
Default settings: [Players.Worked, Players.Banked, Players.Level, Players.location, Players.Skill, Players.Random]
e.g. [True, True, false, true, false, false]
VarNames is a TStringArray, and the order has to be the one you'll use in the TIntegerArrays
e.g. ['bool1', 'bool2', 'int1', 'string1', 'string2', 'extended1' ]
e.g. ['safe', 'ready', 'fishes', 'EquipName', 'FishType', 'AverageTime/Fish' ]
PlayerBooleans: the index of the booleans you wish to show
e.g. show Players.Boolean[0] and Players.Booleans[3]
==> [0, 3]
Same applies for similarly name TIntegerArrays

Additions by Daniel:
.. note::
* Allow's printing to the Progess Report Form (created by Daniel, resides in
ProgressForm.simba).
* Allow's multiple result types: e.g., ResultType = ResultDebugBox or ResultProgressForm.
* Removed ResultReport support (obsolete in Simba).

.. note::

Author: Rasta Magician (modified by Daniel)
Date Modified: 9/01/2012

Example:

.. code-block:: pascal

begin
SRLPlayerReport(ResultDebugBox , 0, False,
[True, True, False, True, False, False],
['fishes', 'Responses', 'FishType'],
[], [0, 1], [0], []
);
end.
*)
function SRLPlayerReport(
ResultType, SkillLevel: Integer; LongReport: boolean;
DefaultSettings: TBooleanArray;
VarNames: TStringArray;
PlayerBooleans, PlayerIntegers, PlayerStrings, PlayerExtendeds: TIntegerArray
): Variant;
var
TSA: TStringArray;
i, i2, i3, L, PN, c, d: integer;
T2DVA: array of TVariantArray;
begin
Result := False;

// Better to do this early on - Daniel
if (not (ResultType and ResultDebugBox <> 0)) then
if (not (ResultType and ResultString <> 0)) then
if (not (ResultType and ResultProgressForm <> 0)) then
begin
SRL_Warn('SRLPlayerReport', 'Invalid Result Type', warn_AllVersions);
Exit;
end;

if (ResultType = ResultString) then
Result := '';

if Length(DefaultSettings) <> 6 then
begin
SRL_Warn('SRLPlayerReport', 'DefaultSettings must be exactly 6 settings!',
warn_AllVersions);
SetLength(DefaultSettings, 6);
end;

L := Length(PlayerBooleans) + Length(PlayerIntegers) + Length(PlayerStrings) +
Length(PlayerExtendeds);
if length(VarNames) <> L then
begin
SRL_Warn('SRLPlayerReport',
'VarNames and VarValues must be the same length', warn_AllVersions);
exit;
end;

if LongReport then
begin
L := 3;
for i := 0 to high(DefaultSettings) do
if DefaultSettings[i] then
inc(L);

L := L + Length(VarNames);
SetLength(TSA, L * HowManyPlayers + 1);
d := 8;
for i := 0 to High(VarNames) do
d := Max(d, Length(VarNames[i]));

i := 0;
for PN := 0 to (HowManyPlayers - 1) do
begin

TSA[i] := replicate('=', 16);
with Players[PN] do
begin
TSA[i + 1] := Nick;
TSA[i + 2] := padr('Active', d) + ' : ' + BoolToStr(Active);
end;

i := i + 3;
if DefaultSettings[0] then
begin
TSA[i] := padr('Worked', d) + ' : ' + MSToTime(playerWorked(PN),
Time_Short);
inc(i);
end;

for i2 := 1 to High(DefaultSettings) do
if DefaultSettings[i2] then
begin
case i2 of
1: TSA[i] := padr('Banked', d) + ' : ' +
IntToStr(Players[PN].Banked);
2: TSA[i] := padr('Level', d) + ' : ' +
IntToStr(Players[PN].Level[SkillLevel]);
3: TSA[i] := padr('Location', d) + ' : ' + Players[PN].Loc;
4: TSA[i] := padr('Skill', d) + ' : ' + Players[PN].Skill;
5: TSA[i] := padr('Random', d) + ' : ' + Players[PN].Rand;
end;
inc(i);
end;

i2 := 0;
for i3 := 0 to High(PlayerBooleans) do
begin
c := PlayerBooleans[i3];
TSA[i] := padr(VarNames[i2], d) + ' : ' +
BoolToStr(Players[PN].Booleans[c]);
inc(i);
inc(i2);
end;

for i3 := 0 to High(PlayerIntegers) do
begin
c := PlayerIntegers[i3];
TSA[i] := padr(VarNames[i2], d) + ' : ' +
IntToStr(Players[PN].Integers[c]);
inc(i);
inc(i2);
end;

for i3 := 0 to High(PlayerStrings) do
begin
c := PlayerStrings[i3];
TSA[i] := padr(VarNames[i2], d) + ' : ' + Players[PN].Strings[c];
inc(i);
inc(i2);
end;

for i3 := 0 to High(PlayerExtendeds) do
begin
c := PlayerExtendeds[i3];
TSA[i] := padr(VarNames[i2], d) + ' : ' +
FloatToStr(Players[PN].Extendeds[c]);
inc(i);
inc(i2);
end;

end;

i2 := 0;
for i := 0 to High(TSA) do
i2 := Max(i2, Length(TSA[i]));

if i2 > 16 then
for PN := 0 to (HowManyPlayers - 1) do
TSA[PN * L] := Replicate('=', i2);

TSA[High(TSA)] := Replicate('=', i2);

//centering the nick
for PN := 0 to (HowManyPlayers - 1) do
TSA[PN * L + 1] := Replicate(' ', round((i2 - Length(Players[PN].Nick)) /
2)) + Players[PN].Nick;

for i := 0 to High(TSA) do
begin
if i mod L = 0 then
begin
if (ResultType and ResultDebugBox <> 0) then
Writeln('[=' + Padr(TSA[i], i2) + '=]');
if (ResultType and ResultString <> 0) then
Result := Result + '[=' + Padr(TSA[i], i2) + '=]' + chr(13);
if (ResultType and ResultProgressForm <> 0) then
Progress_Writeln('[=' + Padr(TSA[i], i2) + '=]');
end
else
begin
if (ResultType and ResultDebugBox <> 0) then
Writeln('[ ' + Padr(TSA[i], i2) + ' ]');
if (ResultType and ResultString <> 0) then
Result := Result + '[ ' + Padr(TSA[i], i2) + ' ]' + chr(13);
if (ResultType and ResultProgressForm <> 0) then
Progress_Writeln('[ ' + Padr(TSA[i], i2) + ' ]');
end;
end;

if (not (ResultType and ResultString <> 0)) then
Result := True;
end
else
begin
SetLength(T2DVA, HowManyPlayers + 2)
// T2DVA[0] will be used to store string lengths
// T2DVA[1] will be used to store variable names
// The others will be used to store Player Info as strings
SetLength(TSA, HowManyPlayers + 3);
L := 2;

for i := 0 to high(DefaultSettings) do
if DefaultSettings[i] then
inc(L);

L := L + Length(VarNames);
SetLength(T2DVA[0], L);
SetLength(T2DVA[1], L);

T2DVA[1][0] := 'Nick';
T2DVA[1][1] := 'Active';
i := 2;

for i2 := 0 to high(DefaultSettings) do
if DefaultSettings[i2] then
begin
case i2 of
0: T2DVA[1][i] := 'Worked';
1: T2DVA[1][i] := 'Banked';
2: T2DVA[1][i] := 'Level';
3: T2DVA[1][i] := 'Loc';
4: T2DVA[1][i] := 'Skill';
5: T2DVA[1][i] := 'Rand';
end;
inc(i);
end;

for i2 := 0 to High(VarNames) do
begin
T2DVA[1][i] := VarNames[i2];
inc(i);
end;

i := 0;
for PN := 0 to HowManyPlayers - 1 do
begin
SetLength(T2DVA[PN + 2], L);
T2DVA[PN + 2][0] := Players[PN].Nick;
T2DVA[PN + 2][1] := BoolToStr(Players[PN].Active);

i := 2;
for i2 := 0 to high(DefaultSettings) do
if DefaultSettings[i2] then
begin
case i2 of
0: T2DVA[PN + 2][i] := MsToTime(PlayerWorked(PN), Time_Bare);
1: T2DVA[PN + 2][i] := IntToStr(Players[PN].Banked);
2: T2DVA[PN + 2][i] := IntToStr(Players[PN].Level[SkillLevel]);
3: T2DVA[PN + 2][i] := Players[PN].Loc;
4: T2DVA[PN + 2][i] := Players[PN].Skill;
5: T2DVA[PN + 2][i] := Players[PN].Rand;
end;
inc(i);
end;

for i2 := 0 to High(PlayerBooleans) do
begin
c := PlayerBooleans[i2];
T2DVA[PN + 2][i] := BoolToStr(Players[PN].Booleans[c]);
inc(i);
end;

for i2 := 0 to High(PlayerIntegers) do
begin
c := PlayerIntegers[i2];
T2DVA[PN + 2][i] := IntToStr(Players[PN].Integers[c]);
inc(i);
end;

for i2 := 0 to High(PlayerStrings) do
begin
c := PlayerStrings[i2];
T2DVA[PN + 2][i] := Players[PN].Strings[c];
inc(i);
end;

for i2 := 0 to High(PlayerExtendeds) do
begin
c := PlayerExtendeds[i2];
T2DVA[PN + 2][i] := FloatToStr(Players[PN].Extendeds[c]);
inc(i);
end;
end;

L := High(T2DVA[0]);

for i := 1 to High(T2DVA) do
for i2 := 0 to L do
T2DVA[0][i2] := Max(T2DVA[0][i2], Length(T2DVA[i][i2]));

for i := 1 to High(T2DVA) do
for i2 := 0 to L do
begin
TSA[i] := TSA[i] + Padr(T2DVA[i][i2], T2DVA[0][i2]);
if i2 <> L then
TSA[i] := TSA[i] + ' | ';
end;

i2 := Length(TSA[1]);

TSA[0] := Replicate('=', i2);
TSA[High(TSA)] := Replicate('=', i2);

for i := 0 to High(TSA) do
begin
if (i = 0) or (i = High(TSA)) then
begin
if (ResultType and ResultDebugBox <> 0) then
Writeln('[=' + Replicate('=', i2) + '=]');
if (ResultType and ResultString <> 0) then
Result := Result + '[=' + Replicate('=', i2) + '=]' + chr(13);
if (ResultType and ResultProgressForm <> 0) then
Progress_Writeln('[=' + Replicate('=', i2) + '=]');

Continue;
end;

if (ResultType and ResultDebugBox <> 0) then
Writeln('[ ' + TSA[i] + ' ]');
if (ResultType and ResultString <> 0) then
Result := Result + '[ ' + TSA[i] + ' ]' + chr(13);
if (ResultType and ResultProgressForm <> 0) then
Progress_Writeln('[ ' + TSA[i] + ' ]');

if i = 1 then
begin
if (ResultType and ResultDebugBox <> 0) then
Writeln('[=' + Replicate('=', i2) + '=]');
if (ResultType and ResultString <> 0) then
Result := Result + '[=' + Replicate('=', i2) + '=]' + chr(13);
if (ResultType and ResultProgressForm <> 0) then
Progress_Writeln('[=' + Replicate('=', i2) + '=]');
end;

if i > 5 then
if ((i - 1) mod 5) = 0 then
if i <> (High(TSA) - 1) then
begin
if (ResultType and ResultDebugBox <> 0) then
Writeln('[ ' + Replicate('-', i2) + ' ]');
if (ResultType and ResultString <> 0) then
ResultString: Result := Result + '[ ' + Replicate('-', i2) + ' ]'
+ chr(13);
if (ResultType and ResultProgressForm <> 0) then
Progress_Writeln('[ ' + Replicate('-', i2) + ' ]');
end;
end;
end;
end;

Daniel

2012-01-09 04:38:56

Coh3n:

That's with default settings and a custom background, running the above script (with the addition of a TimeRunning in the progress report) :)

Coh3n

2012-01-09 04:40:45

Oo neat. :) I may add this to my scripts and MSI (after it's added to SRL). Suggestion: have the TMemo's width set to how many characters the longest line in the progress report is.

Kyle Undefined

2012-01-09 05:29:21

Very nice work Daniel! :D

P.S. Did it help you sleep? :p

NCDS

2012-01-09 08:56:03

From: Coh3n
Oo neat. :) I may add this to my scripts and MSI (after it's added to SRL). Suggestion: have the TMemo's width set to how many characters the longest line in the progress report is.


Agree with this. The whole thing (by default) should be relative to the longest line that needs to be printed. Then the user can make changes if necessary.

Looks good though daniel. :)

Daniel

2012-01-09 08:58:09

From: NCDS
Agree with this. The whole thing (by default) should be relative to the longest line that needs to be printed. Then the user can make changes if necessary.

Looks good though daniel. :)

I intentionally set it up so the scripter has a choice on the size, as the scripter would know the size of his/her progress report and the space it will take up.

If we do it that way, the form will 'flash' and move around too much (e.g. when clearing the text).

NCDS

2012-01-09 09:09:31

From: Daniel
I intentionally set it up so the scripter has a choice on the size, as the scripter would know the size of his/her progress report and the space it will take up.

If we do it that way, the form will 'flash' and move around too much (e.g. when clearing the text).


Makes sense. Although, by 'changes' I meant pre-compilation. if not definedValues then Default; or something similar.

Nice job regardless.

Daniel

2012-01-09 09:11:15

From: NCDS
Makes sense. Although, by 'changes' I meant pre-compilation. if not definedValues then Default; or something similar.

Nice job regardless.


Yes, I gathered that. However, I chose a size which would fit standard, wide progress reports (as they are nowadays) with lot's of information. :) I hope that can suffice?

NCDS

2012-01-09 15:16:16

From: Daniel
Yes, I gathered that. However, I chose a size which would fit standard, wide progress reports (as they are nowadays) with lot's of information. :) I hope that can suffice?


No problem with me. I was merely throwing out idea's. :)

Coh3n

2012-03-15 18:10:39

Trying to add this to MSI, but it's executing the script instead of updating the progress report. Haven't been able to find out why yet.

E: I'll figure it out eventually. This is great, though, especially for those long progress reports that can't be painted on SMART (like MSI).

E: Nvm I can't figure it out. I'll have to come back to it later.

Daniel

2012-03-17 08:15:33

The setup should be fairly simple and straightforward.

Also, the form will eventually crash due to this bug :( Hence why development on this has been unable to continue :(

Coh3n

2012-03-17 13:14:34

From: Daniel
The setup should be fairly simple and straightforward.

Also, the form will eventually crash due to this bug :( Hence why development on this has been unable to continue :(
Hm, could somehow be related.

Do the variables have to be declared in the mainloop? I don't see why they would, but you never know.

Sin

2012-03-17 13:20:46

Wow, this looks really nice!
I'll be sure to use it!

Wyn

2012-03-22 13:26:57

Any update on the simba bug related issue?

Coh3n

2012-03-22 13:43:32

No, but I haven't been able to recreate it unless I have this file included, which makes me think it's something to do with that. Rather than Simba.

Daniel

2012-03-24 06:45:03

Hey guys!

Just an update! I have recently created a clone to the TTimer component used in Simba, and I have only today pushed these changes to Simba! :) It is a multi-threaded control, and through several runs, works quite nicely with no errors!

This updated control should be available in the next Simba release.

Cheers,
Daniel. :)

Wyn

2012-03-24 14:35:38

From: Daniel
Hey guys!

Just an update! I have recently created a clone to the TTimer component used in Simba, and I have only today pushed these changes to Simba! :) It is a multi-threaded control, and through several runs, works quite nicely with no errors!

This updated control should be available in the next Simba release.

Cheers,
Daniel. :)


Glad to hear.

Coh3n

2012-03-25 02:48:53

From: Daniel
Hey guys!

Just an update! I have recently created a clone to the TTimer component used in Simba, and I have only today pushed these changes to Simba! :) It is a multi-threaded control, and through several runs, works quite nicely with no errors!

This updated control should be available in the next Simba release.

Cheers,
Daniel. :)
Looking forward to it. :)