Recent

Author Topic: Typing Speed Measurement Interface  (Read 4469 times)

yorako1

  • Guest
Typing Speed Measurement Interface
« on: January 19, 2012, 11:54:10 pm »
Hello,
for those who are interested...

I am new to lazarus...

Yes, I posted a quite trivial code... But anyway: this Class is for those guys who are interested in getting the typing speed for training or sth...

Code an demo here:
http://yorako1.bplaced.net/lazarus/typespeed_interface.zip

pas-units from here (have fun :)

Interface and implementation:
Code: [Select]
unit cl_TypeMeasurement;

{$mode delphi}{$H+}

interface

uses
  Classes, SysUtils, ExtCtrls;

type
  TOnHitsPerMinEvent = procedure(Sender: TObject; AHits: Integer) of object;

  { ITypeSpeedMeasurement }

  ITypeSpeedMeasurement = interface
    ['{A250DA8B-92A9-4A37-8C02-C3625E2CE861}']
    procedure Start;
    function Stop: Integer;
    procedure IncreaseHit;
    procedure SetTimer(const AValue: TTimer);
    function GetTimer: TTimer;
    property Timer: TTimer read GetTimer write SetTimer;
    function GetOnHitsPerMin: TOnHitsPerMinEvent;
    procedure SetOnHitsPerMin(const AValue: TOnHitsPerMinEvent);
    property OnHitsPerMin: TOnHitsPerMinEvent read GetOnHitsPerMin write SetOnHitsPerMin;
  end;

  { TTypeSpeedMeasurement }

  TTypeSpeedMeasurement = class(TInterfacedObject, ITypeSpeedMeasurement)
  private
    FNbrHit: Integer;
    FStartTime: TDateTime;
    FTimer: TTimer;
    FOnHitsPerMin: TOnHitsPerMinEvent;
    procedure SetTimer(const AValue: TTimer);
    function GetTimer: TTimer;
    function GetOnHitsPerMin: TOnHitsPerMinEvent;
    procedure SetOnHitsPerMin(const AValue: TOnHitsPerMinEvent);
  protected
    procedure OnTimer(Sender: TObject); virtual;
    procedure DoHit(AHits: Integer); virtual;
  public
    constructor Create(AInterval: Integer = 2000);
    destructor Destroy; override;
    procedure Start;
    function Stop: Integer;
    procedure IncreaseHit;
    property Timer: TTimer read GetTimer write SetTimer;
    property OnHitsPerMin: TOnHitsPerMinEvent read GetOnHitsPerMin write SetOnHitsPerMin;
  end;


implementation

{ TTypeSpeedMeasurement }

procedure TTypeSpeedMeasurement.SetTimer(const AValue: TTimer);
begin
  FTimer := AValue;
end;

function TTypeSpeedMeasurement.GetTimer: TTimer;
begin
  Result := FTimer;
end;

function TTypeSpeedMeasurement.GetOnHitsPerMin: TOnHitsPerMinEvent;
begin
  Result := FOnHitsPerMin;
end;

procedure TTypeSpeedMeasurement.SetOnHitsPerMin(
  const AValue: TOnHitsPerMinEvent);
begin
  FOnHitsPerMin := AValue;
end;

procedure TTypeSpeedMeasurement.OnTimer(Sender: TObject);
begin
  Stop;
  Start;
end;

procedure TTypeSpeedMeasurement.DoHit(AHits: Integer);
begin
  if Assigned(FOnHitsPerMin) then
    FOnHitsPerMin(Self, AHits);
end;

constructor TTypeSpeedMeasurement.Create(AInterval: Integer);
begin
  inherited Create;
  FTimer := TTimer.Create(nil);
  FTimer.Enabled := False;
  FTimer.Interval := AInterval;
  FTimer.OnTimer := OnTimer;
  FTimer.Enabled := True;
  Start;
end;

destructor TTypeSpeedMeasurement.Destroy;
begin
  FTimer.Enabled := False;
  FreeAndNil(FTimer);
  inherited Destroy;
end;

procedure TTypeSpeedMeasurement.Start;
begin
  FNbrHit := 0;
  FStartTime := Time;
end;

function TTypeSpeedMeasurement.Stop: Integer;
var
  Hour,Min,Sec,Msec : Word;
  ElapsedMin : Double;
begin
  Result := 0;
  DecodeTime(Time - FStartTime, Hour, Min, Sec, Msec);
  ElapsedMin := (Hour * 60) + Min + (Sec / 60) + (Msec / (60 * 60));
  Result := (round( FNbrHit / ElapsedMin));
  DoHit(Result);
end;

procedure TTypeSpeedMeasurement.IncreaseHit;
begin
  inc(FNbrHit);
end;

end.


Demo app:

Code: [Select]
unit Unit1;

{$mode delphi}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
  ExtCtrls, cl_TypeMeasurement;

type

  { TForm1 }

  TForm1 = class(TForm)
    Label1: TLabel;
    Memo1: TMemo;
    procedure FormCreate(Sender: TObject);
    procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  private
    FTypeMeasure: IInterface;
    procedure OnHitsPerMinute(Sender: TObject; AHits: Integer);
  public
  end;

var
  Form1: TForm1;

implementation


{$R *.lfm}

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
var
  AIntf: IInterface;
begin
  FTypeMeasure := TTypeSpeedMeasurement.Create;
  if Supports(FTypeMeasure,ITypeSpeedMeasurement,AIntf) then
  begin
    (AIntf as ITypeSpeedMeasurement).OnHitsPerMin:=OnHitsPerMinute;
  end;
end;

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
var
  AIntf: IInterface;
begin
  if assigned(FTypeMeasure) then
  begin
    if Supports(FTypeMeasure,ITypeSpeedMeasurement,AIntf) then
      (AIntf as ITypeSpeedMeasurement).IncreaseHit;
  end;
end;

procedure TForm1.OnHitsPerMinute(Sender: TObject; AHits: Integer);
begin
  Label1.Caption:=IntToStr(AHits);
end;

end.


Useful perhaps for a typing tutor...

Cheers,

yorako1

//EDIT:
Tip:
if you declare "FTypeMeasure: IInterface;" as "FTypeMeasure: ITypeSpeedMeasurement ;"
Then you don't need "supports"
« Last Edit: January 20, 2012, 11:54:54 am by yorako1 »

BigChimp

  • Hero Member
  • *****
  • Posts: 5740
  • Add to the wiki - it's free ;)
    • FPCUp, PaperTiger scanning and other open source projects
Re: Typing Speed Measurement Interface
« Reply #1 on: January 20, 2012, 05:28:13 am »
Yorako1,

Nice code!  :)

I think you may be new to Lazarus but have seen Delphi before... ;D

As I'm not still not sure how to pass events from classes to consumers of those classes, your clean and clear code is helping me a lot. (I think understanding how you can have a variable that links to a function is still hard for me  :) )
Want quicker answers to your questions? Read http://wiki.lazarus.freepascal.org/Lazarus_Faq#What_is_the_correct_way_to_ask_questions_in_the_forum.3F

Open source including papertiger OCR/PDF scanning:
https://bitbucket.org/reiniero

Lazarus trunk+FPC trunk x86, Windows x64 unless otherwise specified

yorako1

  • Guest
Re: Typing Speed Measurement Interface
« Reply #2 on: January 20, 2012, 11:24:16 am »
Hi BigChimp,

Thanks,

Yes I come from Delphi... Now I'm playing a little around with Lazarus/Freepascal...

I really like it more and more...

I can't afford Delphi any longer and the Starter version is not enough... I use an older Delphi version and switch slowly to Lazarus...

Cheers,

Yorako1

yorako1

  • Guest
Re: Typing Speed Measurement Interface
« Reply #3 on: January 20, 2012, 11:45:16 am »
Hi,

here is a simple Callback... Hope you understand a bit more...

Code: [Select]
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ComCtrls,
  StdCtrls;

  //Simple Callback passing to a variable

  // for this example just place a button and progressbar on the form

type
  // Callback function to be invoked by any outer function/procedure
  TMyCallbackProc = procedure(const APos, AMax: Integer) of object; stdcall;  // functions as well

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    ProgressBar1: TProgressBar;
    procedure Button1Click(Sender: TObject);
  private
    procedure MyCallBack(const APos, AMax: Integer); stdcall;
    procedure CallReference(ACallback: TMyCallbackProc);
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
begin
  CallReference(@MyCallBack);
end;

procedure TForm1.MyCallBack(const APos, AMax: Integer); stdcall;
begin
  // here you can handle single items
  // e.g. if you iterate (e.g. for-loop) items or sth...

  // i just update the progressbar

  // if this proc was a function
  // you could add conditions to
  // tell the outer function e.g.
  // to stop or go on (or what ever)
  ProgressBar1.Position:=APos;
  ProgressBar1.Max:=AMax;
end;

procedure TForm1.CallReference(ACallback: TMyCallbackProc);
var
  i: integer;
  iMax: Integer;
begin
  if assigned(ACallback) then
  begin
    // CallReference does not care
    // about what ACallback can do :)

    // you can define more
    // MyCallBack-similar function
    // and pass them how you like...
    iMax := 10;
    for i := 0 to iMax-1 do
    begin
      ACallback(i+1,iMax);
      sleep(500);  // just to show, the progressbar steps up
    end;
  end;
end;

end.


Cheers,

yorako1

BigChimp

  • Hero Member
  • *****
  • Posts: 5740
  • Add to the wiki - it's free ;)
    • FPCUp, PaperTiger scanning and other open source projects
Re: Typing Speed Measurement Interface
« Reply #4 on: January 20, 2012, 12:04:27 pm »
Thanks Yorako, I think I'm starting to get it  :D (I do understand the idea of callbacks and raising events in classes, the implemention in Pascal just seems a bit weird.)

That's going into my snippet collection  :D
Want quicker answers to your questions? Read http://wiki.lazarus.freepascal.org/Lazarus_Faq#What_is_the_correct_way_to_ask_questions_in_the_forum.3F

Open source including papertiger OCR/PDF scanning:
https://bitbucket.org/reiniero

Lazarus trunk+FPC trunk x86, Windows x64 unless otherwise specified