|
|
Using Delphi and Python together - An Example
A Delphi app which has all the business logic implemented as Python code. A perfect marriage of two worlds! The Delphi Code
unit mainFrm; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, PythonEngine, AtomPythonEngine, StdCtrls, ExtCtrls, PythonGUIInputOutput, uHeartMachine; type
TfrmMain = class(TForm)
PE: TAtomPythonEngine;
PythonInputOutput1: TPythonInputOutput;
pdvUser: TPythonDelphiVar;
pdvShare: TPythonDelphiVar;
pdvOrderManager: TPythonDelphiVar;
pdvBankBalance: TPythonDelphiVar;
pdvNumShares: TPythonDelphiVar;
pdvSharePrice: TPythonDelphiVar;
PythonDelphiVar2: TPythonDelphiVar;
lblSharePrice: TLabel;
bntBuy: TButton;
btnForceStockToDrop: TButton;
Timer1: TTimer;
lblBankBalance: TLabel;
lblNumShares: TLabel;
btnSell: TButton;
Memo1: TMemo;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Label4: TLabel;
lblSharesAreWorth: TLabel;
Label5: TLabel;
PythonGUIInputOutput1: TPythonGUIInputOutput;
btnForceStockToRise: TButton;
cbNumShares: TComboBox;
Label6: TLabel;
cbUserLimit: TComboBox;
Label7: TLabel;
lblTotalWorth: TLabel;
Label8: TLabel;
cbNumAttempts: TComboBox;
Label9: TLabel;
Panel1: TPanel;
HeartMachine1: THeartMachine;
Panel2: TPanel;
HeartMachine2: THeartMachine;
Panel3: TPanel;
HeartMachine3: THeartMachine;
procedure PythonInputOutput1SendData(Sender: TObject;
const Data: String);
procedure pdvSharePriceSetData(Sender: TObject; Data: Variant);
procedure FormShow(Sender: TObject);
procedure bntBuyClick(Sender: TObject);
procedure btnForceStockToDropClick(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure btnSellClick(Sender: TObject);
procedure btnForceStockToRiseClick(Sender: TObject);
procedure cbUserLimitChange(Sender: TObject);
procedure cbNumAttemptsChange(Sender: TObject);
procedure PEPathInitialization(Sender: TObject; var Path: String);
private
{ Private declarations }
public
{ Public declarations }
end; TmgmStockMarketMainForm = class(TObject) // ; // Transformation Interface
private
LastPrice : integer;
public
procedure display;
procedure repopulateFromGui;
end;var frmMain: TfrmMain; implementation uses AndyDelphiPy, ComCtrls, pythonAtom, Math; var Share, User, OrderManager : OleVariant; mgmMainForm : TmgmStockMarketMainForm; {$R *.DFM}procedure TfrmMain.PythonInputOutput1SendData(Sender: TObject; const Data: String); begin PyConsoleOut(Data); end; procedure TfrmMain.pdvSharePriceSetData(Sender: TObject; Data: Variant); begin lblSharePrice.Caption := Data; end; procedure TfrmMain.FormShow(Sender: TObject);
begin
//PyExeFile('E:\Python20\Boa-0.0.5\AndysTry\Questtest.py', PE);
PyExeFile('QuesttestFROZEN.py', PE); User := PyClass('User()', pdvUser, PE);
Share := PyClass('Share("Friendly Co.", worth=10)', pdvShare, PE);
OrderManager := PyClass('OrderManager()', pdvOrderManager, PE);
mgmMainForm := TmgmStockMarketMainForm.Create;
timer1.enabled := true;
end;procedure TfrmMain.bntBuyClick(Sender: TObject); begin OrderManager.AddOrder(User.myself, strtoint(cbNumShares.text), 'buy', Share.myself); end; procedure TfrmMain.btnSellClick(Sender: TObject); begin OrderManager.AddOrder(User.myself, strtoint(cbNumShares.text), 'sell', Share.myself); end; procedure TfrmMain.Timer1Timer(Sender: TObject);
begin
try
Share.fluxtuate;
OrderManager.ProcessOrders;
mgmMainForm.display;
except
timer1.enabled := false;
showmessage('Some error cancelled the game.');
end;
end;{ TmgmStockMarketMainForm }procedure TmgmStockMarketMainForm.display;
var
f : double;
begin
if LastPrice = Share.CurrentPrice then
with frmMain.lblSharePrice do
Caption := Caption + '.'
else
frmMain.lblSharePrice.Caption := '$ ' + inttostr(Share.CurrentPrice); LastPrice := Share.CurrentPrice;
f := User.BankBalance;
frmMain.lblBankBalance.Caption := format('%m', [ f ]);
frmMain.lblNumShares.Caption := User.NumSharesOwned;
f := User.NumSharesOwned * Share.CurrentPrice;
frmMain.lblSharesAreWorth.Caption := format('%m', [ f ]);
f := f + User.BankBalance;
frmMain.lblTotalWorth.Caption := format('%m', [ f ]);frmMain.cbNumAttempts.Text := OrderManager.MaxAttempts; frmMain.cbUserLimit.Text := User.SharePriceLimit; frmMain.HeartMachine1.AddPoint(0, min(Share.CurrentPrice, 100), 'Share Price'); frmMain.HeartMachine2.AddPoint(0, min(User.BankBalance, 50000), 'Bank Balance'); frmMain.HeartMachine3.AddPoint(0, min(User.NumSharesOwned, 1000), 'Num Shares Owned'); end; procedure TmgmStockMarketMainForm.repopulateFromGui; begin User.SharePriceLimit := strtoint( frmMain.cbUserLimit.Text ); OrderManager.MaxAttempts := strtoint( frmMain.cbNumAttempts.Text ); display; end; procedure TfrmMain.cbUserLimitChange(Sender: TObject); begin mgmMainForm.repopulateFromGui; end; procedure TfrmMain.cbNumAttemptsChange(Sender: TObject); begin mgmMainForm.repopulateFromGui; end; procedure TfrmMain.btnForceStockToRiseClick(Sender: TObject); begin Share.CurrentPrice := Share.CurrentPrice + 10 + random(20); end; procedure TfrmMain.btnForceStockToDropClick(Sender: TObject); begin Share.CurrentPrice := random(10); end; procedure TfrmMain.PEPathInitialization(Sender: TObject; var Path: String); begin //path := 'e:\try\deploy;e:\try\deploy\lib'; end; end.
The Python CodeNote: Not all the python code is shown, due to confidentiality issues. # Share trading game simulator. false = 0 ; true = 1 import random, sys def log(s):
print s
#sys.stdout.flush()class Share:
def __init__(self, name, worth=10):
self.CurrentPrice = worth
self.Name = name
def __str__(self):
return 'Share ' + self.Name + ' Worth= $' + `self.CurrentPrice` + ' per share.'
def fluxtuate(self):
if random.randrange(0,2):
self.CurrentPrice = self.CurrentPrice + random.randrange(-10,10)
if self.CurrentPrice <= 0:
self.CurrentPrice = 1
##log('..time passes.. ' + str(self))
def myself(self):
return selfclass User:
def __init__(self, initialBankBalance=1000, initialNumShares=0, initialSharePriceLimit=10):
self.BankBalance = initialBankBalance
self.NumSharesOwned = initialNumShares
self.SharePriceLimit = initialSharePriceLimit
def __str__(self):
return 'User Bank balance='+`self.BankBalance` + \
' Number of Shares=' + `self.NumSharesOwned` + \
' Share Price Limit=' + `self.SharePriceLimit`
def myself(self):
return selfclass Order:
def candivest(self):
return self.NumberOfShares <= self.User.NumSharesOwned
def canafford(self):
return (self.Share.CurrentPrice*self.NumberOfShares) < self.User.BankBalance
def sharepricetoolow(self):
return self.Share.CurrentPrice < self.User.SharePriceLimit
def sharepricetoohigh(self):
return self.Share.CurrentPrice > self.User.SharePriceLimit
def __init__(self, user, numshares, buyorsell, share):
self.User = user
self.Share = share
self.NumberOfShares = numshares
self.Command = buyorsell
#print 'DEBUG - self.Share.CurrentPrice', self.Share.CurrentPrice # debug !!!!
def __str__(self):
return 'Order to %s %d %s shares' % (self.Command, self.NumberOfShares, self.Share.Name)
etc.
Related 'Python for Delphi' Links on this site:
return to main Andy Patterns home page
|