Harvest festival 2024.png

Dare to try out the Harvest Festival 2024!?

MediaWiki:VanaTime.js

From HorizonXI Wiki
Revision as of 16:21, 25 November 2023 by Starfox9507 (talk | contribs)

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
//*********************************************************************
// Javascript below contributes to live Vana'diel Time listed in Sidebar
// All code taken from: https://www.pyogenes.com/ffxi/timer/v2.html 
//***************************

/* 
Add the class tags below to incorporate current guild times 
<b><p class="page-alchemy_hours"></p></b>

The following are valid class tags:
page-alchemy_hours
page-bonecraft_hours
page-clothcraft_hours
page-cooking_hours
page-fishing_hours
page-goldsmithing_hours
page-leathercraft_hours
page-smithing_hours
page-woodworking_hours

*/
////////////////////////////////////////////////////////////////////
//The following classnames are for <div>s throughout Vanatime.js
const conquest_schedule = "vanatime-page-conquest-schedule";
const moon_phase = "vanatime-page-moon-phase";
const moon_phases_schedule = "vanatime-page-moon-phases-schedule";
const crafting_guilds_schedule = "vanatime-page-crafting-guilds-schedule";
////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////
//The following classnames are for tables throughout Vanatime.js
//const airship_schedule_table = "vanatime-page-airship-schedule-table";
const moon_phase_table = "vanatime-page-moon-phase-table";
const moon_phases_schedule_table = "vanatime-page-moon-phases-schedule-table";
const crafting_guilds_schedule_table = "vanatime-page-crafting-guilds-schedule-table";

class timeElements {
	static ids = {
		airships : {
			main : "vanatime-airship-schedule-table",
			jeuno : "vanatime-airship-schedule-jeuno-table",
			bastok : "vanatime-airship-schedule-bastok-table",
			sandy : "vanatime-airship-schedule-sandy-table",
	        windy : "vanatime-airship-schedule-windy-table",
			kazham : "vanatime-airship-schedule-kazham-table",
		},
		boats : {
			selbina : "vanatime-boat-schedule-selbina-table",
			ahtUrhgan : "vanatime-boat-schedule-ahtUrhgan-table",
			//bibiki : "vanatime-boat-schedule-bibiki-table", //consider removing this and refactoring
            bibiki : "vanatime-boat-schedule-bibikiFullSchedule-table",
            purgonorgoIsle : "vanatime-boat-schedule-purgonorgoIsle-table",
            northLanding : "vanatime-boat-schedule-northLanding-table",
            centralLanding : "vanatime-boat-schedule-centralLanding-table",
            southLanding : "vanatime-boat-schedule-southLanding-table"
		}
	}
}

class schedule {
    static boats = {
        //All manaclipper data is copy/paste from ASB (manaclipper.lua)
        bibiki :  [
            { time :   10, act : "arrive", dest : "Dhalmel Rock" },      // 00:10
            { time :   50, act : "depart", dest : "Dhalmel Rock" },      // 00:50
            { time :  290, act : "arrive", dest : "Purgonorgo Isle" },   // 04:50
            { time :  330, act : "depart", dest : "Purgonorgo Isle" },   // 05:30
            { time :  730, act : "arrive", dest : "Maliyakaleya Reef" }, // 12:10
            { time :  770, act : "depart", dest : "Maliyakaleya Reef" }, // 12:50
            { time : 1010, act : "arrive", dest : "Purgonorgo Isle" },   // 16:50
            { time : 1050, act : "depart", dest : "Purgonorgo Isle" },   // 17:30
        ],
        purgonorgoIsle : [
            { time :  510, act : "arrive", dest : "Bibiki Bay" },       // 08:30
            { time :  555, act : "depart", dest : "Bibiki Bay" },       // 09:15
            { time : 1230, act : "arrive", dest : "Bibiki Bay" },       // 20:30
            { time : 1275, act : "depart", dest : "Bibiki Bay" },       // 21:15
            { time : 1950, act : "arrive", dest : "Bibiki Bay" },       // 32:30

        ],
        northLanding : [
            { time :  965, act : "arrive", dest : "Central Landing" }, // 16:05 Arrive OOS
            { time :  973, act : "depart", dest : "Central Landing" }, // 16:12 Depart OOS
            { time : 1005, act : "arrive", dest : "Central Landing" }, // 16:45 to Central
            { time : 1045, act : "depart", dest : "Central Landing" }, // 17:25 to Central
        ],
        centralLanding : [
            { time :  280, act : "arrive", dest : "South Landing" }, // 04:40 from South Landing - EMFEA
            { time :  310, act : "depart", dest : "South Landing" }, // 05:10 to South Landing - Newtpool
            { time : 1160, act : "arrive", dest : "South Landing" }, // 19:20 from North Landing
            { time : 1190, act : "depart", dest : "South Landing" }, // 19:50 to South Landing - Newtpool PM
        ],
        southLanding : [
            { time :   15, act : "arrive", dest : "Central Landing - EMFEA" }, // 00:15 from Central Landing - EMFEA
            { time :   50, act : "depart", dest : "Central Landing - EMFEA" }, // 00:50 to Central Landing - EMFEA
            { time :  540, act : "arrive", dest : "North Landing" }, // 09:00 Arrive OOS
            { time :  547, act : "depart", dest : "North Landing" }, // 09:07 Depart OOS
            { time :  575, act : "arrive", dest : "North Landing" }, // 09:35 Arrive from North Landing
            { time :  610, act : "depart", dest : "North Landing" }, // 10:10 to North Landing - Main Canal
            { time : 1420, act : "arrive", dest : "Central Landing - EMFEA" }, // 23:40 Arrive OOS
            { time : 1427, act : "depart", dest : "Central Landing - EMFEA" }, // 23:47 Depart OOS
        ]
        
    }
}

class vanaTime {

    #msGameDay	= (24 * 60 * 60 * 1000 / 25);   // milliseconds in a game day = 3456000
    #msRealDay	= (24 * 60 * 60 * 1000);        // milliseconds in a real day = 86400000

    #vanaBirthDate = (((898 * 360) + 30) * 24 * 60 * 60) / (25 / 1000);  // miliseconds since birth of Vanadiel =  1117359360000

    #baseDate; // built at runtime

    constructor() {
        this.#baseDate = new Date();
        this.#baseDate.setUTCFullYear(2002, 5, 23); // Set date to 2003-06-23
        this.#baseDate.setUTCHours(15, 0, 0, 0);    // Set time to 15:00:00.0000
    }


    /**
     * @summary - gets current Vanadiel Time
     * @returns - value in milliseconds
     */
    getVanaDate(){
        var temp = new Date();
        return ((898 * 360 + 30) * this.#msRealDay) + (temp.getTime() - this.#baseDate) * 25;
    }


    /**
     * @summary - used for calculating transport schedules with predetermined offsets
     * @returns - current Vanadiel day with time 00:00 in milliseconds
     */
    _rawVanaToday(){
        var now = this.getVanaDate();
        now = ( now - ( now % this.#msRealDay ));
        return now;
    }


    /**
     * @param value  - minutes to be converted
     * @returns - value in milliseconds
     */
    _convertMinsToMiliseconds(value){ return value * (60 * 1000); }
    

    /**
     * @param time - Vanadiel time needing to be converted
     * @returns - value in milliseconds
     */
    _convertToEarthTime(time){
        if (time === undefined) time = this.getVanaDate();
        var earthTime = time / ( 25 );
        return new Date(Math.floor(earthTime) - (this.#vanaBirthDate - this.#baseDate));
    }


    /*
        Private functions assisting with the manipulation of Vana time for the string generators below
    */
    #getVanaDate_Year(currentVanaTime){     return Math.floor(currentVanaTime / (360 * this.#msRealDay)); }
    #getVanaDate_Month(currentVanaTime){    return Math.floor((currentVanaTime % (360 * this.#msRealDay)) / (30 * this.#msRealDay)) + 1; }
    #getVanaDate_Date(currentVanaTime){     return Math.floor((currentVanaTime % (30 * this.#msRealDay)) / (this.#msRealDay)) + 1; }
    #getVanaDate_Hour(currentVanaTime){     return Math.floor((currentVanaTime % (this.#msRealDay)) / (60 * 60 * 1000)); }
    #getVanaDate_Min(currentVanaTime){      return Math.floor((currentVanaTime % (60 * 60 * 1000)) / (60 * 1000)); }
    //#getVanaDate_Sec(currentVanaTime){      return Math.floor((currentVanaTime % (60 * 1000)) / 1000); }


    /**
     * @param time - Vanadiel time needing to be converted
     * @returns - string of HOURS:MINS
     */
    stringVanaTime(time){
        if (time === undefined) time = this.getVanaDate();

        var vYear = this.#getVanaDate_Year(time);
        var vMonth = this.#getVanaDate_Month(time);
        var vDate = this.#getVanaDate_Date(time);
        var vHour = this.#getVanaDate_Hour(time);
        var vMin = this.#getVanaDate_Min(time);
        //seconds left our because we don't use them for any calcs

        if (vYear < 1000)  vYear = "0" + vYear; 
        if (vMonth  < 10) vMonth  = "0" + vMonth;
        if (vDate  < 10)  vDate  = "0" + vDate;
        if (vHour < 10)  vHour = "0" + vHour; 
        if (vMin  < 10)  vMin  = "0" + vMin; 

        //return vYear + ":" + vMonth + ":" + vDate + " [" + vHour + ":" + vMin + "]" ; // for testing
        return vHour + ":" + vMin; 
    }

     /**
     * @param {Date} time - Earth time needing to be converted
     * @returns - string formatted as HOURS:MINS
     */
    stringEarthTime(time) {
        var eTime = this._convertToEarthTime(time);

        //Most of these arent needed, left in for future inclusion if needed/wanted
        // var eYear = eTime.getFullYear();
        var eMon  = eTime.getMonth();
        var eDate = eTime.getDate();
        var eHour = eTime.getHours();
        var eMin  = eTime.getMinutes();
        var eSec  = eTime.getSeconds();
        var eDay  = eTime.getDay();
        
        // Assigns a leading zero if neccessary
        if (eDate < 10)  eDate = "0" + eDate; 
        if (eHour < 10)  eHour = "0" + eHour; 
        if (eMin < 10)   eMin  = "0" + eMin;  
        if (eSec < 10)   eSec  = "0" + eSec;  
        
        //var EarthDay      = new Array("SUN","MON","TUE","WED","THU","FRI","SAT");
        var EarthMonth    = new Array("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"); 

        //var str = EarthMonth[eMon] + " " + eDate + ", " + eYear + " (" + EarthDay[eDay] + ") " + eHour + ":" + eMin + ":" + eSec;
        //var str = EarthMonth[eMon] + " " + eDate + "," + eHour + ":" + eMin + ":" + eSec;
        var str = eHour + ":" + eMin + ":" + eSec;
        return str;
    }

    /**
     * @param  nextDeparture - Earth time needing to be converted
     * @returns - string of HOURS:MINS
     */
    timeUntil(nextDeparture){
        if (nextDeparture === undefined) { return "00:00:00"; }
        
        var e = this._convertToEarthTime(nextDeparture); //earth time for next departure
        var now = new Date(); // earth time now
        
        //get difference between the next departure and current time... we want this to be in seconds, and Date()
        //and nextDeparture should be in milliseconds, so we /1000
        var seconds = Math.floor((e.getTime() - now.getTime()) / 1000); 

        //basic math functions to get each element of time separated 
        var minutes = Math.floor(seconds / 60);
        var hours = Math.floor(minutes / 60);
        var days = Math.floor(hours / 24);

        hours = hours-(days * 24);
        minutes = minutes-(days * 24 * 60)-(hours * 60);
        seconds = seconds-(days * 24 * 60 * 60 )-(hours * 60 * 60)-(minutes * 60);

        //dont need the vars to be numbers anymore anyway... 
        if (minutes < 10) minutes = "0" +  minutes;
        if (seconds < 10) seconds = "0" +  seconds;

        var str = minutes + ":" + seconds
        if ( hours > 0 ) str = [hours + ":", str].join('');
        return str;
    }

}/// end of 'class vanaTime'
////////////////////////////////////////////////////////////////////



basisDate = new Date();
basisDate.setUTCFullYear(2002, 5, 23); 
basisDate.setUTCHours(15, 0, 0, 0);    

Mndate = new Date();
Mndate.setUTCFullYear(2004, 0, 25); // Set date to 2004-01-25
Mndate.setUTCHours(2, 31, 12, 0);    // Set time to 02:31:12.0000

msGameDay	= (24 * 60 * 60 * 1000 / 25); // milliseconds in a game day = 3456000
msRealDay	= (24 * 60 * 60 * 1000); // milliseconds in a real day = 86400000

VanaDay = new Array("Firesday", "Earthsday", "Watersday", "Windsday", "Iceday", "Lightningday", "Lightsday", "Darksday");
DayColor = new Array("#FF0000", "#AAAA00", "#0000DD", "#00AA22", "#7799FF", "#AA00AA", "#AAAAAA", "#333333");

//PhaseName = new Array("Full Moon","Waning Gibbous","Last Quarter","Waning Crescent","New Moon","Waxing Crescent","First Quarter","Waxing Gibbous");
PhaseName = new Array('\u{1F315}','\u{1F316}','\u{1F317}','\u{1F318}','\u{1F311}','\u{1F312}','\u{1F313}','\u{1F314}');

sMonth = new Array("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec");
//RSErace = new Array("M. Hume","F. Hume","M. Elvaan","F. Elvaan","M. TaruTaru","F. TaruTaru","Mithra","Galka");
//RSEloc = new Array("Gusgen Mines","Shakrami Maze","Ordelle Caves");

BoatSched_selbina = new Array("08:00", "16:00", "00:00");
BoatSched_selbina2 = new Array("06:30", "14:30", "22:30");

BoatSched_ahtUrhgan = new Array("04:00", "12:00", "20:00");
BoatSched_ahtUrhgan2 = new Array("02:30", "10:30", "18:30");

BoatSched_bibiki = new Array("05:30", "17:30");
BoatSched_bibiki2 = new Array("04:50", "16:50");

BoatDayOffset = new Array(0,0,7);

var vanadate;
function resetGameTime() { 
	// **** Game time
	var now = new Date();
	vanaDate =  ((898 * 360 + 30) * msRealDay) + (now.getTime() - basisDate.getTime()) * 25;

	vYear = Math.floor(vanaDate / (360 * msRealDay));
	vMon  = Math.floor((vanaDate % (360 * msRealDay)) / (30 * msRealDay)) + 1;
	vDate = Math.floor((vanaDate % (30 * msRealDay)) / (msRealDay)) + 1;
	vHour = Math.floor((vanaDate % (msRealDay)) / (60 * 60 * 1000));
	vMin  = Math.floor((vanaDate % (60 * 60 * 1000)) / (60 * 1000));
	vSec  = Math.floor((vanaDate % (60 * 1000)) / 1000);
	vDay  = Math.floor((vanaDate % (8 * msRealDay)) / (msRealDay));

	if (vYear < 1000) { VanaYear = "0" + vYear; } else { VanaYear = vYear; }
	if (vMon  < 10)   { VanaMon  = "0" + vMon; }  else { VanaMon  = vMon; }
	if (vDate < 10)   { VanaDate = "0" + vDate; } else { VanaDate = vDate; }
	if (vHour < 10)   { VanaHour = "0" + vHour; } else { VanaHour = vHour; }
	if (vMin  < 10)   { VanaMin  = "0" + vMin; }  else { VanaMin  = vMin; }
	if (vSec  < 10)   { VanaSec  = "0" + vSec; }  else { VanaSec  = vSec; }
	
	// Moon phase
	var timenow = new Date();
    var localTime = timenow.getTime();
    var moonDays = (Math.floor((localTime - Mndate.getTime()) / msGameDay))  % 84;

    var mnElapsedTime = (localTime - Mndate.getTime()) % msGameDay;

    // determine phase percentage
     moonpercent = - Math.round((42 - moonDays) / 42 * 100);
     if (moonpercent <= -94)  {
        mnPhase = 0;
        optPhase = 4;
        toNextPhase = (3 - moonDays) * msGameDay - mnElapsedTime;
        toOptimalPhase = (38 - moonDays) * msGameDay - mnElapsedTime;

     }  else if (moonpercent >= 90)  {
    mnPhase = 0;
        optPhase = 4;
        toNextPhase = (87 - moonDays) * msGameDay - mnElapsedTime;
        toOptimalPhase = (38 + 84 - moonDays) * msGameDay - mnElapsedTime;

     }  else if (moonpercent >= -93 && moonpercent <= -62)  {
      mnPhase = 1;
        optPhase = 4;
        toNextPhase = (17 - moonDays) * msGameDay - mnElapsedTime;
        toOptimalPhase = (38 - moonDays) * msGameDay - mnElapsedTime;

     }  else if (moonpercent >= -61 && moonpercent <= -41)  {
      mnPhase = 2;
        optPhase = 4;
        toNextPhase = (25 - moonDays) * msGameDay - mnElapsedTime;
        toOptimalPhase = (38 - moonDays) * msGameDay - mnElapsedTime;

     }  else if (moonpercent >= -40 && moonpercent <= -11)  {
      mnPhase = 3;
        optPhase = 4;
        toNextPhase = (38 - moonDays) * msGameDay - mnElapsedTime;
        toOptimalPhase = (38 - moonDays) * msGameDay - mnElapsedTime;

     }  else if (moonpercent >= -10 && moonpercent <= 6)  {
      mnPhase = 4;
        optPhase = 0;
        toNextPhase = (45 - moonDays) * msGameDay - mnElapsedTime;
        toOptimalPhase = (80 - moonDays) * msGameDay - mnElapsedTime;

     }  else if (moonpercent >= 7 && moonpercent <= 36)  {
      mnPhase = 5;
        optPhase = 0;
        toNextPhase = (58 - moonDays) * msGameDay - mnElapsedTime;
        toOptimalPhase = (80 - moonDays) * msGameDay - mnElapsedTime;

     }  else if (moonpercent >= 37 && moonpercent <= 56)  {
      mnPhase = 6;
        optPhase = 0;
        toNextPhase = (66 - moonDays) * msGameDay - mnElapsedTime;
        toOptimalPhase = (80 - moonDays) * msGameDay - mnElapsedTime;

     }  else if (moonpercent >= 57 && moonpercent <= 89)  {
      mnPhase = 7;
        optPhase = 0;
        toNextPhase = (60 - moonDays) * msGameDay - mnElapsedTime;
        toOptimalPhase = (80 - moonDays) * msGameDay - mnElapsedTime;
     }

     mnpercent = PhaseName[mnPhase]  + Math.abs(moonpercent) + "%";

     if (moonpercent <= 5 && moonpercent >= -10)  {
          mnpercent = "<FONT COLOR='#FF0000'>" + mnpercent+ "</FONT>";
     } else if (moonpercent >= 90 || moonpercent <= -95)  {
          mnpercent = "<FONT COLOR='#0000FF'>" + mnpercent+ "</FONT>";
     }

   //nextPhase = "Next phase (" + PhaseName[(mnPhase + 1) % 8] + "): " + formatCountdown(toNextPhase);
   //nextOptPhase = "Next " + PhaseName[optPhase] + ": " + formatCountdown(toOptimalPhase);
	
	//draw to sidebar element
	VanaTime = "<div><li><b>" + VanaHour + ":" + VanaMin + "</b>  ~  " + VanaYear + "-" + VanaMon + "-" + VanaDate + "</li>"; 
	VanaTime +=	"<li><span style=\"font-weight: bold; font-size:14px; color:" + DayColor[vDay] + "\" >"  + VanaDay[vDay] + "</span><span style=\"font-size:14px;\">  ~ " + mnpercent + "</span></li>"; 
	VanaTime += "</div>";
	
	alchemy_hours = guildHelper(8, 23, 6);
	bonecraft_hours = guildHelper(8, 23, 3);
	clothcraft_hours = guildHelper(6, 21, 0);
	cooking_hours = guildHelper(5, 20, 7);		
	fishing_hours = guildHelper(3, 18, 5);
	goldsmithing_hours = guildHelper(8, 23, 4);	
	leathercraft_hours = guildHelper(3, 18, 4);
	smithing_hours = guildHelper(8, 23, 2);
	woodworking_hours = guildHelper(6, 21, 0);

	// Do not alter this line. This updates sidebar text for current time
	const sidebar_vanatime = document.getElementById("n-vanatime");
	if (sidebar_vanatime) sidebar_vanatime.innerHTML = VanaTime;
		
	const page_vanatime = document.getElementsByClassName("page-vanatime");
	for (let i = 0; i < page_vanatime.length; i = i+1) { page_vanatime[i].textContent = VanaTime; }

	const page_alchemy_hours = document.getElementsByClassName("page-alchemy_hours");
	for (let i = 0; i < page_alchemy_hours.length; i = i+1) { page_alchemy_hours[i].textContent = alchemy_hours; }

	const page_bonecraft_hours = document.getElementsByClassName("page-bonecraft_hours");
	for (let i = 0; i < page_bonecraft_hours.length; i = i+1) { page_bonecraft_hours[i].textContent = bonecraft_hours; }
	
	const page_clothcraft_hours = document.getElementsByClassName("page-clothcraft_hours");
	for (let i = 0; i < page_clothcraft_hours.length; i = i+1) { page_clothcraft_hours[i].textContent = clothcraft_hours; }

	const page_cooking_hours = document.getElementsByClassName("page-cooking_hours");
	for (let i = 0; i < page_cooking_hours.length; i = i+1) { page_cooking_hours[i].textContent = cooking_hours; }
	
	const page_fishing_hours = document.getElementsByClassName("page-fishing_hours");
	for (let i = 0; i < page_fishing_hours.length; i = i+1) { page_fishing_hours[i].textContent = fishing_hours; }
	
	const page_goldsmithing_hours = document.getElementsByClassName("page-goldsmithing_hours");
	for (let i = 0; i < page_goldsmithing_hours.length; i = i+1) { page_goldsmithing_hours[i].textContent = goldsmithing_hours; }
	
	const page_leathercraft_hours = document.getElementsByClassName("page-leathercraft_hours");
	for (let i = 0; i < page_leathercraft_hours.length; i = i+1) { page_leathercraft_hours[i].textContent = leathercraft_hours; }

	const page_smithing_hours = document.getElementsByClassName("page-smithing_hours");
	for (let i = 0; i < page_smithing_hours.length; i = i+1) { page_smithing_hours[i].textContent = smithing_hours; }
	
	const page_woodworking_hours = document.getElementsByClassName("page-woodworking_hours");
	for (let i = 0; i < page_woodworking_hours.length; i = i+1) { page_woodworking_hours[i].textContent = woodworking_hours; }

}
	
function guildHelper(open, close, holiday)  {
   var timenow = new Date();
   var localTime = timenow.getTime();
   var elapsedTime = (localTime - basisDate.getTime()) % msGameDay;
   var dayStart = localTime - elapsedTime;

   // this conversion factor tells us time elapsed since the game day started in milliseconds
   var convFactor = 60 * 60 * 1000 / 25; 
   
   vanaDate =  ((898 * 360 + 30) * msRealDay) + (localTime - basisDate.getTime()) * 25;
   vDay  = Math.floor((vanaDate % (8 * msRealDay)) / (msRealDay));

   open = open * convFactor;
   close = close * convFactor;
   
   openTime = open + dayStart;
   closeTime = close + dayStart;
   outputTxt = "";
   guildCountdown = 0;
   
   if (openTime >= localTime) {
      guildCountdown = openTime - localTime;
      outputTxt2 = "Currently Closed. Open tomorrow.";
      outputTxt1 = "Opens in: ";
   } else if ((openTime < localTime) && (closeTime > localTime)) {
      guildCountdown = closeTime - localTime;
      outputTxt2 = "Currently Open for business.";
      outputTxt1 = "Closes in: ";
   } else if (closeTime <= localTime)  {
      guildCountdown = (msGameDay - elapsedTime) + open;
      outputTxt2 = "Currently Closed. Open tomorrow.";
      outputTxt1 = "Opens in: ";      
   }
   
   // adjust for holiday
   if ((holiday == vDay) && (closeTime > localTime)) {
      guildCountdown = (msGameDay - elapsedTime) + open;
      outputTxt2 = "Currently Closed for Holiday.";
      outputTxt1 = "Opens in: ";
   } else if (((vDay + 1) == holiday) && (closeTime <= localTime))  {
      guildCountdown = (msGameDay - elapsedTime) + open + msGameDay;
      outputTxt2 = "Currently Closed. Holiday tomorrow.";
      outputTxt1 = "Opens in: ";
   }

   return outputTxt1 + formatCountdown(guildCountdown) + ". " + outputTxt2;
}

function formatCountdown(varTime) {

   var dayLeft = varTime / msRealDay;
   var hourLeft = (dayLeft - Math.floor(dayLeft)) * 24;
   var minLeft = (hourLeft - Math.floor(hourLeft)) * 60;
   var secLeft = Math.floor((minLeft - Math.floor(minLeft)) * 60);
   var formattedTime = '';

   dayLeft = Math.floor(dayLeft);
   hourLeft = Math.floor(hourLeft);
   minLeft = Math.floor(minLeft);

   if (minLeft < 10) {minLeft = '0' + minLeft;}
   if (secLeft < 10) {secLeft = '0' + secLeft;}

   if (dayLeft > 0) {
      formattedTime = dayLeft + ':';
      if (hourLeft < 10) {
         formattedTime = formattedTime + '0' + hourLeft + ':';
      } else {
         formattedTime = formattedTime + hourLeft + ':';
      }         
   } else if (hourLeft > 0) {
      formattedTime = hourLeft + ':';
   }

   formattedTime = formattedTime + minLeft + ':' + secLeft;
   return formattedTime;
}

function pageHasElement(element){
	var _found = false;
    for (const [k,v] of Object.entries(element) ){
        var _ = document.getElementById(v);
        if ( _ ) { _found = true; break; }  
    }
    return _found;
}

function _airshipTablesHeader(header){
	header += "<TR><TH ALIGN='LEFT'>Airship Route</TH>";
	//header += "<TH ALIGN='LEFT'>Departure Day</TH>";
	header += "<TH ALIGN='LEFT'>Arrival</TH>";
	header += "<TH ALIGN='LEFT'>Departure</TH></TR>";
	return header;
}

function getAirSched() {
	var _found = false;
    for (const [k,v] of Object.entries(timeElements.ids.airships) ){
        var _ = document.getElementById(v);
        if ( _ ) { _found = true; break; }  
    }
   if (_found === false ) return;
    
   var timenow = new Date(); 
   var localTime = timenow.getTime(); 
   var elapsedTime = (localTime - basisDate.getTime()) % msGameDay; 
   //var dayStart = localTime - elapsedTime; 
   vanaDate = ((898 * 360 + 30) * msRealDay) + (localTime - basisDate.getTime()) * 25; 
   vDay = Math.floor((vanaDate % (8 * msRealDay)) / (msRealDay)); 

   var offset1 = ((1 * 60) + 10) * 60 * 1000 / 25; // 1:10 offset used by B->J J->S 
   var offset2 = ((2 * 60) + 40) * 60 * 1000 / 25; // 2:40 offset used by J->W K-J 
   var offset3 = ((4 * 60) + 10) * 60 * 1000 / 25; // 4:10 offset used by J->B S->J 
   var offset4 = ((5 * 60) + 35) * 60 * 1000 / 25; // 5:35 offset used by J->K 
   var offset5 = ((5 * 60) + 45) * 60 * 1000 / 25; // 5:45 offset used by W->J 

   //var _table_headers = "";
	const airships_main = document.getElementById(timeElements.ids.airships.main);
	if (airships_main) {
		var _HTMLout = "<TABLE CLASS='" + timeElements.ids.airships.main + "' WIDTH='400' CELLSPACING='0' CELLPADDING='0'>";
		_HTMLout += _airshipTablesHeader(_HTMLout);
		_HTMLout += AirHelper(elapsedTime, offset3, vDay, "Jeuno To Bastok");
		_HTMLout += AirHelper(elapsedTime, offset4, vDay, "Jeuno To Kazham");
		_HTMLout += AirHelper(elapsedTime, offset1, vDay, "Jeuno To San d'Oria");
		_HTMLout += AirHelper(elapsedTime, offset2, vDay, "Jeuno To Windurst");
		_HTMLout += AirHelper(elapsedTime, offset1, vDay, "Bastok To Jeuno");
		_HTMLout += AirHelper(elapsedTime, offset2, vDay, "Kazham To Jeuno");
		_HTMLout += AirHelper(elapsedTime, offset3, vDay, "San d'Oria To Jeuno");
		_HTMLout += AirHelper(elapsedTime, offset5, vDay, "Windurst To Jeuno");
		airships_main.innerHTML = _HTMLout + "</TABLE>";
	}
	
	const airships_bastok = document.getElementById(timeElements.ids.airships.bastok);
	if (airships_bastok) {
		var _HTMLout = "<TABLE CLASS='" + timeElements.ids.airships.bastok + "' WIDTH='400' CELLSPACING='0' CELLPADDING='0'>";
		_HTMLout += _airshipTablesHeader(_HTMLout);
		_HTMLout += AirHelper(elapsedTime, offset3, vDay, "Jeuno To Bastok");
		_HTMLout += AirHelper(elapsedTime, offset1, vDay, "Bastok To Jeuno");
		airships_bastok.innerHTML = _HTMLout + "</TABLE>";
	}
	
	const airships_sandy = document.getElementById(timeElements.ids.airships.sandy);
	if (airships_sandy) {
		var _HTMLout = "<TABLE CLASS='" + timeElements.ids.airships.sandy + "' WIDTH='400' CELLSPACING='0' CELLPADDING='0'>";
		_HTMLout += _airshipTablesHeader(_HTMLout);
		_HTMLout += AirHelper(elapsedTime, offset1, vDay, "Jeuno To San d'Oria");
		_HTMLout += AirHelper(elapsedTime, offset3, vDay, "San d'Oria To Jeuno");
		airships_sandy.innerHTML = _HTMLout + "</TABLE>";
	}
	
	const airships_windy = document.getElementById(timeElements.ids.airships.windy);
	if (airships_windy) {
		var _HTMLout = "<TABLE CLASS='" + timeElements.ids.airships.windy + "' WIDTH='400' CELLSPACING='0' CELLPADDING='0'>";
		_HTMLout += _airshipTablesHeader(_HTMLout);
		_HTMLout += AirHelper(elapsedTime, offset2, vDay, "Jeuno To Windurst");
		_HTMLout += AirHelper(elapsedTime, offset5, vDay, "Windurst To Jeuno");
		airships_windy.innerHTML = _HTMLout + "</TABLE>";
	}
	
	const airships_kazham = document.getElementById(timeElements.ids.airships.kazham);
	if (airships_kazham) {
		var _HTMLout = "<TABLE CLASS='" + timeElements.ids.airships.kazham + "' WIDTH='400' CELLSPACING='0' CELLPADDING='0'>";
		_HTMLout += _airshipTablesHeader(_HTMLout);
		_HTMLout += AirHelper(elapsedTime, offset4, vDay, "Jeuno To Kazham");
		_HTMLout += AirHelper(elapsedTime, offset2, vDay, "Kazham To Jeuno");
		airships_kazham.innerHTML = _HTMLout + "</TABLE>";
	}
} 

function getShipSched()  {
	var _found = false;
    for (const [k,v] of Object.entries(timeElements.ids.boats) ){
        var _ = document.getElementById(v);
        if ( _ ) { _found = true; break; }  
    }
   if (_found === false ) return;
   
   var now = new Date();
   var timeDiff = now.getTime() - basisDate.getTime();
   var hours = Math.floor((timeDiff / ( msGameDay / 3)) % 3);

   var timeLeft = (msGameDay / 3 ) - (timeDiff % (msGameDay / 3));
   var repeatFerry =  5 ;

//    vanaDate =  ((898 * 360 + 30) * msRealDay) + (timeDiff) * 25;
//    vDay  = Math.floor((vanaDate % (8 * msRealDay)) / (msRealDay));
	
    // Boats depart at 00:00, 08:00, 16:00 from both Selbina and Mhuara
   // Boats arrive at 06:30, 14:30, 22:30 which is 216 seconds before they leave
	const boats_selbina = document.getElementById(timeElements.ids.boats.selbina);
	if (boats_selbina) {
		var bSched = "<TABLE CLASS='" + timeElements.ids.boats.selbina + "' CELLSPACING='0' CELLPADDING='0'>";
		bSched += "<TR><TH ALIGN='left'>Arrives</TH>";
		bSched += "<TH ALIGN='left'>ETA</TH>";
		bSched += "<TH ALIGN='left'>Departs</TH>";
		bSched += "<TH ALIGN='left'>ETD</TH></TR>";
	   
		for ( i = 0; i < repeatFerry; i++) {
		  timeLeftLoop = timeLeft + ( i* msGameDay / 3);
		  //dPos = (vDay + Math.floor((hours + 1 + i)/3)) % 8;
		  //dPos2 = (dPos + BoatDayOffset[(hours + i) % 3]) % 8;
		  arrivalTime = timeLeftLoop - 216000;
		  if (arrivalTime <= 0)
		     arrivalTime = 0;
		
			//bSched = bSched + '<TR><TD><FONT COLOR="' + DayColor[dPos2] + '">' + VanaDay[dPos2] + '</FONT></TD><TD>' + BoatSched2[(hours + i) % 3] + '</TD><TD>' + formatCountdown(arrivalTime) + '</TD><TD><FONT COLOR="' + DayColor[dPos] + '">' + VanaDay[dPos] + '</FONT></TD><TD>' + BoatSched[(hours + i) % 3] + '</TD><TD ALIGN="left">' + formatCountdown(timeLeftLoop) + '</TD></TR>';
			bSched = bSched + '<TR><TD>' + BoatSched_selbina2[(hours + i) % 3] + '</TD><TD>' + formatCountdown(arrivalTime) + '</TD><TD>' + BoatSched_selbina[(hours + i) % 3] + '</TD><TD ALIGN="left">' + formatCountdown(timeLeftLoop) + '</TD></TR>';
		}
	
	   if (repeatFerry < 1) { out = ''; } else { out = bSched + "</TABLE>"; }

		boats_selbina.innerHTML = out;
	}
	
	const boats_ahturhgan = document.getElementById(timeElements.ids.boats.ahtUrhgan);
	if (boats_ahturhgan) {
		var bSched = "<TABLE CLASS='" + timeElements.ids.boats.ahtUrhgan + "' CELLSPACING='0' CELLPADDING='0'>";
		bSched += "<TR><TH ALIGN='left'>Arrives</TH>";
		bSched += "<TH ALIGN='left'>ETA</TH>";
		bSched += "<TH ALIGN='left'>Departs</TH>";
		bSched += "<TH ALIGN='left'>ETD</TH></TR>";
	   
		for ( i = 0; i < repeatFerry; i++) {
		  timeLeftLoop = timeLeft + ( i* msGameDay / 3);
		 // dPos = (vDay + Math.floor((hours + 1 + i)/3)) % 8;
		  //dPos2 = (dPos + BoatDayOffset[(hours + i) % 3]) % 8;
		  arrivalTime = timeLeftLoop - 216000;
		  if (arrivalTime <= 0)
		     arrivalTime = 0;
		
			//bSched = bSched + '<TR><TD><FONT COLOR="' + DayColor[dPos2] + '">' + VanaDay[dPos2] + '</FONT></TD><TD>' + BoatSched2[(hours + i) % 3] + '</TD><TD>' + formatCountdown(arrivalTime) + '</TD><TD><FONT COLOR="' + DayColor[dPos] + '">' + VanaDay[dPos] + '</FONT></TD><TD>' + BoatSched[(hours + i) % 3] + '</TD><TD ALIGN="left">' + formatCountdown(timeLeftLoop) + '</TD></TR>';
			bSched = bSched + '<TR><TD>' + BoatSched_ahtUrhgan2[(hours + i) % 3] + '</TD><TD>' + formatCountdown(arrivalTime) + '</TD><TD>' + BoatSched_ahtUrhgan[(hours + i) % 3] + '</TD><TD ALIGN="left">' + formatCountdown(timeLeftLoop) + '</TD></TR>';
		}

	   if (repeatFerry < 1) { out = ''; } else { out = bSched + "</TABLE>"; }
		boats_ahturhgan.innerHTML = out;
	}
	
    // TESTING DEPARTURE SCHEDULE
    populateShipSchedule(timeElements.ids.boats.bibiki, schedule.boats.bibiki, 7);
    populateShipSchedule(timeElements.ids.boats.purgonorgoIsle, schedule.boats.purgonorgoIsle, 7);
    populateShipSchedule(timeElements.ids.boats.northLanding, schedule.boats.northLanding, 5);
    populateShipSchedule(timeElements.ids.boats.southLanding, schedule.boats.southLanding, 8);
    populateShipSchedule(timeElements.ids.boats.centralLanding, schedule.boats.centralLanding, 5);

}

/**
 * @param {timeElements} classname - class name from timeElements to be used for the table class
 * @param {schedule} scheduleID - 
 * @param {*} scheduleSize 
 */
function populateShipSchedule(classname, scheduleID, scheduleSize){

    const boats_bibiki = document.getElementById(classname);
	if (boats_bibiki) {
        var bSched = "<TABLE CLASS='" + classname + "' WIDTH='400' CELLSPACING='0' CELLPADDING='0'>";
		bSched += "<TR><TH ALIGN='left'>VanaTime</TH>";
		bSched += "<TH ALIGN='left'>Earth Time</TH>";
		bSched += "<TH ALIGN='left'>Departure</TH>";
		bSched += "<TH ALIGN='left'>Location</TH></TR>";

        var vanatime = new vanaTime();
        var currentTime = vanatime.getVanaDate();

        // trying to get _count - this is the start point for the schedule based on current time
        // stops after 20 loops, just in case... 
        var _startPoint = 0;
        while ( _startPoint < scheduleID.length && _startPoint < 20) {
            var scheduleDeparts = vanatime._rawVanaToday() + vanatime._convertMinsToMiliseconds(scheduleID[_startPoint].time);
            timerCountdown = scheduleDeparts - currentTime;
            if (timerCountdown >= 0 ) { break;}
            _startPoint++;
        }
        
        var _dayMultiplier = 0; // helps us add another day if we need to calc any time on the next days schedule 
        var _displayCounter = 0;  // # of entries in the printed schedule
        
        while ( _displayCounter < scheduleSize ){
            if ( _startPoint >= scheduleID.length){ //if we reach the end of the schedule array, then we need to start over and add 1440 to the times, so we can calc for the next day 
                        _startPoint = 0;
                        _dayMultiplier++;
                    }
            var _nextTime = scheduleID[_startPoint].time + ( _dayMultiplier * 1440 );
            
            
            var scheduleDeparts = vanatime._rawVanaToday() + vanatime._convertMinsToMiliseconds(_nextTime) ;
            timerCountdown = scheduleDeparts - currentTime;

                if (timerCountdown >= 0 ) {
                    bSched = bSched + '<TR><TD>' + vanatime.stringVanaTime(scheduleDeparts) + '</TD><TD>' + vanatime.stringEarthTime(scheduleDeparts) + '</TD><TD>' + vanatime.timeUntil(scheduleDeparts) + '</TD><TD>' + scheduleID[_startPoint].dest +'</TD></TR>';
                    _displayCounter++;
                }
                _startPoint++;
        }
        
        boats_bibiki.innerHTML = bSched + "</TABLE>";
    }
}



function AirHelper(elapsed, offset, day, city) { 

   var newOffset = offset; 
   var count = 0; 
   while (newOffset < elapsed) { 
      count += 1; 
      newOffset += (msGameDay / 4); 
   } 
   if (count >= 4) { 
      day = (day + 1) % 8; 
   }

   output = "<TR><TD>" + city + "</TD>"; 
   //output += "<TD><FONT COLOR=" + DayColor[day] + ">" + VanaDay[day] + "</FONT></TD>"; 
   arrivalTime = newOffset - elapsed - 144000;
   if (arrivalTime < 0)  {
      arrivalTime = 0;
   }
   output += "<TD>" + formatCountdown(arrivalTime,1) + "</TD>";
   output += "<TD>" + formatCountdown(newOffset - elapsed,1) + "</TD></TR>"; 
   
   return output; 
}

function getConquest()  {

   var now = new Date();
   var timeLeft = (7 * msRealDay) - ((now.getTime() - basisDate.getTime()) % (7 * msRealDay));
   vanaConq = Math.floor(timeLeft / (msGameDay)) + 1;

   conqDays = timeLeft / msRealDay;
   conqHours = (conqDays - Math.floor(conqDays)) * 24;
   conqMin = (conqHours - Math.floor(conqHours)) * 60;
   conqSec = Math.floor((conqMin - Math.floor(conqMin)) * 60);

   if (conqDays < 10) { conqDays = '0' + Math.floor(conqDays); } else { conqDays = Math.floor(conqDays); }
   if (conqHours < 10) { conqHours = '0' + Math.floor(conqHours ); } else { conqHours = Math.floor(conqHours ); }
   if (conqMin < 10) { conqMin = '0' + Math.floor(conqMin ); } else { conqMin = Math.floor(conqMin ); }
   if (conqSec < 10) { conqSec = '0' + Math.floor(conqSec ); } else { conqSec = Math.floor(conqSec ); }
   
   conqDate = formatDate(now.getTime() + timeLeft, 2);

   conq = vanaConq + ' Vana´diel Days <BR>' + conqDate + ' (' + formatCountdown(timeLeft) + ')';

   const conquest_time = document.getElementById(conquest_schedule);
   if (conquest_time) conquest_time.innerHTML = conq; 
}


function getMoonPhase()  {

   var timenow = new Date();
   var localTime = timenow.getTime();
   var moonDays = (Math.floor((localTime - Mndate.getTime()) / msGameDay))  % 84;

   var mnElapsedTime = (localTime - Mndate.getTime()) % msGameDay;

   // determine phase percentage
         moonpercent = - Math.round((42 - moonDays) / 42 * 100);
         if (moonpercent <= -94)  {
            mnPhase = 0;
            optPhase = 4;
            toNextPhase = (3 - moonDays) * msGameDay - mnElapsedTime;
            toOptimalPhase = (38 - moonDays) * msGameDay - mnElapsedTime;

         }  else if (moonpercent >= 90)  {
	    mnPhase = 0;
            optPhase = 4;
            toNextPhase = (87 - moonDays) * msGameDay - mnElapsedTime;
            toOptimalPhase = (38 + 84 - moonDays) * msGameDay - mnElapsedTime;

         }  else if (moonpercent >= -93 && moonpercent <= -62)  {
	      mnPhase = 1;
            optPhase = 4;
            toNextPhase = (17 - moonDays) * msGameDay - mnElapsedTime;
            toOptimalPhase = (38 - moonDays) * msGameDay - mnElapsedTime;

         }  else if (moonpercent >= -61 && moonpercent <= -41)  {
	      mnPhase = 2;
            optPhase = 4;
            toNextPhase = (25 - moonDays) * msGameDay - mnElapsedTime;
            toOptimalPhase = (38 - moonDays) * msGameDay - mnElapsedTime;

         }  else if (moonpercent >= -40 && moonpercent <= -11)  {
	      mnPhase = 3;
            optPhase = 4;
            toNextPhase = (38 - moonDays) * msGameDay - mnElapsedTime;
            toOptimalPhase = (38 - moonDays) * msGameDay - mnElapsedTime;

         }  else if (moonpercent >= -10 && moonpercent <= 6)  {
	      mnPhase = 4;
            optPhase = 0;
            toNextPhase = (45 - moonDays) * msGameDay - mnElapsedTime;
            toOptimalPhase = (80 - moonDays) * msGameDay - mnElapsedTime;

         }  else if (moonpercent >= 7 && moonpercent <= 36)  {
	      mnPhase = 5;
            optPhase = 0;
            toNextPhase = (58 - moonDays) * msGameDay - mnElapsedTime;
            toOptimalPhase = (80 - moonDays) * msGameDay - mnElapsedTime;

         }  else if (moonpercent >= 37 && moonpercent <= 56)  {
	      mnPhase = 6;
            optPhase = 0;
            toNextPhase = (66 - moonDays) * msGameDay - mnElapsedTime;
            toOptimalPhase = (80 - moonDays) * msGameDay - mnElapsedTime;

         }  else if (moonpercent >= 57 && moonpercent <= 89)  {
	      mnPhase = 7;
            optPhase = 0;
            toNextPhase = (60 - moonDays) * msGameDay - mnElapsedTime;
            toOptimalPhase = (80 - moonDays) * msGameDay - mnElapsedTime;
         }

         mnpercent = PhaseName[mnPhase] + " (" + Math.abs(moonpercent) + "%)";

         if (moonpercent <= 5 && moonpercent >= -10)  {
              mnpercent = "<FONT COLOR='#FF0000'>" + mnpercent+ "</FONT>";
         } else if (moonpercent >= 90 || moonpercent <= -95)  {
              mnpercent = "<FONT COLOR='#0000FF'>" + mnpercent+ "</FONT>";
         }

   nextPhase = "Next phase (" + PhaseName[(mnPhase + 1) % 8] + "): " + formatCountdown(toNextPhase);
   nextOptPhase = "Next " + PhaseName[optPhase] + ": " + formatCountdown(toOptimalPhase);

   //mnpercent = "<DIV onmouseover='javascript:getMoonDetails()'>" + mnpercent + "</DIV>  ";
	//document.getElementById("mPhase").innerHTML = mnpercent + nextPhase + "<BR>" + nextOptPhase;
	const moon_phase_div = document.getElementById(moon_phase);
	if (moon_phase_div) moon_phase_div.innerHTML = mnpercent + nextPhase + "<BR>" + nextOptPhase;;


   // new moon starts on day 38 (-10%)
   // full moon starts at 80 (90%)
   // Moon cycle lasts 84 game days.

   // Determine most recent full moon
   var fullMoonBasis = Mndate.getTime() + (3 * msGameDay);
   var repeatCal = 5;

   moonCal = "<TABLE CLASS='blank' CELLSPACING='0' CELLPADDING='0' border='1px solid black'><TR><TH WIDTH='115' ALIGN='left'>New Moon Start</TH><TH WIDTH='115' ALIGN='left'>New Moon End</TH><TH WIDTH='115' ALIGN='left'>Full Moon Start</TH><TH WIDTH='115' ALIGN='left'>Full Moon End</TH></TR>";
   for ( i = 0; i < repeatCal; i++)  {
      elapsedCycles = Math.floor( (localTime - fullMoonBasis) / (84 * msGameDay) ) + i;
      FullEnd = fullMoonBasis + (elapsedCycles * 84 * msGameDay);
      //Full Moon starts 7 games days prior to end
      FullStart = FullEnd - 7 * msGameDay;
      //New Moon starts 49 games days prior to Full Moon end
      NewStart = FullEnd - 49 * msGameDay;
      //New Moon ends 42 games days prior to Full Moon end
      NewEnd = FullEnd - 42 * msGameDay;

      moonCal = moonCal + "<TR><TD>" + formatDate(NewStart, 2) + "</TD><TD>" + formatDate(NewEnd, 2) + "</TD><TD>" + formatDate(FullStart,2) + "</TD><TD>" + formatDate(FullEnd, 2) + "</TD></TR>";
   }
   if (repeatCal < 1) { moonCal = ""; } else { moonCal = moonCal + '</TABLE>'; }
   
   // moon_phases
   //document.getElementById("mCalendar").innerHTML = moonCal;
   	const moon_phases_schedule_div = document.getElementById(moon_phases_schedule);
	if (moon_phases_schedule_div) moon_phases_schedule_div.innerHTML = moonCal;
}

function formatDate(varTime, showDay) {

   var varDate = new Date(varTime);
   var yyyy = varDate.getYear();

   var mm = varDate.getMonth() + 1;
   if (mm < 10) { mm = "0" + mm; }

   var dd = varDate.getDate();
   if (dd < 10) { dd = "0" + dd; }

   var day = varDate.getDay();

   var hh = varDate.getHours();
   
   if (hh < 10) { hh = "0" + hh; }

   var min = varDate.getMinutes();
   if (min < 10) { min = "0" + min; }

   var ss = varDate.getSeconds();
   if (ss < 10) { ss = "0" + ss; }

   if (showDay == 1)  {
      dateString = EarthDay[day] + ", " + sMonth[mm-1] + ' ' + dd + ', ' + yyyy + " " + hh + ":" + min + ":" + ss;
   } else if (showDay == 2)  {
      dateString = sMonth[mm-1] + " " + dd + ",  " + hh + ":" + min + ":" + ss;
   }
   return dateString;
}

function getGuildHours()  {
    
   alchemy = guildHelper(8, 23, 6);
   blacksmith = guildHelper(8, 23, 2);
   bonework = guildHelper(8, 23, 3);
   goldsmith = guildHelper(8, 23, 4);
   cloth = guildHelper(6, 21, 0);
   wood = guildHelper(6, 21, 0);
   leather = guildHelper(3, 18, 4);
   fishing = guildHelper(3, 18, 5);
   cooking = guildHelper(5, 20, 7);


   guildOut = "<TABLE CLASS='"+ crafting_guilds_schedule_table + "' CELLSPACING='0' CELLPADDING='0' border='1px solid black'>";
   guildOut = guildOut + "<TR><TH ALIGN='center' WIDTH=100 >Guild</TH>";
   guildOut = guildOut + "<TH ALIGN='center' WIDTH=175 >Status</TH></TR>";
   guildOut = guildOut + "<TR><TH> Alchemy</TH><td>" + alchemy + "</td></TR>";
   guildOut = guildOut + "<TR><TH> Blacksmithing</TH><td>" + blacksmith 	+ "</td></TR>";
   guildOut = guildOut + "<TR><TH> Boneworking</TH><td>" + bonework 	+ "</td></TR>";
   guildOut = guildOut + "<TR><TH> Goldsmithing</TH><td>" + goldsmith 	+ "</td></TR>";
   guildOut = guildOut + "<TR><TH> Clothcrafting</TH><td>" + cloth 	+ "</td></TR>";
   guildOut = guildOut + "<TR><TH> Woodworking</TH><td>" + wood 	+ "</td></TR>";
   guildOut = guildOut + "<TR><TH> Leatherworking </TH><td>" + leather 	+ "</td></TR>";
   guildOut = guildOut + "<TR><TH> Fishing</TH><td>" + fishing 	+ "</td></TR>";
   guildOut = guildOut + "<TR><TH> Cooking</TH><td>" + cooking 	+ "</td></TR>";
   guildOut = guildOut + "</TABLE>";
   
	//document.getElementById(crafting_guilds_schedule).innerHTML = guildOut;
	const crafting_guilds_schedule_div = document.getElementById(crafting_guilds_schedule);
	if (crafting_guilds_schedule_div) crafting_guilds_schedule_div.innerHTML = guildOut;
}

function gametick(){
	resetGameTime();
	getConquest();
	getMoonPhase();
	getAirSched();
	getShipSched();
	getGuildHours();
	setTimeout("gametick()", 500);
}

gametick();