更新:这是我遵循的要求,详细说明:
- 无论表中有多少歌曲或播放列表中的当前位置,客户端需要存储的信息(例如 cookie 中)都必须具有恒定大小。
- 使用 'next' 100 次,然后使用 'prev' 100 次应该会产生 100 首歌曲的某个序列(可能包括重复),然后将确切的序列颠倒,无论在任何“下一个”之间可能已插入任何内容或“上一个”动作。 (“上一首歌曲总是指上一首歌曲。”)
- 将跳过“在生成/初始化时”在播放列表中并已被删除的歌曲。
我认为您还需要一条信息:除了您的 GUID(或者您可以用它替换它)之外,还有一个整数位置的辅助歌曲键。然后,结合PRNG,您可以进行最简单快捷的查找。伪代码:
def next_song(initial_seed, current_prng_index, high_song_index):
"""Returns the next song and the parameters to be later passed
to next/prev_song."""
while True:
current_prng_index += 1
current_seed = PRNG_advance(initial_seed, current_prng_index)
song_index = song_index_from_seed(current_seed, high_song_index)
song_id = (SELECT SongID FROM Songs WHERE SongIndex=song_index)
if song_id: # test, somehow, for non-deleted songs
return song_id, (initial_seed, current_prng_index, high_song_index)
# include values that must be passed on the next call
# prev is the same, except uses -= 1
def song_index_from_seed(seed, highest):
return seed % (highest + 1)
# simple, but better possibilities might exist for your data
def new_playlist():
"""Returns the parameters to be passed to next/prev_song."""
high_song_index = (SELECT MAX(SongIndex) FROM Songs)
return get_a_random_number(), 0, high_song_index
这将在每首下一首歌曲中逐渐变慢,并且不允许通过向后进行包装(没有一些创造力)。如果您找到合适的可逆 PRNG(尽管在好的 PRNG 中并不常见,AFAIK):
def next_song(current_seed, high_song_index):
while True:
current_seed = PRNG_next(current_seed)
song_index = song_index_from_seed(current_seed, high_song_index)
song_id = (SELECT SongID FROM Songs WHERE SongIndex=song_index)
if song_id: # test, somehow, for non-deleted songs
return song_id, (current_seed, high_song_index)
# include values that must be passed on the next call
# prev is the same, except uses PRNG_prev
这通过跳过这些歌曲来处理删除(或者如果您从不删除这甚至不是问题),但是无论删除多少歌曲都不会改变顺序。插入由 song_index_from_seed 函数处理,通过约束索引使新歌曲永远不会“看到”。如果所有可用的歌曲都被删除,这也是一个无限循环,但我认为这段代码可以处理所有其他极端情况。
(将下一个/上一个版本重构为一个通用函数的简单包装器并不难,但为了清晰起见,这里省略了。)
我已经用我的位置索引有效地替换了你的 dateAdded,但这是一个改进,因为你不需要像计算位置索引那样将已删除的行保留为虚拟对象(但仍然不能重用它们的索引)按添加日期订购。
使用这样的 PRNG 看起来很幼稚,但很有效;并且您必须小心选择的 PRNG 和 song_index_from_seed 组合的行为符合您的预期:一些初始种子可能会生成“非随机”播放列表。 (不是因为它们不是随机的,而是因为听众期望混合歌曲,而不仅仅是4, 4、9, 9、...)