PageSourceSearch

https://gamechannel.io/solitaire/v-util.js

js gamechannel.io collected 2026-10-02 01:57:31 UTC 12,477 bytes, 407 lines download raw bytes

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

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.