Programming approach advice please...
Programming approach advice please...
Hi All,
I'm in the middle of buildin a PB app that uses INI files containing logic and values to calculate Migration Work Effort. I'm trying to avoid hard-coding any of the logic.
I guess I'm effectively trying to build a maths algebra parser.
./Migration.ini:
[Scenario1]
MigrationScenario = MyApplication v3 - v4.6 upgrade
Task1 = 2.5 # Pilot days
Task2 = .5 # Data Conversion days
Task3 = 3 # Application and OS Install days
Task4 = 2.3 # Testing days
./Formula.ini
[ServerMigrationFormula]
Workeffort=(SourceServers.w * Task2) + (TargetServers * (Task3 + Task4 ) + Task1 + (DataToxfer * 1Gbps.w)
So my question is very open - what approach would you take to try do this in PB - any advice would be greatly appreciated?
Should I try to parse each element in the formula?
Would it be best to simply give up and Hard Code the formula?
Is there an equivalent to UNIX'x expr function?
Does anyone know of a PB Lib that makes this stuff easier?
I'm in the middle of buildin a PB app that uses INI files containing logic and values to calculate Migration Work Effort. I'm trying to avoid hard-coding any of the logic.
I guess I'm effectively trying to build a maths algebra parser.
./Migration.ini:
[Scenario1]
MigrationScenario = MyApplication v3 - v4.6 upgrade
Task1 = 2.5 # Pilot days
Task2 = .5 # Data Conversion days
Task3 = 3 # Application and OS Install days
Task4 = 2.3 # Testing days
./Formula.ini
[ServerMigrationFormula]
Workeffort=(SourceServers.w * Task2) + (TargetServers * (Task3 + Task4 ) + Task1 + (DataToxfer * 1Gbps.w)
So my question is very open - what approach would you take to try do this in PB - any advice would be greatly appreciated?
Should I try to parse each element in the formula?
Would it be best to simply give up and Hard Code the formula?
Is there an equivalent to UNIX'x expr function?
Does anyone know of a PB Lib that makes this stuff easier?
Ta - N
-
PolyVector
- Enthusiast

- Posts: 499
- Joined: Wed Sep 17, 2003 9:17 pm
- Location: Southern California
- Contact:
Here's a great expression evaluator that may help you... Look about 10 posts down...
viewtopic.php?t=8059&highlight=eval
To use it with variables you might do something like this:
viewtopic.php?t=8059&highlight=eval
To use it with variables you might do something like this:
Code: Select all
Expression$=ReplaceString(Expression$,"SourceServers",SourceServers)
Answer$=Eval(Expression$)
Last edited by PolyVector on Mon Sep 13, 2004 1:39 pm, edited 1 time in total.
Are .ini files and parsing, etc, required or would embedded scripting be an answer?
BalrogSoft:
viewtopic.php?t=9651&highlight=
FloHimself:
viewtopic.php?t=8056&highlight=lua
Also IIRC there are some VB scripting egs around somewhere.
BalrogSoft:
viewtopic.php?t=9651&highlight=
FloHimself:
viewtopic.php?t=8056&highlight=lua
Also IIRC there are some VB scripting egs around somewhere.
@}--`--,-- A rose by any other name ..
@Dare2,
No not scripting - definitely Formula parsing (cant give the users too much control
@Poly
Hmmm! That looks interesting, I did some searches for eval but there were 100's of *hits* that didnt quite match. I obviously missed that one - but it seems to be perfect, even MEM facility....
Guys thanks very much for your help, unfortunately, I wont be able to post the fruits of my labour because my employer has copyright to my every passing thought
- again thanks for your advice
No not scripting - definitely Formula parsing (cant give the users too much control
@Poly
Hmmm! That looks interesting, I did some searches for eval but there were 100's of *hits* that didnt quite match. I obviously missed that one - but it seems to be perfect, even MEM facility....
Guys thanks very much for your help, unfortunately, I wont be able to post the fruits of my labour because my employer has copyright to my every passing thought
Ta - N
@GedB,
A doddle for you maybe - but I'm a pretty average coder at best...
Also, using s-expressions would discourage my users from adding their own formulae - they need something familiar.
What I'm hoping to do is create 50 - 100 scenarios initially, then for my users to expand this themselves - so it has to be easy to notate.
My requirements are fairly simple, I think
()+-*/ and variables
- not much more than that...
A doddle for you maybe - but I'm a pretty average coder at best...
Also, using s-expressions would discourage my users from adding their own formulae - they need something familiar.
What I'm hoping to do is create 50 - 100 scenarios initially, then for my users to expand this themselves - so it has to be easy to notate.
My requirements are fairly simple, I think
()+-*/ and variables
- not much more than that...
Ta - N
Naw,
Trust me, you can get away with some easy easy code. I'll post a sample if I get time.
However, it really isn't something for end users to have to deal with.
Slightly more difficult is using spreadsheet style format:
Workeffort = Sum(Multiply(SourceServer, Task2), Multiply(TargetServers, Sum(Task3, Task4)), Task1, Multiply(DataToxfer, 1Gbps.w))
This makes more sense to end users, especially if they have spreadsheet experience.
The main thing is trying to avoid having to write a recursive descent parser. That is when coding become more difficult.
Trust me, you can get away with some easy easy code. I'll post a sample if I get time.
However, it really isn't something for end users to have to deal with.
Slightly more difficult is using spreadsheet style format:
Workeffort = Sum(Multiply(SourceServer, Task2), Multiply(TargetServers, Sum(Task3, Task4)), Task1, Multiply(DataToxfer, 1Gbps.w))
This makes more sense to end users, especially if they have spreadsheet experience.
The main thing is trying to avoid having to write a recursive descent parser. That is when coding become more difficult.
@GedB

The Spreadsheet format looks ok
Workeffort = Sum(Multiply(SourceServer, Task2), Multiply(TargetServers, Sum(Task3, Task4)), Task1, Multiply(DataToxfer, 1Gbps.w))
- I guess this would be easier to pasrse than
Workeffort=(SourceServers.w * Task2) + (TargetServers * (Task3 + Task4 ) + Task1 + (DataToxfer * 1Gbps.w)
I prefer the second example - but either would do what I want
Thanks for the reply, I hope you can find time to post an example, it would be veryt much appreciated and useful learning for me
Ta - N
The Spreadsheet format looks ok
Workeffort = Sum(Multiply(SourceServer, Task2), Multiply(TargetServers, Sum(Task3, Task4)), Task1, Multiply(DataToxfer, 1Gbps.w))
- I guess this would be easier to pasrse than
Workeffort=(SourceServers.w * Task2) + (TargetServers * (Task3 + Task4 ) + Task1 + (DataToxfer * 1Gbps.w)
I prefer the second example - but either would do what I want
Thanks for the reply, I hope you can find time to post an example, it would be veryt much appreciated and useful learning for me
Ta - N
Ta - N
Purely by accident, I came accross FMLCalc on http://www.purearea.net/ coded by Sebastian Lackner. Unfortunately, its a DLL - but it seems to do the job I want very nicely - even includes support of Variables which can be notated outside of PB but have their values loaded inside PB...
for instance:
setvarS_("ABC","1234")
Debug(formel_("(([ABC]*2) + 4321) / 2"))
Documentation is in German but I translated through Babelfish (hence the interesting choice of wording in places :-\ )
Thanks All - N
fmlcalc.dll
===========
FmlCalc is DLL for counting complex formulas the running time of a program! With it formulas
can be computed, which does not admit to compiling the program yet at all was and by the user
was entered or from a file read! The DLL contains functions for the following actions:
All basic instructions for counting:
(+ , - , * , / , ^(Power))
Comparisons of text and numbers also:
(= , < , <= , > , >= , <>)
Appendices of texts (&) Using comma numbers and numbers within the negative range (float one uses!)
Counting after more correctly math. order! (point before line...) Extending the DLL by inserting
external functions: Functions can have 0-10 parameters! -Die parameters are always handed over into
stringers! Variables can be used!: They is "[" of; and "]" enclosed!
AGAIN! Now 4 formats are supported! Dec, Hex, is, Oct. In order to define, what for a number it is,
the initial letter must be attached: e.g.. HEX: 4ABh IS: 100101b OCT: 3527o even if it as result a
value in these formats to have want, then they must insert suitable functions (see appendix!)
Functions Parameter Description
========== ========= ============
INSTRUCTIONS FOR EXTERNAL FUNCTIONS
RemFunc FncName.s removes an external function from the list
SetFunc FncName.s specifies an external function or changes the
ParamCnt.l characteristics. Those ADDR-EATS can in PB with
Addresse.l @Prozedur_Name() be determined!
ClearFuncs -n/a- Empties the list with all external functions
GetFuncCallID FncName.s supplies address of the indicated function!
GetFuncParamCnt FncName.s supplies the number of parameters of the indicated
function!
INSTRUCTIONS FOR VARIABLES
==========================
RemVar VarName.s removes a variable from the list
SetVarS VarName.s A variable sets on a text or a number, which is
strVal.s contained in the stringer!
SetVarL VarName.s LngVal.l into a stringer and puts the variable converts
lngVal.l the parameter to the indicated value!
ClearVars -n/a- Empties the list with all variables!
GetVarS VarName.s Supplies ADDR-EAT to the value indicated variable.
Around the value too gotten the instruction PeekS
(can be used...) in PB!
Form of an external function in PB
===========================
Global Result.s ; Definiert a global variable, thereby the result of the function
; also after "ProcedureReturn" remains still preserved!
Procedure.l Externe_Funktion(Parameter1.s, Parameter2.s); Definition the procedure!
;HERE COUNTED AND the RESULT IN Result.s MUST STORED
ProcedureReturn @Result.s ; Return the result!
EndProcedure
Appendix
========
Here still the functions of kind of condition to the expenditure of Hex, are and Oct numbers
;----HEX----
Global Result.s
Procedure.l _Hex( value.s )
Result=Chr(34)+Hex(Val(value))+Chr(34)
ProcedureReturn @Result
EndProcedure
;----BIN----
Global Result.s
Procedure.l _Bin( value.s )
Result=Chr(34)+Bin(Val(value))+Chr(34)
ProcedureReturn @Result
EndProcedure
;----OCT----
Global Result.s
Procedure.l _Oct( value.s )
Result=""
DecValue=Abs(Val(value))
Repeat
Result=Str(DecValue&7)+Result
DecValue>>3
Until DecValue=0
Result=Chr(34)+Result+Chr(34)
ProcedureReturn @Result
EndProcedure
SetFunc_("Hex",1,@_Hex())
SetFunc_("Bin",1,@_Bin())
SetFunc_("Oct",1,@_Oct())
After this code also the instructions are e.g. Hex(9999), Bin(1024) or Oct(999) possible, in order to control the output format.
Author
=====
Programmer: Sebastian Lackner (www.adventuretipps.de)
Fragen, Anregungen und Kritik an purefan@freenet.de
for instance:
setvarS_("ABC","1234")
Debug(formel_("(([ABC]*2) + 4321) / 2"))
Documentation is in German but I translated through Babelfish (hence the interesting choice of wording in places :-\ )
Thanks All - N
fmlcalc.dll
===========
FmlCalc is DLL for counting complex formulas the running time of a program! With it formulas
can be computed, which does not admit to compiling the program yet at all was and by the user
was entered or from a file read! The DLL contains functions for the following actions:
All basic instructions for counting:
(+ , - , * , / , ^(Power))
Comparisons of text and numbers also:
(= , < , <= , > , >= , <>)
Appendices of texts (&) Using comma numbers and numbers within the negative range (float one uses!)
Counting after more correctly math. order! (point before line...) Extending the DLL by inserting
external functions: Functions can have 0-10 parameters! -Die parameters are always handed over into
stringers! Variables can be used!: They is "[" of; and "]" enclosed!
AGAIN! Now 4 formats are supported! Dec, Hex, is, Oct. In order to define, what for a number it is,
the initial letter must be attached: e.g.. HEX: 4ABh IS: 100101b OCT: 3527o even if it as result a
value in these formats to have want, then they must insert suitable functions (see appendix!)
Functions Parameter Description
========== ========= ============
INSTRUCTIONS FOR EXTERNAL FUNCTIONS
RemFunc FncName.s removes an external function from the list
SetFunc FncName.s specifies an external function or changes the
ParamCnt.l characteristics. Those ADDR-EATS can in PB with
Addresse.l @Prozedur_Name() be determined!
ClearFuncs -n/a- Empties the list with all external functions
GetFuncCallID FncName.s supplies address of the indicated function!
GetFuncParamCnt FncName.s supplies the number of parameters of the indicated
function!
INSTRUCTIONS FOR VARIABLES
==========================
RemVar VarName.s removes a variable from the list
SetVarS VarName.s A variable sets on a text or a number, which is
strVal.s contained in the stringer!
SetVarL VarName.s LngVal.l into a stringer and puts the variable converts
lngVal.l the parameter to the indicated value!
ClearVars -n/a- Empties the list with all variables!
GetVarS VarName.s Supplies ADDR-EAT to the value indicated variable.
Around the value too gotten the instruction PeekS
(can be used...) in PB!
Form of an external function in PB
===========================
Global Result.s ; Definiert a global variable, thereby the result of the function
; also after "ProcedureReturn" remains still preserved!
Procedure.l Externe_Funktion(Parameter1.s, Parameter2.s); Definition the procedure!
;HERE COUNTED AND the RESULT IN Result.s MUST STORED
ProcedureReturn @Result.s ; Return the result!
EndProcedure
Appendix
========
Here still the functions of kind of condition to the expenditure of Hex, are and Oct numbers
;----HEX----
Global Result.s
Procedure.l _Hex( value.s )
Result=Chr(34)+Hex(Val(value))+Chr(34)
ProcedureReturn @Result
EndProcedure
;----BIN----
Global Result.s
Procedure.l _Bin( value.s )
Result=Chr(34)+Bin(Val(value))+Chr(34)
ProcedureReturn @Result
EndProcedure
;----OCT----
Global Result.s
Procedure.l _Oct( value.s )
Result=""
DecValue=Abs(Val(value))
Repeat
Result=Str(DecValue&7)+Result
DecValue>>3
Until DecValue=0
Result=Chr(34)+Result+Chr(34)
ProcedureReturn @Result
EndProcedure
SetFunc_("Hex",1,@_Hex())
SetFunc_("Bin",1,@_Bin())
SetFunc_("Oct",1,@_Oct())
After this code also the instructions are e.g. Hex(9999), Bin(1024) or Oct(999) possible, in order to control the output format.
Author
=====
Programmer: Sebastian Lackner (www.adventuretipps.de)
Fragen, Anregungen und Kritik an purefan@freenet.de
Ta - N
-
FloHimself
- Enthusiast

- Posts: 229
- Joined: Wed May 14, 2003 3:38 pm
- Location: Lüneburg - Germany
but it's a very simple task using the lua lib. you can define how much control the user should have. check this simple example:naw wrote:@Dare2,
No not scripting - definitely Formula parsing (cant give the users too much control![]()
example.pb:
Code: Select all
Global WorkEffort.f, MigrationScenario$ ;global variables
Procedure lua_getglobal(L, s$)
lua_pushstring(L, s$)
lua_gettable(L, #LUA_GLOBALSINDEX)
EndProcedure
Procedure LoadConfig(FileName$)
L = lua_open()
lua_baselibopen(L)
lua_iolibopen(L)
lua_strlibopen(L)
lua_mathlibopen(L)
If (lua_dofile(L, FileName$) <> 0)
MessageRequester("Error","Cannot run configuration file!")
End
Else
lua_getglobal(L, "MigrationScenario")
lua_getglobal(L, "WorkEffort")
If (lua_isnumber(L, -1) = #False) Or (lua_isstring(L, -2) = #False)
MessageRequester("Error","Invalid configuration file!")
End
Else
WorkEffort = lua_tonumber(L, -1)
MigrationScenario$ = PeekS(lua_tostring(L, -2))
EndIf
lua_close(L)
EndIf
EndProcedure
LoadConfig("formula.lua")
MessageRequester(MigrationScenario$, Str(WorkEffort))
EndCode: Select all
-- formula.lua
-- file contains formula to calculate the var "WorkEffort"
--
-- to hide this file from users you can compile it with luac.exe
-- so users can't change any values
--
-- only the vars "WorkEffort" and "MigrationScenario" are read by purebasic
-- any changes in this file may currupt the application and raise
-- a error message
dofile ("migration.lua")
-- program version
MigrationScenario = "MyApplication v3 - v4.6 upgrade"
-- needed values for calculation
SourceServers = 5
TargetServers = 10
DataToxfer = 3
Gbps = 2
-- formula
WorkEffort = (SourceServers * Task2) + (TargetServers * (Task3 + Task4)) + Task1 + (DataToxfer * Gbps)Code: Select all
-- migration.lua
-- file to set custom values
Task1 = 2.5 -- Pilot days
Task2 = 0.5 -- Data Conversion days
Task3 = 3 -- Application and OS Install days
Task4 = 2.3 -- Testing days Hi Flo,
Hmm! I dunno now - I started coding this using the FMLcalc DLL - this actually does exactly what I want.
I can load my Constants and Formulae into a User editable (and extendible) INI file.
I can Define variables in PB - such as Number of Servers, Data to Migrate, Application & OS stuff from the Server&Application Audit data that the user enters
Then I can use these simple User Editable formulae & Constants with PB generated Variables to determine an answer.
I can see though that LUA has advantages too...
I'll play around a little.
I'm glad I posted this note, I wanted to be *aware* of things that otherwise I wouldnt have considered & thats happened very nicely - thanks to all
Hmm! I dunno now - I started coding this using the FMLcalc DLL - this actually does exactly what I want.
I can load my Constants and Formulae into a User editable (and extendible) INI file.
I can Define variables in PB - such as Number of Servers, Data to Migrate, Application & OS stuff from the Server&Application Audit data that the user enters
Then I can use these simple User Editable formulae & Constants with PB generated Variables to determine an answer.
I can see though that LUA has advantages too...
I'll play around a little.
I'm glad I posted this note, I wanted to be *aware* of things that otherwise I wouldnt have considered & thats happened very nicely - thanks to all
Ta - N
-
FloHimself
- Enthusiast

- Posts: 229
- Joined: Wed May 14, 2003 3:38 pm
- Location: Lüneburg - Germany
hi naw,
just wanted to show that it isn't a problem to do this kind of things with lua. sure you can use a ini file for customization, or just create a option window to let the user change values. no problem. just replyed to let everyone know that i'm here, if someone whats to implement scripting features in an application and consider using lua.
if you started with FMLcalc go for it, if it fits your needs!
just wanted to show that it isn't a problem to do this kind of things with lua. sure you can use a ini file for customization, or just create a option window to let the user change values. no problem. just replyed to let everyone know that i'm here, if someone whats to implement scripting features in an application and consider using lua.
if you started with FMLcalc go for it, if it fits your needs!
-
PolyVector
- Enthusiast

- Posts: 499
- Joined: Wed Sep 17, 2003 9:17 pm
- Location: Southern California
- Contact:
Hey FloHimself!
Just wanted to say that your Lua lib is amazing stuff... Keep it up!
I'm still waiting for better 3d support so I can impliment it in a game
Edit:
I was playing with the Lua examples and noticed that average_example.pb crashes when average(l) returns... I changed it to a ProcedureCDLL and it works fine... Does lua use cdecl?
Just wanted to say that your Lua lib is amazing stuff... Keep it up!
I'm still waiting for better 3d support so I can impliment it in a game
Edit:
I was playing with the Lua examples and noticed that average_example.pb crashes when average(l) returns... I changed it to a ProcedureCDLL and it works fine... Does lua use cdecl?
-
FloHimself
- Enthusiast

- Posts: 229
- Joined: Wed May 14, 2003 3:38 pm
- Location: Lüneburg - Germany
thanks polyvector!
yes use cdecl functions as cclosure! had to change the calling convention of the lua functions to stdcall, to make it possible to call them from purebasic. therefore i tried to change the cclosure function inside lua to take stdcall functions. changed that back for some reasons, but not the examples. will update the examples when i get some time..
if you don't like to use ProcedureCDLL you can use a macro.. something like:
and call it like:
yes use cdecl functions as cclosure! had to change the calling convention of the lua functions to stdcall, to make it possible to call them from purebasic. therefore i tried to change the cclosure function inside lua to take stdcall functions. changed that back for some reasons, but not the examples. will update the examples when i get some time..
if you don't like to use ProcedureCDLL you can use a macro.. something like:
Code: Select all
!macro ProcedureReturn NRetVals
!{
!MOV eax, NRetVals
!ADD esp, 16 ;maybe must adjusted..
!POP edi
!POP esi
!POP ebp
!POP ecx
!POP ebx
!RET
!}Code: Select all
[..]
lua_pushnumber(l, sum/n) ; first result average
lua_pushnumber(l, sum) ; second result sum
!ProcedureReturn 2
EndProcedure-
PolyVector
- Enthusiast

- Posts: 499
- Joined: Wed Sep 17, 2003 9:17 pm
- Location: Southern California
- Contact:

