-2

我运行一个 irc 机器人,用 ruby​​ 编写,运行 cinch irc 框架。机器人回复有趣的事实并循环浏览这些事实,这样您就不会厌倦它们。我设置了一个冷却时间,所以它们不能在 6 小时内显示。它不再显示最初显示的事实,而是显示随机选择的事实,这可能是之前显示的事实。

line = IO.readlines("facts.txt")
factnumber = rand(line.length)
    if fact_not_next_6_hours[factnumber] == true
    factnumber = rand(line.length)
    m.reply "fact #{factnumber}: #{line[factnumber]}"
    fact_not_next_6_hours[factnumber] = true

fact_not_next_6_hours[factnumber]是 6 小时冷却的变量;如果设置为 true,则冷却处于活动状态。我需要去做:

factnumber = rand(line.length) 

直到它没有将 6 小时冷却设置为 true,然后执行

m.reply "fact #{factnumber}: #{line[factnumber]}"
fact_not_next_6_hours[factnumber] = true

我的第一个想法是做多个ifs,但没有奏效,我相信有更好的方法。

4

3 回答 3

1

首先,如果你只是设置一个布尔标志,你怎么知道什么时候“解冻”它?我会在对象中保留上次访问时间的“时间戳”。此外,我不会到处使用原始类型,而是以更面向对象的方式来做。

这是我的解决方案:

class Fact
  attr_reader :text

  def initialize(text)
    @text = text
    @last_accessed = Time.new(0) # a long time ago, not in cooldown
  end

  def in_cooldown?
    Time.now - @last_accessed < 60*60*6
  end

  def cooldown!
    @last_accessed = Time.now
  end
end

class Facts
  attr_reader :all

  def initialize(file_name)
    @all = IO.readlines("facts.txt").map{|line| Fact.new(line)} 
  end
end

class FactRandomizer
  def initialize(facts)
    @facts = facts
  end

  def get
    fact = not_in_cooldown.sample || all.sample # all can be in cooldown
    fact.cooldown!
    fact.text
  end

  private

  def not_in_cooldown
    @facts.select{|fact| !fact.in_cooldown?}
  end
end

用法:

facts = Facts.new("whatever").all
randomizer = FactRandomizer.new(facts)
randomizer.get

编辑:

我重构了代码,使其不再使用类方法。请注意,现在测试此代码将变得多么容易,以及交换部分代码是多么容易(例如替换从文件中读取事实的部分或事实处于冷却状态意味着什么)。

于 2012-04-05T15:31:52.853 回答
1

你真的应该重命名linelines,因为它实际上是一个行数组。我已经在我的回答中这样做了。

这本质上是一个“do while”循环:

begin 
  factnumber = rand(lines.length)
end while fact_not_next_6_hours[factnumber]

但是根据您拥有多少事实以及您希望“使用”多少事实,过滤掉您不能首先使用的事实可能更有意义:

fact = (0...lines.length).zip(lines).reject do |k, v|
  fact_not_next_6_hours[k]
end.sample

m.reply "fact #{fact[0]}: #{fact[1]}"

( ) 的第一位(0...lines.length).zip(lines)只是将每一行与一个数字相关联(例如[[0, "fact"], [1, "afact"], ...])。我建议单独运行方法链的每个部分,这样您就可以完全了解正在发生的事情。

于 2012-04-05T15:21:52.273 回答
1

你可以做:

factnumber = rand(line.length)
while fact_not_next_6_hours[factnumber] == true
  factnumber = rand(line.length)
end
m.reply "fact #{factnumber}: #{line[factnumber]}"
fact_not_next_6_hours[factnumber] = true

或者:

nil while fact_not_next_6_hours[factnumber = rand(line.length)] == true
m.reply "fact #{factnumber}: #{line[factnumber]}"
fact_not_next_6_hours[factnumber] = true
于 2012-04-05T15:17:58.380 回答