I have a Petrol Pump system that runs a timer that simulates the litres that run and the display shows the images inserting into an image box. Then the Price at current is the litres * the set price per litre.

Thats where the problem is because I can't get the Price of the sale working.

I understand the fact of helping with homework and that you won't just do it all for me, if you want to ask more questions then PM me and you can get my MSN if you need to explain in person.

procedure TfrmPump.Timer2Timer(Sender: TObject);
var
 n1,n2,n3,n4,n5:char;
 thissalestr,tempstr:string[5];
 i:integer;


begin
  thissale:= (PriceLitre)*(litres/10) ;
  thissaleStr:=floattostr(thissale);

for i:=1 to length(thissalestr) DO
  IF    thissalestr <> '.' THEN
    tempstr:=tempstr+ thissalestr;

begin

  While Length(tempstr) <5 do
 tempstr:='0'+tempstr;

  Begin
  n1:=thissaleStr[1];
  n2:=thissaleStr[2];
  n3:=thissaleStr[3];
  n4:=thissaleStr[4];
  n5:=thissaleStr[5];

Case n1 of
  '0':Img1.picture.loadfromfile('0.bmp');
  '1':Img1.picture.loadfromfile('1.bmp');
  '2':Img1.picture.loadfromfile('2.bmp');
  '3':Img1.picture.loadfromfile('3.bmp');
  '4':Img1.picture.loadfromfile('4.bmp');
  '5':Img1.picture.loadfromfile('5.bmp');
  '6':Img1.picture.loadfromfile('6.bmp');
  '7':Img1.picture.loadfromfile('7.bmp');
  '8':Img1.picture.loadfromfile('8.bmp');
  '9':Img1.picture.loadfromfile('9.bmp');
End;

Case n2 of
  '0':Img2.picture.loadfromfile('0.bmp');
  '1':Img2.picture.loadfromfile('1.bmp');
  '2':Img2.picture.loadfromfile('2.bmp');
  '3':Img2.picture.loadfromfile('3.bmp');
  '4':Img2.picture.loadfromfile('4.bmp');
  '5':Img2.picture.loadfromfile('5.bmp');
  '6':Img2.picture.loadfromfile('6.bmp');
  '7':Img2.picture.loadfromfile('7.bmp');
  '8':Img2.picture.loadfromfile('8.bmp');
  '9':Img2.picture.loadfromfile('9.bmp');

End;

Case n3 of
  '0':Img3.picture.loadfromfile('0.bmp');
  '1':Img3.picture.loadfromfile('1.bmp');
  '2':Img3.picture.loadfromfile('2.bmp');
  '3':Img3.picture.loadfromfile('3.bmp');
  '4':Img3.picture.loadfromfile('4.bmp');
  '5':Img3.picture.loadfromfile('5.bmp');
  '6':Img3.picture.loadfromfile('6.bmp');
  '7':Img3.picture.loadfromfile('7.bmp');
  '8':Img3.picture.loadfromfile('8.bmp');
  '9':Img3.picture.loadfromfile('9.bmp');
End;

Case n4 of
  '0':Img4.picture.loadfromfile('0.bmp');
  '1':Img4.picture.loadfromfile('1.bmp');
  '2':Img4.picture.loadfromfile('2.bmp');
  '3':Img4.picture.loadfromfile('3.bmp');
  '4':Img4.picture.loadfromfile('4.bmp');
  '5':Img4.picture.loadfromfile('5.bmp');
  '6':Img4.picture.loadfromfile('6.bmp');
  '7':Img4.picture.loadfromfile('7.bmp');
  '8':Img4.picture.loadfromfile('8.bmp');
  '9':Img4.picture.loadfromfile('9.bmp');

end;

Case n5 of
  '0':Img5.picture.loadfromfile('0.bmp');
  '1':Img5.picture.loadfromfile('1.bmp');
  '2':Img5.picture.loadfromfile('2.bmp');
  '3':Img5.picture.loadfromfile('3.bmp');
  '4':Img5.picture.loadfromfile('4.bmp');
  '5':Img5.picture.loadfromfile('5.bmp');
  '6':Img5.picture.loadfromfile('6.bmp');
  '7':Img5.picture.loadfromfile('7.bmp');
  '8':Img5.picture.loadfromfile('8.bmp');
  '9':Img5.picture.loadfromfile('9.bmp');

end;
end;
end;
end;

end.

Why are you dividing the number of liters by 10?

Don't say string[5]. Just use string.

You haven't yet explained exactly what is wrong, so I don't know what better to say... Does this help?

string[5] is just to keep it simple and limited, Do you have msn? it will be much easier to explain my problem there.

I'm afraid not. I'm still in the dark ages...

Explain your problem in terms of what you would like to see and what you are actually seeing, and give a specific example.

For example:
Each time the price changes it should say
000.00
001.99
003.98
etc. but what I am seeing is
000.00
999.99
784.32
...

Well I've tried to PM you more of my code and it doesnt work. Do you have an e-mail I can send to because I dont really want to post all my code here.

Now it will run the litres round at an interval of 1.
So it will go from 00.1 to 00.2...

And the price of the sale should go round the same showing every number but faster because of what the price per litre is.e.g. when the litres is at exactly 01.0 then the price of the sale should show 001.00 if the price per litre is 100.0.

My PM is magically filled with 2701 messages. I stopped trying to clear them a while ago (it only lets you delete 25 at a time), and I can't seem to raise Dani from normal email...

Send it to me at michael.thomas.greer at google mail.

I can't do anything with that. Go into your project directory. Delete all the binary files (exe and dcu), then zip up everything else and attach it to an email. At the very least I need the dfm files for unit2 and unit3.

Okay thanks, I will keep an eye out. E-mail me the too if you like, either way i will get it.

OK, I've looked it over and made some fixes.

Your first problem was that you had the timer interval set to 1 millisecond. That's too fast. I bumped it up to a half-second.

You should avoid using more than one timer for the same event. I removed the second timer and combined the timer1timer and timer2timer procedures.

The second problem has to do with handling your data and converting between string and number. Check out the code for commentary on that.

I would recommend that you fix the TfrmPump.Litres to be a real value... or rename it to match its value (like TenthsOfLitre).

I fixed your forms to center themselves on the screen, and adjusted the text layout a little on the main form (so that it centers itself automatically). Oh yeah, I also changed text color to white so I could read it...

Lastly, your main form uses a non-standard font. My XP just recently crashed and I restored it from a backup image, so at the moment I don't have any fonts other than Microsoft defaults. Generally, if you must use a non-standard font for titles, use an image instead.

Some suggestions:

Don't use globals if you can avoid it. I notice you've got buttons to lift and seat the pump handle. Make yourself a boolean variable and stick it in the class definition (where I moved your Litres and ThisSale variables). Then, in the timer1timer procedure start off with: if not OkToPump then exit; Make sure to initialize values. The new variable (that I called "OkToPump") should be initialized in the FormCreate procedure. Likewise, you should have a default price per litre.

The ThisSale and Litres variables should be reset (to zero) when you lift the pump handle.

Well, that's all I can think of ATM. If you have any questions just ask.

Hope this helps.

Okay you have helped very much and I appreciate that and understand why all my code has been changed so it has improved my understanding.

The only thing that I need to explain to you now that I dont get either is the way the price per litre works in the UK.

You are right that we have pounds and pence and there are 100 pence in a pound. at a petrol station though the price of 1 litre would be 104.9 or something.
this means 1 pound, 4 pence and .9 of a pence.

99.8 = 99 pence and .8 of a pence.
111.5 = 1 pound, 11 pence and .5 of a pence.

Kind of confusing but I hope you understand because I don't see how that would run.

Thanks very much and I hope you can solve this major problem in the logic of the way the pump runs.

Ah, I get it. So the price is listed in pence, not pounds sterling.

Yes, they use the same daft trick here in the USA. You get 104.9 (in pence) and we get 1.049 (in dollars). The decimal point is just put in a different spot since the units differ.

You'll have to update your code to obtain and display the price per litre in pence, then divide by 100 to get the price per litre in pounds. If it gives you trouble let me know.

(Take your time in thinking about what units each of your variables represents: Litres, ThisSale, and PriceLitre.)

Hope this helps.

You appear to have got a nice conversation going Lynxus & Duos so I hesitate to butt in. However, having looked at the original post there are a few issues that struck me so I thought I would comment.

  • Running a case statement block each time you want to change a digit and then loading multiple images from file does not sound like a great way to do things.
  • A better approach would be to overlay all digits, 0-9, one on top of the other for each number in your display. Set their visibility to false and on each tick of your timer simply set it to true for the digit to be displayed.
  • A better approach would be not to use images at all - it is pretty easy to create a calculator-style 7 segment display using aligned shapes inside a panel. With that done all you need to do on each timer tick is to show/hide the relevant segments for each digit. I am suggesting this beause I am assuming that you cannot simply use a 7-seg LED component (plenty of those around and I have one of my own somewhere)

If you want to figure out some of the Math involved in programming such a display I have a CSS version of it here

http://www.explainth.at/en/css/csscapt.shtml

Yeah, we've already discussed this. I've already replaced his big case statements with a single line of code each...

The best fix is to have an array of bitmaps (obtained either from hidden images on the form, or from resource, or by using a TImageList), and assigning the image as appropriate.

Okay well now I don't really understand how to get the this sale working properly...

Also I used a case statement because it was the easiest way to have it run through all the digits like a real petrol pump does but this way seems more simple so I guess it's fine.

Since PriceLitre is in pounds sterling (but displayed in pence), I just adjusted the math in the program to convert behind the scenes.

try
    // convert to pence (string) to pounds (real)
    PriceLitre := StrToFloat( PriceLitreedt.text ) /100;
  except on EConvertError do
    ...  // (stuff you already have is omitted here)
  end;

  ... // (stuff you already have is omitted here)

  // Convert the validated pounds sterling to a string
  // representing pence and tenths-pence
  PriceLitreStr := FormatFloat( '000.0', PriceLitre *100 );

  // Load the images
  Img15.picture.loadfromfile( PriceLitreStr[1] +'.bmp' );
  ...

A case statement is just a selector returning a single item. There is no iteration involved...

Your program produces the animation by changing all the numbers once per timer timeout.

Hope this helps.

Okay I understand now, a case statement was a rather long way of going round. Thanks a lot, it's all working fine now :).

The only thing that I don't understand is this...

Begin
try
PriceLitre := StrToFloat(PriceLitreedt.text) /100;
except on EConvertError do

What is that...could you just explain the bolded part and perhaps why it's there?

Try entering a price per litre of "abc" and pressing the button. Without the try...except block, your program would crash.

Okay but I was just interested in knowing what that bit of code does.

It keeps the program from crashing on bad input.

Read up on exceptions. The first two links here on google are very good.

Whenever you use a function like strToInt or strToFloat (conversion routines), or any kind of I/O routine, put your cursor on the name of the procedure and press F1, then read what exceptions may be raised when the conversion or I/O or whatever fails. Then use a try..except block so to catch the exception and do something more intelligent than simply terminate the program.

You never know what a user will type when given the chance, so it is always best to make sure the program can continue even if the user types something really idiotic. The example I gave you catches bad input by complaining with a message dialog, focusing the input box, and exiting the routine to wait for the user to try again.

Hope this helps.

This article has been dead for over six months. Start a new discussion instead.