/* *****************************************************************************************
 *	Das Modul stellt den Worker für das Hauptprogramm der automatischen Berechnungen dar.
 *  Hier die Berechnung ab dem aktuellen Datum.
 *  Es wird die Datums- und Zeitangabe als LT, JD und MJD angezeigt. Dabei
 *  kann sich die Geschwindigkeit (DELAY) automatisch ändern.
 *  Dies geschieht in der Haupt-Funktion "calculateJD()"
 *
 *	-------------------------------------------------------------------------------------------------------------
 * The module represents the worker for the main program of automatic calculations.
 * Here the calculation from the current date.
 * The date and time is displayed as LT, JD and MJD. In doing so
 * the speed (DELAY) can change automatically.
 * This is done in the main function “calculateJD () “
 *
 ***************************************************************************************** */
const PERCENTMILLI = 1.0 / (60 * 60 * 1000 * 24);// Millisekundenanteil an einem Tag
																		// Millisecond fraction on a day
const PERCENTDAY	=	(1.0 / 24.0);				// Stundenanteil an einem Tag
																		// Hour fraction on a day
var DELAYJD = 500;										// Wartezeit bis die Threads wieder ausgeführt werden
																		// Waiting for the threads to be executed again
var TIMELAPS = 0;											// Der Zeitsprung, in dessen Abstand die Berechnungen gemacht werden sollen 
																		// The time jump at which the calculations are to be made
var TIMEZONE = 0;											// Die Info über Zeitzone + DST. ACHTUNG sind nach Osten negativ und Westen positiv
																		// Info about time zone + DST. ATTENTION are negative to the East and positive to the West
var ONLYDST = 0;											// Der Wert aus der Auswahlbox der Sommer/Winterzeit.
																		// The value from the summer/winter time selection box.
var LONGITUDE = 0.0;									// Der Wert aus der Textbox der Länge.
																		// The value from the text box of the longitude.
var LATITUDE = 0.0;										// Der Wert aus der Textbox der Breite.
																		// The value from the latitude text box.
var ONLYTIMEZONE = 0;								// Wert aus der Auswahlbox Zeitzone.
																		// The value from the timezone selection box.
var TWILIGHTKIND	= "";									// Wert aus der Auswahlbox Dämmerung.
																		// The value from the twilight selectiont box.
var HEADER = "";											// Überschrift des Datenberichts als String
																		// Heading of the data report as string
var startDate = 0;												// Julianisches Datum des Startdatums
																		// Julian data of start date
var endDate = 0;												// Julianisches Datum des Enddatums
																		// Julian date of end date
var virtualDate = 0;											// Die vergangenen Millisekunden seit 1.1.1970 00:00 Uhr UTC
																		// The past milliseconds since 1.1.1970 00:00 UTC
var endDate = 0;												// Millisekunden des Enddatums
																		// Milliseconds of end date
var actualDate = 0;											// Millisekunden des aktuellen Datums
																		// Milliseconds of actual date
var startProgressTimeJD = 0;							// Startzeit für die Verarbeitungsdauer JD
																		// Start time for processing time JD
var stopProgressTimeJD = 0;							// Stoppzeit für die Verarbeitungsdauer JD
																		// Stop time for processing time JD
var diffProgressTimeJD = 0;							// Die Zeitdifferenz der Verarbeitung des JD
																		// The time difference of the processing of the JD
var splitData = [];												// Array mit empfangenen Daten aus den Message Queues der Worker
																		// Array with received data from the message queues of the workers
var dataLineNumber = 0;									// Die Zeilennummerierung für die an den Hauptthread zu sendenden Daten.
																		// The row numbering for the data to be sent to the main thread	
var sendString = "";											// Der String für Daten die an das externe Textfeld gesendet wird ...
																		// The string for data sent to the external text field ...
var channel = new BroadcastChannel ("com"); // Einen Nachrichtenkanal zu anderen Programmen erstellen. Zum Hören und Senden.
																		// Create a message channel to other programs. To listen and broadcast.
var workerChoiceEndless = null;						// Das Hintergrund Worker Objekt für die Hintergrundverarbeitung und Simulation von Datum - bis Datum
																		// The background worker object for background processing and simulation from date to date
																		
/*	*************************************** Importieren der extern benötigten Module und Funktionen ********************************************* */


// Nützliche Funktionen wie Sommerzeit/Winterzeit, Popup Öffnen ...
// Useful functions like Daylight Savings Time, open popups ...
importScripts('../../Bibliotheken/Utilities.js');

// Äquatoriale Koordinaten nach Horizontalkoordinaten konvertieren ...
importScripts('../../Bibliotheken/ObjectHeight.js');
//importScripts('../../Projekt Mondphasenberechnung/Sonne-Mond/ObjectHeight.js');
					
// Julianisches Datum Manuell
importScripts('../../Bibliotheken/Sonne-Mond/JulianDate.js');
				
// Funktionen für Sonnen Auf- und Untergang
// Functions for the sunrise and sunset
importScripts('../../Bibliotheken/SunRiseSet.js');
//importScripts('../../Projekt Mondphasenberechnung/Sonne-Mond/SunRiseSet.js');

// Funktionen für die Sonnenpositionen
// Functions for the sun positions
importScripts('../../Bibliotheken/Moonpositions.js');
				
// Konvertierung von Uhrzeiten
// Conversion of times
importScripts('../../Bibliotheken/decTime.js');
				
// Funktionen zur Berechnungen/Konvertierung des Julianischen Datum
// Functions for calculations/conversion of the Julian date
importScripts('../../Bibliotheken/calculateJD.js');
				
// Funktionen für die Sonnenpositionen
// Functions for the sun positions
importScripts('../../Bibliotheken/Sunpositions.js');
				
// Funktionen für Mond Auf- und Untergang
// Functions for the moonrise and moonset
importScripts('../../Bibliotheken/MoonRiseSet.js');

// Berechnung aller Sonnenparameter
// Calculation of all solar parameters
importScripts('../../Bibliotheken/Sonne-Mond/sunParameters.js');

// Berechnung aller Mondparameter
// Calculation of all moon parameters
importScripts('../../Bibliotheken/Sonne-Mond/moonParameters.js');

// Die Message Queue des Workers "worker-automatic-choicedate-endless.js". Wird
// in controlAutomatic.js" in der Funktion "startWorkerChoiceEndless(timelaps, velosity, timezone, startdate)"
// gestartet.
// Hier treffen die Daten und Einstellungen aus dem Overlay ein und dienen der
// Einstellung des Workers.
//
// The message queue of the worker “worker-automatic-actualdate-endless.js.”
// in controlAutomatic.js” in the function “startWorkerChoiceEndless (Timelaps, Velosity, Timezone, startdate) “
// started.
// Here the data and settings from the overlay arrive and serve the
// Setting the worker.
onmessage = function (event){
	// Im Array splitData findet man zwei Werte als Key=Value.
	// Sie sind durch "=" getrennt.
	// In the splitData array you find two values as Key=Value.
	// They are separated by “=.”
	splitData = event.data.split("=");
	// Hier, nach dem Key, die einzelnen Ergebnisse den Ausgabebereichen
	// zuweisen.
	// Here, after the key, the individual results of the output areas
	// assign.
	// 
	// Das Hintergrund Worker Objekt für die Hintergrundverarbeitung und Simulation von Datum - bis Datum
	// The background worker object for background processing and simulation from date to date
	if (splitData[0] == "workeruntil"){
		workerChoiceEndless = Object(splitData[1]);
	// ... den Zeitsprung für Animationen über einen längeren Zeitraum. Es wird
	// dann nach der Wartezeit ein Sprung in der berechneten zeit gemacht und angezeigt ...
	// then after the waiting time a jump in the calculated time made and displayed ...
	}else if (splitData[0] == "timelaps"){
		TIMELAPS = Number(splitData[1]);
	// ... die Wartezeit bis zur nächsten Berechnung ...
	// ... the waiting time for the next calculation ...
	}else if (splitData[0] == "delay"){
		DELAYJD = splitData[1];
		// Die Mindestgeschwindigkeit der Wiederholungen liegt bei 50ms
		// Minimum repetition speed is 50ms
		if (DELAYJD < 50) DELAYJD = 50;
	// ... die Zeitzone + DST (Sommer/Winterzeit) als Wert, der zur Zeit addiert werden
	// muss, um auf die entsprechende Zeit LT oder UT zu kommen ...
	// Ist die Zeitzone + DST positiv, also eine Zeit östlich Greenwich, dann ist der Wert
	// negativ. Man muss nur addieren, um auf die UT zu kommen.
	// Ist die Zeitzone + DST negativ, also eine Zeit westlich Greenwich, dann ist der Wert
	// positiv. Man muss nur addieren, um auf die UT zu kommen.
	//
	// ... the time zone + DST (summer/winter time) as a value that is currently being added
	// must in order to get to the appropriate time LT or UT ...
	// If the time zone + DST is positive, i.e. a time east of Greenwich, then the value is
	// Negative. You just have to add up to get to UT.
	// If the time zone + DST is negative, i.e. a time west of Greenwich, then the value is
	// positive. You just have to add up to get to UT.
	}else if (splitData[0] == "timezone"){
		TIMEZONE = parseInt(splitData[1]);
	// Der Wert, der in der Auswahlbox der Zeitzonen hinterlegt wurde. Dies ist nach Osten
	// positiv von 1 - 12 und nach westen von -1 - -12.
	// The value stored in the time zone selection box. This is to the East
	// positive from 1 – 12 and to the west from -1 – -12.
	}else if ( splitData[0] == "OptionTimezone"){
		ONLYTIMEZONE = parseInt(splitData[1]) * -1;
	// Der Wert des Längengrades des zu berechnenden Ortes in dezimalen Grad.
	// The value of the longitude of the place to be calculated in decimal degrees.
	}else if ( splitData[0] == "OptionLongitude"){
		LONGITUDE = Number(splitData[1]);
	// Die Art der Dämmerungsberechnung: A=Astronomisch, N=Nautisch und C=Bürgerlich.
	// The type of twilight calculation: A=Astronomical, N=Nautical and C=Civil.
	}else if ( splitData[0] == "OptionTwilightkind"){
		TWILIGHTKIND = splitData[1];
	// Der Wert des Auswahlfeldes Sommer/Winterzeit, schon um den Wert 1 vermindert, da
	// die Auswahlbox 1=Winter und 2=Sommer hat.
	// The value of the selection field Summer/Winter Time, already reduced by the value 1, because
	// has the selection box 1=Winter and 2=Summer.
	}else if ( splitData[0] == "OptionDST"){
		ONLYDST = parseInt(splitData[1]) * -1;
	// Der Wert des Breitengrades des zu berechnenden Ortes in dezimalen Grad.
	// The value of the latitude of the place to be calculated in decimal degrees.
	}else if ( splitData[0] == "OptionLatitude"){
		LATITUDE = splitData[1];
	// Der Startwert des Datums in Millisekunden als Ganzzahl. Der
	// Wert dient der virtuellen Berechnung des Datums.
	// The start value of the date in milliseconds as an integer. The
	// Value is used for the virtual calculation of the date.
	}else if ( splitData[0] == "startdate"){
		// ... ist das Startdatum und das virtuelle Animationsdatum für die Berechnungen 
		// als lokales Julianisches Datum ...
		// ... is the start date and the virtual animation date for the calculations 
		// as local Julian date ...
		startDate = Number(splitData[1]);
	}else if ( splitData[0] == "enddate"){
		// ... ist das Enddatum und das virtuelle Animationsdatum für die Berechnungen 
		// als lokales Julianisches Datum ...
		// ... is the end date and the virtual animation date for the calculations 
		// as local Julian date ...
		endDate = Number(splitData[1]);
	}else if ( splitData[0] == "Header"){
		// ... ist das Enddatum und das virtuelle Animationsdatum für die Berechnungen 
		// als lokales Julianisches Datum ...
		// ... is the end date and the virtual animation date for the calculations 
		// as local Julian date ...
		HEADER = String(splitData[1]);
		sendString = HEADER;
	}

}// End of Message Queue



/* ******************************************************
	Die Funktion ist die Hauptroutine und wird nach
	einer bestimmten Pause = DELAY plus einem
	eventuelle Zeitspung immer wieder aufgerufen. Bei
	der Erstellung des Workers wird die Routine automatisch
	gestartet.
	
	Sendewerte:
	--------------------
		Date			=	Aktuelles Datumspbjekt
		UTC			=	Aktuelles lokales Datum als formatierter String
		UT			=	Universal Time in Greenwich als formatierter String
		JD			=	Julianisches Datum als Gleitkommazahl
		JDDate		=	Das aus dem JD zurückgerechnete Datum als formatierter String
		MJD			=	Modifiziertes Julianisches Datum als Gleitkommazahl
		MJDDate	=	Zurückgerechnetes Datum aus dem MJD als formatierter String
		sendedWholeDataAsString	=	Der komplette formatierte Sendestring
														aus den obigen Daten
		Progress	=	Verarbeitungszeit in ms
		
	Rückgabewert:
	---------------------
		Keine, sendet aber alle berechneten Daten einzeln an das 
		Erstellungsprogramm "worker-automatic-actualdate-endless.js". 
		und einen kompletten Sendestring, um diesen vom Erstellungs-
		programm an das 	Ausgabefenster  senden zu lassen.
	----------------------------------------------------------------
	The function is the main routine and is
	a certain break = DELAY plus one
	any time spacing called again and again. In case of
	of the creation of the worker, the routine is automatically
	Started.
	
	Transmission values:
	--------------------
		Date   = Current Date Object
		UTC   = Current local date as formatted string
		UT   = Universal Time in Greenwich as formatted string
		JD   = Julian date as floating point number
		JDDate  = The date recovered from the JD as a formatted string
		MJD   = Modified Julian date as floating point number
		MJDDate = Recalculated date from the MJD as formatted string
		sendedWholeDataAsString = The complete formatted transmitter string
														from the above data
		Progress = processing time in ms
		
	Return value:
	---------------------
		None, but sends all calculated data individually to the 
		Create program “worker-automatic-actualdate-endless.js.” 
		and a complete transmitter ring to get it from the creation
		program to the output window.
   *************************************************** */
function calculateJD(){
	// Beginne die Berechnung, wenn ein Startdatum empfangen wurde ...
	// Start the calculation when a start date has been received ...
	if (startDate > 0){
		// ... ermittelt zuerst die Anfangszeit der Verarbeitung in Millisekunden über die PC Zeit...
		// ... first determines the start time of processing in milliseconds via PC time...
		startProgressTimeJD = Date.now();
		startDate += Number(TIMELAPS);
		// Variablen der Hilfsgrößen ...
		// Variables of auxiliary variables ...
		var ret = 0.0; var Date1;  var MJD = 0.0;
		var dateMJD = null; var date = null; var JDUTC = 0.0; var dateJDUTC = "";
		var MJDUTC = 0.0; var dateMJDUTC = "";
		// ... berechne aus dem empfangenen Startdatum der virtuellen Zeit, als Julianisches Datum,
		// zuerst das JD in Greenwich, als die Universale Zeit UT mit Zeitzonenwert und Sommer/Winterzeit,
		// wobei die Vorzeichen so gesetzt sind, das sie durch eine Addition immer Himmelsrichtung Abhängig richtig sind ...
		//
		// ... calculate from the received start date of the virtual time, as Julian date,
		// first the JD in Greenwich, as the Universal Time UT with time zone value and summer/winter time,
		// where the signs are set in such a way that they are always correct by an addition depending on the cardinal direction ...
		startDateJD = startDate + ((ONLYDST + ONLYTIMEZONE) / 24 );
		// ... dann konvertiere das JD UT in die Datums und Zeitangaben ...
		// ... then convert the JD UT to the date and time ...
		var dateJD =  julianDate2Date(startDateJD);
		var HMSMS0 = percentageOfDecimal2Time(decPart(dateJD[0]), "array");
		var dayJD		= Number(dateJD[0] - decPart(dateJD[0]));
		var monthJD	= Number(dateJD[1]);
		var yearJD		= Number(dateJD[2]);
		var hourJD		= Number(HMSMS0[0]);
		var minuteJD	= Number(HMSMS0[1]);
		var secondJD	= Number(HMSMS0[2]);
		var msecondJD= Number(HMSMS0[3]);
		// ... das Julianische Datum der UTC ist das empfangene Startdatum ...
		// ... the Julian date of the UTC is the received start date ...
		// ... und das Julianische Datum der UTC wieder zurück in ein Datum verwandeln ...
		// ... and turn the Julian date of the UTC back into a date ...
		dateJDUTC =  julianDate2Date(startDate);
		var HMSMS = percentageOfDecimal2Time(decPart(dateJDUTC[0]), "array");
		var day		= Number(dateJDUTC[0] - decPart(dateJDUTC[0]));
		var month	= Number(dateJDUTC[1]);
		var year		= Number(dateJDUTC[2]);
		var hour		= Number(HMSMS[0]);
		var minute	= Number(HMSMS[1]);
		var second	= Number(HMSMS[2]);
		var msecond= Number(HMSMS[3]);
		// ... dann aus dem Julianischen Datum des UTC das Modifizierte Julianische Datum UTC berechnen ...
		// ... then calculate the modified Julian date UTC from the Julian date of the UTC ...
		MJDUTC = calculateMJD(startDate);
		// ... und aus dem Modifizierten Julianischen Datum UTC wieder das formatierte Datum ...
		// ... and from the modified Julian date UTC again the formatted date ...
		dateMJDUTC = calculateDateFromMJD(MJDUTC);
		// ... Modified Julian Date ermitteln ...
		// ... Find Modified Julian Date ...
		MJD = calculateMJD(startDateJD);
		// ... und das Datum aus dem MJD berechnen ...
		// ... and calculate the date from the MJD ...
		dateMJD = calculateDateFromMJD(MJD);
		// ... dann aus dem JD der UT in Greenwich das Datum zurückrechnen ...
		// ... then recalculate the date from the JD of the UT in Greenwich ...
		Date1 = julianDate2Date(startDateJD);
		var t = decPart(Date1[0]);
		var Date1HMSMS = percentageOfDecimal2Time(t, "string");
		// --------------------------------------------------------------------------------------------------------------------------------------------
		// Die berechneten Daten an das Programm "controlAutomatic.js" zur Ausgabe senden ...
		// Send the calculated data to the program “controlAutomatic.js” for output ...
		//
		// ... das aktuelle Datumsobjekt und Datum + Uhrzeit als formatierter String und zum Sendestring hinzufügen ...
		// ... add the current date object and date + time as formatted string and to send string ...
		postMessage("DateAndTime=" + startDate);
		sendString += "[" + LPAD(dataLineNumber, 9, "0")+ "]" + "\n";
		sendString += "UTC\t\t\t\t\t\t: " + LPAD(day, 2, "0") + "." + LPAD(month, 2, "0") + "." + LPAD(year, 4, "0") + " - "  +
							  LPAD(hour, 2, "0") + ":"  +  LPAD(minute, 2, "0") + ":" + LPAD(second, 2, "0") + "." + LPAD(msecond, 3, "0") + "\n";
		// ... die normale Uhrzeit = UTC als formatierter String ...
		// ... the normal time = UTC as formatted string ...
		postMessage("UTC=" + LPAD(day, 2, "0") + "." + LPAD(month, 2, "0") + "." + LPAD(year, 4, "0") + " - " +
							LPAD(hour, 2, "0") + ":"  +  LPAD(minute, 2, "0") + ":" +  LPAD(second, 2, "0") + "." + LPAD(msecond, 3, "0"));
		// ... die Universal Time = UT als formatiertes Datum und Uhrzeit und zum Sendestring hinzufügen ...
		// ... add the Universal Time = UT as formatted date and time and to the transmitter string ...
		postMessage("UT=" + LPAD(dayJD, 2, "0") + "." + LPAD(monthJD, 2, "0") + "." +LPAD(yearJD, 4, "0") + " - " +  LPAD(hourJD, 2, "0") + ":" + LPAD(minuteJD, 2, "0") + 
								":" + LPAD(secondJD, 2, "0") + "." + LPAD(msecondJD, 3, "0"));
		sendString +=  "UT\t\t\t\t\t\t: " + LPAD(hourJD, 2, "0") + ":" + LPAD(minuteJD, 2, "0") + 
								":" + LPAD(secondJD, 2, "0") + "." + LPAD(msecondJD, 3, "0")  +  "\n";
		// ... das Julianische Datum UT in Greenwich als Gleitkommazahl und zum Sendestring hinzufügen ...
		// ... add the Julian date UT in Greenwich as a floating point number and to the transmitter string ...
		postMessage("JD=" + startDate);
		sendString +=  "JD\t\t\t\t\t\t: " +  startDate.toFixed(3) +  "\t";
		// ... das aus den JD der UT in Greenwich das zurückgerechnete formatierte Datum senden und zum Sendestring hinzufügen ...
		// ... to send the calculated formatted date from the JD of the UT in Greenwich and add it to the transmitter string ...
		postMessage("JDDate=" + LPAD(( Date1[0] - decPart(Date1[0]) ), 2, "0") + "." + LPAD(Date1[1], 2, "0") + "." 
											  + LPAD(Date1[2], 4 , "0") + " - " + Date1HMSMS);
		sendString += "JD Datum :  " + ( LPAD(( Date1[0] - decPart(Date1[0]) ), 2, "0") + "." + LPAD(Date1[1], 2, "0") + "."
													 + LPAD(Date1[2],4 , "0") + "- " + Date1HMSMS) + "\n";
		// Die Berechnung des MJD Modifizierten Julianischen Datums  ist hier erst ab J1900, also der
		// Periode 1900 möglich ...
		// The calculation of the MJD Modified Julian date is only from J1900, i.e.
		// Period 1900 possible ...
		if ( parseInt(Date1[2]) >= 1900 ){	
			// ... nun das modifizierte Julianische Datum als Gleitkommazahl  und zum Sendestring hinzufügen ...
			// ... now add the modified Julian date as floating point number and to the transmitter string ...
			postMessage("MJD=" + MJD);
			sendString += "MJD\t\t\t\t\t\t: "  +  MJD.toFixed(5)  + "\t";
			// ... das formatierte modifizierte Julianische Datum und zum Sendestring hinzufügen ...
			// ... add the formatted modified Julian date and to the transmitter string ...
			postMessage("MJDDate=" + LPAD(dateMJD[0], 2, "0") + "." + LPAD(dateMJD[1], 2, "0") + 
						"." + dateMJD[2] + " - " + LPAD(dateMJD[3], 2, "0") + ":" + LPAD(dateMJD[4], 2, "0") + 
						":" + LPAD(dateMJD[5], 2, "0") + "." + LPAD(dateMJD[6], 3, "0"));
			sendString += "MJD Datum :  " + ( LPAD(dateMJD[0], 2, "0") + "." + LPAD(dateMJD[1], 2, "0") + 
						"." + dateMJD[2] + " - " + LPAD(dateMJD[3], 2, "0") + ":" + LPAD(dateMJD[4], 2, "0") + 
						":" + LPAD(dateMJD[5], 2, "0") + "." + LPAD(dateMJD[6], 3, "0"))  +  "\n";
		// Werte sind hier nicht möglich, da vor 1900 ...
		// Values are not possible here, since before 1900 ...
		}else{
			postMessage("MJD=" + "N/A");
			sendString += "MJD\t\t\t\t\t\t: N/A\t\t";
			postMessage("MJDDate=" + "N/A");
			sendString += "MJD Datum : N/A\n";
		}
		// ... das Julianische Datum der UTC, also normalen Berechnungszeit am Ort senden und zum
		// Sendestring für das Ausgabefenster hinzufügen ...
		// ... send the Julian date of the UTC, i.e. normal calculation time on site and to
		// Add transmit string for the output window ...
		postMessage("JDUTC=" + startDate);
		sendString += "JD UTC\t\t\t\t\t: "  +  startDate.toFixed(3)  + "\t";
		// ... das aus dem Julianischen Datum der UTC zurüchgerechnete formatierte Datum berechnen
		// und senden und dem Sendestring hinzufügen ...
		// ... calculate the formatted date added from the Julian date to the UTC
		// and send and add to the transmit string ...
		postMessage("dateJDUTC=" + LPAD(day, 2, "0") + "." + LPAD(month, 2, "0") + 
								"." + LPAD(year, 4, "0") + " - " + LPAD(hour, 2, "0") + ":" + LPAD(minute, 2, "0") + 
								":" + LPAD(second, 2, "0") + "." + LPAD(msecond, 3, "0"));
		sendString += "JD UTC Datum : " + ( LPAD(day, 2, "0") + "." + LPAD(month, 2, "0") + 
								"." + LPAD(year, 4, "0") + " - " + LPAD(hour, 2, "0") + ":" + LPAD(minute, 2, "0") + 
								":" + LPAD(second, 2, "0") + "." + LPAD(msecond, 3, "0"))  +  "\n";
		// Die Berechnung des MJD UTC Modifizierten Julianischen Datums  ist hier erst ab J1900, also der
		// Periode 1900 möglich ...
		// The calculation of the MJD UTC Modified Julian date is only from J1900, i.e.
		// Period 1900 possible ...
		if ( parseInt(Date1[2]) >= 1900 ){	
			// ... das mosifizierte Julianische Datum des UTC, also der Berechnungszeit am Ort senden
			// und zum Sendestring hinzufügen ...
			// ... send the mosified Julian date of the UTC, i.e. the calculation time on site
			// and add to the transmitter string ...
			postMessage("MJDUTC=" + MJDUTC);
			sendString +="MJD UTC\t\t\t\t\t: "  +  MJDUTC.toFixed(5)  + "\t";
			// ... das aus dem Modifizierten Julianischen Datum der UTC zurüchgerechnete formatierte Datum 
			// senden und dem Sendestring hinzufügen ...
			// ... the formatted date added from the modified Julian date of the UTC 
			// send and add to the transmitter string ...
			postMessage("dateMJDUTC=" + LPAD(dateMJDUTC[0], 2, "0") + "." + LPAD(dateMJDUTC[1], 2, "0") + 
						"." + dateMJDUTC[2] + " - " + LPAD(dateMJDUTC[3], 2, "0") + ":" + LPAD(dateMJDUTC[4], 2, "0") + 
						":" + LPAD(dateMJDUTC[5], 2, "0") + "." + LPAD(dateMJDUTC[6], 3, "0"));
			sendString += "MJD UTC Datum : " + ( LPAD(dateMJDUTC[0], 2, "0") + "." + LPAD(dateMJDUTC[1], 2, "0") + 
						"." + dateMJDUTC[2] + " - " + LPAD(dateMJDUTC[3], 2, "0") + ":" + LPAD(dateMJDUTC[4], 2, "0") + 
						":" + LPAD(dateMJDUTC[5], 2, "0") + "." + LPAD(dateMJDUTC[6], 3, "0"))  +  "\n";
		// Werte sind hier nicht möglich, da vor 1900 ...
		// Values are not possible here, since before 1900 ...
		}else{
			postMessage("MJDUTC=" + "N/A");
			postMessage("dateMJDUTC=" + "N/A");
			sendString += "MJD UTC\t\t\t\t\t: " + "N/A\t\t";
			sendString += "MJD UTC Datum : " + "N/A\n";
		}
		// ************************************ Sonnenparameter berechnen *********************************************
		// multiArray ist ein Array mit zwei Arrays Sonnenparameter und Mondparameter
		// multiArray[0] = Sonnen Parameter als kompletter Sendestring
		// multiArray[1] = Mond Parameter, die hier einmal in den Sendestring zum Ausgabefenster gesendet werden
		//						   und einmal in den Ausgabetextfeldern ausgegeben werden müssen, dazu müssen sie erst
		// 						   zurück an controlautomatic.js gesendet werden, damit sie dort ausgegeben werden können ...
		//
		// multiArray is an array with two arrays solar parameters and moon parameters
		// multiArray[0] = Sun parameters as complete transmitter string
		// multiArray[1] = Moon Parameters, which are sent to the transmit string to the output window
		//      and must be output once in the output text fields, for this they must first
		//       back to controlautomatic.js so that they can be output there ...
		var multiArray =  sunParameter(Number(day), Number(month), Number(year), hour, minute, second, msecond, TWILIGHTKIND, sendString, "automatic");
		// multiArray[1] = Mond Parameter Indizes
		// multiArray[1] = Moon Parameter Indices
		sendString = multiArray[0];
		// Index 0 = Zeit des Mondaufgangs - Time of moonrise ...
		sendString += "\nMondaufgang \t\t\t\t: " + multiArray[1][0] + "\n";
		// Index 1 = Status des Mondaufgangs - State of moonrise
		sendString += "Status Mondaufgang \t\t\t: " + multiArray[1][1];
		// Index 2 = Der Azimuth des Sonnenaufgangs - The Azimuth of the Sunrise ...		
		sendString += "\nAzimuth Mondaufgang \t\t: " + multiArray[1][2];
		// Index 3 = Die Höhe des Mondaufgangs über dem Horizont - The altitude of the moonrise above the horizon ...
		sendString += "\nHoehe Mondaufgang \t\t\t: " + multiArray[1][3];
		// Index 4 = Der Azimuth des Monduntergangs  - The Azimuth of the moonset ...
		sendString += "\nAzimuth Monduntergang \t\t: " + multiArray[1][4];
		// Index 5 = Die Höhe des Mondes beim Untergang über dem Horizont - The height of the moon at setting above the horizon...
		sendString += "\nHoehe Monduntergang \t\t: " + multiArray[1][5];		
		// Index 6 = Zeit des Monduntergangs - Time of moonset ...
		sendString += "\nMonduntergang \t\t\t\t: " + multiArray[1][6];
		// Index 7 = Status des Monduntergangs - State of moonset ...
		sendString += "\nStatus Monduntergang \t\t: " + multiArray[1][7];
		// Index 8 = Höchststand des Monds - The maximum of the moon ...
		sendString += "\nMaximum Mond \t\t\t\t: " + multiArray[1][8];
		// Index 9 = Der Azimuth beim Mondhöchststand - The azimuth at the moon’s highest point ...
		sendString += "\nAzimuth Hoechststand \t\t: " + multiArray[1][9];
		// Index 10 = Die geozentrische Höhe des Mondes über dem Horizont - The geocentric height of the Moon above the horizon ...
		sendString += "\nHoehe Hoechststand \t\t\t: " + multiArray[1][10];
		// Index 11 = Die Entfernung Erde-Mond - The distance Earth-Moon ...
		sendString += "\nEntfernung Erde-Mond \t\t: " + multiArray[1][13];
		// Index 12 = Durchmesser des Mondes am Himmel in Grad - Diameter of the Moon in the Sky in degrees ...
		sendString += "\nDurchmesser Mond \t\t\t: " + multiArray[1][14];
		// Index 13 = Die  aktuelle Höhe des Mondes in Grad - The actual altitude of the Moon in degrees ...
		sendString += "\nAktuelle Hoehe Mond \t\t\t: " + multiArray[1][11];
		// Index 13 = Der aktuelle Azimuth des Mondes in Grad - The actual azimuth of the Moon in degrees ...
		sendString += "\nAktueller Az. Mond \t\t\t: " + multiArray[1][12] + "\n";
		
		// Den Mondaufgang an controlAutomatic.js zur Ausgabe senden ...
		// Send the moonrise to controlAutomatic.js for output ...
		postMessage("moonrise=" + multiArray[1][0] );
		// Den Status des Mondaufgang an controlAutomatic.js zur Ausgabe senden ...
		// Send the state of the moonrise to controlAutomatic.js for output ...
		postMessage("statemoonrise=" + multiArray[1][1] );
		// Azimuth des Mondes beim Aufgang
		// Azimuth of the Moon at rising
		postMessage("azimuthmoonrise=" + multiArray[1][2] );
		// Höhe des Mondes beim Aufgang
		// Altitude of the Moon at rising
		postMessage("altitudemoonrise=" + multiArray[1][3] );
		// Azimuth des Mondes beim Unterfgang
		// Azimuth of the Moon at sunset
		postMessage("azimuthmoonset=" + multiArray[1][4] );
		// Höhe des Mondes über dem Horizont beim Untergang
		// Height of the Moon above the horizon at sunset
		postMessage("altitudemoonset=" + multiArray[1][5] );
		// Den Mondunterfgang an controlAutomatic.js zur Ausgabe senden ...
		// Send the moonset to controlAutomatic.js for output ...
		postMessage("moonset=" + multiArray[1][6] );
		// Den Status des Monduntergang an controlAutomatic.js zur Ausgabe senden ...
		// Send the state of the moonset to controlAutomatic.js for output ...
		postMessage("statemoonset=" + multiArray[1][7] );
		// Den Höchststand des Mondes an controlAutomatic.js zur Ausgabe senden ...
		// Send the maximum of the moon to controlAutomatic.js for output ...
		postMessage("moonhigh=" + multiArray[1][8] );
		// Den Azimuth des Höchststand des Mondes an controlAutomatic.js zur Ausgabe senden ...
		// Send the azimuth of the the maximum of the moon to controlAutomatic.js for output ...
		postMessage("moonhighaz=" + multiArray[1][9] );
		// Die geozentrische Höhe des Mondes über dem Horizont an controlAutomatic.js zur Ausgabe senden ...
		// Send The geocentric height of the Moon above the horizon to controlAutomatic.js for output ...
		postMessage("moonhighdeg=" + multiArray[1][10] );
		// Die Entfernung Erde-Mond an controlAutomatic.js zur Ausgabe senden ...
		// Send the distance Earth-Moon to controlAutomatic.js for output ...
		postMessage("moondist=" + multiArray[1][13] );
		// Durchmesser des Mondes am Himmel in Grad an controlAutomatic.js zur Ausgabe senden ...
		// Send the Diameter of the Moon in the Sky in degrees to controlAutomatic.js for output ...
		postMessage("moondia=" + multiArray[1][14] );
		// Index 13 = Die aktuelle Höhe des Mondes über dem Horizont in Grad
		// Index 13 = The actual altitude of the Moon above horizon in degrees ...
		postMessage("moonh=" + multiArray[1][11] );
		// Index 13 = Der aktuelle Azimuth des Mondes in Grad
		// Index 13 = The actual azimuth of the Moon in degrees ...
		postMessage("moonaz=" + multiArray[1][12] );
		// ... am Ende ermittelt die Endzeit der Verarbeitung in Millisekunden für die komplette Berechnung ...
		// ... at the end determines the end time of the processing in milliseconds for the complete calculation ...
		stopProgressTimeJD = Date.now();
		// ... aus der realen Stop- und Starzeit ergibt sich die Differenz als verronnene Zeit während der
		// Berechnungen. Plus die Wartezeit ergibt sich der reale Zeitfortschritt ...
		// ... from the real stop and start time, the difference results as missed time during the
		// Calculations. Plus the waiting time results in real time progress ...
		var diff = Number(stopProgressTimeJD - startProgressTimeJD) + Number(DELAYJD);
		// ... und dieser wird auf das virtuelle Datum addiert. Damit hat man das virtuellen Datum
		// mit dem Zeitfortschritt ...
		// ... and this is added to the virtual date. This gives you the virtual date
		// with the progress of time ...
		startDate += (diff * PERCENTMILLI);
		// ... und wenn die neue Verarbeitungszeit größer ist als die letzte ...
		// ... and if the new processing time is longer than the last one ...
		if ( (Number(stopProgressTimeJD) - Number(startProgressTimeJD)) > Number(diffProgressTimeJD) ){
			// ... dann speichere die neue Verarbeitungszeit als die Höhere ...
			// ... then save the new processing time as the Higher ...
			diffProgressTimeJD = Number(stopProgressTimeJD) - Number(startProgressTimeJD);
			// ... und ist die neue Verarbeitungszeit größer als die Wartezeit ...
			// ... and the new processing time is greater than the waiting time ...
			if ( diffProgressTimeJD > DELAYJD){
				// ... dann passe die Wartezeit an + eine kleine Sicherheit von 10 ms ...
				// ... then adjust the waiting time + a small security of 10 ms ...
				DELAYJD = Number(DELAYJD) + Number(diffProgressTimeJD) + 10;
			}
		}
		// Horizontaler Strich - Horizontal stroke
		sendString +=  LPAD("_", 80, "_") + "\n";
		// ... nun den an das Ausgabefenster zu sendenden Datenstring an  das Programm "controlAutomatic.js" senden ...
		// ... now send the data string to the output window to the program “controlAutomatic.js” ...
		postMessage("sendedChoiceWholeDataAsString=" + sendString );
		sendString = "";
		// ... die Zeilennummerierung für den Sendestring an das Ausgabefenster + 1 ...
		// ... the line numbering for the transmitter string to the output window + 1 ...
		dataLineNumber++;
		// ... nun sende die Verarbeitungszeit zur Ausgabe an das Programm "controlAutomatic.js" ...
		// ... now send the processing time for output to the program “controlAutomatic.js” ...
		//var d = Number(DELAYJD) + Number(diffProgressTimeJD);
		postMessage("Progress=" + DELAYJD);
	}
	// Die Berechnungen nur durchführen, wenn Startdatum > 0 und Enddatum = 0 -> Berechnung "Ab gewähltem Datum"
	// nach einem virtuellen Datum und Uhrzeit ...
	// oder wenn Startdatum kleiner oder gleich dem Enddatum -> Berechnung "Ab gewähltem Datum" "Bis zum Datum"
	// nach einem virtuellen Datum und Uhrzeit ...
	//
	// Perform calculations only if start date > 0 and end date = 0 -> calculation “From selected date”
	// after a virtual date and time ...
	// or if start date is less than or equal to the end date -> Calculation “From selected date” “To date”
	// after a virtual date and time ...
	if ( (startDate > 0 && endDate == 0) || (startDate <= endDate) ){
		// ... und nach der Wartezeit rufe die Funktion wieder rekursiv auf.
		// ... and after waiting call the function recursively again.
		setTimeout("calculateJD()", DELAYJD);
	}else{
		// Der Worker wird durch Ablauf der Zeit als Animation beenden.
		// The worker will end as an animation by the end of the time.
		if (workerChoiceEndless){
			postMessage("workerChoiceEndlessUntil=stopped");
		}

	}
	
}// End of calculateJD() 

// Startet die Funktionen erstmals als Thread im Background.
// Starts the functions first time as a thread in the background.
calculateJD();