Home > Net >  How can I shuffle a list weekly and have it consistent across all devices?
How can I shuffle a list weekly and have it consistent across all devices?

Time:03-24

I want to create a HTML list that will shuffle itself once a week and anybody who accesses the website will view the same shuffled list. The shuffling JavaScript is identical to the highest upvoted question on the matter so I will refrain from posting that here.

The problem with this, is that the shuffled list is inconsistent across devices. I had attempted to set a timer to control when the script activates, as you can view here:

var ul = document.querySelector("ul"), // get the list
    temp = ul.cloneNode(true); // clone the list

// shuffle the cloned list (better performance)
for (var i = temp.children.length   1; i--; )
temp.appendChild(temp.children[Math.random() * i |0] );

var weekInMilliseconds = 60*1000; // == 604800000 ms
var lastInfo = parseInt(localStorage.getItem('info'), 10); // either NaN or timestamp

if(isNaN(lastInfo))
    lastInfo = 0; // 1970, mind you

// if last info showed earlier than one week ago:
if(lastInfo < (Date.now() - weekInMilliseconds)){
    localStorage.setItem('info',Date.now()); // set info date now
    ul.parentNode.replaceChild(temp, ul); // copy shuffled back to 'ul' // display your information
}

My problems with this were that, again the list wasn't consistent, and, though it did successfully stop the script from activating until sufficient time had passed, since there was no actual alteration to the HTML, if there was a refresh before the interval the page would just load with the default, unshuffled, list order, as written in the original HTML.

I'm quite new to web design so I'm unsure what to try next and and my browsing of W3 has been unfruitful. Any help would be appreciated, thanks!

CodePudding user response:

So shuffling randomly will be inconsistent since it's differs each time you reload the page. To shuffle consistently you can try to create a pseudo random shuffle logic - so avoid using Math.random() here.

Explanation

We need to create a seed, in this case we are calulating the calendar week index and concatting this particular number with the current year to avoid repeating the same shuffle behaviour every year.

const seed = Math.ceil((new Date().getDay()   1   Math.floor((new Date() - new Date(new Date().getFullYear(), 0, 1)) / (24 * 60 * 60 * 1000))) / 7)   new Date().getFullYear();

We need a "Random"-generator like this simple method:

const getRandom = () => {
  const val = seed / (2 ** 32);
  seed = (1664525 * seed   1013904223) % (2 ** 32);
  return val;
}

Now we can start shuffeling the entries of our list using the linked answer to this question:

for (var i = list.children.length; i >= 0; i--)
  list.appendChild(list.children[getRandom() * i | 0]);

Snippet

Take a look at this working snippet, note that the order of the list will change every week:

// create seed that changes every new week and will not repeat since we concat it with the current year
let seed = Math.ceil((new Date().getDay()   1   Math.floor((new Date() - new Date(new Date().getFullYear(), 0, 1)) / (24 * 60 * 60 * 1000))) / 7)   new Date().getFullYear();

// create pseudo random numbers
const getRandom = () => {
  const val = seed / (2 ** 32);
  seed = (1664525 * seed   1013904223) % (2 ** 32);
  return val;
}

// pseudo shuffel list
const list = document.querySelector('ol');
for (let i = list.children.length; i >= 0; i--)
  list.appendChild(list.children[getRandom() * i | 0]);
<ol>
  <li>Al Pacino</li>
  <li>Bill Gates</li>
  <li>Carsten Stahl</li>
  <li>David Beckham</li>
  <li>Elon Musk</li>
  <li>Frank Ocean</li>
</ol>

  • Related