0

我正在使用cinch IRC 机器人框架来创建一个 irc 机器人,它可以智能地将用户踢出频道。为此,我需要了解机器人的用户模式并将其与用户的用户模式进行比较。有 4 种重要的模式:q、a、o、h。

基本上:所有者 (q) > 管理员 (a) > 运营商 (o) > 半运营 (h) > *。用户可以有多个用户模式。有人可以拥有模式 qao,但我不在乎用户是所有者还是管理员,我只关心用户是所有者。

Cinch 提供频道中所有已知用户及其用户模式的哈希值。例如:

Users{"bot" => {"a", "o"}, "fred" => {"q", "o"}, "mike" => "o", "larry" => "v"}

我想做的是,尽可能简洁地采用一些可以解释机器人何时是的逻辑,例如,“ao”,fred 是“qo”,mike 是“o”,然后说“OK。我“我是管理员,麦克是操作员,所以我可以踢麦克,但弗雷德是所有者,所以我不能踢弗雷德。”

我的实现想法很混乱(涉及很多 if then else 循环..),我知道必须有更好的方法。此外,我不确定如何遍历键值并忽略某个点的值。我觉得我的想法好像会迭代,遇到“ao”并设置为管理员,然后重置为操作员,这不是我需要的。

谢谢您的帮助。

4

2 回答 2

1

@I,@carolclarinet 有正确的想法,您可能不需要更多。但是,我想提一个更复杂的处理问题的方法,您可能会发现它在相关应用程序中很有用。首先,假设您的哈希看起来像这样:

h = {"bot" => ["a", "o"], "fred" => ["q", "o"], "mike" => ["o"], "larry" => ["h"]}

这就是你所拥有的,除了我已经制作了所有单个哈希值数组。显然,将它变成这种形式很简单。下面我将展示如何将值数组重新定义为我调用的新类的实例UserModes,它是Array. 通过这样做,您可以以非常自然的方式比较值数组:

h["bot"]                      # => ["a", "o"]
h["fred"]                     # => ["q", "o"]
h["bot"].can_kick? h["fred"]  # => false

h["mike"]                     # => ["o"]
h["bot"].can_kick? h["mike"]  # => true

h["larry"]                    # => ["h"]
h["bot"].can_kick? h["larry"] # => true

kickees[]
h.each {|k,v| kickees << k if k!="bot" && h["bot"].can_kick?(h[k])} # final () req'd
  # kickees => ["mike", "larry"]  

如果添加其他方法:

h["bot"] < h["fred"]   # => true
h["bot"] >= h["fred"]  # => false

h["bot"] == h["mike"]  # => false
h["bot"] > h["mike"]   # => true

h["bot"] <= h["larry"] # => false
h["bot"] >= h["larry"] # => true

这是类定义:

class UserModes < Array

  # Change > to >= in in can_kick? if I've misunderstood the kicking rule
  def can_kick?(other) rating(self) > rating(other) end

  # Add any or all of the following if useful to you: 
  def <=>(other) rating(self) <=> rating(other) end
  def ==(other)  rating(self) ==  rating(other) end
  def <(other)   rating(self) <   rating(other) end
  def >(other)   rating(self) >   rating(other) end
  def <=(other)  rating(self) <=  rating(other) end
  def >=(other)  rating(self) >=  rating(other) end

  private

  def rating a
    case
    when (a.include? ?q) then 3
    when (a.include? ?a) then 2
    when (a.include? ?o) then 1
    when (a.include? ?v) then 0
    else
      # raise exception
    end
  end
end

您会看到所有公共方法都使用私有方法rating,它将数组转换为数字分数,与@carolclarinet 的答案一致。您可以将每个哈希值从一个实例转换Array为一个实例,UserModes如下所示:

h.each_key {|k| h[k] = UserModes.new(h[k])}

我们可以确认这按预期工作:

h["fred"].class => UserModes

您可以将这些值h视为普通数组,但您现在还拥有该方法can_kick?,如果需要,还可以使用其他几个方法。其中一些 ( < <= >= >) 没有为Array对象定义;必须定义others( <=> ==) 以覆盖 中的同名方法Array

于 2013-10-13T07:39:43.283 回答
0

我会认为它就像采用机器人拥有的“最大”用户模式并将其与您想要踢的用户的“最大”用户模式进行比较。如果 bot 大于或等于其他用户的,则 bot 可以踢该用户。

在这种情况下,您需要一个方法来获取用户模式列表并返回对应于最大用户模式的数值。一种实现可能是:

def greatest_usermode(array_of_usermodes)
  if array_of_usermodes.include?("q")
    4
  elsif array_of_usermodes.include?("a")
    3
  elsif array_of_usermodes.include?("o")
    2
  elsif array_of_usermodes.include?("h")
    1
  else 
    0
  end
end

然后,您可以定义一个方法,该方法仅使用数学>=运算符来比较从该方法返回的机器人和相关用户的数字。

有许多其他方法可以做到这一点,但这是一种非常简单直接的方法。

于 2013-10-13T01:38:53.177 回答