VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
  Persistable = 0  'NotPersistable
  DataBindingBehavior = 0  'vbNone
  DataSourceBehavior  = 0  'vbNone
  MTSTransactionMode  = 0  'NotAnMTSObject
END
Attribute VB_Name = "AutoClan"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit

Private m_Preferred As Collection, m_Alternates As Collection, m_Recent As Collection, m_Waiting As Collection
Private m_Clan As Clan
Private WithEvents m_Queue As Timer
Attribute m_Queue.VB_VarHelpID = -1

Public Event UserPromoted(Username As String, ByVal IsPreferred As Boolean)
Public Event UserDemoted(Username As String)

Private Sub Class_Initialize()
    Dim i As Long
    i = 0
    Set m_Preferred = New Collection
    Set m_Alternates = New Collection
    Set m_Recent = New Collection
    Set m_Waiting = New Collection
On Error GoTo Trap
    Set m_Queue = frmMain.Controls.Add("VB.Timer", "tmrAutoClan_" & i)
    m_Queue.Enabled = False
    m_Queue.Interval = 1000
    m_Queue.Enabled = True
    Exit Sub
Trap:
    i = i + 1
    Resume
End Sub

Public Sub ScanChannel(B As BnetBot)
    Dim U As User
    
    For Each U In B.ChannelUsers
        UserEntered U.Username
    Next
End Sub

Public Sub Clear()
    Do While m_Preferred.Count > 0
        m_Preferred.Remove 1
    Loop
    
    Do While m_Alternates.Count > 0
        m_Alternates.Remove 1
    Loop
End Sub

Public Sub AddPreferred(User As String)
On Error GoTo Trap
    m_Preferred.Add User, LCase$(User)
Trap:
End Sub

Public Sub AddAlternate(User As String)
On Error GoTo Trap
    m_Alternates.Add User, LCase$(User)
Trap:
End Sub

Public Sub AddManyPreferred(Users() As String)
    Dim i As Long
    For i = LBound(Users) To UBound(Users)
        AddPreferred Users(i)
    Next i
End Sub

Public Sub AddManyAlternates(Users() As String)
    Dim i As Long
    For i = LBound(Users) To UBound(Users)
        AddAlternate Users(i)
    Next i
End Sub

Public Property Get PreferredCount() As Long
    PreferredCount = m_Preferred.Count
End Property

Public Property Get AlternateCount() As Long
    AlternateCount = m_Alternates.Count
End Property

Public Property Get Preferred() As String()
    Dim Ret() As String, i As Long
    
    ReDim Ret(PreferredCount - 1) As String
    For i = 0 To (PreferredCount - 1)
        Ret(i) = m_Preferred(i + 1)
    Next i
    
    Preferred = Ret
End Property

Public Property Get Alternates() As String()
    Dim Ret() As String, i As Long
    
    ReDim Ret(AlternateCount - 1) As String
    For i = 0 To (AlternateCount - 1)
        Ret(i) = m_Alternates(i + 1)
    Next i
    
    Alternates = Ret
End Property

Private Function IsPending(Username As String)
On Error GoTo Trap
    Dim Workaround As Variant
    Workaround = m_Recent(Username)
    IsPending = True
    Exit Function
Trap:
    IsPending = False
End Function

Public Sub UserEntered(Username As String)
    Dim Member As ClanMember, Victim As ClanMember, Name As String
    
    Set Member = m_Clan.GetMember(Username)
    If (Member Is Nothing) Then Exit Sub
    
    Name = LCase$(Username)
    
    If (IsPreferred(Name) And Member.Rank < rankShaman) Then
        If (OnlineShamanCount < 5) Then
            If (IsPending(Name)) Then Exit Sub
            SchedulePromotion Username
        Else
            Set Victim = FindAlternate()
            If (Victim Is Nothing) Then Exit Sub
            
            If (IsPending(Name)) Then Exit Sub
            ScheduleDemotion Victim.Username, Username
        End If
    ElseIf (IsAlternate(Name) And Member.Rank < rankShaman) Then
        If (OnlineShamanCount < 5) Then
            If (IsPending(Name)) Then Exit Sub
            SchedulePromotion Username
        End If
    End If
End Sub

Public Sub UserLeft(Username As String)
    Dim Member As ClanMember, Victim As ClanMember, Name As String
    
    Set Member = m_Clan.GetMember(Username)
    If (Member Is Nothing) Then Exit Sub
    
    Name = LCase$(Username)
    
    If (IsAlternate(Name) And Member.Rank = rankShaman) Then
        If (IsPending(Name)) Then Exit Sub
        ScheduleDemotion Username
    End If
End Sub

Public Sub ShamanDisconnected(Username As String)
    Dim Member As ClanMember
    
    If Not (IsPreferred(Username)) Then
        Exit Sub
    End If
    
    Set Member = FindAvailableAlternate()
    If (Member Is Nothing) Then
        Exit Sub
    End If
    
    ScheduleDemotion Username, Member.Username
End Sub

Private Function FindAlternate() As ClanMember
    Dim Members() As ClanMember, i As Long
    
    m_Clan.GetMembers Members
    
    For i = 0 To UBound(Members)
        If (Members(i).Rank = rankShaman And IsAlternate(LCase$(Members(i).Username))) Then
            Set FindAlternate = Members(i)
            Exit Function
        End If
    Next i
    
    Set FindAlternate = Nothing
End Function

Private Function FindAvailableAlternate() As ClanMember
    Dim Members() As ClanMember, i As Long, U As User
    
    m_Clan.GetMembers Members
    
    Set FindAvailableAlternate = Nothing
    For i = 0 To UBound(Members)
        If (Members(i).Rank < rankShaman And Members(i).Online = True) Then
            Set U = Bot.GetUser(Members(i).Username)
            If (U Is Nothing) Then _
                Exit Function
            
            If (IsAlternate(LCase$(Members(i).Username))) Then
                Set FindAvailableAlternate = Members(i)
                Exit Function
            End If
        End If
    Next i
End Function

Private Function FindOfflinePreferred() As ClanMember
    Dim Members() As ClanMember, i As Long
    
    m_Clan.GetMembers Members
    
    For i = 0 To UBound(Members)
        If (Members(i).Rank = rankShaman And Members(i).Online = False) Then
            If (IsPreferred(LCase$(Members(i).Username))) Then
                Set FindOfflinePreferred = Members(i)
                Exit Function
            End If
        End If
    Next i
    
    Set FindOfflinePreferred = Nothing
End Function

Private Function FindDemotedPreferred() As ClanMember
    Dim Members() As ClanMember, i As Long
    
    m_Clan.GetMembers Members
    
    For i = 0 To UBound(Members)
        If (Members(i).Rank < rankShaman) Then
            If (IsPreferred(LCase$(Members(i).Username))) Then
                Set FindDemotedPreferred = Members(i)
                Exit Function
            End If
        End If
    Next i
    
    Set FindDemotedPreferred = Nothing
End Function

Private Function IsPreferred(Username As String)
    Dim U
On Error GoTo Trap
    U = m_Preferred(Username)
    IsPreferred = True
    Exit Function
Trap:
    IsPreferred = False
End Function

Private Function IsAlternate(Username As String)
    Dim U
On Error GoTo Trap
    U = m_Alternates(Username)
    IsAlternate = True
    Exit Function
Trap:
    IsAlternate = False
End Function

Public Property Get Clan() As Clan
    Set Clan = m_Clan
End Property

Public Property Set Clan(NewClan As Clan)
    Set m_Clan = NewClan
End Property

Public Property Get ShamanCount() As Long
    Dim Members() As ClanMember, i As Long
    
    m_Clan.GetMembers Members
    
    ShamanCount = 0
    For i = 0 To UBound(Members)
        If (Members(i).Rank = rankShaman) Then
            ShamanCount = ShamanCount + 1
        End If
    Next i
End Property

Public Property Get OnlineShamanCount() As Long
    Dim Members() As ClanMember, i As Long
    
    m_Clan.GetMembers Members
    
    OnlineShamanCount = 0
    For i = 0 To UBound(Members)
        If (Members(i).Rank = rankShaman And Members(i).Online = True) Then
            OnlineShamanCount = OnlineShamanCount + 1
        End If
    Next i
End Property

Public Sub UserWasPromoted(Username As String, Extra As String)
On Error GoTo Trap
    m_Recent.Remove LCase$(Username)
    RaiseEvent UserPromoted(Username, IsPreferred(Username))
    AddC "Automatically promoted " & Username & ".", vbYellow
Trap:
End Sub

Public Sub UserWasDemoted(Username As String, Extra As String)
    Dim Temp As ClanMember
On Error GoTo Trap
    m_Recent.Remove LCase$(Username)
    RaiseEvent UserDemoted(Username)
    AddC "Automatically demoted " & Username & ".", vbYellow
    If (LenB(Extra) > 0) Then
        SchedulePromotion Extra
    ElseIf (IsAlternate(LCase$(Username))) Then
        If (ShamanCount < 5) Then
            Set Temp = FindDemotedPreferred()
            If (Temp Is Nothing) Then _
                Exit Sub
            SchedulePromotion Temp.Username
        End If
    End If
Trap:
    
End Sub

Private Sub SchedulePromotion(Username As String, Optional Extra As String = vbNullString)
    If (UserClan.Rank < rankShaman) Then Exit Sub
    If (LenB(Extra) > 0) Then
        m_Waiting.Add "p/" & Username & "/" & Extra
    Else
        m_Waiting.Add "p/" & Username
    End If
End Sub

Private Sub ScheduleDemotion(Username As String, Optional Extra As String = vbNullString)
    If (UserClan.Rank < rankShaman) Then Exit Sub
    If (LenB(Extra) > 0) Then
        m_Waiting.Add "d/" & Username & "/" & Extra
    Else
        m_Waiting.Add "d/" & Username
    End If
End Sub

Private Sub m_Queue_Timer()
    Dim Frag() As String, Current As String, Username As String, Temp As ClanMember
    If (m_Waiting.Count() = 0) Then Exit Sub
    
    Current = m_Waiting(1)
    Debug.Print Current
    Frag = Split(Current, "/")
    m_Waiting.Remove 1
    Username = LCase$(Frag(1))

On Error GoTo Trap
    m_Recent.Add Username, Username
On Error GoTo Trap2
    Select Case Frag(0)
        Case "p"
            If (ShamanCount >= 5 And OnlineShamanCount < 5) Then
                If IsPreferred(Username) Then
                    Set Temp = FindAlternate()
                    If (Temp Is Nothing) Then
                        Exit Sub
                    End If
                Else
                    Set Temp = FindOfflinePreferred()
                    If (Temp Is Nothing) Then
                        Exit Sub
                    End If
                End If
                
                ScheduleDemotion Temp.Username, Frag(1)
            End If
            
            If (OnlineShamanCount >= 5 And Not IsPreferred(Username)) Then
                Exit Sub
            End If
            
            If Not (SanityCheck(Frag(1))) Then
                Exit Sub
            End If
            
            If (UBound(Frag) >= 2) Then
                m_Clan.Promote Frag(1), asAuto, Frag(2)
            Else
                m_Clan.Promote Frag(1), asAuto
            End If
        Case "d"
            If Not (SanityCheck(Frag(1), False)) Then
                Exit Sub
            End If
            If (UBound(Frag) >= 2) Then
                m_Clan.Demote Frag(1), asAuto, Frag(2)
            Else
                m_Clan.Demote Frag(1), asAuto
            End If
    End Select
    Exit Sub
Trap:
    Exit Sub
Trap2:
End Sub

Private Function SanityCheck(Username As String, Optional ByVal IsPromoting As Boolean = True) As Boolean
On Error GoTo Trap
    Dim User As ClanMember, R As ClanRanks
    
    SanityCheck = False
    
    Set User = m_Clan.GetMember(Username)
    If (User Is Nothing) Then
        Exit Function
    End If
    
    R = User.Rank
    If (IsPromoting And R <> rankGrunt) Or (Not IsPromoting And R <> rankShaman) Then
        Exit Function
    End If
    
    SanityCheck = True
Trap:
End Function
