我怎样才能每周洗牌并在所有设备上保持一致?

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

我想创建一个 HTML 列表,该列表将每周随机播放一次,任何访问该网站的人都会看到相同的随机播放列表。改组 JavaScript 与 highest upvoted question on the matter 相同,因此我不会在此处发布。

问题在于,洗牌后的列表在设备之间不一致。我曾尝试设置一个计时器来控制脚本何时激活,您可以在此处查看:

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
}

我的问题是,列表再次不一致,虽然它确实成功地阻止了脚本激活,直到经过足够的时间,因为没有对 HTML 进行实际更改,如果在间隔之前有刷新,页面将按照原始 HTML.

中所写的默认、未打乱的列表顺序加载

我对网页设计还很陌生,所以我不确定下一步该尝试什么,而且我浏览 W3 也没有结果。任何帮助将不胜感激,谢谢!

所以随机排列会不一致,因为每次重新加载页面时它都不一样。要始终如一地随机播放,您可以尝试创建一个伪随机播放逻辑 - 因此请避免在此处使用 Math.random()

说明

我们需要创建一个种子,在这种情况下,我们正在计算日历周索引并将该特定数字与当前年份相结合,以避免每年重复相同的随机播放行为。

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();

或更小:

const seed = Math.ceil(((new Date() - new Date(new Date().getFullYear(), 0, 1)) / 86400000 + new Date(new Date().getFullYear(), 0, 1).getDay() + 1) / 7);

我们需要一个“随机”生成器,就像这个简单的方法:

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

现在我们可以使用这个问题的链接答案开始洗牌我们列表的条目:

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

片段

看看这个工作片段,注意列表的顺序每周都会改变:

// 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() - new Date(new Date().getFullYear(), 0, 1)) / 86400000 + new Date(new Date().getFullYear(), 0, 1).getDay() + 1) / 7);

// 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>