1var VAWLT_MAX_COOKIE_AGE = (15 * 365 * 24 * 60 * 60); // 15 years in the future, not accounting for leap years 2 3function getMMDDYYYY() { 4 var today = new Date(); 5 var dd = today.getDate(); 6 var mm = today.getMonth() + 1; 7 8 var yyyy = today.getFullYear(); 9 if (dd < 10) { 10 dd = '0' + dd; 11 } 12 if (mm < 10) { 13 mm = '0' + mm; 14 } 15 return mm + '/' + dd + '/' + yyyy; 16} 17 18 19/// 20// If we don't have an anonymous uuid, let's get one. 21/// 22if (!getPersistedValue("va_uuid")) { 23 setPersistedValue("va_uuid", createGUID()); 24 setPersistedValue("va_start_date", getMMDDYYYY()); 25} 26 27var vURLParams = new URLSearchParams(window.location.search); 28 29if (vURLParams.has('g') || vURLParams.has('G')) { 30 31 var g = parseInt(vURLParams.get('g') || vURLParams.get('G'), 10); 32 if (!isNaN(g) && g >= 1 && g <= 2) { 33 setPersistedValue("g", g); 34 } 35} 36 37if (vURLParams.has('a') || vURLParams.has('A')) { 38 var av = vURLParams.get('a') || vURLParams.get('A'); 39 if (av.indexOf("-") > 0) { 40 var ab = -1; 41 var ae = -1; 42 var aparts = av.split("-"); 43 if (aparts.length >= 2) { 44 ab = parseInt(aparts[0]); 45 ae = parseInt(aparts[1]); 46 } else if (aparts.length === 1) { 47 ab = parseInt(aparts[0]); 48 ae = 99; 49 } 50 if (!isNaN(ab) && !isNaN(ae) && ab > 13 && ae >= ab) { 51 setPersistedValue("a", ab + "-" + ae); 52 } 53 } else { 54 var a = parseInt(vURLParams.get('a') ||vURLParams.get('A'), 10); 55 if (!isNaN(a) && a >= 13) { 56 setPersistedValue("a", a); 57 } 58 } 59} 60 61if (vURLParams.has('i') || vURLParams.has('I')) { 62 var i = vURLParams.get('i') || vURLParams.get('I'); 63 var ei = getPersistedValue('i'); 64 if (ei) { 65 var eiparts = ei.split("|"); 66 var has = false; 67 for (var ii=0; ii < eiparts.length; ii++) { 68 if (eiparts[ii] === i) { console.log("Already has", i); has = true; break; } 69 } 70 if (!has) { setPersistedValue("i", ei + "|" + i); } 71 } else { 72 setPersistedValue("i", i); 73 } 74} 75 76 77/// Our Vawlt Anonymous Unique User Id. 78var _VAUUID 79function getVAUUID() { 80 if (!_VAUUID) { _VAUUID = getPersistedValue("va_uuid"); } 81 return _VAUUID; 82} 83 84function getStartDate() { 85 return getPersistedValue("va_start_date"); 86} 87 88/// 89// Just for getting started purposees. Maybe not use this guid function in real life due to Math.random 90// TODO: Validate this is ok solution, but we are static site generation at the moment with no backend. 91/// 92function S4() { 93 return (((1+Math.random())*0x10000)|0).toString(16).substring(1); 94} 95function createGUID() { 96 console.log("CREATE GUID TEMPORARY. REPLACE WITH MORE ROBUST SOLUTION"); 97 // then to call it, plus stitch in '4' in the third group 98 guid = (S4() + S4() + "-" + S4() + "-4" + S4().substr(0,3) + "-" + S4() + "-" + S4() + S4() + S4()).toLowerCase(); 99 return guid; 100} 101 102 103/// 104// Can we use local storage? 105/// 106function canUseLocalStorage() { 107 108 try { 109 if (localStorage === undefined || localStorage === null) { return false; } 110 const key = createGUID(); 111 localStorage.setItem(key, key); 112 localStorage.removeItem(key); 113 return true; 114 } catch (e) { 115 return false; 116 } 117} 118 119/// 120// Do we think we are on iOS? 121/// 122function isIOS() { 123 return /iPhone|iPod|iPad/.test(navigator.platform); 124} 125 126function isAndroid() { 127 console.log("User Agent is:", navigator.userAgent); 128 return /(android)/i.test(navigator.userAgent); 129} 130 131function isSafari () { 132 return navigator.userAgent.toLowerCase().indexOf('safari') > -1; 133} 134 135function isMobile() { 136 return isIOS() || isAndroid(); 137} 138 139function isDesktop() { 140 return !isMobile(); 141} 142 143function isSamsung() { 144 //return navigator.userAgent.match(/SAMSUNG|Samsung|SGH-[I|N|T]|GT-[I|N]|SM-[A|N|P|T|Z]|SHV-E|SCH-[I|J|R|S]|SPH-L/i); 145 return /SamsungBrowser/.test(navigator.userAgent); 146} 147 148function isChrome() { 149 return !!window.chrome; 150} 151 152/// 153// What is our root domain? E.g subdomain.domain.com will return domain.com. localhost is localhost 154/// 155function rootDomain() { 156 if (location.hostname === "localhost") { return location.hostname; } 157 var rootDomain = location.hostname.split('.').reverse()[1] + "." + 158 location.hostname.split('.').reverse()[0]; 159 console.log("RootDomain:" + rootDomain); 160 return rootDomain; 161} 162 163/// 164// Set a cookie value by key. Set persisted to true to make "permanent" 165/// 166function setCookieValue (key, value, persist=true) { 167 var cookieStr ="" + key + "=" + value + ";"; 168 if (persist) { cookieStr += " max-age=" + VAWLT_MAX_COOKIE_AGE +";"; } 169 cookieStr +=" domain=" + rootDomain() +"; path=/;"; 170 console.log("CookieStr:" + cookieStr); 171 document.cookie = cookieStr; 172} 173 174/// 175// Get a cookie value by key 176///
177function getCookieValue (key) { 178 var d=[], 179 e=document.cookie.split(";"); 180 a=RegExp("^\\s*"+key+"=\\s*(.*?)\\s*$"); 181 for(var b=0;b<e.length;b++){ 182 var f=e[b].match(a); 183 f&&d.push(f[1]) 184 } 185 return (d ? d[0] : undefined); 186} 187 188/// 189// Clear out a cookie value 190/// 191function clearCookieValue (key) { 192 var cookieStr ="" + key + "=; expires=Thu, 01 Jan 1970 00:00:01 GMT"; // Valid Epoch usage. WITNESS! 193 document.cookie = cookieStr; 194} 195 196/// 197// Persisted Values try to set values in both cookie and localstorage 198// Localstorage has priority over cookies and should be sync'd. reading a value will result 199// in the cookie being set as well. 200/// 201function getPersistedValue(key, defaultVal=undefined) { 202 var val = undefined; 203 204 // We check the cookie value first, as it is second priority 205 var cookieVal = getCookieValue(key) 206 val = cookieVal; // Initially set the value to be the cookie value (including undefined) 207 208 // Can we use local storage? If so, grab the value 209 if (canUseLocalStorage()) { 210 localVal = localStorage.getItem(key); 211 // We have a local value 212 if (localVal) { 213 val = localVal; // return local 214 setCookieValue(key, localVal); // Set the cookie value to sync 215 216 // We don't have a local, but we have a cookievalue, so use that and set local 217 } else if (cookieVal) { localStorage.setItem(key, cookieVal); } 218 } 219 220 // return the value if we have one, otherwise return default value. 221 return (val ? val : defaultVal); 222 223} 224 225/// 226// Set a value in the most persistent way we can. Set in a cookie and localStorage if possible 227/// 228function setPersistedValue(key, val) { 229 console.log("Setting Persistent Value", val); 230 setCookieValue(key, val, true); 231 if (canUseLocalStorage()) { 232 localStorage.setItem(key, val); 233 } 234} 235 236/// 237// Do we think we are in a PWA instance? 238/// 239function isPWA() { 240 var displayModes = ["fullscreen", "standalone", "minimal-ui"]; 241 242 for (var ii=0; ii < displayModes.length; ii++) { 243 var displayMode = displayModes[ii]; 244 if (window.matchMedia('(display-mode: ' + displayMode + ')').matches) { 245 console.log("is PWA true with displaymode:" + displayMode); 246 return true; 247 } 248 } 249 console.log("is PwA no match"); 250 return false; 251} 252// gaReportEvent will use this to queue up pending events if ga() is not defined 253// This can happen if a game is using defer.js to push all 3rd party libs/etc to load after the page is fully loaded 254// call flushPendingGAEvents() to clear. gaReportEvent will also call 255var _pendingGAEvents = []; 256 257/// 258// Send this event to google analytics 259/// 260function gaReportEvent(category, action, label, value = 1) { 261 if (typeof ga != "function") { 262 console.log("GA not ready yet"); 263 _pendingGAEvents.push({category: category, action: action, label: label, value: value}); 264 return; // We don't have ga loaded yet 265 } 266 267 // If there are any things pending, let's get them out of here before we do our call. 268 // Note: We don't use the queue unnecessarily as ga will handle queueing itself. We have our own queue in just a defer load case 269 flushPendingGAEvents(); 270 271 console.log("GA Report Event: Category:" + category + " Action:" + action + " Label:" + label + " Value:" + value); 272 ga('send', { 273 hitType: 'event', 274 eventCategory: category, 275 eventAction: action, 276 eventLabel: label, 277 eventValue: value, 278 hitCallback: function() { 279 console.log("gaReportEvent callback"); 280 } 281 }); 282} 283 284function flushPendingGAEvents() { 285 286 if (_pendingGAEvents.length > 0) { 287 console.log("Flusing pending GA events*********"); 288 for (var ii=0; ii < _pendingGAEvents.length; ii++ ) { 289 var pending = _pendingGAEvents.pop(); 290 ga('send', { 291 hitType: 'event', 292 eventCategory: pending.category, 293 eventAction: pending.action, 294 eventLabel: pending.label, 295 eventValue: pending.value, 296 hitCallback: function() { 297 console.log("gaReportEvent callback"); 298 } 299 }); 300 } 301 } 302} 303 304// Is WebView Code
305//var isIosWebview =/(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(navigator.userAgent) 306// if (typeof Android != "undefined") { means you are in a webview 307 308var vGameConfig = {}; 309// 310// Parse out the game configuration from the gc paramater and/or persistent storage. 311// For now the full string is stored, not distinct values. 312// The gc parameter is encoded with | as the separator. 313function initGameConfig(gameName="default") { 314 var configString = ""; 315 if (vURLParams.has('gc') || vURLParams.has('GC')) { 316 configString = vURLParams.get('gc') || vURLParams.get('GC'); 317 } else { 318 configString = getPersistedValue(gameName + "_gc"); 319 } 320 321 // Do we have a config string to parse? 322 if (!configString) { 323 return; // If not, let's bail 324 } else { 325 setPersistedValue(gameName + "_gc", configString); // Store the config string for future use. 326 } 327 328 console.log("ConfigString", configString); 329 var configParts = configString.split("|"); 330 console.log("ConfigParts", configParts); 331 for (var ii=0; ii < configParts.length; ii++) { 332 console.log("Checking Parts", configParts[ii]); 333 switch(configParts[ii]) { 334 335 case "cf0": // Card Faces 336 console.log("SZetting card faces to false"); 337 vGameConfig["card_faces"] = "false"; 338 break; 339 340 case "cf1": 341 vGameConfig["card_faces"] = "true"; 342 break; 343 } 344 } 345 console.log("vGameConfig", vGameConfig); 346}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.