2012-04-05 10 views
-2

Ich starte einen IRC-Bot, geschrieben in Ruby, mit dem Cinch-IRC-Framework. Der Bot antwortet mit interessanten Fakten und durchläuft diese Fakten, damit Sie sich nicht langweilen. Ich habe eine Abkühlung eingestellt, so dass sie 6 Stunden lang nicht gezeigt werden können. Anstatt die Tatsachen zu zeigen, die es zuerst zeigte, zeigt es jetzt zufällig ausgewählte, die die früher gezeigten sein konnten.Variable ändern, bis sie richtig ist (wenn, sonst)

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] ist die Variable, für die 6 Stunden Abkühlzeit; Wenn es auf True gesetzt ist, ist Cool Down aktiv. Ich muss tun:

factnumber = rand(line.length) 

, bis er eine bekommt, die die 6 Stunden haben dosen't Abkühlphase auf true gesetzt, und dann tun

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

Meine erste Idee mehrere if s zu tun war, aber es hat nicht funktioniert und ich bin mir sicher, dass es einen besseren Weg gibt.

Antwort

1

können Sie tun:

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 

Oder:

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 
+0

Das scheint zu funktionieren! Vielen Dank. Ich ging mit der 2. Lösung, es ist so sauber und schön – qwerty1911

+0

wenn alle Fakten verwendet werden, wird dies in einer Endlosschleife enden – psyho

+0

Ich bin bewusst der Endlosschleife, aber der Kanal hat rund 680 Fakten, so sollte es in Ordnung sein.Ich plane auch eine "sofortige Abkühlung" hinzuzufügen – qwerty1911

1

Sie wirklich line zu lines umbenennen sollte, wie es in der Tat eine Reihe von Linien ist. Ich habe es in meiner Antwort getan.

Dies ist im Wesentlichen ein „do while“ Schleife:

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

Aber je nachdem, wie viele Fakten, die Sie haben und wie viele Sie erwarten, „gebraucht“ zu sein, Sie diejenigen herausfiltern kann nicht zuerst verwenden kann mehr Sinn machen:

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]}" 

das erste Bit des ((0...lines.length).zip(lines)) wird nur jede der Linien mit einer Zahl zuordnet (zB [[0, "fact"], [1, "afact"], ...]). Ich empfehle, jeden Teil der Methodenkette einzeln auszuführen, damit Sie vollständig verstehen können, was passiert.

1

Zuerst, wenn Sie nur eine boolesche Flagge setzen, wie werden Sie wissen, wann Sie es "auflösen"? Ich würde den "Zeitstempel" der zuletzt aufgerufenen Zeit im Objekt behalten. Anstatt primitive Typen zu verwenden, würde ich es auch objektorientierter machen.

Hier ist meine Lösung:

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 

Verbrauch:

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

EDIT:

ich den Code Refactoring, so dass sie Klassenmethoden nicht mehr verwenden. Beachte, wie viel einfacher es wäre, diesen Code jetzt zu testen und wie einfach es ist, Teile davon auszutauschen (wie zum Beispiel den Teil zu ersetzen, der die Fakten aus der Datei liest oder was es bedeutet, dass eine Tatsache in der Abklingzeit ist).

+0

Kann ich die facts.txt leicht zu # {m.channel} ändern? Ich denke nur, weil es eine globale Variable ist, und ich füge facts.txt bei der Beschreibung dieser Sache für die Leichtigkeit – qwerty1911