代码之家  ›  专栏  ›  技术社区  ›  Xavier

如何为随机元素提供服务,以便每个用户以相同的顺序获得相同的随机元素?

  •  0
  • Xavier  · 技术社区  · 7 年前

    我正在建一个在线电台。我创建了一个XML数据库来存储 播放列表 歌曲信息,以便可以向用户提供特定音频文件,该文件由播放列表(XML)按照预定义顺序定义;从而产生一种 显示 。这些节目通常长达一小时。我想做的是在节目结束后随机生成歌曲信息,从我的整个数据库中创建一个无限、随机的播放列表。但是,需要向所有用户提供一首随机歌曲,以便每个用户都能获得相同的体验(相同的歌曲)。还必须说明我的节目是如何实时播出的,因为这类节目决定了我的 随机发生器 应该有用。为了节省时间和空间,我将省略这些功能的某些功能,因为它们可能会变得相当冗长。如果您希望看到这些省略的函数,我可以根据要求提交它们。我最初的想法是创建这个 随机发生器 将使用 上海证券交易所 (服务器发送的事件)但是,可能有一种更简单的方法。

    我有一个Javascript文档,它使用AJAX查询数据库(播放列表):

    load_prs(track_data_complete , "playlist.xml") ;
    

    track_data_complete() 接收响应并更新 音频播放器 使用当前歌曲信息,然后对 timestamp.php :

    var current_play = 0 ; // current_play is global to indicate current song element in the playlist XML array
    var track_length ; // Store current track length in seconds
    var track_obj ; // object data for current song
    var showtime ; // the shows beginning unix time
    var timestamp ; // current unix time
    
    function track_data_complete( XML )
    {
    var th = XML.children[current_play] ;
    var band = get_val(th , "band") ; // get_val parses the XML data
    var album = get_val(th , "album") ;
    var title = get_val(th , "title") ;
    var genre = get_val(th , "genre") ;
    track_length = get_val(th , "length") ;
    var tid = th.getAttribute("id") ;
    var tsrc = "songs/" + tid + ".mp3" ;
    track_obj = new tobj(band , album , title , genre , length , tsrc) ; // tobj creates a new object to store the data
    
    showtime = Number(XML.getAttribute("showtime")) ;
    load_prs(load_track , "timestamp.php?time=0") ;
    }
    

    时间戳。php

    <?php echo ( time() + $_REQUEST['time'] . "" ) ; ?>
    

    load_track() 使用返回的Unix时间戳实时播放歌曲 时间戳。php 然后用歌曲信息更新播放器:

    function load_track( resp )
    {
    timestamp = Number(resp) ;
    track_src.src = track_obj.tsrc ; // track_src is the audio element source
    player_title.innerHTML = track_obj.band + " - " + track_obj.title ;
    player_album.innerHTML = "Album: " + track_obj.album ;
    track_audio.onended = function() { next_track() ; } ; // track_audio is the HTML audio element
    track_audio.load() ;
    begin_play() ;
    }
    

    begin_play() 使用数学计算实时时间,以决定何时开始播放音频。这将模拟实时音频播放。如果时间超过第一首歌曲的长度,则跳到下一首歌曲,直到当前时间大于 showtime :

    function begin_play()
    {
    swap("stop_track") ;
    var time = timestamp - showtime ;
    if ( time < track_length ) { track_audio.currentTime = time ; }
    else { return next_track() ; }
    track_audio.play() ;
    }
    

    next_track() 增量 current_play 并添加 演出时间 和当前 track_length 一起,然后打电话 track_list_complete() 然后重新开始这个过程。

    playlist.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <playlist auto="no" showtime="1526448420">
      <track id="funeral_doom_003">
        <genre>Funeral Doom</genre>
        <band>Depressed Mode</band>
        <album>Ghosts of Devotion</album>
        <title>Words of Silence</title>
        <length>3016</length>
      </track>
      <track id="funeral_doom_001">
        <genre>Funeral Doom</genre>
        <band>Evoken</band>
        <album>A Caress of the Void</album>
        <title>Descend the Lifeless Womb</title>
        <length>4270</length>
      </track>
    </playlist>
    

    注意:我的整个数据库都在XML文件中。每个文件都是一种音乐类型。因为我有三种类型,所以有三个XML文件。播放列表文件是独立的,因为它使我能够创建节目。播放列表文件和流派文件在结构上非常相似,播放列表列出了给定歌曲的大部分相同数据。乍一看,您认为只需从流派数据库中随机获取一首歌曲,但这将为每个用户生成可能不同的歌曲。类似地,从播放列表中随机抓取歌曲会遗漏我数据库的其余部分。

    1 回复  |  直到 7 年前
        1
  •  0
  •   Peter Cordes    7 年前

    使用客户端PRNG以随机顺序循环播放列表,并为每个客户端提供相同的种子 they all get the same infinite of random numbers 。您可以实现自己的更简单的PRNG,如线性同余生成器,在出现任何重复之前生成每个数字一次,或者您可以使用PRNG提供随机洗牌算法。

    您可以硬编码种子值,如 42 变成一个。js,或将其放入 <script> php生成HTML的一部分。或者,如您所说,如果客户端需要下载XML文件,请将PRNG参数放在其中,以便您轻松编辑播放列表文件以获得不同的顺序。

    您甚至可以通过 只是 给他们PRNG参数以生成0中的随机数。。N范围,并将这些数字映射到歌曲服务器端。