How can i calculate the percent of full moon on a given date? - date

I need to find the percentage of a full moon on a given date, but i can not figure out how to calculate this. My attempt to do this is wrong, because the percent of to day is about 96.9%. Can anyone see what i'm doing wrong in my delphi-code.
procedure TfrmLag.btnCalcClick(Sender: TObject);
var
whatDate : TDateTime; // Now;
lunarDays : Double; // 29.53058770576
lunarSecs : LongInt; // lunarDays * (24*60*60);
new2000 : TDateTime; // 6.1 2000 18:14
totalSecs : LongInt; // whatDate - new2000
currSecs : LongInt; // totalSecs MOD lunarSecs
currFrac : Double; // currSecs / lunarSecs
currDays : LongInt; // currFrac * lunarDays
perOfFull : Double;
begin
whatDate := Now;
lunarDays := 29.53058770576;
lunarSecs := Round(lunarDays * (24*60*60));
new2000 := EncodeDateTime(2000,1,6,18,14,00,000);
totalSecs := SecondsBetween(whatDate, new2000);
currSecs := totalSecs MOD lunarSecs;
currFrac := currSecs / lunarSecs;
currDays := Round(currFrac*lunarDays);
perOfFull := (100*currFrac);
lb.Items.Add('Date : '+FormatDateTime('dd.mm.yyyy hh:mm:ss',whatDate));
lb.Items.Add('Lunar days : '+IntToStr(lunarSecs));
lb.Items.Add('First full 2000 : '+FormatDateTime('dd.mm.yyyy hh:mm:ss',new2000));
lb.Items.Add('Total seconds : '+IntToStr(totalSecs));
lb.Items.Add('Current seconds : '+IntToStr(currSecs));
lb.Items.Add('Current fraction : '+FloatToStr(currFrac));
lb.Items.Add('Current days : '+IntToStr(currDays));
lb.items.Add('Percent of full : '+FloatToStr(perOfFull));
end;

I suppose new2000 is the first new moon in the year 2000? If so then this code should calculate correctly.
If new2000 is the full moon, you only have to remove the -1 in the cos() function.
uses
DateUtils;
procedure Calculate();
const
MoonPeriod = 29.53058770576;
var
KnownNewMoon: TDateTime;
NowUTC: TDateTime;
DaysSinceLastNewMoon, NumberOfNewMoons, MoonPart: Extended;
begin
KnownNewMoon := EncodeDateTime(2000,1,6,18,14,00,000);
NowUTC := TTimeZone.Local.ToUniversalTime(Now);
//How many moon periods (new moon -> full moon -> new moon) have passed
//since that known new moon date?
NumberOfNewMoons := (NowUTC - KnownNewMoon)/MoonPeriod;
DaysSinceLastNewMoon := Frac(NumberOfNewMoons)*MoonPeriod;
//The "moon part" is a sine/cosine function that starts at new moon with -0,
//reaches 1 at full moon and goes back to 0 at the next new moon.
//Starting at cos(-Pi) gives a -1 as "new moon value". Add 1 to set this to 0.
//Full moon is cos(0) gives 1. With the 1 added before, we have to divide by 2.
MoonPart := (cos((NumberOfNewMoons*2 - 1) * Pi) + 1)/2;
lb.items.Add('Number/amount of new moons: '+ FormatFloat('0.000000', NumberOfNewMoons));
lb.items.Add('Current moon part/position: '+ FormatFloat('0.000000', MoonPart));
lb.items.Add('Days since last new moon: '+ FormatFloat('0.000000', DaysSinceLastNewMoon));
end;
This should give you the visible moon part in MoonPart and the days (incl. fraction) since the last new moon.

Related

Delphi 10.4. Fast Report 6. REST application. Print Failure

I have created a REST server in Delphi using WebBroker. My intention is to use it as a label printer. A client prepares and sends a JSON request detailing the printer name, Fast Report & variables. The server reads the JSON, creates a tFrxReport object loads the requisite report and populates the variables.
This all works admirably, except it will not print to a physical printer. If I select OneNote as my destination, the label is saved to the desktop. If I select a network attached printer, no label emerges.
I have tried PrintOptions.ShowDialog:=True The print dialog shows, indicating the correct printer, but it does not print.
If anyone has any experience, could you point me in the right direction please?
function processJson(itm : sat; jtr : tJsonTextReader): sat;
var
idx : integer;
//itm : sat; // simple array type [idx, 'val1', 'val2']
begin
setlength(itm,0);
idx:=0;
while jtr.Read do
begin
if jtr.TokenType = tJsonToken.PropertyName then
begin
setlength(itm, length(itm)+1);
itm[idx].st_idx := idx;
itm[idx].st_code := jtr.Value.ToString; // property name
jtr.Read;
itm[idx].st_desc := jtr.Value.AsString; // property value
inc(idx);
end;
end;
processJson := itm;
end;
function getPrinterInfo(pnam: string):printinfo_type;
var
ptr : printinfo_type;
idx : integer;
begin
ptr.idx := -1; //default printer
ptr.name := trim(pnam);
for idx := 0 to Printer.Printers.Count - 1 do
if AnsiContainsText(Printer.Printers[idx], ptr.name) then
ptr.idx := idx;
result := ptr;
end;
procedure Ttfdq.tfdqactLabelAction(Sender: TObject; Request: TWebRequest;
Response: TWebResponse; var Handled: Boolean);
var
post : simpleArray_type;
pdx, idx, iitm : integer;
jtr : tJsonTextReader;
sr : tStringReader;
pish : string;
fr : tFrxReport;
thePtr : printinfo_type;
itm : sat;
tstprt : boolean;
begin
d.myHost := 'http://' + Request.host + ':' + intToStr(Request.ServerPort);
d.hostIP := Request.host;
d.Request := Request;
d.Response := Response;
d.remAddr := Request.RemoteAddr;
post := explode(Request.Content);
tstprt := false;
pdx := isset(post, 'json');
pish:='';
if (pdx >=0) then
begin
sr := tStringReader.Create(post[pdx].st_desc);
jtr := tJsonTextReader.Create(sr);
while jtr.read do
begin
if jtr.TokenType = tJsonToken.StartObject then
itm := processJson(itm, jtr);
end;
if fileexists(itm[2].st_desc) then
begin
thePtr := getPrinterInfo(itm[1].st_desc);
fr := tFrxReport.Create(nil);
fr.LoadFromFile(itm[2].st_desc);
// pre load any vars so report does not fail
for idx := 0 to fr.Variables.Count-1 do
fr.Variables.Items[iitm].Value := frText('');
for idx := 4 to High(itm) do
begin
pish := pish + 'index of '+itm[idx].st_code+' = '+ intToStr (fr.Variables.IndexOf(itm[idx].st_code))+'<br>';
iitm := fr.Variables.IndexOf(itm[idx].st_code);
if iitm > -1 then
fr.Variables.Items[iitm].Value := frText(itm[idx].st_desc);
end;
if fr.PrepareReport then
begin
//fr.ShowPreparedReport;
fr.PrintOptions.Printer := thePtr.name;
fr.PrintOptions.PrnOutFileName := 'Trace Label';
fr.PrintOptions.ShowDialog := tstprt;
fr.ShowProgress := tstprt;
fr.Print;
end;
fr.Free;
end;
Response.Content := pish ;
end
else
begin
Response.Content := '<html>' +
'<head><title>Label List</title></head>' +
'<body>This is only used by print serve clients</p>'+
'</body>' +
'</html>';
end;
end;
The problem lies here:
fr.PrintOptions.PrnOutFileName := 'Trace Label';
I erroneously thought that would add a description in the print queue. What it actually did is send the report into limbo :)

PineScript - zigzag trend change counter

I've made an indicator that is similiar to zigzag. I want to write a formula that will count number of up trends or number of trend changes (from up to down and from down to up). I have problem with it, because my variable is still setting to 0. Could you help me to correct it?
//#version=3
study("ZigZag Poker", overlay=true)
//INPUTS
trend = 0
trend := na(trend[1]) ? 1 : trend[1] //Beggining trend set to up
LL = 0.0
LL := na(LL[1]) ? low : LL[1] //LastLow
HH = 0.0
HH := na(HH[1]) ? high : HH[1] //LastHigh
LO = 0.0
LO := na(LO[1]) ? open : LO[1] //LastOpen
LC = 0.0
LC := na(LC[1]) ? close : LC[1] //LastClose
LOLO = 0.0
LOLO := na(LOLO[1]) ? low : LOLO[1] //LowestLow
HIHI = 0.0
HIHI := na(HIHI[1]) ? high : HIHI[1] //HighestHigh
zigzag = na
kolor = 0 //variable that counts number of trend changes
imp = input(true, "Alt imp")
kolor := imp == true ? 2 : 0
if (trend > 0) // trend is up, look for new swing low
if close >= min(LO, LC)
LC := close
LL := low
LO := open
LOLO := low
HIHI := high
else
zigzag := HIHI
trend := -1
HH := high
HIHI := high > HIHI ? high : HIHI
LC := close
LL := low
LO := open
LOLO := low
kolor := kolor[1] + 1
else // trend is down, look for new swing high
if close <= max(LO, LC)
HH := high
HIHI := high
LC := close
LL := low
LO := open
LOLO := low < LOLO ? low : LOLO
else
zigzag := LOLO
trend := 1
HH := high
LC := close
LL := low
LO := open
kolor: = kolor[1] + 1
plot(kolor)
plot(zigzag, color = trend < 0 ? blue : orange, linewidth=2, offset=-1)
I know it's too late to help the OP, but the error is in the line
kolor := imp == true ? 2 : 0, that always sets the value of kolor to 2 or 0, for all the candles that are in the current trend.
What is missing is copying the last kolor's value on every loop, so kolor[1] can have a valid counter.
Replacing that line with kolor := na(kolor[1])? 0: kolor[1] will do it.

Delay Timer in Structured Text

I have Just started working on PLC using Structured text, I have to store values in Array of Temperature variable after delay of 1 min every time but i am not able to do that.
FOR i := 0 TO 5 DO
Temp[i] := tempsensor;
END_FOR;
This is kind a pseudo code.
I just need to bring in the delay in the loop that after every 1 min it could read the value and store it in the array location.
Even if there is any other way then I will really appreciate that.
Try this
VAR
i:INT;
Temp: ARRAY[0..10000] OF LREAL;
delayTimer: TON;
END_VAR
delayTimer(IN := not delayTimer.Q, PT := T#1m);
IF delayTimer.Q THEN
Temp[i] := tempsensor;
i := i + 1;
IF i > 10000 THEN
i := 0;
END_IF;
END_IF;
After 1 minute it will record 1 temperature value and index the array. If it reaches the end of the array it will start to write over at the beginning.
Once every minute you cycle through array and set values.
VAR
i: INT := 1; (* Cycle number *)
temp: ARRAY[1..5] OF REAL; (* Array of temperatures *)
ton1: TON; (* Timer *)
END_VAR
ton1(IN := NOT ton1.Q, PT := T#1m);
IF ton1.Q THEN
temp[i] := tempsensor;
IF i >= 5 THEN i := 1 ELSE i := i + 1 END_IF;
END_IF;

Numbering with TRichEdit in Delphi

I am trying to implement numbering in TRichEdit component, Delphi. Ideally I want to get the same behavior as in these 3rd party component:
As you can see Numbering button works similar way as Bullet button. I mean it sets FirstIdent or LeftIdent (I am not sure) and put the numbers 1,2,3,... instead of bullets. When you move cursor to the left close to number it does not allow to move onto number but jumps one line up.
This is what I got so far:
procedure TMainForm.NumberingButtonClick(Sender: TObject);
var
i: Integer;
s: String;
begin
if NumberingButton.Down then
begin
Editor.Paragraph.Numbering := nsNone;
i := Editor.ActiveLineNo;
s := Editor.Lines[i];
insert(inttostr(i)+'. ', s, 1);
//Editor.Paragraph.LeftIndent := 10;
Editor.Paragraph.FirstIndent := 10;
Editor.Lines[i] := s;
end;
end;
But it does not work as I want. Anybody have any ideas?
This code works exactly how I expected:
procedure TMainForm.NumberingButtonClick(Sender: TObject);
var
i: Integer;
s: String;
fmt: TParaFormat2;
begin
FillChar(fmt, SizeOf(fmt), 0);
fmt.cbSize := SizeOf(fmt);
fmt.dwMask := PFM_NUMBERING or PFM_NUMBERINGSTART or
PFM_NUMBERINGSTYLE or PFM_NUMBERINGTAB;
if NumberingButton.Down then
fmt.wNumbering := 2
else
fmt.wNumbering := 0;
// wNumbering:
// 0 - no numbering
// 1 - bullet list (·, ·, ·, ...).
// 2 - Arabic numbers (1, 2, 3, ...).
// 3 - small letters (a, b, c, ...).
// 4 - capital letters (A, B, C, ...).
// 5 - small Roman numbers (i, ii, iii, ...).
// 6 - capital Roman numbers (I, II, III, ...).
// 7 - Unicode character sequence
fmt.wNumberingStart := 1;
// wNumberingStart:
// The number at which the numbering starts.
fmt.wNumberingStyle := $200;
// wNumberingStyle:
// Numbering Style
// 0 : 1)
// $100 : (1)
// $200 : 1.
// $300 : 1
// $400 : remove list
// $8000 : continues to number the list without changing the style
fmt.wNumberingTab := 1440 div 4;
// wNumberingTab:
// the space between number and paragraph text
Editor.Perform( EM_SETPARAFORMAT, 0, lParam( #fmt ) );
if BulletsButton.Down then
BulletsButton.Down := False;
end;
Thanks to www.decoding.dax.ru

Display Serial Number as Roman letters in Crystal Reports

need to display serial no as roman letters(i,ii,iii,iv etc) in my crystal reports. I have the serial number captured as record number (1,2,3,4...).so what i have to do for it in crystal report.
Just use the Roman() function provided by Crystal Reports
I can't take much of the credit; I simply ported the code from this VB Helper article into Crystal, but it was a fun exercise:
NumberVar iCounter := 0;
Local StringVar ch := "";
Local NumberVar result := 0;
Local NumberVar new_value := 0;
Local NumberVar old_value := 0;
Local StringVar temp := "";
temp := UpperCase({?#Roman});
old_value = 1000;
For iCounter := 1 To Len(temp) do
(
// See what the next character is worth.
ch := Mid(temp, iCounter, 1);
if ch = "I" then new_value := 1
else if ch = "V" then new_value := 5
else if ch = "X" then new_value := 10
else if ch = "L" then new_value := 50
else if ch = "C" then new_value := 100
else if ch = "D" then new_value := 500
else if ch = "M" then new_value := 1000;
// See if this character is bigger
// than the previous one.
If new_value > old_value Then
// The new value > the previous one.
// Add this value to the result
// and subtract the previous one twice.
result := result + new_value - 2 * old_value
Else
// The new value <= the previous one.
// Add it to the result.
result := result + new_value;
old_value := new_value;
);
// Format the number without commas or decimals
ToText(result, 0, "");
Simply replace my {?#Roman} parameter placeholder with your variable, and you're all set.
I tried to fix it [enter image description here][1]
<https://www.tek-tips.com/viewthread.cfm?qid=887691>
or
<https://www.tek-tips.com/viewthread.cfm?qid=1613334>
and
<https://www.youtube.com/watch?v=X_UaulmICtM&list=TLPQMTUwMjIwMjMRAYZJzCsXDQ&index=6>
specifically: at crystal report
TH1: Fomula fields/new/"nameabc"/enter/"Roman(GroupNumber)"/ ctrl+S/and pull it out
TH2: Fomula fields/new/"nameabc"/enter/
select GroupNumber
case 1 : " I"
case 2 : " II"
case 3 : " III"
case 4 : " IV"
case 5 : " V"
case 6 : " VI"
case 7 : " VII"
case 8 : "VIII"
case 9 : " IX"
case 10 : " X"
case 11 : " XI"
case 12 : " XII"
case 13 : "XIII"
case 14 : " XIV"
case 15 : " XV"
case 16 : " XVI"
case 17 : "XVII"
default : ""
/ ctrl+S/and pull it out
But it really doesn't help t so there will be this 3 case (t improved from link 2-3) it can apply to the 3rd or even 10th group of headings
TH3: ex: (you want to create a text message for group 3)
Formula fields/new/"nameabc"/enter/
"
WHILEPRINTINGRECORDS;
GLOBAL NUMBERVAR INTSTTGRTEST;
INTSTTGRTEST :=0;
/ ctrl+S/ drag it out and put it in heading group 2 and hide it (= right click/format field/common/ check Suppress/ok) you can go to link 3 to see
Formula fields/new/"nameabcd"/enter/
"
WHILEPRINTINGRECORDS;
GLOBAL numbervar INTSTTGRTEST := INTSTTGRTEST + 1;
stringvar y;
STRINGVAR ARRAY X := ["A","B","C","D","E","F","G","H","I","J","K", "L","M","N","O","P","Q","R","S","T","U","V","W","X ","Y","Z"];
if INTSTTGRTEST <= 26 then (
redim preserve X[INTSTTGRTEST];
y := X[INTSTTGRTEST]
);
y;
/ ctrl+S/and pull it out and place it at group 3
and the alphabet can be whatever we want. ex:
X := ["I","II","III","IV","V","VI","VII","VIII","IX","X","XI" ,"XII","XIII","XIV","XV","XVI","XVII","XVIII","XIX","XX","XXI","XXII","XXIII"," XXIV","XXV","XXVI","XXVII","XXVIII","XXIX","XXX","XXXI","XXXII","XXXIII","XXXIV","XXXV","XXXVI" ,"XXXVII","XXXVIII","XXXIX","XL","XLI","XLII","XLIII","XLIV","XLV","XLVI","XLVII","XLVIII"," XLIX","L"];
or
X := ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"];
hope it can help you
enter code here [1]: https://i.stack.imgur.com/OeBBQ.png