/* *****************************************************************************************
 *	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 () “
 *
 ***************************************************************************************** */

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;												// Millisekunden des Startdatums
																		// Milliseconds of start date
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 workerActualEndless = null;						// Das Hintergrund Worker Objekt für die Hintergrundverarbeitung und Simulation von Aktuellem Datum - bis Aktuellem Datum
																		// The background worker object for background processing and simulation from actual date to actual date

/*	*************************************** Importieren der extern benötigten Module und Funktionen ********************************************* */
/* ************************************************* Import of external modules and functions ******************************************************* */

// 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-actualdate-endless.js". Wird
// in controlAutomatic.js" in der Funktion "startWorkerActualEndless(timelaps, velosity, timezone)"
// 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 “startWorkerActualEndless (Timelaps, Velosity, Timezone) “
// 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] == "workeractualuntil"){
		workerActualEndless = 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 = 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]);
	// 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]);
	// 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];
	// Das JD Startdatum - The julian date start date
	}else if ( splitData[0] == "startdate"){
		// Das JD des Startdatums muss hier nicht in einen MS Millisekundenwert
		// konvertiert werden, da der aktuelle MS Datumswert noch einmal ermittelt
		// wird und es nur wichtig ist das es ein Wert > 0 ist ...
		// The JD of the start date does not have to be in an MS millisecond value
		// be converted, because the current MS date value is determined again
		// becomes and it is only important that it is a value > 0 ...
		startDate = splitData[1];
	// Das JD Enddatum - The julian date end date
	}else if ( splitData[0] == "enddate"){
		endDate = splitData[1];
		// Ist das empfangene Endedatum größer 0, dann soll bis zu einem
		// Endedatum gerechnet werden ... nur dann das Julianische Endedatum in
		// ein MS Millisekundenwert umrechnen ...
		// If the received end date is greater than 0, then up to one
		// end date to be calculated ... only then the Julian end date in
		// convert an MS millisecond value ...
		if (endDate > 0){
			var dateArr = julianDate2Date(Number(endDate));
			var timeArr = percentageOfDecimal2Time(decPart(dateArr[0]), "array");
			endDate = new Date(dateArr[2], dateArr[1], lInt(dateArr[0]), timeArr[0], timeArr[1], timeArr[2], timeArr[3]);
		}
	// Die Kopfdaten für die Datenausgabe an "sendString" übergeben
	// Pass the header data for the data output to “sendString”
	}else if ( splitData[0] == "Header"){
		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(){
	// Die Dämmerungsart wird nicht schnell genug entgegen genommen, darum wird erst berechnet, wenn der Wert
	// zur Verfügung steht, ansonsten sind die Berechnungen nicht vollständig. Der erste Datensatz fehlt dann ...
	// The twilight mode is not accepted fast enough, so it is only calculated when the value
	// is available, otherwise the calculations are not complete. The first record is then missing ...
	if ( TWILIGHTKIND != ""){
		// Ermittelt zuerst die Anfangszeit der Verarbeitung in Millisekunden ...
		// First determine the start time of processing in milliseconds ...
		startProgressTimeJD = Date.now();
		// Variablen der Hilfsgrößen ...
		// Variables of auxiliary variables ...
		var y = 0; var m = 0; var B = 0; 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 = "";
		// Zu berechnendes Datumsobjekt ...
		// Date object to be calculated ...
		date = new Date();
		// Das Ende Datum der Berechnungszeit wenn "Bis zum Datum" gewählt wurde,
		// das aktuelle Datum ermitteln. ACHTUNG: Zeitzone und Sommer/Winterzeit muss
		// mit berücksichtigt werden ...
		if (startDate > 0 && endDate > 0)
			actualDate = date.getTime() + Number(TIMEZONE);
		year = date.getFullYear();				// Das Jahr ... the year
		month = date.getMonth() + 1;		// der Monat + 1, da 0 = Januar ... the month + 1, because 0 = January
		day = date.getDate();					// der Tag des Monats ... the day of the month
		// ... Universal Time = GMT als Gleitkommazahl, also UTC + Timezone + DST ...
		// ... Universal Time = GMT as floating point number, i.e. UTC + Timezone + DST ...
		UT = Number(date.getHours()) + Number(date.getMinutes()/60.) + Number(date.getSeconds()/3600.) + Number(date.getMilliseconds()/1000./3600.) + Number(TIMEZONE);
		// ... Date Objekte für die Umstellung von Julianischen- auf
		// Gregorianischen Kalender ...
		// ... Date objects for switching from Julian to
		// Gregorian Calendar ...
		var date1 = new Date("1582", "10", "4");
		var date2 = new Date("1582", "10", "15")
		// ... Hilfsgrößen berechnen ...
		// ... Calculate auxiliary variables ...
		if (month <= 2) {
			y = year - 1;
			m = month + 12; 
		}else{
			y = year;
			m = month;
		}
		/* **************************************************
		 * Beschränkt man sich bei den Berechnungen nur auf den
		 * Zeitraum vom 01.03.1900 - 28.02.2100, dann kann man
		 * B = -15 setzen.
		 * The calculations are limited to the
		 * Period from 01.03.1900 – 28.02.2100, then you can
		 * B = -15.
		 * **************************************************/
		// ... das übergebenes Datum liegt im Julianischen Bereich ...
		// ... the given date is in the Julian area ...
		if (date <= date1){
			B = -2;
		// ... das übergebenes Datum liegt im Gregorianischen Bereich ...
		// ... the given date is in the Gregorian area ...
		}else if (date >= date2){
			B = Math.floor(y/400) - Math.floor(y/100);
		}
		// ... nun das Julianisches Datum UT berechnen ...
		// ... now calculate the Julian date UT...
		ret = Number(Math.floor(365.25 * y) + Math.floor(30.6001 * (m + 1)) + B + 1720996.5 + day + (UT/24) );
		// ... jetzt das Julianische Datum der UTC berechnen ...
		// ... now calculate the Julian date of the UTC ...
		JDUTC = calculateJD1(day,month,year, Number(date.getHours()) + Number(date.getMinutes()/60.) + Number(date.getSeconds()/3600.) + Number(date.getMilliseconds()/1000./3600.) );
		// ... und das Julianische Datum der UTC wieder zurück in ein Datum als Kontrolle verwandeln ...
		// ... and turn the Julian date of the UTC back into a date as a control ...
		dateJDUTC =  calculateDate(JDUTC);
		// ... 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(JDUTC);
		// ... 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);
		// ... dann aus dem JD das Datum rückrechnen ...
		// ... then recalculate the date from the JD.
		Date1 = calculateDate(ret);
		// ... Modified Julian Date ermitteln ...
		// ... Find Modified Julian Date ...
		MJD = calculateMJD(ret);
		// ... und das Datum aus dem MJD berechnen ...
		// ... and calculate the date from the MJD ...
		dateMJD = calculateDateFromMJD(MJD);

		// --------------------------------------------------------------------------------------------------------------------------------------------
		// 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=" + date);
		sendString += "[" + LPAD(dataLineNumber, 6, "0")+ "]" + "\n"
		// ... die normale Uhrzeit = UTC als formatierter String für die Datenausgabe...
		// ... the normal time = UTC as formatted string for data output ...
		sendString += "UTC\t\t\t\t\t\t: " + LPAD(date.getDate(), 2, "0") + "." + LPAD((date.getMonth()+ 1), 2, "0")+ "." + LPAD(date.getFullYear(), 4, "0") + " - "  +
							  LPAD(date.getHours(), 2, "0") + ":"  +  LPAD(date.getMinutes(), 2, "0") + ":" + LPAD(date.getSeconds(), 2, "0") + "." + LPAD(date.getMilliseconds(), 3, "0")+ "\n";			  
		// ... die Millisekunden getrennt, da sie im date Objekt beim Senden verloren gehen ...
		// ... the milliseconds separated, because they are lost in the date object when sending ...
		postMessage("DateAndTimeMilliseconds=" + LPAD(date.getMilliseconds(), 3, "0"));
		// ... die normale Uhrzeit = UTC als formatierter String für die Datenausgabe ...
		// ... the normal time = UTC as formatted string for data display ...
		postMessage("UTC=" + LPAD(day, 2, "0") + "." + LPAD(month, 2, "0") + "." + year + " - " +
								LPAD(date.getHours(), 2, "0") + ":" + LPAD(date.getMinutes(), 2, "0") + ":" + 
								LPAD(date.getSeconds(), 2, "0") + "." + LPAD(date.getMilliseconds(), 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(Date1[0], 2, "0") + "." + LPAD(Date1[1], 2, "0") + "." + Date1[2] + " - " +  LPAD(Date1[3], 2, "0") + ":" + LPAD(Date1[4], 2, "0") + 
								":" + LPAD(Date1[5], 2, "0") + "." + LPAD(Date1[6], 3, "0"));
		sendString +=  "UT\t\t\t\t\t\t: " + LPAD(Date1[0], 2, "0") + "." + LPAD(Date1[1], 2, "0") + "." + Date1[2] + " - " + LPAD(Date1[3], 2, "0") + ":" + LPAD(Date1[4], 2, "0") + 
								":" + LPAD(Date1[5], 2, "0") + "." + LPAD(Date1[6], 3, "0")  +  "\n";
		// ... das Julianische Datum als Gleitkommazahl und zum Sendestring hinzufügen ...
		// ... add the Julian date as a floating point number and to the transmitter string ...
		postMessage("JD=" + ret);
		sendString += "JD\t\t\t\t\t\t: " +  ret.toFixed(3)  +  "\t";	
		// ... das aus den JD zurückgerechnete formatierte Datum .und zum Sendestring hinzufügen ...
		// ... the formatted date recovered from the JD .and add to the transmitter string ...
		postMessage("JDDate=" + LPAD(Date1[0], 2, "0") + "." + LPAD(Date1[1], 2, "0") + "." + 
								LPAD(Date1[2],2 , "0") + " - " + LPAD(Date1[3], 2, "0") + ":" + LPAD(Date1[4], 2, "0") + 
								":" + LPAD(Date1[5], 2, "0") + "." + LPAD(Date1[6], 3, "0"));
		sendString +=  "JD Datum : " + ( LPAD(Date1[0], 2, "0") + "." + LPAD(Date1[1], 2, "0") + "." + 
								LPAD(Date1[2],2 , "0") + " - " + LPAD(Date1[3], 2, "0") + ":" + LPAD(Date1[4], 2, "0") + 
								":" + LPAD(Date1[5], 2, "0") + "." + LPAD(Date1[6], 3, "0"))  +  "\n";
		// ... 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";
		// ... 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=" + JDUTC);
		sendString += "JD UTC\t\t\t\t\t: "  +  JDUTC.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(dateJDUTC[0], 2, "0") + "." + LPAD(dateJDUTC[1], 2, "0") + 
					"." + dateJDUTC[2] + " - " + LPAD(dateJDUTC[3], 2, "0") + ":" + LPAD(dateJDUTC[4], 2, "0") + 
					":" + LPAD(dateJDUTC[5], 2, "0") + "." + LPAD(dateJDUTC[6], 3, "0"));
		sendString += "JD UTC Datum : " + ( LPAD(dateJDUTC[0], 2, "0") + "." + LPAD(dateJDUTC[1], 2, "0") + 
					"." + dateJDUTC[2] + " - " + LPAD(dateJDUTC[3], 2, "0") + ":" + LPAD(dateJDUTC[4], 2, "0") + 
					":" + LPAD(dateJDUTC[5], 2, "0") + "." + LPAD(dateJDUTC[6], 3, "0"))  +  "\n";
		// ... 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";
		
		// ************************************ 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(day, month, year, date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds(), TWILIGHTKIND, sendString, /*moonArray,*/ "automatic");
		// multiArray[1] = Mond Parameter Indizes
		// multiArray[1] = Moon Parameter Indices
		sendString = multiArray[0];
		// Index 0 = Zeit des Mondaufgangs - Time of moon rise
		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 -Azimuth of sun rise		
		sendString += "\nAzimuth Mondaufgang \t\t: " + multiArray[1][2];
		// Index 3 = Die Höehe des Mondaufgangs über dem Horizont - The altitude of the moon over horizon
		sendString += "\nHoehe Mondaufgang \t\t\t: " + multiArray[1][3];
		// Index 4 = Der Azimuth des Monduntergangs - The azimuth of the moon set
		sendString += "\nAzimuth Monduntergang \t\t: " + multiArray[1][4];
		// Index 5 = Die Höhe des Mondes beim Untergang über dem Horizont - The altitude of the moon set over 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();
		// ... 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("sendedActualWholeDataAsString=" + sendString );
		// ... danach muss der String geleeert werden, ansonsten werden die Daten immer wieder aufaddiert ...
		// ... then the string must be emptied, otherwise the data will be added up again and again ...
		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);
		
	}// End of if (TWILIGHTKIND ...)
		
	// Die Berechnungen nur durchführen, wenn Startdatum = 0 und Enddatum = 0 -> laufende Berechnung
	// nach der aktuellen Uhrzeit ...
	// oder wenn Startdatum = > 0 und Enddatum > 0 und das aktuelle Datum kleiner gleich dem Endedatum ist-> laufende Berechnung
	// nach der aktuellen Uhrzeit .bis zu einem Enddatum.
	//
	// Perform calculations only if start date = 0 and end date = 0 -> running calculation
	// according to the current time ...
	// or if start date = > 0 and end date > 0 and the current date is less than the end date-> running calculation
	// according to the current time .up to an end date.
	if ( (startDate > 0 && endDate == 0) || (actualDate <= 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 (workerActualEndless){
			postMessage("workerActualEndlessUntil=stopped");
		}
	}
	
}// End of calculateJD() 


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