Module Pepperbet

    'Seconds between updates
    Const updatedelay = 2
    Const version As String = "1.10"
    Const downloadurl As String = "https://long-cat.net/projects/pepperbet/pepperbet.exe?v=" & version
    Const versionurl As String = "https://long-cat.net/projects/pepperbet/version.txt?v=" & version
    Const dbfilename As String = "pepperdata.xml"
    Dim TheList As New List(Of Glicko)
    Dim match As Long = 0
    Dim names As New List(Of String)
    Dim watching As Boolean = True
    Dim autoupdate As Boolean = False
    Dim lastupdatecheck As New DateTime(0)
    Dim accuracies(9) As Double
    'These are the time constants for the exponentially weighted falloff
    Dim accuracytimeconstants() As Double = {10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000}

    Enum ModeTypes
        Matchmaking
        Tournament
        Exhibitions
    End Enum
    Dim Mode As ModeTypes

    Sub Main()
        'test case in case you modify the glicko functions
        'THIS TEST MAY NO LONGER WORK WITH MY MODIFICATIONS TO RD IN THE CASE OF UPSETS
        'Dim testman As New Glicko("testman", 0)
        'testman.K = 1500
        'testman.RD = 200
        'Dim opp1 As New Glicko("1", 0)
        'opp1.K = 1400
        'opp1.RD = 30
        'Dim opp2 As New Glicko("2", 0)
        'opp2.K = 1550
        'opp2.RD = 100
        'Dim opp3 As New Glicko("3", 0)
        'opp3.K = 1700
        'opp3.RD = 300

        'testman.Update({opp1, opp2, opp3}, {1, 0, 0}, 0)
        'testmans K should be 1464 and RD should be 151.4


        Try

            Dim xdoc As New Xml.XmlDocument
            xdoc = Nothing
            Dim wc As New System.Net.WebClient
            Dim p1 As Glicko = Nothing
            Dim p1name As String
            Dim p2 As Glicko = Nothing
            Dim p2name As String
            Dim tempindex As Integer
            Dim state As String
            Dim manualmode As Boolean = False
            Dim tempkey As ConsoleKeyInfo
            Dim bootstrap As Boolean = True
            Dim blankline As String = "                                                                               "
            Dim lastupdate As Date
            Dim skippingmatch As Boolean = False
            Dim alertstr As String = ""
            Dim remainingstr As String = ""

            Try
                If Environment.GetCommandLineArgs.Count > 1 Then
                    For Each x In Environment.GetCommandLineArgs
                        If x.StartsWith("-delupdater") Then
                            Thread.Sleep(250)
                            FileIO.FileSystem.DeleteFile(x.Substring(11))
                        End If
                    Next
                End If
            Catch
            End Try

            Console.WindowWidth = 80
            Console.BufferHeight = 420
            Console.Title = "PepperBet"
            Console.BackgroundColor = ConsoleColor.Black
            Console.ForegroundColor = ConsoleColor.White
            Console.WriteLine("                              ╔════════════════╗")
            Console.Write("──────────────────────────────╢   ")
            Console.ForegroundColor = ConsoleColor.Red
            Console.Write("Pepper ")
            Console.ForegroundColor = ConsoleColor.Cyan
            Console.Write("Bet")
            Console.ForegroundColor = ConsoleColor.White
            Console.WriteLine("   ╟──────────────────────────────")
            'DONT FORGET TO CHANGE IT UP IN THE CONST
            Console.WriteLine("──────────────────────────────╢     v" & version & "      ╟──────────────────────────────")
            'DONT FORGET TO CHANGE IT UP IN THE CONST
            Console.WriteLine("                              ╚════════════════╝")
            Console.WriteLine()
            Console.ForegroundColor = ConsoleColor.Gray
            Console.WriteLine("(c) 2013-2020 by moose crap http://long-cat.net")
            Console.WriteLine("Thanks to Fredstonemason for help and testing")
            Console.WriteLine()
            helpstring()
            'Console.WriteLine("[T]ier")
            Console.WriteLine()
            Load()
            If autoupdate Then
                CheckForUpdates()
            End If
            Console.WriteLine("{0} fighters loaded from " & dbfilename & ".", TheList.Count)
            If names.Count > 0 Then
                Console.Write("Watching: ")
                For Each x In names
                    Console.Write(x & ", ")
                Next
                Console.WriteLine()
            End If


            While xdoc Is Nothing
                Try
                    xdoc = Newtonsoft.Json.JsonConvert.DeserializeXmlNode(wc.DownloadString("http://www.saltybet.com/state.json"), "saltybet")
                Catch ex As Exception
                    xdoc = Nothing
                    System.Threading.Thread.Sleep(1500)
                End Try
            End While

            state = "nigga"

            While True      'main loop
                lastupdate = Date.UtcNow

                If Not bootstrap Then  'dont reload state.json if we're in bootstrap mode
                    Try
                        xdoc = Newtonsoft.Json.JsonConvert.DeserializeXmlNode(wc.DownloadString("http://www.saltybet.com/state.json"), "saltybet")
                    Catch ex As Exception
                        xdoc = Nothing
                    End Try
                End If

                If Not xdoc Is Nothing AndAlso
                xdoc.SelectSingleNode("saltybet/status").InnerText <> state Then

                    alertstr = xdoc.SelectSingleNode("saltybet/alert").InnerText
                    remainingstr = xdoc.SelectSingleNode("saltybet/remaining").InnerText
                    UpdateTitle(manualmode, alertstr, remainingstr)

                    If bootstrap = True Then  'advance states as we rotate through in bootstrap mode
                        Select Case state
                            Case "nigga"
                                state = "open"
                            Case "open"
                                state = "locked"
                            Case Else
                                state = xdoc.SelectSingleNode("saltybet/status").InnerText
                        End Select
                        If xdoc.SelectSingleNode("saltybet/status").InnerText = state Then
                            bootstrap = False
                        End If
                    Else
                        state = xdoc.SelectSingleNode("saltybet/status").InnerText
                    End If

                    Select Case state
                        Case "open"
                            If autoupdate Then
                                CheckForUpdates()
                            End If

                            If remainingstr.Contains("exhibition match") Then
                                Mode = ModeTypes.Exhibitions
                            ElseIf remainingstr.Contains("FINAL ROUND") Or remainingstr.Contains("bracket") Then
                                Mode = ModeTypes.Tournament
                            Else
                                Mode = ModeTypes.Matchmaking
                            End If

                            match += 1
                            skippingmatch = False
                            p1name = xdoc.SelectSingleNode("saltybet/p1name").InnerText
                            p2name = xdoc.SelectSingleNode("saltybet/p2name").InnerText
                            tempindex = TheList.FindIndex(Function(a) a.Name = p1name)

                            If Mode = ModeTypes.Exhibitions Then
                                skippingmatch = True
                            End If

                            If tempindex = -1 Then      'p1 never seen before
                                p1 = New Glicko(p1name, match)
                                If Not skippingmatch Then
                                    TheList.Add(p1)
                                End If
                            Else
                                p1 = TheList(tempindex)
                            End If

                            tempindex = TheList.FindIndex(Function(a) a.Name = p2name)
                            If tempindex = -1 Then      'p2 never seen before
                                p2 = New Glicko(p2name, match)
                                If Not skippingmatch Then
                                    TheList.Add(p2)
                                End If
                            Else
                                p2 = TheList(tempindex)
                            End If


                            If skippingmatch And (TheList.Contains(p1) And TheList.Contains(p2)) Then
                                DoMatchup(p1, p2, False, True)
                            ElseIf skippingmatch Then
                                Console.WriteLine()
                                If TheList.Contains(p1) Then
                                    Console.ForegroundColor = ConsoleColor.Gray
                                    Console.BackgroundColor = ConsoleColor.Black
                                    Console.Write("[{0,4:####}]", p1.K)
                                    Console.Write(" {0,-3:###} ", p1.RD)
                                    Console.ForegroundColor = ConsoleColor.Red
                                    'Console.Write("{0,26}", TrimString(If(p1.LastMatch = match, "(N) ", "") + If((p1.Tier <> p2.Tier) And (p1.Tier <> Glicko.Tiers.Unknown) And (p2.Tier <> Glicko.Tiers.Unknown), "(" + p1.TierLetter + ") ", "") + p1.Name, 26))
                                    Console.Write("{0,26}", TrimString(p1.Name, 26))
                                Else
                                    Console.ForegroundColor = ConsoleColor.Red
                                    Console.BackgroundColor = ConsoleColor.Black
                                    Console.Write("{0,37}", TrimString(p1.Name, 37))
                                End If

                                Console.ForegroundColor = ConsoleColor.Gray
                                Console.Write(" vs ")
                                Console.ForegroundColor = ConsoleColor.Cyan
                                Console.BackgroundColor = ConsoleColor.Black
                                If TheList.Contains(p2) Then

                                    'Console.Write("{0,-26}", TrimString(If(p2.LastMatch = match, "(N) ", "") + If((p1.Tier <> p2.Tier) And (p1.Tier <> Glicko.Tiers.Unknown) And (p2.Tier <> Glicko.Tiers.Unknown), "(" + p2.TierLetter + ") ", "") + p2.Name, 26))
                                    Console.Write("{0,-26}", TrimString(p2.Name, 26))
                                    Console.BackgroundColor = ConsoleColor.Black
                                    Console.ForegroundColor = ConsoleColor.Gray
                                    Console.Write(" [{0,4:####}]", p2.K)
                                    Console.Write(" {0,-3:###} " + vbNewLine, p2.RD)
                                Else
                                    Console.WriteLine("{0,-37}", TrimString(p2.Name, 37))
                                End If
                            Else

                                DoMatchup(p1, p2, False)
                            End If


                            'Glicko.UpdateTiers(p1, p2)

                        Case "locked"
                            If xdoc.SelectSingleNode("saltybet/p1name").InnerText <> p1.Name Or
                            xdoc.SelectSingleNode("saltybet/p2name").InnerText <> p2.Name Then
                                state = "nigga"
                                bootstrap = True
                                Exit Select
                            End If
                            Dim p1t As Long = xdoc.SelectSingleNode("saltybet/p1total").InnerText.Replace(",", "")
                            Dim p2t As Long = xdoc.SelectSingleNode("saltybet/p2total").InnerText.Replace(",", "")
                            Dim ratiostring As String

                            Console.ForegroundColor = ConsoleColor.Red
                            Console.Write("{0,34} ", "$" + xdoc.SelectSingleNode("saltybet/p1total").InnerText)
                            If p1t > p2t Then
                                Console.ForegroundColor = ConsoleColor.Red
                                ratiostring = (p1t / p2t).ToString("0.0") + ":1"
                            Else
                                Console.ForegroundColor = ConsoleColor.Cyan
                                ratiostring = "1:" + (p2t / p1t).ToString("0.0")
                            End If
                            Console.Write("{0,-8}", ratiostring)
                            Console.ForegroundColor = ConsoleColor.Cyan
                            Console.Write("{0,-34} " + vbCrLf, "$" + xdoc.SelectSingleNode("saltybet/p2total").InnerText)
                            If watching = False Or names.Count = 0 Then
                                Exit Select
                            End If
                            Dim zdata As New Xml.XmlDocument
                            Try
                                zdata = Newtonsoft.Json.JsonConvert.DeserializeXmlNode(wc.DownloadString("http://www.saltybet.com/zdata.json").ToLowerInvariant, "saltybet")
                            Catch
                            End Try
                            If Not zdata Is Nothing Then
                                For Each x In names
                                    Dim didbet As Boolean = False
                                    Dim bank As Long
                                    Dim wager As Long
                                    Dim player As Integer
                                    If watching And names.Count <> 0 Then
                                        Dim playerelement As Xml.XmlElement = zdata.SelectSingleNode("saltybet/*/n[.=""" & x.ToLowerInvariant & """]")
                                        If Not playerelement Is Nothing Then
                                            playerelement = playerelement.ParentNode
                                            bank = CLng(playerelement.SelectSingleNode("b").InnerText)
                                            wager = CLng(playerelement.SelectSingleNode("w").InnerText)
                                            player = CInt(playerelement.SelectSingleNode("p").InnerText)
                                            didbet = True
                                        End If
                                    End If
                                    If didbet Then
                                        Console.ForegroundColor = ConsoleColor.Gray
                                        If player = 1 Then
                                            Console.WriteLine("{0,-78}", x & ": " & bank.ToString("$#,#") & " [" & wager.ToString("$#,#") & " " & (wager / bank).ToString("#0.0%") & "] " & Math.Ceiling(wager * (p2t / p1t)).ToString("+$#,#"))
                                        Else
                                            Console.WriteLine("{0,78}", x & ": " & bank.ToString("$#,#") & " [" & wager.ToString("$#,#") & " " & (wager / bank).ToString("#0.0%") & "] " & Math.Ceiling(wager * (p1t / p2t)).ToString("+$#,#"))

                                        End If
                                    End If
                                Next
                            End If
                        Case "1"
                            If xdoc.SelectSingleNode("saltybet/p1name").InnerText <> p1.Name Or
                            xdoc.SelectSingleNode("saltybet/p2name").InnerText <> p2.Name Then
                                state = "nigga"
                                bootstrap = True
                                Exit Select
                            End If
                            If skippingmatch Then
                                Console.ForegroundColor = ConsoleColor.Red
                                Console.BackgroundColor = ConsoleColor.Black
                                Console.WriteLine("                                   <-------")
                                Exit Select
                            End If
                            If manualmode = True Then
                                Console.ForegroundColor = ConsoleColor.Gray
                                Console.Write("Enter match scores: ")
                                Dim scorestr As String = Console.ReadLine
                                Console.CursorTop -= 1
                                DoResults(p1, p2, True, False, scorestr)
                                manualmode = False
                                UpdateTitle(manualmode, alertstr, remainingstr)
                            Else
                                DoResults(p1, p2, True, False)
                            End If

                            Save()

                        Case "2"
                            If xdoc.SelectSingleNode("saltybet/p1name").InnerText <> p1.Name Or
                            xdoc.SelectSingleNode("saltybet/p2name").InnerText <> p2.Name Then
                                state = "nigga"
                                bootstrap = True
                                Exit Select
                            End If
                            If skippingmatch Then
                                Console.ForegroundColor = ConsoleColor.Cyan
                                Console.BackgroundColor = ConsoleColor.Black
                                Console.WriteLine("                                   ------->")
                                Exit Select
                            End If
                            If manualmode = True Then
                                Console.ForegroundColor = ConsoleColor.Gray
                                Console.Write("Enter match scores: ")
                                Dim scorestr As String = Console.ReadLine
                                Console.CursorTop -= 1
                                DoResults(p1, p2, False, False, scorestr)
                                manualmode = False
                                UpdateTitle(manualmode, alertstr, remainingstr)
                            Else
                                DoResults(p1, p2, False, False)
                            End If

                            Save()

                    End Select
                End If

                While Not bootstrap And (Date.UtcNow - lastupdate).TotalSeconds < updatedelay
                    tempkey = Nothing
                    While Console.KeyAvailable
                        tempkey = Console.ReadKey(True)
                    End While

                    If tempkey.Key = ConsoleKey.Enter Then
                        If Not skippingmatch Then
                            manualmode = True
                            UpdateTitle(manualmode, alertstr, remainingstr)
                        End If
                        'Console.ForegroundColor = ConsoleColor.Gray
                        'Console.BackgroundColor = ConsoleColor.Black
                        'Console.WriteLine("Manual input engaged")

                    ElseIf tempkey.Key = ConsoleKey.Escape Then
                        manualmode = False
                        UpdateTitle(manualmode, alertstr, remainingstr)

                    ElseIf tempkey.Key = ConsoleKey.H OrElse tempkey.Key = ConsoleKey.Oem2 Then
                        Console.ForegroundColor = ConsoleColor.Gray
                        helpstring()

                    ElseIf tempkey.Key = ConsoleKey.N Then
                        Console.ForegroundColor = ConsoleColor.Gray
                        Console.Write("Saltybet usernames: ")
                        For Each x In names
                            System.Windows.Forms.SendKeys.SendWait(x & ",")
                        Next
                        names.Clear()
                        Dim namestr As String = Console.ReadLine
                        For Each x In namestr.Split(",".ToCharArray)
                            If x <> String.Empty Then
                                names.Add(x.Trim(" ".ToCharArray))
                            End If
                        Next
                        Console.CursorTop -= 1
                        Console.Write(blankline)
                        Console.CursorLeft = 0
                        Save()

                    ElseIf tempkey.Key = ConsoleKey.W Then
                        watching = Not watching
                        Console.ForegroundColor = ConsoleColor.Gray
                        Console.WriteLine(blankline)
                        Console.CursorTop -= 1
                        Console.CursorLeft = 0
                        If watching Then
                            Console.Write("Bet display enabled")
                        Else
                            Console.Write("Bet display disabled")
                        End If
                        Console.CursorLeft = 0

                    ElseIf tempkey.Key = ConsoleKey.F Then
                        Console.ForegroundColor = ConsoleColor.Gray
                        Console.WriteLine(blankline)
                        Console.CursorTop -= 1
                        Console.CursorLeft = 0
                        Console.Write("Checking for updates...")
                        Console.CursorLeft = 0
                        CheckForUpdates(True)
                    ElseIf tempkey.Key = ConsoleKey.A Then
                        autoupdate = Not autoupdate
                        Console.ForegroundColor = ConsoleColor.Gray
                        Console.WriteLine(blankline)
                        Console.CursorTop -= 1
                        Console.CursorLeft = 0
                        If autoupdate Then
                            Console.Write("Automatic updates enabled")
                        Else
                            Console.Write("Automatic updates disabled")
                        End If
                        Console.CursorLeft = 0

                    ElseIf tempkey.Key = ConsoleKey.R Then
                        Console.ForegroundColor = ConsoleColor.Gray
                        Console.BackgroundColor = ConsoleColor.Black
                        Console.WriteLine("Prediction accuracy")
                        For i = 0 To accuracies.Length - 1
                            Console.WriteLine("{0,5}: {1:0.000000}", accuracytimeconstants(i), accuracies(i))
                        Next
                    ElseIf tempkey.Key = ConsoleKey.C Then
                        Console.ForegroundColor = ConsoleColor.Gray
                        Console.BackgroundColor = ConsoleColor.Black
                        Console.Write("This will attempt a cleanup of fighters, are you sure? ")
                        If Console.ReadLine.ToLowerInvariant = "y" Then
                            Dim rcount As Integer = 0
                            Dim j As Integer = 0
                            While j < TheList.Count
                                If TheList(j).RD = 350 OrElse TheList(j).RD = 290.230506091092 OrElse TheList(j).K = 1500 OrElse TheList(j).K = 1662.2120026057642 OrElse TheList(j).K = 1337.7879973942358 OrElse (((match - TheList(j).LastMatch) > 60000) And (TheList(j).RD > 250)) Then
                                    TheList.RemoveAt(j)
                                    rcount += 1
                                Else
                                    j += 1
                                End If
                            End While
                            Save()
                            Console.WriteLine("Cleaned up {0} entries", rcount)
                        End If


                        'ElseIf tempkey.Key = ConsoleKey.T Then
                        '    Console.ForegroundColor = ConsoleColor.Gray
                        '    Console.BackgroundColor = ConsoleColor.Black
                        '    Console.Write("Tier [U/X/P/B/A/S]: ")
                        '    Dim qstr As String = Console.ReadLine
                        '    Select Case qstr.ToLower
                        '        Case "u"
                        '            p1.Tier = Glicko.Tiers.Unknown
                        '            p2.Tier = Glicko.Tiers.Unknown
                        '        Case "x"
                        '            p1.Tier = Glicko.Tiers.X
                        '            p2.Tier = Glicko.Tiers.X
                        '        Case "p"
                        '            p1.Tier = Glicko.Tiers.Potato
                        '            p2.Tier = Glicko.Tiers.Potato
                        '        Case "b"
                        '            p1.Tier = Glicko.Tiers.B
                        '            p2.Tier = Glicko.Tiers.B
                        '        Case "a"
                        '            p1.Tier = Glicko.Tiers.A
                        '            p2.Tier = Glicko.Tiers.A
                        '        Case "s"
                        '            p1.Tier = Glicko.Tiers.S
                        '            p2.Tier = Glicko.Tiers.S
                        '    End Select
                        '    Console.CursorTop -= 1
                        '    Console.Write(blankline)
                        '    Console.CursorLeft = 0


                    ElseIf tempkey.Key = ConsoleKey.Q Then
                        Console.ForegroundColor = ConsoleColor.Gray
                        Console.BackgroundColor = ConsoleColor.Black
                        Console.Write("Character name: ")
                        Dim qstr As String
                        Dim result As Glicko = Nothing
                        Dim found As Boolean = True

                        found = Search(result)

                        If found = True Then
                            Console.Write("[U]pdate [D]elete [M]atch: ")
                            qstr = Console.ReadLine

                            Select Case qstr.ToLowerInvariant

                                Case "u"
                                    Console.Write("New K: ")
                                    qstr = Console.ReadLine
                                    If qstr <> "" Then
                                        Try
                                            result.K = CSng(qstr)
                                        Catch
                                            Console.WriteLine("Invalid string")
                                        End Try

                                    End If

                                    Console.Write("New RD: ")
                                    qstr = Console.ReadLine
                                    If qstr <> "" Then
                                        Try
                                            result.RD = CSng(qstr)
                                        Catch
                                            Console.WriteLine("Invalid string")
                                        End Try
                                    End If

                                    Console.Write("New Age: ")
                                    qstr = Console.ReadLine
                                    If qstr <> "" Then
                                        Try
                                            result.LastMatch = match - CInt(qstr)
                                        Catch
                                            Console.WriteLine("Invalid string")
                                        End Try
                                    End If

                                    'Console.Write("New Tier: ")
                                    'qstr = Console.ReadLine
                                    'If qstr <> "" Then
                                    '    Select Case qstr.ToLower
                                    '        Case "u"
                                    '            result.Tier = Glicko.Tiers.Unknown
                                    '        Case "x"
                                    '            result.Tier = Glicko.Tiers.X
                                    '        Case "p"
                                    '            result.Tier = Glicko.Tiers.Potato
                                    '        Case "b"
                                    '            result.Tier = Glicko.Tiers.B
                                    '        Case "a"
                                    '            result.Tier = Glicko.Tiers.A
                                    '        Case "s"
                                    '            result.Tier = Glicko.Tiers.S
                                    '    End Select
                                    'End If

                                    'Console.WriteLine("K: [{0,4:####}]  RD: {1,-3:###}  Age: {2:0}  Tier: {3}  " & TrimString(result.Name, 38), result.K, result.RD, match - result.LastMatch, result.TierLetter)
                                    Console.WriteLine("K: [{0,4:####}]  RD: {1,-3:###}  Age: {2:0}  " & result.Name, result.K, result.RD, match - result.LastMatch)
                                    Save()
                                Case "d"
                                    Console.Write("Are you sure? ")
                                    qstr = Console.ReadLine
                                    If qstr.ToLowerInvariant = "y" Then
                                        Console.WriteLine("{0} deleted", result.Name)
                                        TheList.Remove(result)
                                        Save()
                                    End If

                                Case "m"
                                    Console.Write("Opponent name: ")
                                    Dim result2 As Glicko = Nothing
                                    found = Search(result2)

                                    If found = True Then
                                        DoMatchup(result, result2, True)
                                        Console.Write("Enter match scores: ")
                                        Dim scorestr As String = Console.ReadLine
                                        Console.CursorTop -= 1
                                        Console.CursorLeft = 0
                                        If scorestr <> Nothing Then
                                            DoResults(result, result2, False, True, scorestr)
                                        End If
                                        Save()
                                    End If

                                Case Else
                                    Console.CursorTop -= 1
                                    Console.Write(blankline)
                                    Console.CursorLeft = 0

                            End Select


                        Else
                            Console.CursorTop -= 1
                            Console.Write(blankline)
                            Console.CursorLeft = 0
                        End If

                    End If

                    If Not bootstrap Then
                        System.Threading.Thread.Sleep(33.3333)
                    End If
                End While



            End While



        Catch ex As Exception
            Console.ForegroundColor = ConsoleColor.White
            Console.BackgroundColor = ConsoleColor.Red
            Console.WriteLine(ex.ToString)
            Console.ReadLine()
        End Try
    End Sub

    Private Sub UpdateTitle(manual As Boolean, alert As String, remaining As String)
        Dim titlestr As String = String.Empty
        titlestr = "PepperBet - "
        If manual Then
            titlestr &= "(Manual mode) - "
        End If
        If alert <> "" Then
            titlestr &= "Alert: " & alert & " - "
        End If
        If remaining <> "" Then
            titlestr &= remaining
        End If

        titlestr &= accuracies(0).ToString(" 0.000")
        titlestr &= accuracies(3).ToString(" 0.000")
        titlestr &= accuracies(6).ToString(" 0.000")

        Console.Title = titlestr
    End Sub

    Private Function Search(ByRef result As Glicko) As Boolean
        Dim qstr As String = "quit snooping the source code"
        Dim found As Boolean = True
        Dim results As New List(Of Glicko)
        Dim leftindex As Integer = Console.CursorLeft
        While qstr <> ""
            qstr = Console.ReadLine
            results = TheList.FindAll(Function(k) k.Name.ToLowerInvariant.Contains(qstr.ToLowerInvariant))
            If results.Count = 0 Then
                Console.CursorTop -= 1
                Console.CursorLeft = leftindex
                Console.Write(New String(" ", qstr.Length))
                Console.CursorLeft = leftindex
            Else
                Exit While
            End If
        End While

        

        If qstr = "" Then
            found = False
        ElseIf results.Count = 1 Then
            result = results(0)
            'Console.WriteLine("K: [{0,4:####}]  RD: {1,-3:###}  Age: {2:0}  Tier: {3}  " & TrimString(result.Name, 38), result.K, result.RD, match - result.LastMatch, result.TierLetter)
            Console.WriteLine("K: [{0,4:####}]  RD: {1,-3:###}  Age: {2:0}  " & result.Name, result.K, result.RD, match - result.LastMatch)

        Else
            results.Sort(Function(a, b) a.Name.CompareTo(b.Name))
            Console.ForegroundColor = ConsoleColor.White
            'Console.WriteLine("{0," + Math.Ceiling(Math.Log10(results.Count)).ToString + "}  K       RD   Age    Tier    Name", "")
            Console.WriteLine("{0," + Math.Ceiling(Math.Log10(results.Count)).ToString + "}  K       RD   Age     Name", "")
            Console.ForegroundColor = ConsoleColor.Gray
            For Each j In results
                Console.WriteLine("{3," + Math.Ceiling(Math.Log10(results.Count)).ToString + "}: [{0,4:####}]  {1,-3:###}  {2,-6:####0}  " & j.Name, j.K, j.RD, match - j.LastMatch, results.IndexOf(j))
            Next
            Console.Write("Select: ")
            Try
                result = results(CInt(Console.ReadLine))
            Catch
                found = False
            End Try
        End If
        Return found
    End Function

    Private Sub DoResults(p1 As Glicko, p2 As Glicko, p1win As Boolean, invcolors As Boolean, Optional scorestr As String = "")
        Dim p1ki As Double = p1.K
        Dim p2ki As Double = p2.K
        Dim p1rdi As Double = p1.RD
        Dim p2rdi As Double = p2.RD
        Dim result As Integer                     'red, blue, draw
        Dim expectedresult As Integer
        If p1ki > p2ki Then
            expectedresult = 1
        ElseIf p2ki > p1ki Then
            expectedresult = 2
        Else
            expectedresult = 3
        End If
        Console.ForegroundColor = ConsoleColor.Gray
        Console.BackgroundColor = ConsoleColor.Black
        If scorestr = "" Then
            If p1win = True Then
                Glicko.UpdateBatch(p1, p2, 1, 0, match)
                result = 1
            Else
                Glicko.UpdateBatch(p1, p2, 0, 1, match)
                result = 2
            End If
        Else
            Try
                If scorestr.Split("-").Count = 3 Then  'draw included
                    Glicko.UpdateBatch(p1, p2, CInt(scorestr.Split("-")(0)), CInt(scorestr.Split("-")(1)), match, CInt(scorestr.Split("-")(2)))
                    If CInt(scorestr.Split("-")(0)) > CInt(scorestr.Split("-")(1)) Then
                        result = 1
                    ElseIf CInt(scorestr.Split("-")(0)) < CInt(scorestr.Split("-")(1)) Then
                        result = 2
                    Else
                        result = 3
                    End If
                ElseIf scorestr.Split("-").Count = 2 Then   'normal
                    Glicko.UpdateBatch(p1, p2, CInt(scorestr.Split("-")(0)), CInt(scorestr.Split("-")(1)), match)
                    If CInt(scorestr.Split("-")(0)) > CInt(scorestr.Split("-")(1)) Then
                        result = 1
                    ElseIf CInt(scorestr.Split("-")(0)) < CInt(scorestr.Split("-")(1)) Then
                        result = 2
                    Else
                        result = 3
                    End If
                Else                                        'error or something
                    If p1win = True Then
                        Glicko.UpdateBatch(p1, p2, 1, 0, match)
                        result = 1
                    Else
                        Glicko.UpdateBatch(p1, p2, 0, 1, match)
                        result = 2
                    End If
                End If
            Catch

            End Try
        End If


        Console.Write("K': {0,-4:####} [", p1.K)
        If p1.K > p1ki Then
            Console.ForegroundColor = ConsoleColor.Green
        ElseIf p1.K < p1ki Then
            Console.ForegroundColor = ConsoleColor.Red
        Else
            Console.ForegroundColor = ConsoleColor.Gray
        End If
        Console.Write("{0,5:+####;-####;0}", p1.K - p1ki)
        Console.ForegroundColor = ConsoleColor.Gray
        Console.Write("] RD': {0,-3:###} (", p1.RD)
        If p1.RD < p1rdi Then
            Console.ForegroundColor = ConsoleColor.Green
        ElseIf p1.RD > p1rdi Then
            Console.ForegroundColor = ConsoleColor.Red
        Else
            Console.ForegroundColor = ConsoleColor.Gray
        End If
        Console.Write("{0,4:+###;-###;0}", p1.RD - p1rdi)
        Console.ForegroundColor = ConsoleColor.Gray
        Console.Write(") ")
        If invcolors Then
            Select Case result
                Case 1
                    Console.BackgroundColor = ConsoleColor.Red
                    Console.ForegroundColor = ConsoleColor.Black
                    Console.Write("  <-------  ")
                Case 2
                    Console.BackgroundColor = ConsoleColor.Cyan
                    Console.ForegroundColor = ConsoleColor.Black
                    Console.Write("  ------->  ")
                Case 3
                    Console.BackgroundColor = ConsoleColor.Gray
                    Console.ForegroundColor = ConsoleColor.Black
                    Console.Write("  --------  ")
            End Select
        Else
            Select Case result
                Case 1
                    Console.ForegroundColor = ConsoleColor.Red
                    Console.Write("  <-------  ")
                Case 2
                    Console.ForegroundColor = ConsoleColor.Cyan
                    Console.Write("  ------->  ")
                Case 3
                    Console.ForegroundColor = ConsoleColor.Gray
                    Console.Write("  --------  ")
            End Select
        End If

        Console.BackgroundColor = ConsoleColor.Black
        Console.ForegroundColor = ConsoleColor.Gray
        Console.Write(" K': {0,-4:####} [", p2.K)
        If p2.K > p2ki Then
            Console.ForegroundColor = ConsoleColor.Green
        ElseIf p2.K < p2ki Then
            Console.ForegroundColor = ConsoleColor.Red
        Else
            Console.ForegroundColor = ConsoleColor.Gray
        End If
        Console.Write("{0,5:+####;-####;0}", p2.K - p2ki)
        Console.ForegroundColor = ConsoleColor.Gray
        Console.Write("] RD': {0,-3:###} (", p2.RD)
        If p2.RD < p2rdi Then
            Console.ForegroundColor = ConsoleColor.Green
        ElseIf p2.RD > p2rdi Then
            Console.ForegroundColor = ConsoleColor.Red
        Else
            Console.ForegroundColor = ConsoleColor.Gray
        End If
        Console.Write("{0,4:+###;-###;0}", p2.RD - p2rdi)
        Console.ForegroundColor = ConsoleColor.Gray
        Console.Write(")" + vbCrLf)

        ' Update prediction accuracies
        Dim correct As Integer
        If result = expectedresult Then
            correct = 1
        Else
            correct = 0
        End If
        For i = 0 To accuracytimeconstants.Length - 1
            Dim exp As Double = Math.Exp(1 / accuracytimeconstants(i))
            accuracies(i) = accuracies(i) * (2 - exp) + correct * (exp - 1)
        Next

    End Sub

    Private Sub DoMatchup(p1 As Glicko, p2 As Glicko, invcolors As Boolean, Optional skip As Boolean = False)
        If Not skip Then
            p1.Prep(match)
            p2.Prep(match)
        End If

        Console.ForegroundColor = ConsoleColor.DarkGray
        Console.BackgroundColor = ConsoleColor.Black
        Console.WriteLine()
        Console.ForegroundColor = ConsoleColor.Gray
        Console.Write("[")
        If p1.K > p2.K Then
            Console.ForegroundColor = ConsoleColor.Green
        End If
        Console.Write("{0,4:####}", p1.K)

        Console.ForegroundColor = ConsoleColor.Gray
        Console.Write("]")
        If p1.K > p2.K Then
            Console.ForegroundColor = ConsoleColor.White
            Console.Write(" {0,3:#0%}", Glicko.Conf(p1, p2))
            Console.ForegroundColor = ConsoleColor.Gray
        End If
        Console.Write(" {0,-3:###} ", p1.RD)
        If invcolors Then
            Console.BackgroundColor = ConsoleColor.Red
            Console.ForegroundColor = ConsoleColor.Black
        Else
            Console.ForegroundColor = ConsoleColor.Red
        End If
        'Console.Write("{0,26}", TrimString(If(p1.LastMatch = match, "(N) ", "") + If((p1.Tier <> p2.Tier) And (p1.Tier <> Glicko.Tiers.Unknown) And (p2.Tier <> Glicko.Tiers.Unknown), "(" + p1.TierLetter + ") ", "") + p1.Name, 26))
        If p1.K > p2.K Then
            Console.Write("{0,22}", TrimString(If((p1.LastMatch = match) And Not invcolors, "(N) ", "") & p1.Name, 22))
        Else
            Console.Write("{0,26}", TrimString(If((p1.LastMatch = match) And Not invcolors, "(N) ", "") & p1.Name, 26))
        End If


        Console.BackgroundColor = ConsoleColor.Black
        Console.ForegroundColor = ConsoleColor.Gray
        Console.Write(" vs ")
        If invcolors Then
            Console.BackgroundColor = ConsoleColor.Cyan
            Console.ForegroundColor = ConsoleColor.Black
        Else
            Console.ForegroundColor = ConsoleColor.Cyan
        End If
        'Console.Write("{0,-26}", TrimString(If(p2.LastMatch = match, "(N) ", "") + If((p1.Tier <> p2.Tier) And (p1.Tier <> Glicko.Tiers.Unknown) And (p2.Tier <> Glicko.Tiers.Unknown), "(" + p2.TierLetter + ") ", "") + p2.Name, 26))
        If p2.K > p1.K Then
            Console.Write("{0,-22}", TrimString(If((p2.LastMatch = match) And Not invcolors, "(N) ", "") & p2.Name, 22))
        Else
            Console.Write("{0,-26}", TrimString(If((p2.LastMatch = match) And Not invcolors, "(N) ", "") & p2.Name, 26))
        End If
        Console.BackgroundColor = ConsoleColor.Black
        Console.ForegroundColor = ConsoleColor.Gray
        Console.Write(" [")
        If p2.K > p1.K Then
            Console.ForegroundColor = ConsoleColor.Green
        End If
        Console.Write("{0,4:####}", p2.K)
        Console.ForegroundColor = ConsoleColor.Gray
        Console.Write("]")
        If p2.K > p1.K Then
            Console.ForegroundColor = ConsoleColor.White
            Console.Write(" {0,3:#0%}", Glicko.Conf(p1, p2))
            Console.ForegroundColor = ConsoleColor.Gray
        End If
        Console.Write(" {0,-3:###} " & vbNewLine, p2.RD)
    End Sub

    Private Function TrimString(s As String, len As Integer) As String
        If s.Length <= len Then
            Return s
        Else
            Return s.Substring(0, len)
        End If
    End Function


    Private Sub Save()
        Dim thr As New Threading.Thread(AddressOf SaveDelegate)
        thr.Start()

    End Sub

    Private Sub SaveDelegate()
        Dim xd As New XElement("PepperBet")
        Dim nodelist As New List(Of XElement)
        For Each x In TheList
            xd.Add(x.GenerateXMLItem)
        Next
        xd.Add(New XElement("count", match))
        For Each x In names
            xd.Add(New XElement("name", x))
        Next
        xd.Add(New XElement("watching", watching.ToString))
        xd.Add(New XElement("autoupdate", autoupdate.ToString))
        For i = 0 To accuracies.Length - 1
            xd.Add(New XElement("accuracy" & accuracytimeconstants(i), CStr(accuracies(i))))
        Next
        xd.Save(dbfilename)
    End Sub

    Private Sub Load()
        If Not FileIO.FileSystem.FileExists(dbfilename) Then
            Exit Sub
        End If
        Dim xd As New XDocument
        xd = XDocument.Load(dbfilename)
        match = CLng(xd.<PepperBet>.<count>.First.Value)

        For Each x In xd.<PepperBet>.<name>
            names.Add(x.Value)
        Next

        Try
            watching = CBool(xd.<PepperBet>.<watching>.Value)
        Catch
        End Try

        Try
            autoupdate = CBool(xd.<PepperBet>.<autoupdate>.Value)
        Catch
        End Try

        Try
            For i = 0 To accuracies.Length - 1
                accuracies(i) = CDbl(xd.Root.Element("accuracy" & accuracytimeconstants(i)).Value)
            Next
        Catch
        End Try

        For Each x In xd.<PepperBet>.<glicko>
            Dim temp As New Glicko(x.@name, CLng(x.@lastmatch))
            temp.K = CDbl(x.@k)
            temp.RD = CDbl(x.@rd)
            temp.Tier = CInt(x.@tier)
            TheList.Add(temp)
        Next

        'Dim thelist2 As New List(Of Glicko)
        'xd = XDocument.Load("data - Copy (2).xml")
        'For Each x In xd.<PepperBet>.<glicko>
        '    Dim temp As New Glicko(x.@name, CLng(x.@lastmatch))
        '    temp.K = CDbl(x.@k)
        '    temp.RD = CDbl(x.@rd)
        '    temp.Tier = CInt(x.@tier)
        '    TheList2.Add(temp)
        'Next

        'For Each x In thelist2
        '    If TheList.FindIndex(Function(a) a.Name = x.Name) = -1 Then
        '        TheList.Add(x)
        '    End If
        'Next

        'Save()
    End Sub

    Private Sub CheckForUpdates(Optional force As Boolean = False)
        If ((Now - lastupdatecheck).TotalMinutes > 30) Or force Then
            Dim thr As New Thread(AddressOf AutoUpdateDelegate)
            thr.Start(force)
        End If
        lastupdatecheck = Now
    End Sub

    Private Sub AutoUpdateDelegate(report As Boolean)
#If CONFIG = "Debug" Then
        Return
#Else
        If Not report Then
            Threading.Thread.Sleep(2000)
        End If
        Dim wc As New Net.WebClient
        Dim verstring As String = ""
        Try
            verstring = wc.DownloadString(versionurl)
        Catch ex As Exception
        End Try
        If (verstring <> version) And (verstring <> String.Empty) Then
            Try
                Console.ForegroundColor = ConsoleColor.White
                Console.BackgroundColor = ConsoleColor.Blue
                Console.WriteLine("New version detected: v{0}", verstring)
                Console.WriteLine("Extracting autoupdater")
                Dim tempfile As String = FileIO.FileSystem.GetTempFileName
                FileIO.FileSystem.WriteAllBytes(tempfile, My.Resources.AutoUpdater, False)
                FileIO.FileSystem.RenameFile(tempfile, tempfile.Split("\").Last & ".exe")
                tempfile = tempfile & ".exe"
                Console.WriteLine("Starting autoupdater")

                Process.Start(tempfile, " """ & Process.GetCurrentProcess.MainModule.FileName & """ """ & downloadurl & """")
                Process.GetCurrentProcess.Kill()
            Catch
                Console.WriteLine("Error starting autoupdater")
                Console.ForegroundColor = ConsoleColor.Gray
                Console.BackgroundColor = ConsoleColor.Black
            End Try
        Else
            If report Then
                Console.Write("No new updates available")
                Console.CursorLeft = 0
            End If
        End If
#End If
    End Sub

    Private Sub helpstring()
        Console.WriteLine("[Enter/Esc] Enter/exit manual data entry")
        Console.WriteLine("[Q]uery database")
        Console.WriteLine("[C]leanup database")
        Console.WriteLine("[R]eport accuracy")
        Console.WriteLine("[N]ames (for bet watching)")
        Console.WriteLine("[W]atch display toggle")
        Console.WriteLine("[A]utomatic updates toggle")
        Console.WriteLine("[F]orce update check")
        Console.WriteLine("[H]elp message")
    End Sub

End Module
