Plotting a TChart with time as the X-axis - delphi

I have a series of 3,600 values, one every second for an hour. I want to chart them as a single series, using TChart in Delphi 7.
The values should be plotted on the Y-axis. What should I pass to AddXY() as the X-axis value? The count of points?
I want to label the X-axis as MM:SS, how do I do that? What do I need beyond this? ...
Chart1.Series[0].XValues.DateTime := True;
Chart1.BottomAxis.DateTimeFormat := 'nn:ss';
I have been stuck for a while with this one. Can anyone post some sample code? Thanks

You can use Add function instead of AddXY.
Add( 100, FormatDateTime('nn:ss',Now), clRed );
Add( 80, FormatDateTime('nn:ss',Now), clRed );

If I am not wrong, this is what you want
Series1.AddXY(<Pass the data value>, <Pass Your value>, '', clRed);
Series1.AddXY(now, 1, '', clRed);
Series1.AddXY(now + ( 1 /(24*60*60)), 2, '', clRed); //After 1 seconds
Series1.AddXY(now + ( 2 /(24*60*60)), 3, '', clRed); //After 2 seconds

Related

delphi combination algorithm

Hello I cant write the combination algorithm. For example; I have 1 Red and 2 White balls and I want to write number red balls + number white balls. Like below;
R->Red
W->White
RWW
WRW
WWR
totally 3 combinasion I have. But How can I write it in Delpi? Because, may be I have 10 RED 8 White or 15 RED 20 White etc.. How can I oreder this kombination.
I have one rules .
1- I have to use all balls eveytime. My order, combination Length has to be total ball. In my example it has to be 2+1=3.
how can I do this?
procedure Combination( pLeft : string;pRedCount, pWhiteCount : integer; pResult : strings );
begin
if (pRedCount = 0) and (pWhiteCount = 0) then
begin
pResult.Add( pLeft );
exit;
end;
if pRedCount > 0 then Combination( pLeft + 'R', pRedCount - 1, pWhiteCount, pResult );
if pWhiteCount > 0 then Combination( pLeft + 'W', pRedCount, pWhiteCount - 1, pResult )
end;
For example if in your main program you had a TMemo called Memo, a spinedit called RCount and another called WCount, then on your action button you would execute
Memo.Lines.Clear
Combination( '', RCount.Value, WCount.Value, Memo.Lines );

Custom datetime step on teechart

I'm making a software where i plot samples measured from an electric circuit on a teechart chart.
The user needs to be able to select the time window of the samples on the screen. For example, the chart has 10 fixed divisons on the screen, and each of these divisions can represent a 0,5s, 1s, 2s or 5s window.
The problem is that teechart only has fixed datetime increments, for example 1 second or 5 seconds. What i need to do is be able to select custom increments on a datetime bottom axis on teechart.
I'm setting the bottom axis increment with this code:
Form1.Osc.BottomAxis.Increment := DateTimeStep[dtonesecond];
The Increment property is a TDateTime type, which is declared as a Double.
So, just use normal math to set a custom increment.
Examples how to set different increments:
Form1.Osc.BottomAxis.Increment := 0.5*DateTimeStep[dtonesecond]; // 0.5 sec
Form1.Osc.BottomAxis.Increment := DateTimeStep[dtonesecond]; // 1 sec
Form1.Osc.BottomAxis.Increment := 2*DateTimeStep[dtonesecond]; // 2 sec
Form1.Osc.BottomAxis.Increment := 5*DateTimeStep[dtonesecond]; // 5 sec
or
Form1.Osc.BottomAxis.Increment := 0.5*(1.0/SecsPerDay); // 0.5 sec
Form1.Osc.BottomAxis.Increment := 1.0/SecsPerDay; // 1 sec
Form1.Osc.BottomAxis.Increment := 2.0/SecsPerDay; // 2 sec
Form1.Osc.BottomAxis.Increment := 5.0/SecsPerDay; // 5 sec

Calculating Hurst Exponent

Hi there =) And sorry for my English, in advance
I have a task to calculate hurst exponent by method of linear regression. And I have text description of solution. It looks very easy, but always i get values, that go out from range 0..1. Usually, value is 1.9 or something similar. Sometimes it gets negative value that is close to zero.
I have looked over code about thousand times but couldn't see a mistake.
var
max_z,min_z,x_m:real; //max and min of cumulative sum and mean value of X for every Tau
st,ss,sst,st2 :real;
Al, Herst: real;
x_vr:array of double; //a piece of array with length=tau
i, j, nach: integer;
begin
//file opening and getting values of X array are in another function
nach:=3; //initial value of tau
Setlength(ln_rs,l-nach); //length of ln(R/S) array
Setlength(ln_t,l-nach); //length of ln(tau) array
Setlength(r,l-nach); //length of R array
Setlength(s,l-nach); //length of S array
//Let's start
for tau:=nach to l do //we will change tau
begin
Setlength(x_vr,tau+1); //set new local array (length=tau)
for i:=0 to length(x_vr)-1 do
x_vr[i]:=x[i];
x_m:=Mean(x_vr); //mean value
Setlength(y,tau+1); //length of array of difference from mean value
Setlength(z,tau+1); //length of array of cumulative sum
for i:=0 to tau do
y[i]:=x_vr[i]-x_m; //difference from mean value
z[0]:=y[0];
for i:=1 to tau do //cumulative sum
for j :=i downto 0 do
z[i]:=z[i]+y[j];
max_z:=z[0];
for i:=1 to tau do //max of cumulative sum
max_z:=max(max_z,z[i]);
min_z:=z[0];
for i:=1 to tau do //min of cumulative sum
min_z:=min(min_z,z[i]);
r[tau-nach]:=max_z-min_z; //R value
s[tau-nach]:=0;
for i:=0 to tau do
s[tau-nach]:=power(y[i],2)+s[tau-nach]; //S value
s[tau-nach]:=sqrt(s[tau-nach]/(tau+1));
//new array values
ln_rs[tau-nach]:=Ln(R[tau-nach]/S[tau-nach]); // ln(R/S)
ln_t[tau-nach]:=ln(tau); // ln (tau)
end; //End of calculating
//Method of Least squares
for i:=0 to length(ln_rs)-1 do
st:=st+ln_t[i];
st:=(1/length(ln_rs))*st;
for i:=0 to length(ln_rs)-1 do
ss:=ss+ln_rs[i];
ss:=(1/length(ln_rs))*ss;
for i:=0 to length(ln_rs)-1 do
sst:=sst+ln_t[i]*ln_rs[i];
sst:=(1/length(ln_rs))*sst;
for i:=0 to length(ln_rs)-1 do
st2:=st2+ln_t[i]*ln_t[i];
st2:=(1/length(ln_rs))*st2;
Herst:=(sst-st*ss)/(st2-st*st); //coefficient of approximal function
al:=ss-st*Herst;
Thanks everybody =)
P.S.
for tau:=nach to l do
There is L, not 1. And L is Length of X array. And L>nach always besides last step, when l=nach.
P.P.S.
It works, guys. But values are not right. And they go out from range. Maybe, there is mistake in algorithm. Or maybe I skiped some step.
Last Update
It's mystic, but i only changed method of calculating array Z and it started works correctly....
Thanks all =)
First thing I see:
nach := 3;
for tau := nach to l do //w
This counts up. And because nach>1, the body of this loop won't be executed.
If you expect to count down. Use the downto variant. To count down:
for tau := nach downto l do //w
Given that the main loop (for tau) iterates from nach to l, the first four SetLength calls should set the length of l - nach + 1 instead of l - nach.
Should the line
z[i]:=z[i]+y[j];
not be
z[i]:=z[i - 1]+y[j];
?

How can I know why my program calculations and output is incorrect?

I'm working on a programming problem.
Note: This is not a student project. I am working on this for a new Quest for the website Try My Quest Dot Com, for which i am the admin.
Problem:
Jenny just started work as a programmer for Justine's Java Workshop. She is paid $10
an hour, with a few exceptions. She earns an extra $1.50 an hour for any part of a day where she works more than 8 hours, and an extra $2.50 an hour for hours beyond 40 in any one week. Also, she earns a 125% bonus for working on Saturday, and a 50% bonus for working on Sunday. The bonuses for Saturday and Sunday are computed based on the hours worked those days; they are not used to calculate any bonus for working more than 40 hours in a week. You'll be given the number of hours Jenny worked each day in a week (Sunday, Monday, etc ), and you need to compute her salary for the week. The input will be positive integers, less than or equal to 24. The output must be formatted with a dollar sign and rounded up to the nearest penny. For example, $2" and $2.136666" are wrong answers; the correct versions are $2.00" and $2.14", respectively.
Anyway, i am trying to write this in Delphi (No form project). I pass the program a command line argument - timecard.dat
input
0, 8, 8, 8, 8, 8, 0
0, 10, 10, 10, 10, 10, 0
0, 0, 8, 8, 8, 8, 8
0, 0, 0, 10, 10, 10, 10
10, 10, 10, 9, 9, 9, 9
Output
Output #1: $400.00
Output #2: $540.00
Output #3: $500.00
Output #4: $540.75
Output #5: $905.88
My Out put however is:
Output #1: $400.00
Output #2: $540.00
Output #3: $500.00
Output #4: $537.00
Output #5: $902.50
The last two output values of mine are different from the actual results. Not sure why, and the more i stare at the code, the less i see it
Can anyone tell me what i have done wrong?
program ACSL_Time_Cards;
{assumes Sunday = 1, Monday 3, etc}
uses
SysUtils,
Dialogs;
const
HourlyWage = 10.00;
OverEightWage = 1.50;
OverFortyWage = 2.50;
var
F: TextFile;
I, ArrayIndex: Integer;
WeeklyHours: Array[0..6] of Integer; //weekly hours
HourStr, LineStr: String;
TotalHours, TotalOverFortyHours, TotalOverEightHours, TotalSatHours, TotalSunHours: Integer;
TotalWages: Real;
begin
//initialize variables
TotalHours:= 0;
TotalOverEightHours:= 0;
TotalOverFortyHours:= 0;
TotalSatHours:= 0;
TotalSunHours:= 0;
TotalWages:= 0.00;
ArrayIndex:= 0;
//open file "timecard.dat" for input
if FileExists(ParamStr(1)) then
begin
AssignFile(F, ParamStr(1));
Reset(F);
//step through file and extract each line and store in hoursStr
while not EOF(F) do
begin
Readln(F, LineStr);
//step through hours string and fill Array with weekly hours
for I:= 1 to length(LineStr) do
begin
//if character is not a ',' then add it to hourStr
if LineStr[I] <> ',' then
HourStr:= HourStr + LineStr[I]
else
begin
//add HourStr to Array
WeeklyHours[ArrayIndex]:= StrToInt(HourStr);
//reset the variable
HourStr:= '';
//increment Variable
Inc(ArrayIndex);
end; //else
end; //for I:= 1 to length(HoursStr) do
//clean up by adding the last remaining one
WeeklyHours[ArrayIndex]:= StrToInt(HourStr);
//step through array and figure out overtime Daily and Weekly
for I:= Low(WeeklyHours) to High(WeeklyHours) do
begin
TotalHours:= TotalHours + WeeklyHours[I];
if WeeklyHours[I] > 8 then
TotalOverEightHours:= TotalOverEightHours + WeeklyHours[I]-8;
//get sunday hours
if I + 1 = 1 then
TotalSunHours:= TotalSunHours + WeeklyHours[I];
//get saturday hours
if I + 1 = 7 then
TotalSatHours:= TotalSatHours + WeeklyHours[I];
end;
//get total over 40 hours
if TotalHours > 40 then
TotalOverFortyHours:= TotalHours-40;
//compute Regular Hours
TotalWages:= TotalWages + TotalHours * 10.00;
//compute overtime hours
TotalWages:= TotalWages + TotalOverEightHours * 1.50;
TotalWages:= TotalWages + TotalOverFortyHours * 2.50;
//compute bonuses
TotalWages:= TotalWages + (TotalSatHours * 10.00) * 1.25;
TotalWages:= TotalWages + (TotalSunHours * 10.00) * 0.50;
ShowMessage('TotalWages: ' + FormatFloat('$0.00', TotalWages));
//reset variables
TotalWages:= 0.00;
TotalHours:= 0;
TotalOverEightHours:= 0;
TotalOverFortyHours:= 0;
TotalSatHours:= 0;
TotalSunHours:= 0;
HourStr:= '';
ArrayIndex:= 0;
end; //while not EOF(F) do
CloseFile(F);
end
else
ShowMessage('File does not exist!');
end.
I'm sure there are many ways that this could have been written better. I really am just interested in why my values different from the expected values. Thanks!
For a simple problem like this, you might want to write it out by hand and then see if your code follows the same steps you did.
For Output 4, the 125% bonus for Saturday is not including the $1.50 per hour extra after 8:
she should earn
Wed: $103 | $100 for 10 hours plus $3 for 2 hours over 8
Thu: $103 | $100 for 10 hours plus $3 for 2 hours over 8
Fri: $103 | $100 for 10 hours plus $3 for 2 hours over 8
Sat: $231.75 | ($100 for 10 hours, $3 for 2 hours over 8), $128.75 for 125% bonus
for a total of 540.75
The code would benefit from the I/O and the calculation being separated. You problems are with the calculation. I'd write it something like this:
uses
Math;
type
TDay = (
daySunday,
dayMonday,
dayTuesday,
dayWednesday,
dayThursday,
dayFriday,
daySaturday
);
TDayArray = array [TDay] of Integer;
function Wage(const Hours: TDayArray): Double;
const
BasicRate = 10.0;
DailyOvertimeRate = 1.5;
WeeklyOvertimeRate = 2.5;
DailyOvertimeThreshold = 8;
WeeklyOvertimeThreshold = 40;
DailyBonus: array [TDay] of Double = (1.5, 1.0, 1.0, 1.0, 1.0, 1.0, 2.25);
var
Day: TDay;
DailyOvertimeHours, WeeklyOvertimeHours, TotalHours: Double;
DailyPay: array [TDay] of Double;
begin
TotalHours := 0.0;
for Day := low(Day) to high(Day) do begin
TotalHours := TotalHours + Hours[Day];
DailyOvertimeHours := Max(Hours[Day]-DailyOvertimeThreshold, 0.0);
DailyPay[Day] := Hours[Day]*BasicRate;
DailyPay[Day] := DailyPay[Day] + DailyOvertimeHours*DailyOvertimeRate;
DailyPay[Day] := DailyPay[Day]*DailyBonus[Day];
end;
WeeklyOvertimeHours := Max(TotalHours-WeeklyOvertimeThreshold, 0.0);
Result := Sum(DailyPay) + WeeklyOvertimeHours*WeeklyOvertimeRate;
end;
This is still a little unpolished and I'm not very happy with the variable names for pay rates, overtime etc.
Once have such a utility function available, then putting it together with the rest of your program becomes a lot easier.
The biggest weakness in your current program is that everything is housed in one giant routine. Break it down into small pieces and you'll be able to verify those small pieces more readily than hunting for problems in a single large routine.
Find this by yourself by learning How to debug a Delphi program.
Pay atention to this parts:
Watches - you add a watch to track the values of program variables or expressions as you step over or trace into code.
Breakpoints - when pressing the F5 button or clicking on the left bar in your editor you can add a red line to your source. This line of source will have a breakpoint. When running the program, the execution will stop when it passes the source line. Now you can trace into your source by using some function keys.

Using Length() with multi-dimensional dynamic arrays in Delphi

I am using a multi-dimensional dynamic array in delphi and am trying to figure this out:
I have 2 seperate values for the first index and second index that are totally seperate of each other.
As new values come I want to grow the array if that new value is outside of either bound.
For new values x, y
I check:
if Length(List) < (x + 1) then
SetLength(List, x + 1);
if Length(List[0]) < (y + 1) then
SetLength(List, Length(List), y + 1);
Is this the correct way to do this or is there a better way to grow the array as needed?
It looks fine to me - if you change the last line to
SetLength(List, Length(List), y + 1);
I think you forgot to use the second index on the second dimension;
Your code should probably read like this :
if Length(List) < (x + 1) then
SetLength(List, x + 1);
if Length(List[x]) < (y + 1) then
SetLength(List[x], y + 1);
Note the use of 'x' as the first dimension index when growing the second dimension.
One caution though :
You should be aware of the fact that Delphi uses reference-counting on dynamic arrays too (just like how it's done with AnsiString).
Because of this, growing the array like above will work, but any other reference to it will still have the old copy of it!
The only way around this, is keeping track of these array's with one extra level of indirection - ie. : Use a pointer to the dynamic array (which is also a pointer in itself, but that's okay).
Also note that any of those 'external' pointers should be updated in any situation that the address of the dynamic array could change, as when growing/shrinking it using SetLength().
#PatrickvL:
Sorry, but that is just plain wrong. Your code does not even compile because it tries to set two dimensions for the single-dimensional element List[x]. (PatrickvL updated his code so this part of the answer is no longer valid.)
The following code demonstrates multidimensional array resizing.
program TestDimensions;
{$APPTYPE CONSOLE}
uses
SysUtils;
var
List: array of array of integer;
begin
//set both dimensions
SetLength(List, 3, 2);
Writeln('X = ', Length(List), ', Y = ', Length(List[0])); //X = 3, Y = 2
//set main dimension to 4, keep subdimension untouched
SetLength(List, 4);
Writeln('X = ', Length(List), ', Y = ', Length(List[0])); //X = 4, Y = 2
//set subdimension to 3, keep main dimenstion untouched
SetLength(List, Length(List), 3);
Writeln('X = ', Length(List), ', Y = ', Length(List[0])); //X = 4, Y = 3
//all List[0]..List[3] have 3 elements
Writeln(Length(List[0]), Length(List[1]), Length(List[2]), Length(List[3])); //3333
//you can change subdimension for each List[] vector
SetLength(List[0], 1);
SetLength(List[3], 7);
//List is now a ragged array
Writeln(Length(List[0]), Length(List[1]), Length(List[2]), Length(List[3])); //1337
//this does not even compile because it tries to set dimension that does not exist!
// SetLength(List[0], Length(List[0]), 12);
Readln;
end.
The Delphi help also explains this quite nicely (Structured Types, Arrays).
Multidimensional Dynamic Arrays
To declare multidimensional dynamic arrays, use iterated array of ... constructions. For example,
type TMessageGrid = array of array of string;
var Msgs: TMessageGrid;
declares a two-dimensional array of strings. To instantiate this array, call SetLength with two integer arguments. For example, if I
and J are integer-valued variables,
SetLength(Msgs,I,J);
allocates an I-by-J array, and Msgs[0,0] denotes an element of that array.
You can create multidimensional dynamic arrays that are not rectangular. The first step is to call SetLength, passing it parameters for the first n dimensions of the array. For example,
var Ints: array of array of Integer;
SetLength(Ints,10);
allocates ten rows for Ints but no columns. Later, you can allocate the columns one at a time (giving them different lengths); for example
SetLength(Ints[2], 5);
makes the third column of Ints five integers long. At this point (even if the other columns haven't been allocated) you can assign values to the third column - for example, Ints[2,4] := 6.
The following example uses dynamic arrays (and the IntToStr function declared in the SysUtils unit) to create a triangular matrix of strings.
var
A : array of array of string;
I, J : Integer;
begin
SetLength(A, 10);
for I := Low(A) to High(A) do
begin
SetLength(A[I], I);
for J := Low(A[I]) to High(A[I]) do
A[I,J] := IntToStr(I) + ',' + IntToStr(J) + ' ';
end;
end;

Resources