 Rem Utilitiy for Dndbbs v5.0a r2.0a t5.0a
 Rem File: Topten.bas v1.5a 09/10/2024.
 Rem Subs: Top.Ten/Top.Ten.Teams
 Rem $Include: 'dndbbs.inc'

 Rem  v1.3a trims some code,
 Rem   Adds topten.ans output.
 Rem  v1.4a fixes command line.
 Rem  v1.5a edits node when nul.
 Rem   Adds /D debug mode switch.

 Dim Shared TempFile3 As Integer
 Dim Shared TempFile4 As Integer

 On Error Goto Main.Error
 If Command$="/?" Then Goto Boot.Usage
 If Instr(Command$,"/D") Then
    Debug.Mode=-1
 Endif
 Call Get.Node
 Call Open.Arrays
 Call Get.Config
 Call Make.FileNames
 Call Reset.Cursor
 Call Open.Files
 Call Top.Ten
 Call Top.Ten.Teams
 Strng=Chr$(27)+"[0m"
 Print #TempFile4,Strng
 If Instr(Command$,"/Z") Then
    Close
    End
 Endif
 Color 15,0
 Print
 Print "Topten Module v"+Version$+" r"+Release$+" t"+Tweak$
 Color 14,0
 FileName2$=DND.Path+"TOPTEN"+NodeX+".DAT"
 Print "Data file "+Filename2$+" written to disk."
 Color 7.0
 PRINT "Topten exited normally.."
 Close
Main.Resume:
 End
Boot.Usage:
 Color 15
 Print "Topten Usage:"
 Color 14
 Print "  Topten [/Z][/N:<node>]"
 Color 15
 Print "Where:"
 Color 14
 Print "  /Z  display off."
 Print "  /N:<node> is node."
 Print "    Node must be <nul>,0-9,A-Z,10-99."
 Color 7
 End
Main.Error:
 Resume Main.Resume

Sub Top.Ten
 On Local Error Goto ErrTrap9
 Close #TempFile2
 FileName2$=DND.Path+"TOPTEN"+NodeX+".DAT"
 Open FileName2$ For Output Shared As #TempFile2

 Close #TempFile3
 FileName3$=DND.Path+"TOPTEN"+NodeX+".TXT"
 Open FileName3$ For Output Shared As #TempFile3

 Close #TempFile4
 FileName4$=DND.Path+"TOPTEN"+NodeX+".ANS"
 Open FileName4$ For Output Shared As #TempFile4

 If Debug.Mode Then
    Color 15,0
    Print
    Print "Topten Module v"+Version$+" r"+Release$+" t"+Tweak$
    Print "  Debug mode filename list:"
    Color 14,0
    Print FileName2$
    Print FileName3$
    Print FileName4$
 Endif

 TempX!=Lof(UserFile2)/UserRecLen
 If TempX!=SFalse Then
    Print #TempFile2, ""
    Print #TempFile3, ""
    Print #TempFile4, ""

    Strng="Top Ten Player Ranking"
    Strng2=Chr$(27)+"[0;1;37m"+Strng
    Print #TempFile2, Strng
    Print #TempFile3, Strng
    Print #TempFile4, Strng2

    Strng=String$(22,"-")
    Strng2=Chr$(27)+"[0;1;37m"+Strng
    Print #TempFile2, Strng
    Print #TempFile3, Strng
    Print #TempFile4, Strng2

    Strng="No users exist."
    Strng2=Chr$(27)+"[0;1;35m"+Strng
    Print #TempFile2, Strng
    Print #TempFile3, Strng
    Print #TempFile4, Strng2
    Exit Sub
 Endif

 Print #TempFile2, ""
 Print #TempFile3, ""
 Print #TempFile4, ""
 Close #TempFile1
 FileName=DND.Path+"SORT2"+NodeX+".SWP"
 Open FileName For Random Shared As #TempFile1 Len=12
 Field #TempFile1,4 As U$,8 As Z$
 Strng="DNDBBS v"+Version$+" r"+Release$+" t"+Tweak$+" Top Ten Player Rankings For "+Fclock$+"."
 Print #TempFile2, Strng
 Print #TempFile3, Strng
 Strng=Chr$(27)+"[0;1;37m"+Strng
 Print #TempFile4, Strng
 Strng=Nul
 Print #TempFile2, Strng
 Print #TempFile3, Strng
 Print #TempFile4, Strng
 TempZ!=SFalse
 For Temp.User.Index=1! To TempX!
    Call Read.Record(UserFile2,Temp.User.Index)
    Strng=UserRecord2.CodeName
    If (UserRecord2.Flags And Locked.User)=False Then
       If Left$(Strng,9)<>Deleted$ Then
          If UserRecord2.Level>=1 Then
             TempA#=Cdbl(UserRecord2.PermanentKilled*UserRecord2.Level*10)+ _
             Cdbl(UserRecord2.PlayersKilled*UserRecord2.Level*2)+ _
             Cdbl(UserRecord2.MonstersKilled*UserRecord2.Level)
             If TempA#>DFalse Then
                TempZ!=TempZ!+1!
                Lset U$=Mks$(Temp.User.Index)
                Lset Z$=Mkd$(TempA#)
                Put #TempFile1,TempZ!
             Endif
          Endif
       Endif
    Endif
 Next
 If TempZ!>SFalse Then
    For VarS1!=1! To TempZ!
       For VarS2!=VarS1!+1! To TempZ!
          Get #TempFile1,VarS1!
          TempZ1!=Cvs(U$)
          TempX1#=Cvd(Z$)
          Get #TempFile1,VarS2!
          TempZ2!=Cvs(U$)
          TempX2#=Cvd(Z$)
          If TempX1#<TempX2# Then
             Lset U$=Mks$(TempZ1!)
             Lset Z$=Mkd$(TempX1#)
             Put #TempFile1,VarS2!
             Lset U$=Mks$(TempZ2!)
             Lset Z$=Mkd$(TempX2#)
             Put #TempFile1,VarS1!
          Endif
       Next
    Next
 Endif
 If TempZ!>10! Then
    TempZ!=10!
 Endif
 Strng="Username                       Level   Classname            Ranking"
 Print #TempFile2, Strng
 Print #TempFile3, Strng
 Strng=Chr$(27)+"[0;1;33m"+Strng
 Print #TempFile4, Strng
 Strng=String$(67,"-")
 Print #TempFile2, Strng
 Print #TempFile3, Strng
 Strng=Chr$(27)+"[0;1;33m"+Strng
 Print #TempFile4, Strng
 TempX=False
 For Temp1!=1! To TempZ!
    Get #TempFile1,Temp1!
    TempX!=Cvs(U$)
    TempZ#=Cvd(Z$)
    Call Read.Record(UserFile2,TempX!)
    Strng=UserRecord2.CodeName
    Strng=Lcase$(Strng)
    Mid$(Strng,1,1)=Ucase$(Mid$(Strng,1,1))
    Strng=Rtrim$(Strng)
    Strng=Left$(Strng,30)
    VarQ=31-Len(Strng)
    Strng2=Chr$(27)+"[0;1;35m"+Strng
    Print #TempFile4, Strng2;
    Print #TempFile3, Strng;
    If Len(ANSIPrefixChar) Then
       Strng=Rtrim$(UserRecord2.Prefix1)+Strng
    Endif
    Print #TempFile2, Strng;
    Strng=""
    Strng2=""
    If Len(ANSIPrefixChar) Then
       Strng=ANSIPrefixChar+"FF"
       Strng=Strng+ANSIPrefixChar+"B0"
    Endif
    Strng=Strng+Space$(VarQ)
    If UserRecord2.Level>=32000 Then
       Strng=Strng+"Ghod  "
    Else
       Strng=Strng+Mid$(Str$(UserRecord2.Level),2)
       Strng=Strng+Space$(7-Len(Str$(UserRecord2.Level)))
    Endif
    Strng=Strng+"  "

    Strng2=Strng2+Space$(VarQ)
    If UserRecord2.Level>=32000 Then
       Strng2=Strng2+"Ghod  "
    Else
       Strng2=Strng2+Mid$(Str$(UserRecord2.Level),2)
       Strng2=Strng2+Space$(7-Len(Str$(UserRecord2.Level)))
    Endif
    Strng2=Strng2+"  "
    Print #TempFile2, Strng;
    Print #TempFile3, Strng2;
    Print #TempFile4, Strng2;
    Strng=UserRecord2.ClassName
    Strng=Rtrim$(Strng)
    Strng=Left$(Strng,20)
    VarQ=21-Len(Strng)
    Print #TempFile3, Strng;
    Print #TempFile4, Strng;
    If Len(ANSIPrefixChar) Then
       Strng=Rtrim$(UserRecord2.Prefix2)+Strng
    Endif
    Print #TempFile2, Strng;
    TempX=True
    Strng=""
    Strng2=""
    If Len(ANSIPrefixChar) Then
       Strng=ANSIPrefixChar+"FF"
       Strng=Strng+ANSIPrefixChar+"B0"
    Endif
    Strng=Strng+Space$(VarQ)
    Strng=Strng+Mid$(Str$(TempZ#),2)
    Print #TempFile2, Strng
    Strng2=Strng2+Space$(VarQ)
    Strng2=Strng2+Mid$(Str$(TempZ#),2)
    Print #TempFile3, Strng2
    Print #TempFile4, Strng2
 Next
 If TempX=False Then
    Strng="No users have top scores."
    Print #TempFile2, Strng
    Print #TempFile3, Strng
    Strng2=Chr$(27)+"[0;1;35m"+Strng
    Print #TempFile4, Strng2
 Endif
 Close #TempFile1
 If Dir$(FileName)<>"" Then
    Kill FileName
 Endif
ErrResume9:
 Exit Sub
ErrTrap9:
 Resume ErrResume9
End Sub

Sub Top.Ten.Teams
 On Local Error Goto ErrTrap10
 TempX!=Lof(TeamFile)/TeamRecLen
 If TempX!=SFalse Then
    Print #TempFile2, ""
    Print #TempFile3, ""
    Print #TempFile4, ""

    Strng="Top Ten Team Ranking"
    Strng2=Chr$(27)+"[0;1;37m"+Strng
    Print #TempFile2, Strng
    Print #TempFile3, Strng
    Print #TempFile4, Strng2

    Strng=String$(20,"-")
    Strng2=Chr$(27)+"[0;1;37m"+Strng
    Print #TempFile2, Strng
    Print #TempFile3, Strng
    Print #TempFile4, Strng2

    Strng="No teams exist."
    Strng2=Chr$(27)+"[0;1;35m"+Strng
    Print #TempFile2, Strng
    Print #TempFile3, Strng
    Print #TempFile4, Strng2
    Exit Sub
 Endif

 Print #TempFile2, ""
 Print #TempFile3, ""
 Print #TempFile4, ""
 If Len(ANSIPrefixChar) Then
    Strng=ANSIPrefixChar+"M2" ' green prompt
    Print #TempFile2, Strng;
 Endif

 Close #TempFile1
 FileName=DND.Path+"SORT2"+NodeX+".SWP"
 Open FileName For Random Shared As #TempFile1 Len=12
 Field #TempFile1,4 As U$,8 As Z$
 Strng="DNDBBS v"+Version$+" r"+Release$+" t"+Tweak$+" Top Ten Team Rankings For "+Fclock$+"."
 Print #TempFile2, Strng
 Print #TempFile3, Strng
 Strng=Chr$(27)+"[0;1;37m"+Strng
 Print #TempFile4, Strng
 Strng=Nul
 Print #TempFile2, Strng
 Print #TempFile3, Strng
 Print #TempFile4, Strng
 TempZ!=SFalse
 For Var1!=1! To TempX!
    Call Read.Record(TeamFile,Var1!)
    Strng=Rtrim$(TeamRecord.Name)
    Strng=Lcase$(Strng)
    If Len(Strng) And TeamRecord.Deleted=False Then
       TempQ=False
       TempA#=DFalse
       For Var2=1 To MaxTeamMembers
          Temp2$=Rtrim$(TeamRecord.Member(Var2))
          If Len(Temp2$) Then
             VarY!=TeamRecord.UserIndex(Var2)
             If VarY!>SFalse And VarY!<=Lof(UserFile2)/UserRecLen Then
                Call Read.Record(UserFile2,VarY!)
                Strng=UserRecord2.CodeName
                If Left$(Strng,9)<>Deleted$ Then
                   TempQ=True
                   If UserRecord2.Level>=1 Then
                      TempA#=TempA#+Cdbl(UserRecord2.PermanentKilled*UserRecord2.Level*10)+ _
                      Cdbl(UserRecord2.PlayersKilled*UserRecord2.Level*2)+ _
                      Cdbl(UserRecord2.MonstersKilled*UserRecord2.Level)
                   Endif
                Endif
             Endif
          Endif
       Next
       If TempQ Then
          If TempA#>DFalse Then
             TempZ!=TempZ!+1!
             Lset U$=Mks$(Var1!)
             Lset Z$=Mkd$(TempA#)
             Put #TempFile1,TempZ!
          Endif
       Endif
    Endif
 Next
 If TempZ!>SFalse Then
    For VarS1!=1! To TempZ!
       For VarS2!=VarS1!+1! To TempZ!
          Get #TempFile1,VarS1!
          TempZ1!=Cvs(U$)
          TempX1#=Cvd(Z$)
          Get #TempFile1,VarS2!
          TempZ2!=Cvs(U$)
          TempX2#=Cvd(Z$)
          If TempX1#<TempX2# Then
             Lset U$=Mks$(TempZ1!)
             Lset Z$=Mkd$(TempX1#)
             Put #TempFile1,VarS2!
             Lset U$=Mks$(TempZ2!)
             Lset Z$=Mkd$(TempX2#)
             Put #TempFile1,VarS1!
          Endif
       Next
    Next
 Endif
 If TempZ!>10! Then
    TempZ!=10!
 Endif
 Strng="Teamname                       Members Gold               Ranking"
 Print #TempFile2, Strng
 Print #TempFile3, Strng
 Strng=Chr$(27)+"[0;1;33m"+Strng
 Print #TempFile4, Strng
 Strng=String$(65,"-")
 Print #TempFile2, Strng
 Print #TempFile3, Strng
 Strng=Chr$(27)+"[0;1;33m"+Strng
 Print #TempFile4, Strng
 TempX=False
 For Temp1!=1! To TempZ!
    Get #TempFile1,Temp1!
    TempX!=Cvs(U$)
    TempZ#=Cvd(Z$)
    Call Read.Record(TeamFile,TempX!)
    Strng=TeamRecord.Name
    Strng=Rtrim$(Strng)
    Strng=Lcase$(Strng)
    Call Capitalize(Strng)
    Strng=Left$(Strng,30)
    VarQ=31-Len(Strng)
    If Rtrim$(Strng)<>Nul Then
       Strng2=Chr$(27)+"[0;1;35m"+Strng
       Print #TempFile4, Strng2;
       Print #TempFile3, Strng;
       If Len(ANSIPrefixChar) Then
          Strng=Rtrim$(TeamRecord.Prefix1)+Strng
       Endif
       Print #TempFile2, Strng;
       TempQ=False
       For Temp2=1 To MaxTeamMembers
          VarY!=TeamRecord.UserIndex(Temp2)
          If VarY!>SFalse And VarY!<=Lof(UserFile2)/UserRecLen Then
             Call Read.Record(UserFile2,VarY!)
             Var2$=UserRecord2.CodeName
             If Left$(Var2$,9)<>Deleted$ Then
                TempQ=TempQ+1
             Endif
          Endif
       Next
       Strng=""
       Strng2=""
       If Len(ANSIPrefixChar) Then
          Strng=ANSIPrefixChar+"FF"
          Strng=Strng+ANSIPrefixChar+"B0"
       Endif
       Strng=Strng+Space$(VarQ)
       Strng=Strng+Mid$(Str$(TempQ),2)
       Strng=Strng+Space$(8-Len(Str$(TempQ)))
       Temp#=TeamRecord.Gold
       Strng=Strng+Str$(Temp#)
       Strng=Strng+Space$(19-Len(Str$(Temp#)))
       Strng=Strng+Str$(TempZ#)

       Strng2=Strng2+Space$(VarQ)
       Strng2=Strng2+Mid$(Str$(TempQ),2)
       Strng2=Strng2+Space$(8-Len(Str$(TempQ)))
       Temp#=TeamRecord.Gold
       Strng2=Strng2+Str$(Temp#)
       Strng2=Strng2+Space$(19-Len(Str$(Temp#)))
       Strng2=Strng2+Str$(TempZ#)
       TempX=True
       Print #TempFile2, Strng
       Print #TempFile3, Strng2
       Print #TempFile4, Strng2
    Endif
 Next
 If TempX=False Then
    Strng="No teams have top scores."
    Strng2=Chr$(27)+"[0;1;35m"+Strng
    Print #TempFile2, Strng
    Print #TempFile3, Strng
    Print #TempFile4, Strng2
 Endif
 Close #TempFile1
 If Dir$(FileName)<>"" Then
    Kill FileName
 Endif
ErrResume10:
 Exit Sub
ErrTrap10:
 Resume ErrResume10
End Sub

Sub Get.Node
 On Local Error Goto Node.Error
 NodeX=Nul
 Var$=Command$
 Var$=Ltrim$(Rtrim$(Var$))
 V=Instr(Var$,"/D")
 If V Then
    Var$=Left$(Var$,V-1)+Mid$(Var$,V+2)
 Endif
 V=Instr(Var$,"/Z")
 If V Then
    Var$=Left$(Var$,V-1)+Mid$(Var$,V+2)
 Endif
 If Var$=Nul Then
    Exit Sub
 Endif
 ' check to over-ride specific node number
 NodeX=Nul
 TempA$=Nul
 Var1=Instr(Ucase$(Var$),"/N:")
 If Var1 Then
    VarQ$=Mid$(Var$,Var1+3,1)
    Select Case Ucase$(VarQ$)
    Case ""
       TempA$=Nul
       Exit Sub
    Case "0" To "9"
       TempA$=VarQ$
       VarQ2$=Mid$(Var$,Var1+4,1)
       If VarQ2$>="0" And VarQ2$<="9" Then
          TempA$=TempA$+VarQ2$ ' 10-99
          Var$=Left$(Var$,Var1-1)+Mid$(Var$,Var1+5)
       Else
          Var$=Left$(Var$,Var1-1)+Mid$(Var$, Var1+4)
       Endif
    Case "A" To "Z" ' 64-90
       TempA$=VarQ$
       Var$=Left$(Var$,Var1-1)+Mid$(Var$,Var1+4)
    End Select
 Endif
 NodeX=Nul
 If Len(TempA$) Then
    TempA$=Ucase$(TempA$)
    Select Case Len(TempA$)
    Case 0
       NodeX=""
       TempA$=""
    Case 1
       Select Case TempA$
       Case "0" To "9"
          NodeX=TempA$
          TempA$=Nul
       Case "A" To "Z"
          NodeX=TempA$
          TempA$=Nul
       End Select
    Case 2
       VarX=Int(Val(TempA$)+.5)
       If VarX>=10 And VarX<=99 Then
          NodeX=Mid$(Str$(VarX),2)
          TempA$=Nul
       Endif
    End Select
 Endif
 If TempA$<>Nul Then
    Goto Node.Error
 Endif
 If Var$<>Nul Then
    Goto Node.Error
 Endif
 Exit Sub
Node.Error:
 Color 15,0
 Print
 Print "Topten Module v1.5a"
 Color 14,0
 Print "Error reading node. Node must be <nul>,0-9,A-Z,10-99."
 Color 7,0
 End
End Sub

Sub Open.Arrays
 On Local Error Goto Array.Error
 Local.Mode=True
 Lost.Carrier=False
 Call Read.Rows(Max.Row)
 Locate Max.Row,1,1
 Exit Sub
Array.Error:
 Color 15,0
 Print
 Print "Topten Module v1.5a"
 Color 14,0
 Print "Error opening arrays. Free more RAM."
 Color 7,0
 End
End Sub

Sub Get.Config
 On Local Error Goto Config.Error
 DND.Path=Environ$("DNDBBS")
 If DND.Path<>Nul Then
    If Right$(DND.Path,1)<>"\" Then
       DND.Path=DND.Path+"\"
    Endif
 Endif
 FileName=DND.Path+"DND"+NodeX+".CFG"
 Close #TempFile1
 Open FileName For Input Shared As #TempFile1
 Line Input #TempFile1,Var$
 For Temp1=1 To MaxConfigArray1
    Input #TempFile1,Var!
 Next
 For Temp1=1 To MaxConfigArray2
    Input #TempFile1,Var%
    Select Case Temp1
    Case 48
       Allow.High.Class=Var%
    Case 81
       Allow.Remote.Edit=Var%
    Case 86
       User.Echo=Var%
    Case 87
       User.Linefeeds=Var%
    Case 88
       User.Linelength=Var%
    Case 89
       User.Pagelength=Var%
    Case 90
       User.Wordwrap=Var%
    End Select
 Next
 For Temp1=1 To MaxConfigArray3
    Line Input #TempFile1,Var$
    Select Case Temp1
    Case 11
       Data.Path1=Var$
    Case 15
       File.Extension1=Var$
    Case 21
       User.FileName=Var$
    Case 52
       Data.Path2=Var$
    Case 53
       Data.Path3=Var$
    Case 54
       Data.Path4=Var$
    Case 57
       Team.FileName=Var$
    Case 62
       File.Extension2=Var$
    Case 85
       ANSIPrefixChar=Var$
    End Select
 Next
 Exit Sub
Config.Error:
 Color 15,0
 Print
 Print "Topten Module v1.5a"
 Color 14,0
 Print "Error reading "+Lcase$(FileName)+" (error:"+Str$(Err)+"). Run Dndcnfg."
 Color 7,0
 End
End Sub

Sub Make.FileNames
 On Local Error Goto Make.Error
 Out2=Environ$("DNDDAT")
 If Out2<>Nul Then
    If Right$(Out2,1)<>"\" Then
       Out2=Out2+"\"
    Endif
    Data.Path1=Out2
 Endif
 FileName=Data.Path1+Team.FileName+File.Extension1
 FileName=Data.Path1+User.FileName+File.Extension1
 Team.FileName=Data.Path1+Team.FileName+File.Extension1
 User.FileName=Data.Path1+User.FileName+File.Extension1
 TempFile3=30
 TempFile4=31
 Exit Sub
Make.Error:
 Color 15,0
 Print
 Print "Topten Module v1.5a"
 Color 14,0
 Print "Error making "+Lcase$(FileName)+" (error:"+Str$(Err)+"). Increase files= in config.sys or run Dndcnfg."+Chr$(13)+Chr$(10)
 Color 7,0
 End
End Sub

Sub Open.Files
 On Local Error Goto Open.Error
 Close
 TeamRecLen=Len(TeamRecord)
 UserRecLen=Len(UserRecord)
 FileName=Team.FileName
 Open FileName For Random Shared As #TeamFile Len=TeamRecLen
 FileName=User.FileName
 Open FileName For Random Shared As #UserFile2 Len=UserRecLen
 Exit Sub
Open.Error:
 Color 15,0
 Print
 Print "Topten Module v1.5a"
 Color 14,0
 Print "Error opening "+Lcase$(FileName)+" (error:"+Str$(Err)+"). Increase files= in config.sys or run Dndcnfg."+Chr$(13)+Chr$(10)
 Color 7,0
 End
End Sub

Sub Reset.Cursor
 On Local Error Goto ErrMain13
' Call ScreenANSI(1,37,7)
 Locate Max.Row-1,1,1
 Graphics.Off=False
 Line.Length=False
MainExit13:
 Exit Sub
ErrMain13:
 Resume MainExit13
End Sub

Sub Read.Rows(Var)
 On Local Error Goto Error.Trap62x
 Temp1=50
 Locate 50,1,0
 Var=50
 Exit Sub
Next.Trap1:
 Temp1=43
 Locate 43,1,0
 Var=43
 Exit Sub
Next.Trap2:
 Temp1=25
 Locate 25,1,0
 Var=25
 Exit Sub
Next.Trap3:
 Var=12
Error.Resume62x:
 Exit Sub
Error.Trap62x:
 If Temp1=50 Then
    Resume Next.Trap1
 Endif
 If Temp1=43 Then
    Resume Next.Trap2
 Endif
 If Temp1=25 Then
    Resume Next.Trap3
 Endif
 Resume Error.Resume62x
End Sub

' following stub subroutines from newly edited io.bas
Sub Close.Files
 ' nul
End Sub

Sub Open.Shell.Files
 ' nul
End Sub

Sub Display.Status.Line()
 ' nul
End Sub
