我正在使用cinch IRC bot framework创建一个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”,然后说“好的。我是管理员,迈克是一名操作员,所以我可以踢迈克,但弗雷德是一个拥有者所以我不能踢弗雷德。“
我对实现的想法是混乱的(如果其他的话循环涉及很多......)我知道必须有更好的方法。另外,我不确定如何遍历键值并忽略某个点的值。我觉得好像我的想法会迭代,遇到“ao”并设置为管理员,然后重置为运营商,这不是我需要的。
感谢您的帮助。
答案 0 :(得分: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
个对象定义;其他人(<=> ==
)必须定义为覆盖Array
中的同名方法。
答案 1 :(得分:0)
我认为这就像采用机器人拥有的“最佳”用户模式并将其与您想要踢的用户所使用的“最佳”用户模式进行比较。如果机器人大于或等于其他用户,那么机器人可以踢用户。
在这种情况下,您需要一个获取用户模式列表的方法,并且可以返回与最大值相对应的数值。一种实现可能是:
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
然后,您可以定义一个方法,该方法仅使用数学>=
运算符来比较此方法为机器人和相关用户返回的数字。
还有很多其他方法可以做到,但这是一种非常简单明了的方法。