MediaWiki:VanaTime.js: Difference between revisions
From HorizonXI Wiki
Starfox9507 (talk | contribs) No edit summary |
Starfox9507 (talk | contribs) No edit summary |
||
| (152 intermediate revisions by 3 users not shown) | |||
| Line 1: | Line 1: | ||
/********************************************************************* | |||
Javascript below contributes to Vana'diel Time displays throughout | |||
the HorizonXI Wiki | |||
//*************************** | Credits: ******** | ||
https://www.pyogenes.com/ffxi/timer/v2.html | |||
https://www.mithrapride.org/vana_time/index.html | |||
https://www.rubydoc.info/gems/vanadiel-time/Vanadiel/Time | |||
**********************************************************************/ | |||
class timeElements { | |||
// List of all class names for each element in this model, for styling | |||
// | static sidebar = "n-vanatime"; | ||
// | static conquest = "vanatime-page-conquest-schedule"; // <span ... /> | ||
//static moonPhase = "vanatime-pasidebarge-moon-phase"; // not implemented | |||
static moonSchedule = "vanatime-page-moon-schedule-table"; | |||
static rseSchedule = "vanatime-page-rse-schedule-table"; | |||
static airships = { | |||
//all : "vanatime-airship-schedule-table", // not implemented | |||
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", | |||
}; | |||
static boats = { | |||
selbina : "vanatime-boat-schedule-selbina-table", | |||
mhaura : "vanatime-boat-schedule-mhaura-table", | |||
bibiki : "vanatime-boat-schedule-bibiki-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" | |||
}; | |||
static guilds = { | |||
alchemy : "vanatime-guild-schedule-alchemy", | |||
alchemy_status: "vanatime-guild-schedule-alchemy-status", | |||
alchemy_holiday: "vanatime-guild-schedule-alchemy-holiday", | |||
alchemy_timer: "vanatime-guild-schedule-alchemy-timer", | |||
smithing : "vanatime-guild-schedule-smithing", | |||
smithing_status: "vanatime-guild-schedule-smithing-status", | |||
smithing_holiday: "vanatime-guild-schedule-smithing-holiday", | |||
smithing_timer: "vanatime-guild-schedule-smithing-timer", | |||
bonecrafting : "vanatime-guild-schedule-bonecrafting", | |||
bonecrafting_status: "vanatime-guild-schedule-bonecrafting-status", | |||
bonecrafting_holiday: "vanatime-guild-schedule-bonecrafting-holiday", | |||
bonecrafting_timer: "vanatime-guild-schedule-bonecrafting-timer", | |||
goldsmithing : "vanatime-guild-schedule-goldsmithing", | |||
goldsmithing_status: "vanatime-guild-schedule-goldsmithing-status", | |||
goldsmithing_holiday: "vanatime-guild-schedule-goldsmithing-holiday", | |||
goldsmithing_timer: "vanatime-guild-schedule-goldsmithing-timer", | |||
clothcrafting : "vanatime-guild-schedule-clothcrafting", | |||
clothcrafting_status: "vanatime-guild-schedule-clothcrafting-status", | |||
clothcrafting_holiday: "vanatime-guild-schedule-clothcrafting-holiday", | |||
clothcrafting_timer: "vanatime-guild-schedule-clothcrafting-timer", | |||
woodworking : "vanatime-guild-schedule-woodworking", | |||
woodworking_status: "vanatime-guild-schedule-woodworking-status", | |||
woodworking_holiday: "vanatime-guild-schedule-woodworking-holiday", | |||
woodworking_timer: "vanatime-guild-schedule-woodworking-timer", | |||
leathercrafting : "vanatime-guild-schedule-leathercrafting", | |||
leathercrafting_status: "vanatime-guild-schedule-leathercrafting-status", | |||
leathercrafting_holiday: "vanatime-guild-schedule-leathercrafting-holiday", | |||
leathercrafting_timer: "vanatime-guild-schedule-leathercrafting-timer", | |||
fishing : "vanatime-guild-schedule-fishing", | |||
fishing_status: "vanatime-guild-schedule-fishing-status", | |||
fishing_holiday: "vanatime-guild-schedule-fishing-holiday", | |||
fishing_timer: "vanatime-guild-schedule-fishing-timer", | |||
cooking : "vanatime-guild-schedule-cooking", | |||
cooking_status: "vanatime-guild-schedule-cooking-status", | |||
cooking_holiday: "vanatime-guild-schedule-cooking-holiday", | |||
cooking_timer: "vanatime-guild-schedule-cooking-timer", | |||
all : "vanatime-guild-schedule-all" | |||
}; | |||
} | |||
class schedule { | |||
// All raw datea is from ASB | |||
// route definintion = [ 'Name of route', anim_arrive, anim_depart, timeOffset, time_interval, time_anim_arrive, time_waiting, time_anim_depart] | |||
// Actual arrival time (when the player can enter the transport ) = time_offset + time_anim_arrive = [3] + [5] | |||
// Departure time = arrival time + time_waiting = arrival_time + [6] | |||
// All values listed are in VanaTime minutes, so 1440 is the total minutes in a game hour | |||
static #airship_jeuno_sandy = ['Jeuno -> Sandoria', 0, 360, 12, 60, 12]; | |||
static #airship_jeuno_windy = ['Jeuno -> Windurst', 90, 360, 12, 60, 12]; | |||
static #airship_jeuno_bastok = ['Jeuno -> Bastok', 180, 360, 12, 60, 16]; | |||
static #airship_jeuno_kazham = ['Jeuno -> Kazham', 270, 360, 20, 50, 20]; | |||
static #airship_bastok_jeuno = ['Bastok -> Jeuno', 0, 360, 14, 60, 16]; | |||
static #airship_sandy_jeuno = ['Sandoria -> Jeuno', 180, 360, 12, 60, 16]; | |||
static #airship_windy_jeuno = ['Windurst -> Jeuno', 270, 360, 18, 60, 14]; | |||
static #airship_kazham_jeuno = ['Kazham -> Jeuno', 90, 360, 20, 50, 20]; | |||
static airships = { | |||
jeuno : [ | |||
this.#airship_jeuno_bastok, | |||
this.#airship_jeuno_sandy, | |||
this.#airship_jeuno_windy, | |||
this.#airship_jeuno_kazham, | |||
this.#airship_bastok_jeuno, | |||
this.#airship_sandy_jeuno, | |||
this.#airship_windy_jeuno, | |||
this.#airship_kazham_jeuno | |||
], | |||
bastok : [ this.#airship_bastok_jeuno, this.#airship_jeuno_bastok], | |||
sandy : [this.#airship_sandy_jeuno, this.#airship_jeuno_sandy], | |||
windy : [this.#airship_windy_jeuno, this.#airship_jeuno_windy], | |||
kazham : [this.#airship_kazham_jeuno, this.#airship_jeuno_kazham] | |||
} | |||
static #boat_selbina_mhaura = ['Selbina -> Mhaura', 382, 480, 18, 80, 17]; | |||
static #boat_mhaura_selbina = ['Mhaura -> Selbina', 382, 480, 18, 80, 17]; | |||
static #boat_mhaura_whitegate = ['Mhaura -> Whitegate', 142, 480, 18, 80, 17]; | |||
static #boat_whitegate_mhaura = ['Whitegate -> Mhaura', 142, 480, 18, 80, 16]; | |||
static #boat_whitegate_nashmau = ['Whitegate -> Nashmau', 282, 480, 18, 180, 17]; | |||
static #boat_nashmau_whitegate = ['Nashmau -> Whitegate', 282, 480, 18, 180, 17]; | |||
static #boat_bibiki_tours = ['Bibiki Bay -> Tours', 710, 720, 20, 40, 20]; | |||
static #boat_bibiki_purgo = ['Bibiki Bay -> Purgonorgo Isle', 270, 720, 20, 40, 20]; | |||
static #boat_purgo_bibiki = ['Purgonorgo Isle -> Bibiki Bay', 500, 720, 20, 40, 20]; | |||
static #boat_barge_south_central_emfa = ['South Landing -> Central Landing EMFEA', 5, 1440, 15, 35, 15]; | |||
static #boat_barge_central_south_newtpool1 = ['Central Landing -> South Landing NewtPool', 267, 1440, 12, 30, 15]; | |||
static #boat_barge_south_oos = ['South Landing -> OOS', 1402, 1440, 33, 0, 0]; | |||
static #boat_barge_south_north = ['South Landing -> North Landing', 560, 1440, 15, 35, 15]; | |||
static #boat_barge_north_oos = ['North Landing -> OOS', 925, 1440, 40, 0, 0]; | |||
static #boat_barge_north_central = ['North Landing -> Central Landing', 993, 1440, 12, 40, 15]; | |||
static #boat_barge_central_south_newtpool2 = ['Central Landing -> South Landing NewtPool 2', 1148, 1440, 12, 30, 15]; | |||
static #boat_barge_south_oos1 = ['South Landing -> OOS 2', 512, 1440, 33, 0, 0]; | |||
static boats = { | |||
selbina : [ this.#boat_selbina_mhaura ], | |||
mhaura : [ this.#boat_mhaura_selbina, this.#boat_mhaura_whitegate ], | |||
whitegate : [ this.#boat_whitegate_mhaura, this.#boat_whitegate_nashmau], | |||
nashmau : [ this.#boat_nashmau_whitegate ], | |||
bibiki : [ this.#boat_bibiki_tours, this.#boat_bibiki_purgo], | |||
purgonorgoIsle : [ this.#boat_purgo_bibiki ], | |||
northLanding : [ this.#boat_barge_north_oos, this.#boat_barge_north_central ], | |||
centralLanding : [ this.#boat_barge_central_south_newtpool1, this.#boat_barge_central_south_newtpool2 ], | |||
southLanding : [ this.#boat_barge_south_central_emfa, this.#boat_barge_south_oos, this.#boat_barge_south_north, this.#boat_barge_south_oos1 ] | |||
} | |||
static #alchemy = [480, 1380, 5]; | |||
static #smithing = [480, 1380, 2]; | |||
static #bonecrafting = [480, 1380, 3]; | |||
static #goldsmithing = [480, 1380, 4]; | |||
static #clothcrafting = [360, 1260, 0]; | |||
static #woodworking = [360, 1260, 0]; | |||
static #leathercrafting = [180, 1080, 4]; | |||
static #fishing = [180, 1080, 5]; | |||
static #cooking = [300, 1200, 7]; | |||
static guilds = { | |||
// [ Open, Close, Holiday] | |||
alchemy : this.#alchemy, | |||
smithing : this.#smithing, | |||
bonecrafting : this.#bonecrafting, | |||
goldsmithing : this.#goldsmithing, | |||
clothcrafting : this.#clothcrafting, | |||
woodworking : this.#woodworking, | |||
leathercrafting : this.#leathercrafting, | |||
fishing : this.#fishing, | |||
cooking : this.#cooking, | |||
all : [ this.#alchemy, this.#smithing, this.#bonecrafting,this.#goldsmithing, this.#clothcrafting,this.#woodworking,this.#leathercrafting, this.#fishing, this.#cooking ] | |||
} | |||
} | |||
class VanaTime{ | |||
#elementalDay = ["Firesday", "Earthsday", "Watersday", "Windsday", "Iceday", "Lightningday", "Lightsday", "Darksday"]; | |||
#dayColor = ["#FF0000", "#AAAA00", "#0000DD", "#00AA22", "#7799FF", "#AA00AA", "#AAAAAA", "#333333"]; | |||
#moonPhaseName = ["New Moon", "Waxing Crescent", "First Quarter", "Waxing Gibbous", "Full Moon", "Waning Gibbous", "Last Quarter", "Waning Crescent"]; | |||
#moonIcon = ['\u{1F311}', '\u{1F312}', '\u{1F313}', '\u{1F314}', '\u{1F315}', '\u{1F316}', '\u{1F317}', '\u{1F318}']; | |||
#moonPercentages = ["(10%-0%-5%)", "(7%-38%)", "(40%-55%)", "(57%-88%)", "(90%-100%-95%)", "(93%-62%)", "(60%-45%)", "(43%-12%)"]; | |||
#month = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; | |||
#weekday = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; | |||
#rseRace = ["M. Hume","F. Hume","M. Elvaan","F. Elvaan","M. TaruTaru","F. TaruTaru","Mithra","Galka"]; | |||
#rseLocation = ["Gusgen Mines","Shakrami Maze","Ordelle Caves"]; | |||
// Conversions in Milliseconds | |||
//#baseDate; // built at runtime: 1024844400000 | |||
#moonDate = 1074997872000; // in milliseconds | |||
#VTIME_BIRTH = 1024844400000; // vana birthday - in milliseconds | |||
#VTIME_BASEDATE = 1009810800; // unix epoch - 1009810800 = se epoch (in earth seconds) | |||
rseDate = 1075281264000; | |||
#ONE_SECOND = 1000000; | |||
#ONE_MINUTE; | |||
#ONE_HOUR; | |||
#ONE_DAY; | |||
// #ONE_WEEK; | |||
// #ONE_MONTH; | |||
// #ONE_YEAR; | |||
// Conversions in Minutes | |||
#VTIME_YEAR = 518400; // 360 * GameDay | |||
#VTIME_MONTH = 43200; // 30 * GameDay | |||
#VTIME_WEEK = 11520; // 8 * GameDay | |||
#VTIME_DAY = 1440; // 24 hours * GameHour | |||
#VTIME_HOUR = 60; // 60 minutes | |||
#VMULTIPLIER = 25; | |||
#MOON_CYCLE_DAYS = 84; | |||
// #MOON_CYCLE_PHASE = 17280; // 1 moon phase cycle = 12 vana days = 12 * Gameday | |||
/* | |||
Some of the math... | |||
(((898 * 360) + 30) * 24 * 60 * 60) / (this.#VMULTIPLIER / 1000)..... | |||
converts vana time to earth time by ( / 25 ) then getting to milliseconds ( * 1000 ) | |||
*/ | |||
#vanaBirthday = (((898 * 360) + 30) * 24 * 60 * 60) / (25 / 1000); // 1117359360000 - in earth time milliseconds | |||
#difference = this.#vanaBirthday - this.#VTIME_BIRTH; // 92514960000 - earth time milliseconds | |||
getDifference(){ return this.#difference }; | |||
/** | |||
* Common variables for quick reference to current Vana time | |||
* @returns - integer / number | |||
*/ | |||
// vana_currentTime_inEarthMS = ((898 * 360 + 30) * (24 * 60 * 60 * 1000)) + (this.earthDate.getTime() - this.#VTIME_BIRTH) * this.#VMULTIPLIER; // vana time, represented in earth milliseconds - used for making Date() objects | |||
// vana_currentTime = this.vana_currentTime_inEarthMS / (60 * 1000); // vana time in minutes | |||
// //vana_currentTime = ( ((this.earthDate.getTime() / 1000) - this.#VTIME_BASEDATE ) / 60.0 * this.#VMULTIPLIER) + (886 * this.#VTIME_YEAR); //returned in vana minutes | |||
// vana_year = this.vana_currentTime / this.#VTIME_YEAR; | |||
// vana_month = (this.vana_currentTime / this.#VTIME_MONTH) % 12 + 1; | |||
// vana_date = (this.vana_currentTime / this.#VTIME_DAY) % 30 + 1; | |||
// vana_weekday = Math.floor((this.vana_currentTime % this.#VTIME_WEEK) / this.#VTIME_DAY); | |||
// vana_hour = (this.vana_currentTime % this.#VTIME_DAY) / this.#VTIME_HOUR; | |||
// vana_mins = this.vana_currentTime % this.#VTIME_HOUR; | |||
// vana_moonphase = Math.floor((this.vana_currentTime % this.#MOON_CYCLE_PHASE) / this.#VTIME_DAY); | |||
/** | |||
* Helper functions for quick reference to any Vana time | |||
* @returns - integer / number | |||
*/ | |||
now_inEarthMS(){ | |||
var now = new Date(); | |||
return ((898 * 360 + 30) * (24 * 60 * 60 * 1000)) + (now.getTime() - this.#VTIME_BIRTH) * this.#VMULTIPLIER; | |||
} | |||
now(){ return this.now_inEarthMS() / ( 60 * 1000); } | |||
now_inMS(){ | |||
var timenow = new Date(); | |||
return ((timenow.getTime() - this.#VTIME_BIRTH) % (24 * 60 * 60 * 1000 / 25)); | |||
} | |||
now_inMINS(){ | |||
return this.now_inMS / ( 1000 * 60 ); | |||
} | |||
today_inMS(){ // result in earth Milliseconds | |||
var now = this.now_inEarthMS(); | |||
return ( now - ( now % (24 * 60 * 60 * 1000) )); | |||
} | |||
year(vanatime) { | |||
if (vanatime === undefined || vanatime == null) vanatime = this.now(); | |||
return Math.floor(vanatime / this.#VTIME_YEAR); | |||
} | |||
month(vanatime){ | |||
if (vanatime === undefined || vanatime == null) vanatime = this.now(); | |||
return Math.floor((vanatime / this.#VTIME_MONTH) % 12) + 1; | |||
} | |||
date(vanatime){ | |||
if (vanatime === undefined || vanatime == null) vanatime = this.now(); | |||
return Math.floor((vanatime / this.#VTIME_DAY) % 30) + 1; | |||
} | |||
weekDay(vanatime){ | |||
if (vanatime === undefined || vanatime == null) vanatime = this.now(); | |||
return Math.floor((vanatime % this.#VTIME_WEEK) / this.#VTIME_DAY); | |||
} | |||
hour(vanatime){ | |||
if (vanatime === undefined || vanatime == null) vanatime = this.now(); | |||
return Math.floor((vanatime % this.#VTIME_DAY) / this.#VTIME_HOUR); | |||
} | |||
mins(vanatime){ | |||
if (vanatime === undefined || vanatime == null) vanatime = this.now(); | |||
return Math.floor(vanatime % this.#VTIME_HOUR); | |||
} | |||
dayColor(vanatime){ | |||
if (vanatime === undefined || vanatime == null) vanatime = this.now(); | |||
return this.#dayColor[this.weekDay()]; | |||
} | |||
dayLabel(day){ | |||
if (day === undefined || day == null) return this.#elementalDay[this.weekDay()]; | |||
else return this.#elementalDay[day] | |||
} | |||
moonPhaseIcon(day){ | |||
if (day === undefined || day == null) return this.#moonIcon[this.moonLatentPhase()]; | |||
else return this.#moonIcon[day]; | |||
} | |||
moonPhaseName(day){ | |||
if (day === undefined || day == null) return this.#moonPhaseName[this.moonLatentPhase()]; | |||
else return this.#moonPhaseName[day]; | |||
} | |||
moonPhasePercentages(day){ | |||
if (day === undefined || day == null) return this.#moonPercentages[this.moonLatentPhase()]; | |||
else return this.#moonPercentages[day]; | |||
} | |||
/** | |||
* Time Helper functions - supports string generation for month/week details | |||
* @param (required) - represents which RACE | |||
* @returns - string - from #rseRace or #rseLocation | |||
*/ | |||
monthLabel(m){ return this.#month[m]; } | |||
weekdayLabel(w){ return this.#weekday[w]; } | |||
/** | |||
* RSE Helper functions - supports string generation for RSE details | |||
* @param r (required) - represents which RACE | |||
* @returns - string - from #rseRace or #rseLocation | |||
*/ | |||
rseRace(r){ return this.#rseRace[r]; } | |||
/** | |||
* RSE Helper functions - supports string generation for RSE details | |||
* @param r (required) - represents which RACE | |||
* @returns - string - from #rseRace or #rseLocation | |||
*/ | |||
rseLocation(r){ return this.#rseLocation[r]; } | |||
constructor(){ | |||
this.#ONE_MINUTE = 60 * this.#ONE_SECOND; | |||
this.#ONE_HOUR = 60 * this.#ONE_MINUTE; | |||
this.#ONE_DAY = 24 * this.#ONE_HOUR; | |||
// this.#ONE_WEEK = 8 * this.#ONE_DAY; | |||
// this.#ONE_MONTH = 30 * this.#ONE_DAY; | |||
// this.#ONE_YEAR = 360 * this.#ONE_DAY; | |||
// this.#MOON_CYCLE_PHASE = 12 * this.#VTIME_WEEK; | |||
} | |||
/******************************** MOON PHASES ********************************** | |||
0% NM 7% WXC 40% FQM 57% WXG 90% FM 93% WNG 60% LQM 43% WNC 10% NM | |||
2% NM 10% WXC 43% FQM 60% WXG 93% FM 90% WNG 57% LQM 40% WNC 7% NM | |||
5% NM 12% WXC 45% FQM 62% WXG 95% FM 88% WNG 55% LQM 38% WNC 5% NM | |||
14% WXC 48% FQM 64% WXG 98% FM 86% WNG 52% LQM 36% WNC 2% NM | |||
17% WXC 50% FQM 67% WXG 100% FM 83% WNG 50% LQM 33% WNC | |||
19% WXC 52% FQM 69% WXG 98% FM 81% WNG 48% LQM 31% WNC | |||
21% WXC 55% FQM 71% WXG 95% FM 79% WNG 45% LQM 29% WNC | |||
24% WXC 74% WXG 76% WNG 26% WNC | |||
26% WXC 76% WXG 74% WNG 24% WNC | |||
29% WXC 79% WXG 71% WNG 21% WNC | |||
31% WXC 81% WXG 69% WNG 19% WNC | |||
33% WXC 83% WXG 67% WNG 17% WNC | |||
36% WXC 86% WXG 64% WNG 14% WNC | |||
38% WXC 88% WXG 62% WNG 12% WNC | |||
********************************************************************************/ | |||
/** | |||
* Private function - supports moon phase calculations | |||
* @param vanatime (required) - Vanadiel time, in MILLISECONDS | |||
* @returns - integer - represents the day in the 84 day moon phase cycle | |||
*/ | |||
#moonDays(vanatime){ | |||
if (vanatime === undefined || vanatime == null) vanatime = this.now(); | |||
return ((( vanatime / this.#VTIME_DAY ) + 26) % this.#MOON_CYCLE_DAYS); | |||
} | |||
/** | |||
* Private function for doing arithmetic for moon phase percentage | |||
* @param vanatime (required) - Vanadiel time, in MILLISECONDS | |||
* @returns - integer representing moon phase percentage | |||
*/ | |||
#moonPercent(vanatime){ | |||
if (vanatime === undefined || vanatime == null) vanatime = this.now(); | |||
return Math.abs( -Math.round((42 - Math.floor(this.#moonDays(vanatime))) / 42 * 100) ); | |||
} | |||
/** | |||
* Helper function for getting moon phase percentage | |||
* @param vanatime (required) - Vanadiel time, in MILLISECONDS | |||
* @returns - integer representing moon phase percentage | |||
*/ | |||
getMoonPercent(vanatime) { return this.#moonPercent(vanatime)}; | |||
/** | |||
* @param vanatime - Vanadiel time, in MILLISECONDS; default value is now() | |||
* @returns - integer representing waxing/waning/neither | |||
*/ | |||
#moonDirection(vanatime){ | |||
if (vanatime === undefined || vanatime == null) vanatime = this.now(); | |||
var moondays = Math.floor(this.#moonDays(vanatime)); | |||
//console.log(daysmod); | |||
if (moondays == 42 || moondays == 0) { return 0; }// neither waxing nor waning | |||
else if (moondays < 42){ return 1; } // waning | |||
else{ return 2; } // waxing | |||
} | |||
/** | |||
* @param vanatime - Vanadiel time, in MILLISECONDS; default value is now() | |||
* @returns - total milliseconds remaining until next conquest update | |||
*/ | |||
moonLatentPhase(vanatime){ | |||
if (vanatime === undefined || vanatime == null) vanatime = this.now(); | |||
var moonPhase = this.#moonPercent(vanatime); | |||
var moonDirection = this.#moonDirection(vanatime); | |||
//console.log("*mP", moonPhase); | |||
//console.log("*mD", moonDirection); | |||
if (moonPhase <= 5 || (moonPhase <= 10 && moonDirection == 1)) {return 0;} // New Moon - 10% waning -> 5% waxing | |||
else if (moonPhase >= 7 && moonPhase <= 38 && moonDirection == 2) {return 1;} // Waxing Crescent - 7% -> 38% waxing | |||
else if (moonPhase >= 40 && moonPhase <= 55 && moonDirection == 2){return 2;} // First Quarter - 40%% -> 55% waxing | |||
else if (moonPhase >= 57 && moonPhase <= 88 && moonDirection == 2){return 3;} // Waxing Gibbous - 57% -> 88% | |||
else if (moonPhase >= 95 || (moonPhase >= 90 && moonDirection == 2)){return 4;} // Full Moon - waxing 90% -> waning 95% | |||
else if (moonPhase >= 62 && moonPhase <= 93 && moonDirection == 1){return 5;} // Waning Gibbous - 93% -> 62% | |||
else if (moonPhase >= 45 && moonPhase <= 60 && moonDirection == 1){return 6;} // Last Quarter - 60% -> 45% | |||
else{return 7;} // Waning Crescent - 43% -> 12% | |||
} | |||
/** | |||
* @returns - total milliseconds remaining until next conquest update | |||
*/ | |||
conquestRemainingTime(){ | |||
var now = new Date(); | |||
//console.log(this.earthDate.getTime(), this.#VTIME_BIRTH); | |||
return (7 * (24 * 60 * 60 * 1000)) - ((now.getTime() - this.#VTIME_BIRTH) % (7 * (24 * 60 * 60 * 1000))); | |||
} | |||
/** | |||
* @returns - integer - total Vanadiel days remaining on current conquest | |||
*/ | |||
conquestRemainingVanaDays(){ | |||
return Math.ceil(this.conquestRemainingTime() / (24 * 60 * 60 * 1000 / 25)); | |||
} | |||
/** | |||
* @param time - Vanadiel time, in MILLISECONDS, needing to be converted | |||
* @returns {Date} - value as Date() object | |||
*/ | |||
earthTime(time){ | |||
if (time === undefined) time = this.now_inEarthMS(); | |||
//else time = time * 60 * 1000; | |||
var earthTime = time / ( this.#VMULTIPLIER ); | |||
return new Date(Math.floor(earthTime) - (this.#vanaBirthday - this.#VTIME_BIRTH)); | |||
} | |||
/** | |||
* @param time - Vanadiel time, in minutes, needing to be converted | |||
* @returns - string, formatted 00:00 | |||
*/ | |||
stringVanaTime(time){ | |||
if (time === undefined || time === null) time = this.now(); | |||
//console.log(time); | |||
var vYear = this.year(time); | |||
var vMon = this.month(time) | |||
var vDate = this.date(time); | |||
var vHour = this.hour(time); | |||
var vMin = this.mins(time); | |||
// var vSec = time.getSeconds(); | |||
// var vDay = time.getDay(); | |||
//seconds left our because we don't use them for any calcs | |||
if (vYear < 1000) vYear = "0" + vYear; | |||
if (vMon < 10) vMon = "0" + vMon; | |||
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 time - Vanadiel time, in milliseconds, needing to be converted | |||
* @returns - string, formatted 00:00:00 | |||
*/ | |||
stringEarthTime(time) { | |||
var eTime = this.earthTime(time); | |||
// const monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; | |||
//Most of these arent needed, left in for future inclusion if needed/wanted | |||
// var eYear = eTime.getFullYear(); | |||
// var eMon = monthNames[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 str = eMon + " " + eDate + "," + eHour + ":" + eMin + ":" + eSec; | |||
var str = eHour + ":" + eMin + ":" + eSec; | |||
return str; | |||
} | |||
/** | |||
* @param nextTime - Vana time, in MINUTES, needing to be converted | |||
* @returns - string of HOURS:MINS | |||
*/ | |||
timeUntil(nextTime){ | |||
if (nextTime === undefined) { return "00:00:00"; } | |||
else if ( !(nextTime instanceof Date) ) { | |||
//console.log('!instance of Date'); | |||
var e = this.earthTime(nextTime); | |||
} //earth time for next departure | |||
else e = nextTime; | |||
//console.log( e.getTime() ); | |||
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 days = (e.getTime() - now.getTime()) / (24 * 60 * 60 * 1000); | |||
var hours = (days - Math.floor(days)) * 24; | |||
var minutes = (hours - Math.floor(hours)) * 60; | |||
var seconds = Math.floor((minutes - Math.floor(minutes)) * 60); | |||
days = Math.floor(days); | |||
hours = Math.floor(hours); | |||
minutes = Math.floor(minutes); | |||
if (hours < 10) hours = "0" + hours; | |||
if (minutes < 10) minutes = "0" + minutes; | |||
if (seconds < 10) seconds = "0" + seconds; | |||
var str = minutes + ":" + seconds; | |||
if ( days > 0 ) { str = [days, hours, str].join(':'); } | |||
else if ( hours > 0 || typeof(hours) == 'string') { str = [hours, str].join(':'); } | |||
return str; | |||
} | |||
timer(time1, time2){ | |||
var seconds = Math.floor((time1.getTime() - time2.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); | |||
seconds < 10 ? seconds = "0" + seconds : seconds; | |||
minutes < 10 ? minutes = "0" + minutes : minutes; | |||
hours < 10 ? hours = "0" + hours : hours; | |||
var str = hours + ":" + minutes + ":" + seconds; | |||
if ( days != 0) str = [days, str].join(':'); | |||
return str; | |||
} | |||
} | |||
const vanatime = new VanaTime(); | |||
let currentPopulation = 0; | |||
//////////////////////////////////////////////////// | |||
function pageHasElement(element){ | |||
function test(v){ | |||
var i = document.getElementById(v); | |||
var c = document.getElementsByClassName(v); | |||
if ( i ) { return true; } | |||
if ( c[0] ) { return true; } | |||
} | |||
if (typeof(element) == 'string') return test(element); | |||
else { | |||
for (const [k,v] of Object.entries(element) ){ | |||
if (test(v) == true) return true; | |||
} | |||
} | |||
return false; | |||
} | |||
function updateSidebar() { | |||
if (!pageHasElement(timeElements.sidebar)) return; | |||
var hour = vanatime.hour(); | |||
hour < 10 ? hour = ["0", hour].join('') : hour; | |||
var mins = vanatime.mins(); | |||
mins < 10 ? mins = ["0", mins].join('') : mins; | |||
var sidebarTime = "<div><li><b>" + hour + ":" + mins + "</b> ~ " + vanatime.year() + "-" + vanatime.month() + "-" + vanatime.date() + "</li>"; | |||
sidebarTime += "<li><span style=\"font-weight: bold; font-size:14px; color:" + vanatime.dayColor() + "\" >" + vanatime.dayLabel() + "</span><span style=\"font-size:14px;\"> ~ " + vanatime.moonPhaseIcon() + vanatime.getMoonPercent() + "%</span></li>"; | |||
//sidebarTime += "<li>\u{1F7E2} Online "; | |||
if ( currentPopulation != 0 ) sidebarTime += "<li><span style=\"font-size:9px;\">\u{1F7E2}</span> Online <b>" + currentPopulation + "</b></li>"; | |||
else sidebarTime += "<li><span style=\"font-size:9px;\">\u{1F534}</span> Online <i>~Standby~</i></li>"; | |||
let penaltyPerLvl = "1.5%"; | |||
if ( currentPopulation >= 2001 ) penaltyPerLvl = "2.5%"; | |||
else if ( currentPopulation >= 1001 ) penaltyPerLvl = "2%"; | |||
function | sidebarTime += "<li><a href=\"https://horizonffxi.wiki/Level_Sync#Horizon_Changes\"><span style=\"font-size:12px;\"><i>+10 Exp Penalty: <b>" + penaltyPerLvl + "</b>/lvl</i></span></a></li>"; | ||
sidebarTime += "</div>"; | |||
const sidebar_vanatime = document.getElementById(timeElements.sidebar); | |||
if (sidebar_vanatime) sidebar_vanatime.innerHTML = sidebarTime; | |||
//for (let i = 0; i < page_vanatime.length; i = i+1) { page_vanatime[i].innerHTML = sidebarTime; } | |||
} | |||
function updateBoatSchedule() { | |||
if (!pageHasElement(timeElements.boats)) return; | |||
populateTransportSchedule(timeElements.boats.selbina, schedule.boats.selbina, 3); | |||
populateTransportSchedule(timeElements.boats.mhaura, schedule.boats.mhaura, 3); | |||
populateTransportSchedule(timeElements.boats.whitegate, schedule.boats.whitegate, 1); | |||
populateTransportSchedule(timeElements.boats.nashmau, schedule.boats.nashmau, 1); | |||
populateTransportSchedule(timeElements.boats.bibiki, schedule.boats.bibiki, 1); | |||
populateTransportSchedule(timeElements.boats.purgonorgoIsle, schedule.boats.purgonorgoIsle, 1); | |||
populateTransportSchedule(timeElements.boats.northLanding, schedule.boats.northLanding, 1); | |||
populateTransportSchedule(timeElements.boats.centralLanding, schedule.boats.centralLanding, 1); | |||
populateTransportSchedule(timeElements.boats.southLanding, schedule.boats.southLanding, 1); | |||
} | |||
function updateAirshipSchedule(){ | |||
if (!pageHasElement(timeElements.airships)) return; | |||
populateTransportSchedule(timeElements.airships.jeuno, schedule.airships.jeuno, 1); | |||
populateTransportSchedule(timeElements.airships.bastok, schedule.airships.bastok, 1); | |||
populateTransportSchedule(timeElements.airships.sandy, schedule.airships.sandy, 1); | |||
populateTransportSchedule(timeElements.airships.windy, schedule.airships.windy, 1); | |||
populateTransportSchedule(timeElements.airships.kazham, schedule.airships.kazham, 1); | |||
} | |||
function _transportScheduleHeader(classname){ | |||
var header = "<TABLE CLASS='" + classname + " vanatime-main-table" + "' CELLSPACING='0' CELLPADDING='0'>"; | |||
header += "<TR><TH ALIGN='LEFT'>Destination</TH>"; | |||
//header += "<TH ALIGN='LEFT'>Departure Day</TH>"; | |||
header += "<TH ALIGN='LEFT'>VanaTime</TH>"; | |||
header += "<TH ALIGN='LEFT'>Earth Time</TH>"; | |||
header += "<TH ALIGN='LEFT'>Departs</TH></TR>"; | |||
return header; | |||
} | |||
function _transportScheduleBody(schedule, entriesPerSchedule, numberOfEntries){ | |||
function _helper(sched, n){ | |||
var helperoffset = (sched[1] + sched[3] + sched[4]) * 60 * 1000 / 25; // VANA MILLISECONDS | |||
//console.log("helperoffset: ", helperoffset, vanatime.now_inMS()); | |||
while (helperoffset < vanatime.now_inMS() ) { | |||
helperoffset += (sched[2] * n * 60 * 1000 / 25); | |||
} | |||
return helperoffset; // VANA MILLISECONDS | |||
} | |||
var html = ""; | |||
var offset = {}; | |||
var rowhighlight = true; | |||
for( let n=1; n <= numberOfEntries; n++ ){ | |||
html += '<TR class="vanatime-main-table-row-spacer"><TD></TD><TD></TD><TD></TD><TD></TD></TR>'; | |||
for( let x=0; x < schedule.length; x++ ){ | |||
const offsetVariable = x + (schedule.length * (n-1)); | |||
for( let i=1 ; i <= entriesPerSchedule; i++ ){ | |||
//console.log(n,x,i, offsetVariable); | |||
if ( i > 1 ) offset[offsetVariable] += (schedule[x][2] * 60 * 1000 / 25); | |||
//else if ( lastOffset ) offset = lastOffset; | |||
else offset[offsetVariable] = _helper(schedule[x], n); | |||
// offset must be greater than the offset before it | |||
if ( offsetVariable >= schedule.length && offset[offsetVariable] <= offset[offsetVariable - schedule.length] ) | |||
{ | |||
console.log( "fired " + offsetVariable ); | |||
offset[offsetVariable] = offset[offsetVariable - schedule.length] + (schedule[x][2] * 60 * 1000 / 25); | |||
} | |||
var earthdepTime = (vanatime.today_inMS() + (offset[offsetVariable] * 25)); | |||
var vanadepTime = earthdepTime / ( 60 * 1000); | |||
//var arrTime = depTime - ( sched[2][4] * 60 * 1000); /// LEAVE THIS in the event someone wants to add ARRIVAL TIMES to future HTML tables | |||
//html += '<TR><TD>x= ' + x + '</TD><TD>' + vanatime.stringVanaTime(vanadepTime) + '</TD><TD>' + vanatime.stringEarthTime(earthdepTime) + '</TD><TD>' + vanatime.timeUntil(earthdepTime) +'</TD></TR>'; | |||
var rowclass = ""; | |||
if ( rowhighlight ) rowclass = `class="vanatime-main-table-row-highlight"`; | |||
html += '<TR ' + rowclass + '><TD>' + schedule[x][0] + '</TD><TD>' + vanatime.stringVanaTime(vanadepTime) + '</TD><TD>' + vanatime.stringEarthTime(earthdepTime) + '</TD><TD>' + vanatime.timeUntil(earthdepTime) +'</TD></TR>'; | |||
rowhighlight = !rowhighlight; | |||
} | |||
} | |||
} | |||
return html; | |||
} | |||
function populateTransportSchedule(classname, schedule, entriesPerSchedule){ | |||
const shipSched = document.getElementById(classname); | |||
if (shipSched) { | |||
var numberOfEntries = getSelectedNumberOfEntries(classname); | |||
if (numberOfEntries === 'undefined' || numberOfEntries === null || numberOfEntries == 0 ) numberOfEntries = 1; | |||
var _HTMLheader = _transportScheduleHeader(classname); | |||
var _HTMLbody = this._transportScheduleBody(schedule, entriesPerSchedule, numberOfEntries); | |||
var updatedSched = _HTMLheader + _HTMLbody + "</TABLE>"; | |||
const classname_details = classname + "-details"; | |||
let t = shipSched.getElementsByClassName(classname_details)[0]; | |||
var _HTMLdetails = ''; | |||
if ( !t ){ | |||
var temp = expandTableSelection(classname); | |||
if ( !temp ) temp = ""; | |||
const div = '<div class="vanatime-main-table">' + temp ; | |||
_HTMLdetails = `<span class="${classname_details}">${updatedSched}</span>`; | |||
shipSched.innerHTML = div + _HTMLdetails + '</div>'; | |||
} | |||
else { | |||
t.innerHTML = updatedSched; | |||
} | |||
} | |||
} | |||
function updateGuilds(){ | |||
if (!pageHasElement(timeElements.guilds)) return; | |||
/* ALCHEMY */ | |||
const page_alchemy_hours = document.getElementById(timeElements.guilds.alchemy); | |||
if ( page_alchemy_hours ) { page_alchemy_hours.innerHTML = _guildSchedule(schedule.guilds.alchemy); } | |||
const page_alchemy_status = document.getElementById(timeElements.guilds.alchemy_status); | |||
if ( page_alchemy_status ) { page_alchemy_status.innerHTML = _guildSchedule(schedule.guilds.alchemy, timeElements.guilds.alchemy_status); } | |||
const page_alchemy_holiday = document.getElementById(timeElements.guilds.alchemy_holiday); | |||
if ( page_alchemy_holiday ) { page_alchemy_holiday.innerHTML = _guildSchedule(schedule.guilds.alchemy, timeElements.guilds.alchemy_holiday); } | |||
const page_alchemy_timer = document.getElementById(timeElements.guilds.alchemy_timer); | |||
if ( page_alchemy_timer ) { page_alchemy_timer.innerHTML = _guildSchedule(schedule.guilds.alchemy, timeElements.guilds.alchemy_timer); } | |||
/* BONECRAFT */ | |||
const page_bonecraft_hours = document.getElementById(timeElements.guilds.bonecrafting); | |||
if ( page_bonecraft_hours ) { page_bonecraft_hours.innerHTML = _guildSchedule(schedule.guilds.bonecrafting); } | |||
const page_bonecraft_status = document.getElementById(timeElements.guilds.bonecraft_status); | |||
if ( page_bonecraft_status ) { page_bonecraft_status.innerHTML = _guildSchedule(schedule.guilds.bonecrafting, timeElements.guilds.bonecraft_status); } | |||
const page_bonecraft_holiday = document.getElementById(timeElements.guilds.bonecraft_holiday); | |||
if ( page_bonecraft_holiday ) { page_bonecraft_holiday.innerHTML = _guildSchedule(schedule.guilds.bonecrafting, timeElements.guilds.bonecraft_holiday); } | |||
const page_bonecraft_timer = document.getElementById(timeElements.guilds.bonecraft_timer); | |||
if ( page_bonecraft_timer ) { page_bonecraft_timer.innerHTML = _guildSchedule(schedule.guilds.bonecrafting, timeElements.guilds.bonecraft_timer); } | |||
/* CLOTHCRAFT */ | |||
const page_clothcraft_hours = document.getElementById(timeElements.guilds.clothcrafting); | |||
if ( page_clothcraft_hours ) { page_clothcraft_hours.innerHTML = _guildSchedule(schedule.guilds.clothcrafting); } | |||
const page_clothcraft_status = document.getElementById(timeElements.guilds.clothcraft_status); | |||
if ( page_clothcraft_status ) { page_clothcraft_status.innerHTML = _guildSchedule(schedule.guilds.clothcrafting, timeElements.guilds.clothcraft_status); } | |||
const page_clothcraft_holiday = document.getElementById(timeElements.guilds.clothcraft_holiday); | |||
if ( page_clothcraft_holiday ) { page_clothcraft_holiday.innerHTML = _guildSchedule(schedule.guilds.clothcrafting, timeElements.guilds.clothcraft_holiday); } | |||
const page_clothcraft_timer = document.getElementById(timeElements.guilds.clothcraft_timer); | |||
if ( page_clothcraft_timer ) { page_clothcraft_timer.innerHTML = _guildSchedule(schedule.guilds.clothcrafting, timeElements.guilds.clothcraft_timer); } | |||
/* COOKING */ | |||
const page_cooking_hours = document.getElementById(timeElements.guilds.cooking); | |||
if ( page_cooking_hours ) { page_cooking_hours.innerHTML = _guildSchedule(schedule.guilds.cooking); } | |||
const page_cooking_status = document.getElementById(timeElements.guilds.cooking_status); | |||
if ( page_cooking_status ) { page_cooking_status.innerHTML = _guildSchedule(schedule.guilds.cooking, timeElements.guilds.cooking_status); } | |||
const page_cooking_holiday = document.getElementById(timeElements.guilds.cooking_holiday); | |||
if ( page_cooking_holiday ) { page_cooking_holiday.innerHTML = _guildSchedule(schedule.guilds.cooking, timeElements.guilds.cooking_holiday); } | |||
const page_cooking_timer = document.getElementById(timeElements.guilds.cooking_timer); | |||
if ( page_cooking_timer ) { page_cooking_timer.innerHTML = _guildSchedule(schedule.guilds.cooking, timeElements.guilds.cooking_timer); } | |||
/* FISHING */ | |||
const page_fishing_hours = document.getElementById(timeElements.guilds.fishing); | |||
if ( page_fishing_hours ) { page_fishing_hours.innerHTML = _guildSchedule(schedule.guilds.fishing); } | |||
const page_fishing_status = document.getElementById(timeElements.guilds.fishing_status); | |||
if ( page_fishing_status ) { page_fishing_status.innerHTML = _guildSchedule(schedule.guilds.fishing, timeElements.guilds.fishing_status); } | |||
const page_fishing_holiday = document.getElementById(timeElements.guilds.fishing_holiday); | |||
if ( page_fishing_holiday ) { page_fishing_holiday.innerHTML = _guildSchedule(schedule.guilds.fishing, timeElements.guilds.fishing_holiday); } | |||
const page_fishing_timer = document.getElementById(timeElements.guilds.fishing_timer); | |||
if ( page_fishing_timer ) { page_fishing_timer.innerHTML = _guildSchedule(schedule.guilds.fishing, timeElements.guilds.fishing_timer); } | |||
/* GOLDSMITHING */ | |||
const page_goldsmithing_hours = document.getElementById(timeElements.guilds.goldsmithing); | |||
if ( page_goldsmithing_hours ) { page_goldsmithing_hours.innerHTML = _guildSchedule(schedule.guilds.goldsmithing); } | |||
const page_goldsmithing_status = document.getElementById(timeElements.guilds.goldsmithing_status); | |||
if ( page_goldsmithing_status ) { page_goldsmithing_status.innerHTML = _guildSchedule(schedule.guilds.goldsmithing, timeElements.guilds.goldsmithing_status); } | |||
const page_goldsmithing_holiday = document.getElementById(timeElements.guilds.goldsmithing_holiday); | |||
if ( page_goldsmithing_holiday ) { page_goldsmithing_holiday.innerHTML = _guildSchedule(schedule.guilds.goldsmithing, timeElements.guilds.goldsmithing_holiday); } | |||
const page_goldsmithing_timer = document.getElementById(timeElements.guilds.goldsmithing_timer); | |||
if ( page_goldsmithing_timer ) { page_goldsmithing_timer.innerHTML = _guildSchedule(schedule.guilds.goldsmithing, timeElements.guilds.goldsmithing_timer); } | |||
/* LEATHERCRAFT */ | |||
const page_leathercraft_hours = document.getElementById(timeElements.guilds.leathercrafting); | |||
if ( page_leathercraft_hours ) { page_leathercraft_hours.innerHTML = _guildSchedule(schedule.guilds.leathercrafting); } | |||
const page_leathercraft_status = document.getElementById(timeElements.guilds.leathercraft_status); | |||
if ( page_leathercraft_status ) { page_leathercraft_status.innerHTML = _guildSchedule(schedule.guilds.leathercrafting, timeElements.guilds.leathercraft_status); } | |||
const page_leathercraft_holiday = document.getElementById(timeElements.guilds.leathercraft_holiday); | |||
if ( page_leathercraft_holiday ) { page_leathercraft_holiday.innerHTML = _guildSchedule(schedule.guilds.leathercrafting, timeElements.guilds.leathercraft_holiday); } | |||
const page_leathercraft_timer = document.getElementById(timeElements.guilds.leathercraft_timer); | |||
if ( page_leathercraft_timer ) { page_leathercraft_timer.innerHTML = _guildSchedule(schedule.guilds.leathercrafting, timeElements.guilds.leathercraft_timer); } | |||
/* SMITHING */ | |||
const page_smithing_hours = document.getElementById(timeElements.guilds.smithing); | |||
if ( page_smithing_hours ) { page_smithing_hours.innerHTML = _guildSchedule(schedule.guilds.smithing); } | |||
const page_smithing_status = document.getElementById(timeElements.guilds.smithing_status); | |||
if ( page_smithing_status ) { page_smithing_status.innerHTML = _guildSchedule(schedule.guilds.smithing, timeElements.guilds.smithing_status); } | |||
const page_smithing_holiday = document.getElementById(timeElements.guilds.smithing_holiday); | |||
if ( page_smithing_holiday ) { page_smithing_holiday.innerHTML = _guildSchedule(schedule.guilds.smithing, timeElements.guilds.smithing_holiday); } | |||
const page_smithing_timer = document.getElementById(timeElements.guilds.smithing_timer); | |||
if ( page_smithing_timer ) { page_smithing_timer.innerHTML = _guildSchedule(schedule.guilds.smithing, timeElements.guilds.smithing_timer); } | |||
/* WOODWORKING */ | |||
const page_woodworking_hours = document.getElementById(timeElements.guilds.woodworking); | |||
if ( page_woodworking_hours ) { page_woodworking_hours.innerHTML = _guildSchedule(schedule.guilds.woodworking); } | |||
const page_woodworking_status = document.getElementById(timeElements.guilds.woodworking_status); | |||
if ( page_woodworking_status ) { page_woodworking_status.innerHTML = _guildSchedule(schedule.guilds.woodworking, timeElements.guilds.woodworking_status); } | |||
const page_woodworking_holiday = document.getElementById(timeElements.guilds.woodworking_holiday); | |||
if ( page_woodworking_holiday ) { page_woodworking_holiday.innerHTML = _guildSchedule(schedule.guilds.woodworking, timeElements.guilds.woodworking_holiday); } | |||
const page_woodworking_timer = document.getElementById(timeElements.guilds.woodworking_timer); | |||
if ( page_woodworking_timer ) { page_woodworking_timer.innerHTML = _guildSchedule(schedule.guilds.woodworking, timeElements.guilds.woodworking_timer); } | |||
const page_allguilds_hours = document.getElementById(timeElements.guilds.all); | |||
if ( page_allguilds_hours ) { | |||
var guildOut = "<TABLE CLASS='"+ timeElements.guilds.all + " vanatime-main-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>" + _guildSchedule(schedule.guilds.alchemy) + "</td></TR>"; | |||
guildOut = guildOut + "<TR><TH> Blacksmithing</TH><td>" + _guildSchedule(schedule.guilds.smithing) + "</td></TR>"; | |||
guildOut = guildOut + "<TR><TH> bonecrafting</TH><td>" + _guildSchedule(schedule.guilds.bonecrafting) + "</td></TR>"; | |||
guildOut = guildOut + "<TR><TH> Goldsmithing</TH><td>" + _guildSchedule(schedule.guilds.goldsmithing) + "</td></TR>"; | |||
guildOut = guildOut + "<TR><TH> Clothcrafting</TH><td>" + _guildSchedule(schedule.guilds.clothcrafting) + "</td></TR>"; | |||
guildOut = guildOut + "<TR><TH> Woodworking</TH><td>" + _guildSchedule(schedule.guilds.woodworking) + "</td></TR>"; | |||
guildOut = guildOut + "<TR><TH> Leatherworking </TH><td>" + _guildSchedule(schedule.guilds.leathercrafting) + "</td></TR>"; | |||
guildOut = guildOut + "<TR><TH> Fishing</TH><td>" + _guildSchedule(schedule.guilds.fishing) + "</td></TR>"; | |||
guildOut = guildOut + "<TR><TH> Cooking</TH><td>" + _guildSchedule(schedule.guilds.cooking) + "</td></TR>"; | |||
guildOut = guildOut + "</TABLE>"; | |||
page_allguilds_hours.innerHTML = guildOut; | |||
} | |||
} | } | ||
function | function _guildStatusCheck(guild, statusID) { | ||
return outputText = [outputTxt1, outputTxt2]; | |||
} | |||
function _guildSchedule(guild, statusID) { | |||
if (guild === 'undefined') return "_guildSchedule: error"; | |||
var now = vanatime.now_inMS(); | |||
var guildOpens = guild[0] * 60 * 1000 / 25; | |||
var guildCloses = guild[1] * 60 * 1000 / 25; | |||
// Guild open/close check | |||
var nextOpenTime = 0; | |||
var outputTxt1 = "", outputTxt2 = ""; | |||
if (guildOpens >= now) { | |||
nextOpenTime = (((guildOpens - now) * 25) + vanatime.now_inEarthMS()); | |||
outputTxt1 = "Opens in: "; | |||
outputTxt2 = "Currently Closed. Open tomorrow."; | |||
} else if ((guildOpens < now) && (guildCloses > now)) { | |||
nextOpenTime = (((guildCloses - now) * 25) + vanatime.now_inEarthMS()); | |||
outputTxt1 = "Closes in: "; | |||
outputTxt2 = "Currently Open for business."; | |||
} else if (guildCloses <= now) { | |||
nextOpenTime = ((24 * 60 * 60 * 1000 / 25) - now + guildOpens) * 25 + vanatime.now_inEarthMS(); | |||
outputTxt1 = "Opens in: "; | |||
outputTxt2 = "Currently Closed. Open tomorrow."; | |||
} | |||
if(typeof(statusID) == 'string' && statusID.includes('status')) { | |||
// outputTxt2 = [`<span id=\'${statusID}\'>`, outputTxt2].join(''); | |||
// outputTxt2 = [outputTxt2, '</span'].join(''); | |||
return outputTxt2; | |||
} | |||
// Holiday check | |||
if ((guild[2] == vanatime.weekDay()) && (guildCloses > now)) { | |||
nextOpenTime = ((24 * 60 * 60 * 1000 / 25) - now + guildOpens) * 25 + vanatime.now_inEarthMS(); | |||
outputTxt2 = "Currently Closed for Guild Holiday."; | |||
outputTxt1 = "Opens in: "; | |||
if(typeof(statusID) == 'string' &&statusID.includes('holiday')) { | |||
// outputTxt2 = [`<span id=\'${statusID}\'>`, outputTxt2].join(''); | |||
// outputTxt2 = [outputTxt2, '</span'].join(''); | |||
return outputTxt2; | |||
} | |||
} else if (((vanatime.weekDay() + 1) == guild[2]) && (guildCloses <= now)) { | |||
nextOpenTime = ((24 * 60 * 60 * 1000 / 25) - now + guildOpens) * 25 + (24 * 60 * 60 * 1000 / 25) + vanatime.now_inEarthMS(); | |||
outputTxt2 = "Currently Closed. Guild Holiday tomorrow."; | |||
outputTxt1 = "Opens in: "; | |||
if(typeof(statusID) == 'string' && statusID.includes('holiday')) { | |||
// outputTxt2 = [`<span id=\'${statusID}\'>`, outputTxt2].join(''); | |||
// outputTxt2 = [outputTxt2, '</span'].join(''); | |||
return outputTxt2; | |||
} | |||
} | |||
if(typeof(statusID) == 'string' &&statusID.includes('holiday')) { | |||
// outputTxt2 = [`<span id=\'${statusID}\'>`, outputTxt2].join(''); | |||
// outputTxt2 = [outputTxt2, '</span'].join(''); | |||
return `Guild is not on holiday until ${vanatime.dayLabel(guild[2])}.`; | |||
} | |||
/****DEBUGGING*****/ | |||
// if (guild == schedule.guilds.fishing) { | |||
// console.log(guild[2], nextOpenTime, now, vanatime.timeUntil(nextOpenTime) ); | |||
// } | |||
/****DEBUGGING*****/ | |||
if(typeof(statusID) == 'string' && statusID.includes('timer')) { | |||
return outputTxt1 + vanatime.timeUntil(nextOpenTime); | |||
} | |||
return outputTxt1 + vanatime.timeUntil(nextOpenTime) + ". " + outputTxt2; | |||
} | } | ||
function updateConquest() { | |||
//************************************** | if (!pageHasElement(timeElements.conquest)) return; | ||
function stringNextConquest(remaining){ | |||
//if (nextConquest === undefined) { return "stringConquestTimer: timer undefined"; } | |||
const now = new Date(); | |||
remaining = now.getTime() + remaining; | |||
var nextConquest = new Date(remaining); | |||
var tempHour = nextConquest.getHours(); | |||
var tempMin = nextConquest.getMinutes(); | |||
var tempSec = nextConquest.getSeconds(); | |||
if (tempHour < 10) tempHour = "0" + tempHour; | |||
if (tempMin < 10) tempMin = "0" + tempMin; | |||
if (tempSec < 10) tempSec = "0" + tempSec; | |||
var strNextConquest = nextConquest.toDateString() + " " + tempHour + ":" + tempMin + ":" + tempSec; | |||
// var remaining = (temp.getTime() - now.getTime()) / (24 * 60 * 60 * 1000); | |||
// var hours = (remaining - Math.floor(remaining)) * 24; | |||
// var mins = (hours - Math.floor(hours)) * 60; | |||
// var secs = Math.floor((mins - Math.floor(mins)) * 60); | |||
// remaining = Math.floor(remaining); | |||
// hours = Math.floor(hours); | |||
// mins = Math.floor(mins); | |||
// if (hours < 10) hours = "0" + hours; | |||
// if (mins < 10) mins = "0" + mins; | |||
// if (secs < 10) secs = "0" + secs; | |||
// // tempDays < 10 ? ["0", tempDays].join(':') : tempDays; | |||
// // tempDays > 0 ? [tempDays, strTimer].join(':') : null; | |||
// strDiff = hours + ":" + mins + ":" + secs; | |||
//return strNextConquest + "(" + strDiff + ")"; | |||
return strNextConquest + "(" + vanatime.timeUntil(nextConquest) + ")"; | |||
} | |||
const now = new Date(); | |||
var remaining = vanatime.conquestRemainingTime(); | |||
remainingVanaDaysOnConquest = vanatime.conquestRemainingVanaDays(); | |||
conq = remainingVanaDaysOnConquest + ' Vana´diel Days <BR>'; | |||
conq += stringNextConquest(remaining); //+ ' (' + timer.getHours() + ":" + timer.getMinutes() + ":" + timer.getSeconds() + ')'; | |||
const conquest_time = document.getElementById(timeElements.conquest); | |||
if (conquest_time) conquest_time.innerHTML = conq; | |||
} | |||
function updateMoonPhaseSchedule(){ | |||
if (!pageHasElement(timeElements.moonSchedule)) return; | |||
populateMoonPhaseSchedule(timeElements.moonSchedule, 7); | |||
} | |||
function _moonPhaseScheduleHeader(classname){ | |||
var header = "<TABLE CLASS='" + classname + " vanatime-main-table" + "' WIDTH='500' CELLSPACING='0' CELLPADDING='0'>"; | |||
header += "<TR ><TH ALIGN='LEFT'>Moon Phase</TH>"; | |||
header += "<TH ALIGN='LEFT'>Start Time</TH>"; | |||
header += "<TH ALIGN='LEFT'>End Time</TH>"; | |||
//header += "<TH ALIGN='LEFT'>Phase Ends in...</TH>"; | |||
header += "</TR>"; | |||
return header; | |||
} | |||
function _moonPhaseScheduleBody(numberOfEntries){ | |||
var html = ""; | |||
if ( numberOfEntries === undefined || numberOfEntries === null ) numberOfEntries = 7; | |||
// DEBUGGING | |||
numberOfEntries = 7; | |||
var vTempTime = vanatime.today_inMS() / (60 * 1000); // VANA TIME IN TOTAL MINUTES | |||
var thisMoonPhase = vanatime.moonLatentPhase(vTempTime); | |||
var lunarOffset = 0, | |||
_time; | |||
for(var x = 0 ; x < numberOfEntries; x++ ){ | |||
if ( x > 0 ){ | |||
lunarOffset += 7; | |||
if ( thisMoonPhase == 1 || thisMoonPhase == 3 || thisMoonPhase == 5 || thisMoonPhase == 7) { | |||
_time = vTempTime + (60 * 24 * lunarOffset); | |||
if ( vanatime.moonLatentPhase(_time) == thisMoonPhase) lunarOffset += 7; | |||
} | |||
//console.log(thisMoonPhase); | |||
thisMoonPhase++; | |||
if (thisMoonPhase > 7) thisMoonPhase = 0; | |||
//console.log(thisMoonPhase); | |||
} | |||
var phaseStartTime; | |||
for( var i = 1 ; i >= -13 ; i-- ) { | |||
_time = vTempTime + (60 * 24 * lunarOffset) + (60 * 24 * (i - 1)); // VANA MINUTES | |||
//console.log("s", thisMoonPhase, lunarOffset, vanatime.moonLatentPhase(_time)); | |||
if ( vanatime.moonLatentPhase(_time) != thisMoonPhase ) { | |||
//console.log( "start", i, vanatime.moonLatentPhase(_time), thisMoonPhase ); | |||
break; | |||
} | |||
else phaseStartTime = _time * 60; // VANA SECONDS | |||
} | |||
var phaseEndTime; | |||
for( var i = -1 ; i <= 14 ; i++ ) { | |||
_time = vTempTime + (60 * 24 * lunarOffset) + (60 * 24 * (i + 1));// VANA MINUTES | |||
//console.log("e", thisMoonPhase,lunarOffset,vanatime.moonLatentPhase(_time)); | |||
if ( vanatime.moonLatentPhase(_time) != thisMoonPhase ) { | |||
//console.log( "end", i, vanatime.moonLatentPhase(_time), thisMoonPhase ); | |||
break; | |||
} | |||
else phaseEndTime = (_time + (60 * 24)) * 60; // VANA SECONDS | |||
// for loop breaks when _time is at 00:00 for the day the moon phase changes... | |||
// we add another day to this (60 + 24) to get the start of the next day for the table | |||
} | |||
const startDate = new Date(Math.floor(phaseStartTime / (25 / 1000)) - vanatime.getDifference() ); | |||
const endDate = new Date(Math.floor(phaseEndTime / (25 / 1000)) - vanatime.getDifference() ); | |||
var strDetails = vanatime.moonPhaseIcon(thisMoonPhase) + " " + vanatime.moonPhaseName(thisMoonPhase) + " " + vanatime.moonPhasePercentages(thisMoonPhase); | |||
function dateString(date){ | |||
var sec = date.getSeconds(), hrs = date.getHours(), mins = date.getMinutes(); | |||
sec < 10 ? sec = "0" + sec : sec; | |||
hrs < 10 ? hrs = "0" + hrs : hrs; | |||
mins < 10 ? mins = "0" + mins : mins; | |||
return vanatime.weekdayLabel(date.getDay()) + ", " + date.getDate() + " " + vanatime.monthLabel(date.getMonth()) + " " + hrs + ":" + mins + ":" + sec; | |||
} | |||
html += '<TR ><TD>' + strDetails + '</TD><TD>' + dateString(startDate) + '</TD><TD>' + dateString(endDate) + '</TD>'; | |||
// const now = new Date(); | |||
// var strTimer = vanatime.timer(endDate, now); | |||
// html += '<TD>' + strTimer + '</TD>'; | |||
html += '</TR>'; | |||
} | |||
return html; | |||
} | |||
function populateMoonPhaseSchedule(classname, numberOfEntries){ | |||
const moonSchedule = document.getElementById(classname); | |||
if (moonSchedule) { | |||
numberOfEntries = Number(moonSchedule.getAttribute('data-entries')); | |||
if (numberOfEntries === undefined || numberOfEntries === null || numberOfEntries == 0 ) numberOfEntries = 7; | |||
else numberOfEntries = numberOfEntries * 7; | |||
var _HTMLheader = this._moonPhaseScheduleHeader(classname); | |||
var _HTMLbody = this._moonPhaseScheduleBody(numberOfEntries); | |||
moonSchedule.innerHTML = _HTMLheader + _HTMLbody + "</TABLE>"; | |||
} | |||
} | |||
function updateRSE() { | |||
const rseclass = timeElements.rseSchedule; | |||
const rseSched = document.getElementById(rseclass); | |||
if (!rseSched) return; | |||
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 = vanatime.weekdayLabel(day) + ", " + vanatime.monthLabel(mm-1) + ' ' + dd + ', ' + yyyy + " " + hh + ":" + min + ":" + ss; | |||
} else if (showDay == 2) { | |||
dateString = vanatime.monthLabel(mm-1) + " " + dd + ", " + hh + ":" + min + ":" + ss; | |||
} | |||
return dateString; | |||
} | |||
var timenow = new Date(); | |||
var localtime = timenow.getTime(); | |||
// ??? | |||
var repeatCal = 8; | |||
var rowclass; | |||
var rowhighlight = true; | |||
RSECal = "<TABLE CLASS=\'" + rseclass + " vanatime-main-table" + "\' WIDTH='500' CELLSPACING='0' CELLPADDING='0'><TR><TH ALIGN='LEFT'>Date & Time</TH><TH ALIGN='LEFT'>Race</TH><TH ALIGN='LEFT'>Location</TH></TR>" | |||
var numberOfEntries = getSelectedNumberOfEntries(rseclass); | |||
if (numberOfEntries === 'undefined' || numberOfEntries === null || numberOfEntries == 0 ) numberOfEntries = 1; | |||
numberOfEntries = 1; | |||
for( let n=1; n <= numberOfEntries; n++ ){ | |||
for ( i = 0; i < repeatCal; i++) { | |||
elapsedWeeks = Math.floor( (localtime - vanatime.rseDate) / (8 * (24 * 60 * 60 * 1000 / 25)) ) + i; | |||
RSEstart = vanatime.rseDate + (elapsedWeeks * 8 * (24 * 60 * 60 * 1000 / 25)); | |||
if ( rowhighlight ) rowclass = `class="vanatime-main-table-row-highlight"`; | |||
else rowclass = ""; | |||
RSECal = RSECal + "<TR " + rowclass + "><TD>" + formatDate(RSEstart,2) + '</TD><TD>' + vanatime.rseRace(elapsedWeeks % 8) + '</TD><TD>'; | |||
//RSECal = RSECal + "<A HREF=# onmousedown='javascript:getRSEDetails(" + (elapsedWeeks % 3) + ")'>"; | |||
RSECal = RSECal + vanatime.rseLocation(elapsedWeeks % 3); | |||
RSECal = RSECal + '</A></TD></TR>'; | |||
rowhighlight = !rowhighlight; | |||
} | |||
// if (repeatCal < 1) { RSECal = ""; } | |||
// else { RSECal = RSECal + '</TABLE>'; } | |||
RSECal += '<TR class="vanatime-main-table-row-spacer"><TD></TD><TD></TD><TD></TD></TR>'; | |||
} | |||
RSECal = RSECal + '</TABLE>'; | |||
// else { | |||
// RSECal = "<TABLE CLASS='blank' CELLPADDING='0' CELLSPACING='0'><TR><TH WIDTH='120' ALIGN='LEFT'>Start</TH><TH WIDTH='120' ALIGN='LEFT'>End</TH><TH WIDTH='60' ALIGN='LEFT'>Location</TH></TR>" | |||
// offsetTime = race * 8 * msGameDay; | |||
// for ( i = 0; i < repeatCal; i++) { | |||
// elapsedWeeks = Math.floor( (localtime - vanatime.rseDate) / (64 * msGameDay) ) + i; | |||
// elapsedLocationWeeks = Math.floor( (localtime - vanatime.rseDate) / (8 * msGameDay) ) + (8 * i); | |||
// raceOffset = race - (elapsedLocationWeeks % 8); | |||
// elapsedLocationWeeks = elapsedLocationWeeks + raceOffset; | |||
// RSEstart = vanatime.rseDate + (elapsedWeeks * 64 * msGameDay) + offsetTime ; | |||
// RSEend = RSEstart + (8 * msGameDay); | |||
// RSECal = RSECal + "<TR><TD>" + formatDate(RSEstart,2) + "</TD><TD>" + formatDate(RSEend,2) + "</TD><TD>"; | |||
// //RSECal = RSECal + "<A HREF=# onmousedown='javascript:getRSEDetails(" + (elapsedLocationWeeks % 3) + ")'>"; | |||
// RSECal = RSECal + RSEloc[(elapsedLocationWeeks) % 3] | |||
// RSECal = RSECal + "</A></TD></TR>"; | |||
// } | |||
// if (repeatCal < 1) { RSECal = ""; } else { RSECal = RSECal + '</TABLE>'; } | |||
// } | |||
const classname_details = rseclass + "-details"; | |||
let t = document.getElementsByClassName(classname_details)[0]; | |||
var _HTMLdetails = ''; | |||
//console.log(t); | |||
if ( t === 'undefined' || t === null || !t ){ | |||
var temp = expandTableSelection(rseclass); | |||
if ( !temp ) temp = ""; | |||
const div = '<div class="vanatime-main-table">' + temp ; | |||
_HTMLdetails = `<span class="${classname_details}">${RSECal}</span>`; | |||
rseSched.innerHTML = div + _HTMLdetails + '</div>'; | |||
} | |||
else { | |||
//console.log(t); | |||
t.innerHTML = RSECal; | |||
} | |||
//document.getElementById(rseclass).innerHTML = RSECal; | |||
} | |||
function expandTableSelection(classname){ | |||
const classnameheader = classname + "-header"; | |||
const classnameshowSelect = classname + "-showSelect"; | |||
if ( classname == timeElements.rseSchedule ) { | |||
return ` | |||
<div class="${classnameheader}" style="background:#FFFFFF00; width: max-content; float: right;">Shown: | |||
<select id="${classnameshowSelect}" style="background:#DFDFDF50; "> | |||
<option value="0">All </option> | |||
<option value="1">M. Hume</option> | |||
<option value="2">F. Hume</option> | |||
<option value="3">M. Elvaan</option> | |||
<option value="4">F. Elvaan</option> | |||
<option value="5">M. TaruTaru</option> | |||
<option value="6">F. TaruTaru</option> | |||
<option value="7">Mithra</option> | |||
<option value="8">Galka</option> | |||
</select> | |||
</div> | |||
`; | |||
} | |||
return ` | |||
<div class="${classnameheader}" style="background:#FFFFFF00; width: max-content; float: right;">Shown: | |||
<select id="${classnameshowSelect}" style="background:#DFDFDF50; "> | |||
<option value="0">1 </option> | |||
<option value="1">3</option> | |||
<option value="2">5</option> | |||
<option value="3">10</option> | |||
</select> | |||
</div> | |||
`; | |||
} | |||
function expandRaceTable(classname){ | |||
const classnameheader = classname + "-header"; | |||
const classnameshowSelect = classname + "-showSelect"; | |||
const temp = ` | |||
<div class="${classnameheader}" style="background:#FFFFFF00; width: max-content; float: right;">Shown: | |||
<select id="${classnameshowSelect}" style="background:#DFDFDF50; "> | |||
<option value="0">1 </option> | |||
<option value="1">3</option> | |||
<option value="2">5</option> | |||
<option value="3">10</option> | |||
</select> | |||
</div> | |||
`; | |||
// return popupButton; | |||
return temp; | |||
} | |||
function getSelectedNumberOfEntries(classname){ | |||
// Number of entries comes from selection dropdown | |||
var e = document.getElementById(classname + "-showSelect"); | |||
if ( !e ) return 1; | |||
var entries; | |||
switch(e.value) { | |||
case "1": | |||
entries = 3; | |||
break; | |||
case "2": | |||
entries = 5; | |||
break; | |||
case "3": | |||
entries = 10; | |||
break; | |||
default: | |||
entries = 1; | |||
} | |||
//console.log(classname + ":" + entries); | |||
return entries; | |||
} | |||
function gametick(){ | |||
updateSidebar(); | |||
updateAirshipSchedule(); | |||
updateBoatSchedule(); | |||
updateGuilds(); | |||
updateConquest(); | |||
updateMoonPhaseSchedule(); | |||
updateRSE(); | |||
setTimeout("gametick()", 1000); | |||
//console.log('gametick'); | |||
} | |||
gametick(); | |||
async function fetchWithTimeout(resource, options = {}) { | |||
const { timeout = 10000 } = options; | |||
const controller = new AbortController(); | |||
const id = setTimeout(() => controller.abort(), timeout); | |||
const response = await fetch(resource, { | |||
...options, | |||
signal: controller.signal | |||
}); | |||
clearTimeout(id); | |||
return response; | |||
} | |||
async function populationFetch(){ | |||
try { | |||
const response = await fetchWithTimeout('https://api.horizonxi.com/api/v1/misc/exp-sync-status', {}); | |||
const fetchedPopulation = await response.json(); | |||
//if ( typeof(fetchedPopulation) == 'number' ) currentPopulation = fetchedPopulation; | |||
//console.log(fetchedPopulation); | |||
//return games; | |||
//console.log('populationFetchTick', fetchedPopulation); | |||
//populationFetch(); | |||
currentPopulation = fetchedPopulation; | |||
setTimeout("startPopulationFetch()", 300000); | |||
} catch (error) { | |||
//fetched = 0; | |||
console.log('populationFetch(): ', error); | |||
startPopulationFetch(); | |||
} | |||
//console.log('currentPopulation = ', currentPopulation); | |||
//return fetched; | |||
} | |||
function startPopulationFetch(){ | |||
//console.log('startPopulationFetch'); | |||
populationFetch(); | |||
// if ( currentPopulation == 0) startPopulationFetch(); | |||
// else setTimeout("startPopulationFetch()", 7000); | |||
} | |||
startPopulationFetch(); | |||
Latest revision as of 10:25, 18 July 2025
/*********************************************************************
Javascript below contributes to Vana'diel Time displays throughout
the HorizonXI Wiki
Credits: ********
https://www.pyogenes.com/ffxi/timer/v2.html
https://www.mithrapride.org/vana_time/index.html
https://www.rubydoc.info/gems/vanadiel-time/Vanadiel/Time
**********************************************************************/
class timeElements {
// List of all class names for each element in this model, for styling
static sidebar = "n-vanatime";
static conquest = "vanatime-page-conquest-schedule"; // <span ... />
//static moonPhase = "vanatime-pasidebarge-moon-phase"; // not implemented
static moonSchedule = "vanatime-page-moon-schedule-table";
static rseSchedule = "vanatime-page-rse-schedule-table";
static airships = {
//all : "vanatime-airship-schedule-table", // not implemented
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",
};
static boats = {
selbina : "vanatime-boat-schedule-selbina-table",
mhaura : "vanatime-boat-schedule-mhaura-table",
bibiki : "vanatime-boat-schedule-bibiki-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"
};
static guilds = {
alchemy : "vanatime-guild-schedule-alchemy",
alchemy_status: "vanatime-guild-schedule-alchemy-status",
alchemy_holiday: "vanatime-guild-schedule-alchemy-holiday",
alchemy_timer: "vanatime-guild-schedule-alchemy-timer",
smithing : "vanatime-guild-schedule-smithing",
smithing_status: "vanatime-guild-schedule-smithing-status",
smithing_holiday: "vanatime-guild-schedule-smithing-holiday",
smithing_timer: "vanatime-guild-schedule-smithing-timer",
bonecrafting : "vanatime-guild-schedule-bonecrafting",
bonecrafting_status: "vanatime-guild-schedule-bonecrafting-status",
bonecrafting_holiday: "vanatime-guild-schedule-bonecrafting-holiday",
bonecrafting_timer: "vanatime-guild-schedule-bonecrafting-timer",
goldsmithing : "vanatime-guild-schedule-goldsmithing",
goldsmithing_status: "vanatime-guild-schedule-goldsmithing-status",
goldsmithing_holiday: "vanatime-guild-schedule-goldsmithing-holiday",
goldsmithing_timer: "vanatime-guild-schedule-goldsmithing-timer",
clothcrafting : "vanatime-guild-schedule-clothcrafting",
clothcrafting_status: "vanatime-guild-schedule-clothcrafting-status",
clothcrafting_holiday: "vanatime-guild-schedule-clothcrafting-holiday",
clothcrafting_timer: "vanatime-guild-schedule-clothcrafting-timer",
woodworking : "vanatime-guild-schedule-woodworking",
woodworking_status: "vanatime-guild-schedule-woodworking-status",
woodworking_holiday: "vanatime-guild-schedule-woodworking-holiday",
woodworking_timer: "vanatime-guild-schedule-woodworking-timer",
leathercrafting : "vanatime-guild-schedule-leathercrafting",
leathercrafting_status: "vanatime-guild-schedule-leathercrafting-status",
leathercrafting_holiday: "vanatime-guild-schedule-leathercrafting-holiday",
leathercrafting_timer: "vanatime-guild-schedule-leathercrafting-timer",
fishing : "vanatime-guild-schedule-fishing",
fishing_status: "vanatime-guild-schedule-fishing-status",
fishing_holiday: "vanatime-guild-schedule-fishing-holiday",
fishing_timer: "vanatime-guild-schedule-fishing-timer",
cooking : "vanatime-guild-schedule-cooking",
cooking_status: "vanatime-guild-schedule-cooking-status",
cooking_holiday: "vanatime-guild-schedule-cooking-holiday",
cooking_timer: "vanatime-guild-schedule-cooking-timer",
all : "vanatime-guild-schedule-all"
};
}
class schedule {
// All raw datea is from ASB
// route definintion = [ 'Name of route', anim_arrive, anim_depart, timeOffset, time_interval, time_anim_arrive, time_waiting, time_anim_depart]
// Actual arrival time (when the player can enter the transport ) = time_offset + time_anim_arrive = [3] + [5]
// Departure time = arrival time + time_waiting = arrival_time + [6]
// All values listed are in VanaTime minutes, so 1440 is the total minutes in a game hour
static #airship_jeuno_sandy = ['Jeuno -> Sandoria', 0, 360, 12, 60, 12];
static #airship_jeuno_windy = ['Jeuno -> Windurst', 90, 360, 12, 60, 12];
static #airship_jeuno_bastok = ['Jeuno -> Bastok', 180, 360, 12, 60, 16];
static #airship_jeuno_kazham = ['Jeuno -> Kazham', 270, 360, 20, 50, 20];
static #airship_bastok_jeuno = ['Bastok -> Jeuno', 0, 360, 14, 60, 16];
static #airship_sandy_jeuno = ['Sandoria -> Jeuno', 180, 360, 12, 60, 16];
static #airship_windy_jeuno = ['Windurst -> Jeuno', 270, 360, 18, 60, 14];
static #airship_kazham_jeuno = ['Kazham -> Jeuno', 90, 360, 20, 50, 20];
static airships = {
jeuno : [
this.#airship_jeuno_bastok,
this.#airship_jeuno_sandy,
this.#airship_jeuno_windy,
this.#airship_jeuno_kazham,
this.#airship_bastok_jeuno,
this.#airship_sandy_jeuno,
this.#airship_windy_jeuno,
this.#airship_kazham_jeuno
],
bastok : [ this.#airship_bastok_jeuno, this.#airship_jeuno_bastok],
sandy : [this.#airship_sandy_jeuno, this.#airship_jeuno_sandy],
windy : [this.#airship_windy_jeuno, this.#airship_jeuno_windy],
kazham : [this.#airship_kazham_jeuno, this.#airship_jeuno_kazham]
}
static #boat_selbina_mhaura = ['Selbina -> Mhaura', 382, 480, 18, 80, 17];
static #boat_mhaura_selbina = ['Mhaura -> Selbina', 382, 480, 18, 80, 17];
static #boat_mhaura_whitegate = ['Mhaura -> Whitegate', 142, 480, 18, 80, 17];
static #boat_whitegate_mhaura = ['Whitegate -> Mhaura', 142, 480, 18, 80, 16];
static #boat_whitegate_nashmau = ['Whitegate -> Nashmau', 282, 480, 18, 180, 17];
static #boat_nashmau_whitegate = ['Nashmau -> Whitegate', 282, 480, 18, 180, 17];
static #boat_bibiki_tours = ['Bibiki Bay -> Tours', 710, 720, 20, 40, 20];
static #boat_bibiki_purgo = ['Bibiki Bay -> Purgonorgo Isle', 270, 720, 20, 40, 20];
static #boat_purgo_bibiki = ['Purgonorgo Isle -> Bibiki Bay', 500, 720, 20, 40, 20];
static #boat_barge_south_central_emfa = ['South Landing -> Central Landing EMFEA', 5, 1440, 15, 35, 15];
static #boat_barge_central_south_newtpool1 = ['Central Landing -> South Landing NewtPool', 267, 1440, 12, 30, 15];
static #boat_barge_south_oos = ['South Landing -> OOS', 1402, 1440, 33, 0, 0];
static #boat_barge_south_north = ['South Landing -> North Landing', 560, 1440, 15, 35, 15];
static #boat_barge_north_oos = ['North Landing -> OOS', 925, 1440, 40, 0, 0];
static #boat_barge_north_central = ['North Landing -> Central Landing', 993, 1440, 12, 40, 15];
static #boat_barge_central_south_newtpool2 = ['Central Landing -> South Landing NewtPool 2', 1148, 1440, 12, 30, 15];
static #boat_barge_south_oos1 = ['South Landing -> OOS 2', 512, 1440, 33, 0, 0];
static boats = {
selbina : [ this.#boat_selbina_mhaura ],
mhaura : [ this.#boat_mhaura_selbina, this.#boat_mhaura_whitegate ],
whitegate : [ this.#boat_whitegate_mhaura, this.#boat_whitegate_nashmau],
nashmau : [ this.#boat_nashmau_whitegate ],
bibiki : [ this.#boat_bibiki_tours, this.#boat_bibiki_purgo],
purgonorgoIsle : [ this.#boat_purgo_bibiki ],
northLanding : [ this.#boat_barge_north_oos, this.#boat_barge_north_central ],
centralLanding : [ this.#boat_barge_central_south_newtpool1, this.#boat_barge_central_south_newtpool2 ],
southLanding : [ this.#boat_barge_south_central_emfa, this.#boat_barge_south_oos, this.#boat_barge_south_north, this.#boat_barge_south_oos1 ]
}
static #alchemy = [480, 1380, 5];
static #smithing = [480, 1380, 2];
static #bonecrafting = [480, 1380, 3];
static #goldsmithing = [480, 1380, 4];
static #clothcrafting = [360, 1260, 0];
static #woodworking = [360, 1260, 0];
static #leathercrafting = [180, 1080, 4];
static #fishing = [180, 1080, 5];
static #cooking = [300, 1200, 7];
static guilds = {
// [ Open, Close, Holiday]
alchemy : this.#alchemy,
smithing : this.#smithing,
bonecrafting : this.#bonecrafting,
goldsmithing : this.#goldsmithing,
clothcrafting : this.#clothcrafting,
woodworking : this.#woodworking,
leathercrafting : this.#leathercrafting,
fishing : this.#fishing,
cooking : this.#cooking,
all : [ this.#alchemy, this.#smithing, this.#bonecrafting,this.#goldsmithing, this.#clothcrafting,this.#woodworking,this.#leathercrafting, this.#fishing, this.#cooking ]
}
}
class VanaTime{
#elementalDay = ["Firesday", "Earthsday", "Watersday", "Windsday", "Iceday", "Lightningday", "Lightsday", "Darksday"];
#dayColor = ["#FF0000", "#AAAA00", "#0000DD", "#00AA22", "#7799FF", "#AA00AA", "#AAAAAA", "#333333"];
#moonPhaseName = ["New Moon", "Waxing Crescent", "First Quarter", "Waxing Gibbous", "Full Moon", "Waning Gibbous", "Last Quarter", "Waning Crescent"];
#moonIcon = ['\u{1F311}', '\u{1F312}', '\u{1F313}', '\u{1F314}', '\u{1F315}', '\u{1F316}', '\u{1F317}', '\u{1F318}'];
#moonPercentages = ["(10%-0%-5%)", "(7%-38%)", "(40%-55%)", "(57%-88%)", "(90%-100%-95%)", "(93%-62%)", "(60%-45%)", "(43%-12%)"];
#month = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
#weekday = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
#rseRace = ["M. Hume","F. Hume","M. Elvaan","F. Elvaan","M. TaruTaru","F. TaruTaru","Mithra","Galka"];
#rseLocation = ["Gusgen Mines","Shakrami Maze","Ordelle Caves"];
// Conversions in Milliseconds
//#baseDate; // built at runtime: 1024844400000
#moonDate = 1074997872000; // in milliseconds
#VTIME_BIRTH = 1024844400000; // vana birthday - in milliseconds
#VTIME_BASEDATE = 1009810800; // unix epoch - 1009810800 = se epoch (in earth seconds)
rseDate = 1075281264000;
#ONE_SECOND = 1000000;
#ONE_MINUTE;
#ONE_HOUR;
#ONE_DAY;
// #ONE_WEEK;
// #ONE_MONTH;
// #ONE_YEAR;
// Conversions in Minutes
#VTIME_YEAR = 518400; // 360 * GameDay
#VTIME_MONTH = 43200; // 30 * GameDay
#VTIME_WEEK = 11520; // 8 * GameDay
#VTIME_DAY = 1440; // 24 hours * GameHour
#VTIME_HOUR = 60; // 60 minutes
#VMULTIPLIER = 25;
#MOON_CYCLE_DAYS = 84;
// #MOON_CYCLE_PHASE = 17280; // 1 moon phase cycle = 12 vana days = 12 * Gameday
/*
Some of the math...
(((898 * 360) + 30) * 24 * 60 * 60) / (this.#VMULTIPLIER / 1000).....
converts vana time to earth time by ( / 25 ) then getting to milliseconds ( * 1000 )
*/
#vanaBirthday = (((898 * 360) + 30) * 24 * 60 * 60) / (25 / 1000); // 1117359360000 - in earth time milliseconds
#difference = this.#vanaBirthday - this.#VTIME_BIRTH; // 92514960000 - earth time milliseconds
getDifference(){ return this.#difference };
/**
* Common variables for quick reference to current Vana time
* @returns - integer / number
*/
// vana_currentTime_inEarthMS = ((898 * 360 + 30) * (24 * 60 * 60 * 1000)) + (this.earthDate.getTime() - this.#VTIME_BIRTH) * this.#VMULTIPLIER; // vana time, represented in earth milliseconds - used for making Date() objects
// vana_currentTime = this.vana_currentTime_inEarthMS / (60 * 1000); // vana time in minutes
// //vana_currentTime = ( ((this.earthDate.getTime() / 1000) - this.#VTIME_BASEDATE ) / 60.0 * this.#VMULTIPLIER) + (886 * this.#VTIME_YEAR); //returned in vana minutes
// vana_year = this.vana_currentTime / this.#VTIME_YEAR;
// vana_month = (this.vana_currentTime / this.#VTIME_MONTH) % 12 + 1;
// vana_date = (this.vana_currentTime / this.#VTIME_DAY) % 30 + 1;
// vana_weekday = Math.floor((this.vana_currentTime % this.#VTIME_WEEK) / this.#VTIME_DAY);
// vana_hour = (this.vana_currentTime % this.#VTIME_DAY) / this.#VTIME_HOUR;
// vana_mins = this.vana_currentTime % this.#VTIME_HOUR;
// vana_moonphase = Math.floor((this.vana_currentTime % this.#MOON_CYCLE_PHASE) / this.#VTIME_DAY);
/**
* Helper functions for quick reference to any Vana time
* @returns - integer / number
*/
now_inEarthMS(){
var now = new Date();
return ((898 * 360 + 30) * (24 * 60 * 60 * 1000)) + (now.getTime() - this.#VTIME_BIRTH) * this.#VMULTIPLIER;
}
now(){ return this.now_inEarthMS() / ( 60 * 1000); }
now_inMS(){
var timenow = new Date();
return ((timenow.getTime() - this.#VTIME_BIRTH) % (24 * 60 * 60 * 1000 / 25));
}
now_inMINS(){
return this.now_inMS / ( 1000 * 60 );
}
today_inMS(){ // result in earth Milliseconds
var now = this.now_inEarthMS();
return ( now - ( now % (24 * 60 * 60 * 1000) ));
}
year(vanatime) {
if (vanatime === undefined || vanatime == null) vanatime = this.now();
return Math.floor(vanatime / this.#VTIME_YEAR);
}
month(vanatime){
if (vanatime === undefined || vanatime == null) vanatime = this.now();
return Math.floor((vanatime / this.#VTIME_MONTH) % 12) + 1;
}
date(vanatime){
if (vanatime === undefined || vanatime == null) vanatime = this.now();
return Math.floor((vanatime / this.#VTIME_DAY) % 30) + 1;
}
weekDay(vanatime){
if (vanatime === undefined || vanatime == null) vanatime = this.now();
return Math.floor((vanatime % this.#VTIME_WEEK) / this.#VTIME_DAY);
}
hour(vanatime){
if (vanatime === undefined || vanatime == null) vanatime = this.now();
return Math.floor((vanatime % this.#VTIME_DAY) / this.#VTIME_HOUR);
}
mins(vanatime){
if (vanatime === undefined || vanatime == null) vanatime = this.now();
return Math.floor(vanatime % this.#VTIME_HOUR);
}
dayColor(vanatime){
if (vanatime === undefined || vanatime == null) vanatime = this.now();
return this.#dayColor[this.weekDay()];
}
dayLabel(day){
if (day === undefined || day == null) return this.#elementalDay[this.weekDay()];
else return this.#elementalDay[day]
}
moonPhaseIcon(day){
if (day === undefined || day == null) return this.#moonIcon[this.moonLatentPhase()];
else return this.#moonIcon[day];
}
moonPhaseName(day){
if (day === undefined || day == null) return this.#moonPhaseName[this.moonLatentPhase()];
else return this.#moonPhaseName[day];
}
moonPhasePercentages(day){
if (day === undefined || day == null) return this.#moonPercentages[this.moonLatentPhase()];
else return this.#moonPercentages[day];
}
/**
* Time Helper functions - supports string generation for month/week details
* @param (required) - represents which RACE
* @returns - string - from #rseRace or #rseLocation
*/
monthLabel(m){ return this.#month[m]; }
weekdayLabel(w){ return this.#weekday[w]; }
/**
* RSE Helper functions - supports string generation for RSE details
* @param r (required) - represents which RACE
* @returns - string - from #rseRace or #rseLocation
*/
rseRace(r){ return this.#rseRace[r]; }
/**
* RSE Helper functions - supports string generation for RSE details
* @param r (required) - represents which RACE
* @returns - string - from #rseRace or #rseLocation
*/
rseLocation(r){ return this.#rseLocation[r]; }
constructor(){
this.#ONE_MINUTE = 60 * this.#ONE_SECOND;
this.#ONE_HOUR = 60 * this.#ONE_MINUTE;
this.#ONE_DAY = 24 * this.#ONE_HOUR;
// this.#ONE_WEEK = 8 * this.#ONE_DAY;
// this.#ONE_MONTH = 30 * this.#ONE_DAY;
// this.#ONE_YEAR = 360 * this.#ONE_DAY;
// this.#MOON_CYCLE_PHASE = 12 * this.#VTIME_WEEK;
}
/******************************** MOON PHASES **********************************
0% NM 7% WXC 40% FQM 57% WXG 90% FM 93% WNG 60% LQM 43% WNC 10% NM
2% NM 10% WXC 43% FQM 60% WXG 93% FM 90% WNG 57% LQM 40% WNC 7% NM
5% NM 12% WXC 45% FQM 62% WXG 95% FM 88% WNG 55% LQM 38% WNC 5% NM
14% WXC 48% FQM 64% WXG 98% FM 86% WNG 52% LQM 36% WNC 2% NM
17% WXC 50% FQM 67% WXG 100% FM 83% WNG 50% LQM 33% WNC
19% WXC 52% FQM 69% WXG 98% FM 81% WNG 48% LQM 31% WNC
21% WXC 55% FQM 71% WXG 95% FM 79% WNG 45% LQM 29% WNC
24% WXC 74% WXG 76% WNG 26% WNC
26% WXC 76% WXG 74% WNG 24% WNC
29% WXC 79% WXG 71% WNG 21% WNC
31% WXC 81% WXG 69% WNG 19% WNC
33% WXC 83% WXG 67% WNG 17% WNC
36% WXC 86% WXG 64% WNG 14% WNC
38% WXC 88% WXG 62% WNG 12% WNC
********************************************************************************/
/**
* Private function - supports moon phase calculations
* @param vanatime (required) - Vanadiel time, in MILLISECONDS
* @returns - integer - represents the day in the 84 day moon phase cycle
*/
#moonDays(vanatime){
if (vanatime === undefined || vanatime == null) vanatime = this.now();
return ((( vanatime / this.#VTIME_DAY ) + 26) % this.#MOON_CYCLE_DAYS);
}
/**
* Private function for doing arithmetic for moon phase percentage
* @param vanatime (required) - Vanadiel time, in MILLISECONDS
* @returns - integer representing moon phase percentage
*/
#moonPercent(vanatime){
if (vanatime === undefined || vanatime == null) vanatime = this.now();
return Math.abs( -Math.round((42 - Math.floor(this.#moonDays(vanatime))) / 42 * 100) );
}
/**
* Helper function for getting moon phase percentage
* @param vanatime (required) - Vanadiel time, in MILLISECONDS
* @returns - integer representing moon phase percentage
*/
getMoonPercent(vanatime) { return this.#moonPercent(vanatime)};
/**
* @param vanatime - Vanadiel time, in MILLISECONDS; default value is now()
* @returns - integer representing waxing/waning/neither
*/
#moonDirection(vanatime){
if (vanatime === undefined || vanatime == null) vanatime = this.now();
var moondays = Math.floor(this.#moonDays(vanatime));
//console.log(daysmod);
if (moondays == 42 || moondays == 0) { return 0; }// neither waxing nor waning
else if (moondays < 42){ return 1; } // waning
else{ return 2; } // waxing
}
/**
* @param vanatime - Vanadiel time, in MILLISECONDS; default value is now()
* @returns - total milliseconds remaining until next conquest update
*/
moonLatentPhase(vanatime){
if (vanatime === undefined || vanatime == null) vanatime = this.now();
var moonPhase = this.#moonPercent(vanatime);
var moonDirection = this.#moonDirection(vanatime);
//console.log("*mP", moonPhase);
//console.log("*mD", moonDirection);
if (moonPhase <= 5 || (moonPhase <= 10 && moonDirection == 1)) {return 0;} // New Moon - 10% waning -> 5% waxing
else if (moonPhase >= 7 && moonPhase <= 38 && moonDirection == 2) {return 1;} // Waxing Crescent - 7% -> 38% waxing
else if (moonPhase >= 40 && moonPhase <= 55 && moonDirection == 2){return 2;} // First Quarter - 40%% -> 55% waxing
else if (moonPhase >= 57 && moonPhase <= 88 && moonDirection == 2){return 3;} // Waxing Gibbous - 57% -> 88%
else if (moonPhase >= 95 || (moonPhase >= 90 && moonDirection == 2)){return 4;} // Full Moon - waxing 90% -> waning 95%
else if (moonPhase >= 62 && moonPhase <= 93 && moonDirection == 1){return 5;} // Waning Gibbous - 93% -> 62%
else if (moonPhase >= 45 && moonPhase <= 60 && moonDirection == 1){return 6;} // Last Quarter - 60% -> 45%
else{return 7;} // Waning Crescent - 43% -> 12%
}
/**
* @returns - total milliseconds remaining until next conquest update
*/
conquestRemainingTime(){
var now = new Date();
//console.log(this.earthDate.getTime(), this.#VTIME_BIRTH);
return (7 * (24 * 60 * 60 * 1000)) - ((now.getTime() - this.#VTIME_BIRTH) % (7 * (24 * 60 * 60 * 1000)));
}
/**
* @returns - integer - total Vanadiel days remaining on current conquest
*/
conquestRemainingVanaDays(){
return Math.ceil(this.conquestRemainingTime() / (24 * 60 * 60 * 1000 / 25));
}
/**
* @param time - Vanadiel time, in MILLISECONDS, needing to be converted
* @returns {Date} - value as Date() object
*/
earthTime(time){
if (time === undefined) time = this.now_inEarthMS();
//else time = time * 60 * 1000;
var earthTime = time / ( this.#VMULTIPLIER );
return new Date(Math.floor(earthTime) - (this.#vanaBirthday - this.#VTIME_BIRTH));
}
/**
* @param time - Vanadiel time, in minutes, needing to be converted
* @returns - string, formatted 00:00
*/
stringVanaTime(time){
if (time === undefined || time === null) time = this.now();
//console.log(time);
var vYear = this.year(time);
var vMon = this.month(time)
var vDate = this.date(time);
var vHour = this.hour(time);
var vMin = this.mins(time);
// var vSec = time.getSeconds();
// var vDay = time.getDay();
//seconds left our because we don't use them for any calcs
if (vYear < 1000) vYear = "0" + vYear;
if (vMon < 10) vMon = "0" + vMon;
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 time - Vanadiel time, in milliseconds, needing to be converted
* @returns - string, formatted 00:00:00
*/
stringEarthTime(time) {
var eTime = this.earthTime(time);
// const monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
//Most of these arent needed, left in for future inclusion if needed/wanted
// var eYear = eTime.getFullYear();
// var eMon = monthNames[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 str = eMon + " " + eDate + "," + eHour + ":" + eMin + ":" + eSec;
var str = eHour + ":" + eMin + ":" + eSec;
return str;
}
/**
* @param nextTime - Vana time, in MINUTES, needing to be converted
* @returns - string of HOURS:MINS
*/
timeUntil(nextTime){
if (nextTime === undefined) { return "00:00:00"; }
else if ( !(nextTime instanceof Date) ) {
//console.log('!instance of Date');
var e = this.earthTime(nextTime);
} //earth time for next departure
else e = nextTime;
//console.log( e.getTime() );
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 days = (e.getTime() - now.getTime()) / (24 * 60 * 60 * 1000);
var hours = (days - Math.floor(days)) * 24;
var minutes = (hours - Math.floor(hours)) * 60;
var seconds = Math.floor((minutes - Math.floor(minutes)) * 60);
days = Math.floor(days);
hours = Math.floor(hours);
minutes = Math.floor(minutes);
if (hours < 10) hours = "0" + hours;
if (minutes < 10) minutes = "0" + minutes;
if (seconds < 10) seconds = "0" + seconds;
var str = minutes + ":" + seconds;
if ( days > 0 ) { str = [days, hours, str].join(':'); }
else if ( hours > 0 || typeof(hours) == 'string') { str = [hours, str].join(':'); }
return str;
}
timer(time1, time2){
var seconds = Math.floor((time1.getTime() - time2.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);
seconds < 10 ? seconds = "0" + seconds : seconds;
minutes < 10 ? minutes = "0" + minutes : minutes;
hours < 10 ? hours = "0" + hours : hours;
var str = hours + ":" + minutes + ":" + seconds;
if ( days != 0) str = [days, str].join(':');
return str;
}
}
const vanatime = new VanaTime();
let currentPopulation = 0;
////////////////////////////////////////////////////
function pageHasElement(element){
function test(v){
var i = document.getElementById(v);
var c = document.getElementsByClassName(v);
if ( i ) { return true; }
if ( c[0] ) { return true; }
}
if (typeof(element) == 'string') return test(element);
else {
for (const [k,v] of Object.entries(element) ){
if (test(v) == true) return true;
}
}
return false;
}
function updateSidebar() {
if (!pageHasElement(timeElements.sidebar)) return;
var hour = vanatime.hour();
hour < 10 ? hour = ["0", hour].join('') : hour;
var mins = vanatime.mins();
mins < 10 ? mins = ["0", mins].join('') : mins;
var sidebarTime = "<div><li><b>" + hour + ":" + mins + "</b> ~ " + vanatime.year() + "-" + vanatime.month() + "-" + vanatime.date() + "</li>";
sidebarTime += "<li><span style=\"font-weight: bold; font-size:14px; color:" + vanatime.dayColor() + "\" >" + vanatime.dayLabel() + "</span><span style=\"font-size:14px;\"> ~ " + vanatime.moonPhaseIcon() + vanatime.getMoonPercent() + "%</span></li>";
//sidebarTime += "<li>\u{1F7E2} Online ";
if ( currentPopulation != 0 ) sidebarTime += "<li><span style=\"font-size:9px;\">\u{1F7E2}</span> Online <b>" + currentPopulation + "</b></li>";
else sidebarTime += "<li><span style=\"font-size:9px;\">\u{1F534}</span> Online <i>~Standby~</i></li>";
let penaltyPerLvl = "1.5%";
if ( currentPopulation >= 2001 ) penaltyPerLvl = "2.5%";
else if ( currentPopulation >= 1001 ) penaltyPerLvl = "2%";
sidebarTime += "<li><a href=\"https://horizonffxi.wiki/Level_Sync#Horizon_Changes\"><span style=\"font-size:12px;\"><i>+10 Exp Penalty: <b>" + penaltyPerLvl + "</b>/lvl</i></span></a></li>";
sidebarTime += "</div>";
const sidebar_vanatime = document.getElementById(timeElements.sidebar);
if (sidebar_vanatime) sidebar_vanatime.innerHTML = sidebarTime;
//for (let i = 0; i < page_vanatime.length; i = i+1) { page_vanatime[i].innerHTML = sidebarTime; }
}
function updateBoatSchedule() {
if (!pageHasElement(timeElements.boats)) return;
populateTransportSchedule(timeElements.boats.selbina, schedule.boats.selbina, 3);
populateTransportSchedule(timeElements.boats.mhaura, schedule.boats.mhaura, 3);
populateTransportSchedule(timeElements.boats.whitegate, schedule.boats.whitegate, 1);
populateTransportSchedule(timeElements.boats.nashmau, schedule.boats.nashmau, 1);
populateTransportSchedule(timeElements.boats.bibiki, schedule.boats.bibiki, 1);
populateTransportSchedule(timeElements.boats.purgonorgoIsle, schedule.boats.purgonorgoIsle, 1);
populateTransportSchedule(timeElements.boats.northLanding, schedule.boats.northLanding, 1);
populateTransportSchedule(timeElements.boats.centralLanding, schedule.boats.centralLanding, 1);
populateTransportSchedule(timeElements.boats.southLanding, schedule.boats.southLanding, 1);
}
function updateAirshipSchedule(){
if (!pageHasElement(timeElements.airships)) return;
populateTransportSchedule(timeElements.airships.jeuno, schedule.airships.jeuno, 1);
populateTransportSchedule(timeElements.airships.bastok, schedule.airships.bastok, 1);
populateTransportSchedule(timeElements.airships.sandy, schedule.airships.sandy, 1);
populateTransportSchedule(timeElements.airships.windy, schedule.airships.windy, 1);
populateTransportSchedule(timeElements.airships.kazham, schedule.airships.kazham, 1);
}
function _transportScheduleHeader(classname){
var header = "<TABLE CLASS='" + classname + " vanatime-main-table" + "' CELLSPACING='0' CELLPADDING='0'>";
header += "<TR><TH ALIGN='LEFT'>Destination</TH>";
//header += "<TH ALIGN='LEFT'>Departure Day</TH>";
header += "<TH ALIGN='LEFT'>VanaTime</TH>";
header += "<TH ALIGN='LEFT'>Earth Time</TH>";
header += "<TH ALIGN='LEFT'>Departs</TH></TR>";
return header;
}
function _transportScheduleBody(schedule, entriesPerSchedule, numberOfEntries){
function _helper(sched, n){
var helperoffset = (sched[1] + sched[3] + sched[4]) * 60 * 1000 / 25; // VANA MILLISECONDS
//console.log("helperoffset: ", helperoffset, vanatime.now_inMS());
while (helperoffset < vanatime.now_inMS() ) {
helperoffset += (sched[2] * n * 60 * 1000 / 25);
}
return helperoffset; // VANA MILLISECONDS
}
var html = "";
var offset = {};
var rowhighlight = true;
for( let n=1; n <= numberOfEntries; n++ ){
html += '<TR class="vanatime-main-table-row-spacer"><TD></TD><TD></TD><TD></TD><TD></TD></TR>';
for( let x=0; x < schedule.length; x++ ){
const offsetVariable = x + (schedule.length * (n-1));
for( let i=1 ; i <= entriesPerSchedule; i++ ){
//console.log(n,x,i, offsetVariable);
if ( i > 1 ) offset[offsetVariable] += (schedule[x][2] * 60 * 1000 / 25);
//else if ( lastOffset ) offset = lastOffset;
else offset[offsetVariable] = _helper(schedule[x], n);
// offset must be greater than the offset before it
if ( offsetVariable >= schedule.length && offset[offsetVariable] <= offset[offsetVariable - schedule.length] )
{
console.log( "fired " + offsetVariable );
offset[offsetVariable] = offset[offsetVariable - schedule.length] + (schedule[x][2] * 60 * 1000 / 25);
}
var earthdepTime = (vanatime.today_inMS() + (offset[offsetVariable] * 25));
var vanadepTime = earthdepTime / ( 60 * 1000);
//var arrTime = depTime - ( sched[2][4] * 60 * 1000); /// LEAVE THIS in the event someone wants to add ARRIVAL TIMES to future HTML tables
//html += '<TR><TD>x= ' + x + '</TD><TD>' + vanatime.stringVanaTime(vanadepTime) + '</TD><TD>' + vanatime.stringEarthTime(earthdepTime) + '</TD><TD>' + vanatime.timeUntil(earthdepTime) +'</TD></TR>';
var rowclass = "";
if ( rowhighlight ) rowclass = `class="vanatime-main-table-row-highlight"`;
html += '<TR ' + rowclass + '><TD>' + schedule[x][0] + '</TD><TD>' + vanatime.stringVanaTime(vanadepTime) + '</TD><TD>' + vanatime.stringEarthTime(earthdepTime) + '</TD><TD>' + vanatime.timeUntil(earthdepTime) +'</TD></TR>';
rowhighlight = !rowhighlight;
}
}
}
return html;
}
function populateTransportSchedule(classname, schedule, entriesPerSchedule){
const shipSched = document.getElementById(classname);
if (shipSched) {
var numberOfEntries = getSelectedNumberOfEntries(classname);
if (numberOfEntries === 'undefined' || numberOfEntries === null || numberOfEntries == 0 ) numberOfEntries = 1;
var _HTMLheader = _transportScheduleHeader(classname);
var _HTMLbody = this._transportScheduleBody(schedule, entriesPerSchedule, numberOfEntries);
var updatedSched = _HTMLheader + _HTMLbody + "</TABLE>";
const classname_details = classname + "-details";
let t = shipSched.getElementsByClassName(classname_details)[0];
var _HTMLdetails = '';
if ( !t ){
var temp = expandTableSelection(classname);
if ( !temp ) temp = "";
const div = '<div class="vanatime-main-table">' + temp ;
_HTMLdetails = `<span class="${classname_details}">${updatedSched}</span>`;
shipSched.innerHTML = div + _HTMLdetails + '</div>';
}
else {
t.innerHTML = updatedSched;
}
}
}
function updateGuilds(){
if (!pageHasElement(timeElements.guilds)) return;
/* ALCHEMY */
const page_alchemy_hours = document.getElementById(timeElements.guilds.alchemy);
if ( page_alchemy_hours ) { page_alchemy_hours.innerHTML = _guildSchedule(schedule.guilds.alchemy); }
const page_alchemy_status = document.getElementById(timeElements.guilds.alchemy_status);
if ( page_alchemy_status ) { page_alchemy_status.innerHTML = _guildSchedule(schedule.guilds.alchemy, timeElements.guilds.alchemy_status); }
const page_alchemy_holiday = document.getElementById(timeElements.guilds.alchemy_holiday);
if ( page_alchemy_holiday ) { page_alchemy_holiday.innerHTML = _guildSchedule(schedule.guilds.alchemy, timeElements.guilds.alchemy_holiday); }
const page_alchemy_timer = document.getElementById(timeElements.guilds.alchemy_timer);
if ( page_alchemy_timer ) { page_alchemy_timer.innerHTML = _guildSchedule(schedule.guilds.alchemy, timeElements.guilds.alchemy_timer); }
/* BONECRAFT */
const page_bonecraft_hours = document.getElementById(timeElements.guilds.bonecrafting);
if ( page_bonecraft_hours ) { page_bonecraft_hours.innerHTML = _guildSchedule(schedule.guilds.bonecrafting); }
const page_bonecraft_status = document.getElementById(timeElements.guilds.bonecraft_status);
if ( page_bonecraft_status ) { page_bonecraft_status.innerHTML = _guildSchedule(schedule.guilds.bonecrafting, timeElements.guilds.bonecraft_status); }
const page_bonecraft_holiday = document.getElementById(timeElements.guilds.bonecraft_holiday);
if ( page_bonecraft_holiday ) { page_bonecraft_holiday.innerHTML = _guildSchedule(schedule.guilds.bonecrafting, timeElements.guilds.bonecraft_holiday); }
const page_bonecraft_timer = document.getElementById(timeElements.guilds.bonecraft_timer);
if ( page_bonecraft_timer ) { page_bonecraft_timer.innerHTML = _guildSchedule(schedule.guilds.bonecrafting, timeElements.guilds.bonecraft_timer); }
/* CLOTHCRAFT */
const page_clothcraft_hours = document.getElementById(timeElements.guilds.clothcrafting);
if ( page_clothcraft_hours ) { page_clothcraft_hours.innerHTML = _guildSchedule(schedule.guilds.clothcrafting); }
const page_clothcraft_status = document.getElementById(timeElements.guilds.clothcraft_status);
if ( page_clothcraft_status ) { page_clothcraft_status.innerHTML = _guildSchedule(schedule.guilds.clothcrafting, timeElements.guilds.clothcraft_status); }
const page_clothcraft_holiday = document.getElementById(timeElements.guilds.clothcraft_holiday);
if ( page_clothcraft_holiday ) { page_clothcraft_holiday.innerHTML = _guildSchedule(schedule.guilds.clothcrafting, timeElements.guilds.clothcraft_holiday); }
const page_clothcraft_timer = document.getElementById(timeElements.guilds.clothcraft_timer);
if ( page_clothcraft_timer ) { page_clothcraft_timer.innerHTML = _guildSchedule(schedule.guilds.clothcrafting, timeElements.guilds.clothcraft_timer); }
/* COOKING */
const page_cooking_hours = document.getElementById(timeElements.guilds.cooking);
if ( page_cooking_hours ) { page_cooking_hours.innerHTML = _guildSchedule(schedule.guilds.cooking); }
const page_cooking_status = document.getElementById(timeElements.guilds.cooking_status);
if ( page_cooking_status ) { page_cooking_status.innerHTML = _guildSchedule(schedule.guilds.cooking, timeElements.guilds.cooking_status); }
const page_cooking_holiday = document.getElementById(timeElements.guilds.cooking_holiday);
if ( page_cooking_holiday ) { page_cooking_holiday.innerHTML = _guildSchedule(schedule.guilds.cooking, timeElements.guilds.cooking_holiday); }
const page_cooking_timer = document.getElementById(timeElements.guilds.cooking_timer);
if ( page_cooking_timer ) { page_cooking_timer.innerHTML = _guildSchedule(schedule.guilds.cooking, timeElements.guilds.cooking_timer); }
/* FISHING */
const page_fishing_hours = document.getElementById(timeElements.guilds.fishing);
if ( page_fishing_hours ) { page_fishing_hours.innerHTML = _guildSchedule(schedule.guilds.fishing); }
const page_fishing_status = document.getElementById(timeElements.guilds.fishing_status);
if ( page_fishing_status ) { page_fishing_status.innerHTML = _guildSchedule(schedule.guilds.fishing, timeElements.guilds.fishing_status); }
const page_fishing_holiday = document.getElementById(timeElements.guilds.fishing_holiday);
if ( page_fishing_holiday ) { page_fishing_holiday.innerHTML = _guildSchedule(schedule.guilds.fishing, timeElements.guilds.fishing_holiday); }
const page_fishing_timer = document.getElementById(timeElements.guilds.fishing_timer);
if ( page_fishing_timer ) { page_fishing_timer.innerHTML = _guildSchedule(schedule.guilds.fishing, timeElements.guilds.fishing_timer); }
/* GOLDSMITHING */
const page_goldsmithing_hours = document.getElementById(timeElements.guilds.goldsmithing);
if ( page_goldsmithing_hours ) { page_goldsmithing_hours.innerHTML = _guildSchedule(schedule.guilds.goldsmithing); }
const page_goldsmithing_status = document.getElementById(timeElements.guilds.goldsmithing_status);
if ( page_goldsmithing_status ) { page_goldsmithing_status.innerHTML = _guildSchedule(schedule.guilds.goldsmithing, timeElements.guilds.goldsmithing_status); }
const page_goldsmithing_holiday = document.getElementById(timeElements.guilds.goldsmithing_holiday);
if ( page_goldsmithing_holiday ) { page_goldsmithing_holiday.innerHTML = _guildSchedule(schedule.guilds.goldsmithing, timeElements.guilds.goldsmithing_holiday); }
const page_goldsmithing_timer = document.getElementById(timeElements.guilds.goldsmithing_timer);
if ( page_goldsmithing_timer ) { page_goldsmithing_timer.innerHTML = _guildSchedule(schedule.guilds.goldsmithing, timeElements.guilds.goldsmithing_timer); }
/* LEATHERCRAFT */
const page_leathercraft_hours = document.getElementById(timeElements.guilds.leathercrafting);
if ( page_leathercraft_hours ) { page_leathercraft_hours.innerHTML = _guildSchedule(schedule.guilds.leathercrafting); }
const page_leathercraft_status = document.getElementById(timeElements.guilds.leathercraft_status);
if ( page_leathercraft_status ) { page_leathercraft_status.innerHTML = _guildSchedule(schedule.guilds.leathercrafting, timeElements.guilds.leathercraft_status); }
const page_leathercraft_holiday = document.getElementById(timeElements.guilds.leathercraft_holiday);
if ( page_leathercraft_holiday ) { page_leathercraft_holiday.innerHTML = _guildSchedule(schedule.guilds.leathercrafting, timeElements.guilds.leathercraft_holiday); }
const page_leathercraft_timer = document.getElementById(timeElements.guilds.leathercraft_timer);
if ( page_leathercraft_timer ) { page_leathercraft_timer.innerHTML = _guildSchedule(schedule.guilds.leathercrafting, timeElements.guilds.leathercraft_timer); }
/* SMITHING */
const page_smithing_hours = document.getElementById(timeElements.guilds.smithing);
if ( page_smithing_hours ) { page_smithing_hours.innerHTML = _guildSchedule(schedule.guilds.smithing); }
const page_smithing_status = document.getElementById(timeElements.guilds.smithing_status);
if ( page_smithing_status ) { page_smithing_status.innerHTML = _guildSchedule(schedule.guilds.smithing, timeElements.guilds.smithing_status); }
const page_smithing_holiday = document.getElementById(timeElements.guilds.smithing_holiday);
if ( page_smithing_holiday ) { page_smithing_holiday.innerHTML = _guildSchedule(schedule.guilds.smithing, timeElements.guilds.smithing_holiday); }
const page_smithing_timer = document.getElementById(timeElements.guilds.smithing_timer);
if ( page_smithing_timer ) { page_smithing_timer.innerHTML = _guildSchedule(schedule.guilds.smithing, timeElements.guilds.smithing_timer); }
/* WOODWORKING */
const page_woodworking_hours = document.getElementById(timeElements.guilds.woodworking);
if ( page_woodworking_hours ) { page_woodworking_hours.innerHTML = _guildSchedule(schedule.guilds.woodworking); }
const page_woodworking_status = document.getElementById(timeElements.guilds.woodworking_status);
if ( page_woodworking_status ) { page_woodworking_status.innerHTML = _guildSchedule(schedule.guilds.woodworking, timeElements.guilds.woodworking_status); }
const page_woodworking_holiday = document.getElementById(timeElements.guilds.woodworking_holiday);
if ( page_woodworking_holiday ) { page_woodworking_holiday.innerHTML = _guildSchedule(schedule.guilds.woodworking, timeElements.guilds.woodworking_holiday); }
const page_woodworking_timer = document.getElementById(timeElements.guilds.woodworking_timer);
if ( page_woodworking_timer ) { page_woodworking_timer.innerHTML = _guildSchedule(schedule.guilds.woodworking, timeElements.guilds.woodworking_timer); }
const page_allguilds_hours = document.getElementById(timeElements.guilds.all);
if ( page_allguilds_hours ) {
var guildOut = "<TABLE CLASS='"+ timeElements.guilds.all + " vanatime-main-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>" + _guildSchedule(schedule.guilds.alchemy) + "</td></TR>";
guildOut = guildOut + "<TR><TH> Blacksmithing</TH><td>" + _guildSchedule(schedule.guilds.smithing) + "</td></TR>";
guildOut = guildOut + "<TR><TH> bonecrafting</TH><td>" + _guildSchedule(schedule.guilds.bonecrafting) + "</td></TR>";
guildOut = guildOut + "<TR><TH> Goldsmithing</TH><td>" + _guildSchedule(schedule.guilds.goldsmithing) + "</td></TR>";
guildOut = guildOut + "<TR><TH> Clothcrafting</TH><td>" + _guildSchedule(schedule.guilds.clothcrafting) + "</td></TR>";
guildOut = guildOut + "<TR><TH> Woodworking</TH><td>" + _guildSchedule(schedule.guilds.woodworking) + "</td></TR>";
guildOut = guildOut + "<TR><TH> Leatherworking </TH><td>" + _guildSchedule(schedule.guilds.leathercrafting) + "</td></TR>";
guildOut = guildOut + "<TR><TH> Fishing</TH><td>" + _guildSchedule(schedule.guilds.fishing) + "</td></TR>";
guildOut = guildOut + "<TR><TH> Cooking</TH><td>" + _guildSchedule(schedule.guilds.cooking) + "</td></TR>";
guildOut = guildOut + "</TABLE>";
page_allguilds_hours.innerHTML = guildOut;
}
}
function _guildStatusCheck(guild, statusID) {
return outputText = [outputTxt1, outputTxt2];
}
function _guildSchedule(guild, statusID) {
if (guild === 'undefined') return "_guildSchedule: error";
var now = vanatime.now_inMS();
var guildOpens = guild[0] * 60 * 1000 / 25;
var guildCloses = guild[1] * 60 * 1000 / 25;
// Guild open/close check
var nextOpenTime = 0;
var outputTxt1 = "", outputTxt2 = "";
if (guildOpens >= now) {
nextOpenTime = (((guildOpens - now) * 25) + vanatime.now_inEarthMS());
outputTxt1 = "Opens in: ";
outputTxt2 = "Currently Closed. Open tomorrow.";
} else if ((guildOpens < now) && (guildCloses > now)) {
nextOpenTime = (((guildCloses - now) * 25) + vanatime.now_inEarthMS());
outputTxt1 = "Closes in: ";
outputTxt2 = "Currently Open for business.";
} else if (guildCloses <= now) {
nextOpenTime = ((24 * 60 * 60 * 1000 / 25) - now + guildOpens) * 25 + vanatime.now_inEarthMS();
outputTxt1 = "Opens in: ";
outputTxt2 = "Currently Closed. Open tomorrow.";
}
if(typeof(statusID) == 'string' && statusID.includes('status')) {
// outputTxt2 = [`<span id=\'${statusID}\'>`, outputTxt2].join('');
// outputTxt2 = [outputTxt2, '</span'].join('');
return outputTxt2;
}
// Holiday check
if ((guild[2] == vanatime.weekDay()) && (guildCloses > now)) {
nextOpenTime = ((24 * 60 * 60 * 1000 / 25) - now + guildOpens) * 25 + vanatime.now_inEarthMS();
outputTxt2 = "Currently Closed for Guild Holiday.";
outputTxt1 = "Opens in: ";
if(typeof(statusID) == 'string' &&statusID.includes('holiday')) {
// outputTxt2 = [`<span id=\'${statusID}\'>`, outputTxt2].join('');
// outputTxt2 = [outputTxt2, '</span'].join('');
return outputTxt2;
}
} else if (((vanatime.weekDay() + 1) == guild[2]) && (guildCloses <= now)) {
nextOpenTime = ((24 * 60 * 60 * 1000 / 25) - now + guildOpens) * 25 + (24 * 60 * 60 * 1000 / 25) + vanatime.now_inEarthMS();
outputTxt2 = "Currently Closed. Guild Holiday tomorrow.";
outputTxt1 = "Opens in: ";
if(typeof(statusID) == 'string' && statusID.includes('holiday')) {
// outputTxt2 = [`<span id=\'${statusID}\'>`, outputTxt2].join('');
// outputTxt2 = [outputTxt2, '</span'].join('');
return outputTxt2;
}
}
if(typeof(statusID) == 'string' &&statusID.includes('holiday')) {
// outputTxt2 = [`<span id=\'${statusID}\'>`, outputTxt2].join('');
// outputTxt2 = [outputTxt2, '</span'].join('');
return `Guild is not on holiday until ${vanatime.dayLabel(guild[2])}.`;
}
/****DEBUGGING*****/
// if (guild == schedule.guilds.fishing) {
// console.log(guild[2], nextOpenTime, now, vanatime.timeUntil(nextOpenTime) );
// }
/****DEBUGGING*****/
if(typeof(statusID) == 'string' && statusID.includes('timer')) {
return outputTxt1 + vanatime.timeUntil(nextOpenTime);
}
return outputTxt1 + vanatime.timeUntil(nextOpenTime) + ". " + outputTxt2;
}
function updateConquest() {
if (!pageHasElement(timeElements.conquest)) return;
function stringNextConquest(remaining){
//if (nextConquest === undefined) { return "stringConquestTimer: timer undefined"; }
const now = new Date();
remaining = now.getTime() + remaining;
var nextConquest = new Date(remaining);
var tempHour = nextConquest.getHours();
var tempMin = nextConquest.getMinutes();
var tempSec = nextConquest.getSeconds();
if (tempHour < 10) tempHour = "0" + tempHour;
if (tempMin < 10) tempMin = "0" + tempMin;
if (tempSec < 10) tempSec = "0" + tempSec;
var strNextConquest = nextConquest.toDateString() + " " + tempHour + ":" + tempMin + ":" + tempSec;
// var remaining = (temp.getTime() - now.getTime()) / (24 * 60 * 60 * 1000);
// var hours = (remaining - Math.floor(remaining)) * 24;
// var mins = (hours - Math.floor(hours)) * 60;
// var secs = Math.floor((mins - Math.floor(mins)) * 60);
// remaining = Math.floor(remaining);
// hours = Math.floor(hours);
// mins = Math.floor(mins);
// if (hours < 10) hours = "0" + hours;
// if (mins < 10) mins = "0" + mins;
// if (secs < 10) secs = "0" + secs;
// // tempDays < 10 ? ["0", tempDays].join(':') : tempDays;
// // tempDays > 0 ? [tempDays, strTimer].join(':') : null;
// strDiff = hours + ":" + mins + ":" + secs;
//return strNextConquest + "(" + strDiff + ")";
return strNextConquest + "(" + vanatime.timeUntil(nextConquest) + ")";
}
const now = new Date();
var remaining = vanatime.conquestRemainingTime();
remainingVanaDaysOnConquest = vanatime.conquestRemainingVanaDays();
conq = remainingVanaDaysOnConquest + ' Vana´diel Days <BR>';
conq += stringNextConquest(remaining); //+ ' (' + timer.getHours() + ":" + timer.getMinutes() + ":" + timer.getSeconds() + ')';
const conquest_time = document.getElementById(timeElements.conquest);
if (conquest_time) conquest_time.innerHTML = conq;
}
function updateMoonPhaseSchedule(){
if (!pageHasElement(timeElements.moonSchedule)) return;
populateMoonPhaseSchedule(timeElements.moonSchedule, 7);
}
function _moonPhaseScheduleHeader(classname){
var header = "<TABLE CLASS='" + classname + " vanatime-main-table" + "' WIDTH='500' CELLSPACING='0' CELLPADDING='0'>";
header += "<TR ><TH ALIGN='LEFT'>Moon Phase</TH>";
header += "<TH ALIGN='LEFT'>Start Time</TH>";
header += "<TH ALIGN='LEFT'>End Time</TH>";
//header += "<TH ALIGN='LEFT'>Phase Ends in...</TH>";
header += "</TR>";
return header;
}
function _moonPhaseScheduleBody(numberOfEntries){
var html = "";
if ( numberOfEntries === undefined || numberOfEntries === null ) numberOfEntries = 7;
// DEBUGGING
numberOfEntries = 7;
var vTempTime = vanatime.today_inMS() / (60 * 1000); // VANA TIME IN TOTAL MINUTES
var thisMoonPhase = vanatime.moonLatentPhase(vTempTime);
var lunarOffset = 0,
_time;
for(var x = 0 ; x < numberOfEntries; x++ ){
if ( x > 0 ){
lunarOffset += 7;
if ( thisMoonPhase == 1 || thisMoonPhase == 3 || thisMoonPhase == 5 || thisMoonPhase == 7) {
_time = vTempTime + (60 * 24 * lunarOffset);
if ( vanatime.moonLatentPhase(_time) == thisMoonPhase) lunarOffset += 7;
}
//console.log(thisMoonPhase);
thisMoonPhase++;
if (thisMoonPhase > 7) thisMoonPhase = 0;
//console.log(thisMoonPhase);
}
var phaseStartTime;
for( var i = 1 ; i >= -13 ; i-- ) {
_time = vTempTime + (60 * 24 * lunarOffset) + (60 * 24 * (i - 1)); // VANA MINUTES
//console.log("s", thisMoonPhase, lunarOffset, vanatime.moonLatentPhase(_time));
if ( vanatime.moonLatentPhase(_time) != thisMoonPhase ) {
//console.log( "start", i, vanatime.moonLatentPhase(_time), thisMoonPhase );
break;
}
else phaseStartTime = _time * 60; // VANA SECONDS
}
var phaseEndTime;
for( var i = -1 ; i <= 14 ; i++ ) {
_time = vTempTime + (60 * 24 * lunarOffset) + (60 * 24 * (i + 1));// VANA MINUTES
//console.log("e", thisMoonPhase,lunarOffset,vanatime.moonLatentPhase(_time));
if ( vanatime.moonLatentPhase(_time) != thisMoonPhase ) {
//console.log( "end", i, vanatime.moonLatentPhase(_time), thisMoonPhase );
break;
}
else phaseEndTime = (_time + (60 * 24)) * 60; // VANA SECONDS
// for loop breaks when _time is at 00:00 for the day the moon phase changes...
// we add another day to this (60 + 24) to get the start of the next day for the table
}
const startDate = new Date(Math.floor(phaseStartTime / (25 / 1000)) - vanatime.getDifference() );
const endDate = new Date(Math.floor(phaseEndTime / (25 / 1000)) - vanatime.getDifference() );
var strDetails = vanatime.moonPhaseIcon(thisMoonPhase) + " " + vanatime.moonPhaseName(thisMoonPhase) + " " + vanatime.moonPhasePercentages(thisMoonPhase);
function dateString(date){
var sec = date.getSeconds(), hrs = date.getHours(), mins = date.getMinutes();
sec < 10 ? sec = "0" + sec : sec;
hrs < 10 ? hrs = "0" + hrs : hrs;
mins < 10 ? mins = "0" + mins : mins;
return vanatime.weekdayLabel(date.getDay()) + ", " + date.getDate() + " " + vanatime.monthLabel(date.getMonth()) + " " + hrs + ":" + mins + ":" + sec;
}
html += '<TR ><TD>' + strDetails + '</TD><TD>' + dateString(startDate) + '</TD><TD>' + dateString(endDate) + '</TD>';
// const now = new Date();
// var strTimer = vanatime.timer(endDate, now);
// html += '<TD>' + strTimer + '</TD>';
html += '</TR>';
}
return html;
}
function populateMoonPhaseSchedule(classname, numberOfEntries){
const moonSchedule = document.getElementById(classname);
if (moonSchedule) {
numberOfEntries = Number(moonSchedule.getAttribute('data-entries'));
if (numberOfEntries === undefined || numberOfEntries === null || numberOfEntries == 0 ) numberOfEntries = 7;
else numberOfEntries = numberOfEntries * 7;
var _HTMLheader = this._moonPhaseScheduleHeader(classname);
var _HTMLbody = this._moonPhaseScheduleBody(numberOfEntries);
moonSchedule.innerHTML = _HTMLheader + _HTMLbody + "</TABLE>";
}
}
function updateRSE() {
const rseclass = timeElements.rseSchedule;
const rseSched = document.getElementById(rseclass);
if (!rseSched) return;
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 = vanatime.weekdayLabel(day) + ", " + vanatime.monthLabel(mm-1) + ' ' + dd + ', ' + yyyy + " " + hh + ":" + min + ":" + ss;
} else if (showDay == 2) {
dateString = vanatime.monthLabel(mm-1) + " " + dd + ", " + hh + ":" + min + ":" + ss;
}
return dateString;
}
var timenow = new Date();
var localtime = timenow.getTime();
// ???
var repeatCal = 8;
var rowclass;
var rowhighlight = true;
RSECal = "<TABLE CLASS=\'" + rseclass + " vanatime-main-table" + "\' WIDTH='500' CELLSPACING='0' CELLPADDING='0'><TR><TH ALIGN='LEFT'>Date & Time</TH><TH ALIGN='LEFT'>Race</TH><TH ALIGN='LEFT'>Location</TH></TR>"
var numberOfEntries = getSelectedNumberOfEntries(rseclass);
if (numberOfEntries === 'undefined' || numberOfEntries === null || numberOfEntries == 0 ) numberOfEntries = 1;
numberOfEntries = 1;
for( let n=1; n <= numberOfEntries; n++ ){
for ( i = 0; i < repeatCal; i++) {
elapsedWeeks = Math.floor( (localtime - vanatime.rseDate) / (8 * (24 * 60 * 60 * 1000 / 25)) ) + i;
RSEstart = vanatime.rseDate + (elapsedWeeks * 8 * (24 * 60 * 60 * 1000 / 25));
if ( rowhighlight ) rowclass = `class="vanatime-main-table-row-highlight"`;
else rowclass = "";
RSECal = RSECal + "<TR " + rowclass + "><TD>" + formatDate(RSEstart,2) + '</TD><TD>' + vanatime.rseRace(elapsedWeeks % 8) + '</TD><TD>';
//RSECal = RSECal + "<A HREF=# onmousedown='javascript:getRSEDetails(" + (elapsedWeeks % 3) + ")'>";
RSECal = RSECal + vanatime.rseLocation(elapsedWeeks % 3);
RSECal = RSECal + '</A></TD></TR>';
rowhighlight = !rowhighlight;
}
// if (repeatCal < 1) { RSECal = ""; }
// else { RSECal = RSECal + '</TABLE>'; }
RSECal += '<TR class="vanatime-main-table-row-spacer"><TD></TD><TD></TD><TD></TD></TR>';
}
RSECal = RSECal + '</TABLE>';
// else {
// RSECal = "<TABLE CLASS='blank' CELLPADDING='0' CELLSPACING='0'><TR><TH WIDTH='120' ALIGN='LEFT'>Start</TH><TH WIDTH='120' ALIGN='LEFT'>End</TH><TH WIDTH='60' ALIGN='LEFT'>Location</TH></TR>"
// offsetTime = race * 8 * msGameDay;
// for ( i = 0; i < repeatCal; i++) {
// elapsedWeeks = Math.floor( (localtime - vanatime.rseDate) / (64 * msGameDay) ) + i;
// elapsedLocationWeeks = Math.floor( (localtime - vanatime.rseDate) / (8 * msGameDay) ) + (8 * i);
// raceOffset = race - (elapsedLocationWeeks % 8);
// elapsedLocationWeeks = elapsedLocationWeeks + raceOffset;
// RSEstart = vanatime.rseDate + (elapsedWeeks * 64 * msGameDay) + offsetTime ;
// RSEend = RSEstart + (8 * msGameDay);
// RSECal = RSECal + "<TR><TD>" + formatDate(RSEstart,2) + "</TD><TD>" + formatDate(RSEend,2) + "</TD><TD>";
// //RSECal = RSECal + "<A HREF=# onmousedown='javascript:getRSEDetails(" + (elapsedLocationWeeks % 3) + ")'>";
// RSECal = RSECal + RSEloc[(elapsedLocationWeeks) % 3]
// RSECal = RSECal + "</A></TD></TR>";
// }
// if (repeatCal < 1) { RSECal = ""; } else { RSECal = RSECal + '</TABLE>'; }
// }
const classname_details = rseclass + "-details";
let t = document.getElementsByClassName(classname_details)[0];
var _HTMLdetails = '';
//console.log(t);
if ( t === 'undefined' || t === null || !t ){
var temp = expandTableSelection(rseclass);
if ( !temp ) temp = "";
const div = '<div class="vanatime-main-table">' + temp ;
_HTMLdetails = `<span class="${classname_details}">${RSECal}</span>`;
rseSched.innerHTML = div + _HTMLdetails + '</div>';
}
else {
//console.log(t);
t.innerHTML = RSECal;
}
//document.getElementById(rseclass).innerHTML = RSECal;
}
function expandTableSelection(classname){
const classnameheader = classname + "-header";
const classnameshowSelect = classname + "-showSelect";
if ( classname == timeElements.rseSchedule ) {
return `
<div class="${classnameheader}" style="background:#FFFFFF00; width: max-content; float: right;">Shown:
<select id="${classnameshowSelect}" style="background:#DFDFDF50; ">
<option value="0">All </option>
<option value="1">M. Hume</option>
<option value="2">F. Hume</option>
<option value="3">M. Elvaan</option>
<option value="4">F. Elvaan</option>
<option value="5">M. TaruTaru</option>
<option value="6">F. TaruTaru</option>
<option value="7">Mithra</option>
<option value="8">Galka</option>
</select>
</div>
`;
}
return `
<div class="${classnameheader}" style="background:#FFFFFF00; width: max-content; float: right;">Shown:
<select id="${classnameshowSelect}" style="background:#DFDFDF50; ">
<option value="0">1 </option>
<option value="1">3</option>
<option value="2">5</option>
<option value="3">10</option>
</select>
</div>
`;
}
function expandRaceTable(classname){
const classnameheader = classname + "-header";
const classnameshowSelect = classname + "-showSelect";
const temp = `
<div class="${classnameheader}" style="background:#FFFFFF00; width: max-content; float: right;">Shown:
<select id="${classnameshowSelect}" style="background:#DFDFDF50; ">
<option value="0">1 </option>
<option value="1">3</option>
<option value="2">5</option>
<option value="3">10</option>
</select>
</div>
`;
// return popupButton;
return temp;
}
function getSelectedNumberOfEntries(classname){
// Number of entries comes from selection dropdown
var e = document.getElementById(classname + "-showSelect");
if ( !e ) return 1;
var entries;
switch(e.value) {
case "1":
entries = 3;
break;
case "2":
entries = 5;
break;
case "3":
entries = 10;
break;
default:
entries = 1;
}
//console.log(classname + ":" + entries);
return entries;
}
function gametick(){
updateSidebar();
updateAirshipSchedule();
updateBoatSchedule();
updateGuilds();
updateConquest();
updateMoonPhaseSchedule();
updateRSE();
setTimeout("gametick()", 1000);
//console.log('gametick');
}
gametick();
async function fetchWithTimeout(resource, options = {}) {
const { timeout = 10000 } = options;
const controller = new AbortController();
const id = setTimeout(() => controller.abort(), timeout);
const response = await fetch(resource, {
...options,
signal: controller.signal
});
clearTimeout(id);
return response;
}
async function populationFetch(){
try {
const response = await fetchWithTimeout('https://api.horizonxi.com/api/v1/misc/exp-sync-status', {});
const fetchedPopulation = await response.json();
//if ( typeof(fetchedPopulation) == 'number' ) currentPopulation = fetchedPopulation;
//console.log(fetchedPopulation);
//return games;
//console.log('populationFetchTick', fetchedPopulation);
//populationFetch();
currentPopulation = fetchedPopulation;
setTimeout("startPopulationFetch()", 300000);
} catch (error) {
//fetched = 0;
console.log('populationFetch(): ', error);
startPopulationFetch();
}
//console.log('currentPopulation = ', currentPopulation);
//return fetched;
}
function startPopulationFetch(){
//console.log('startPopulationFetch');
populationFetch();
// if ( currentPopulation == 0) startPopulationFetch();
// else setTimeout("startPopulationFetch()", 7000);
}
startPopulationFetch();
