PepperBet/PepperBet/PepperBet.vb
2020-02-25 14:39:45 -08:00

1255 lines
56 KiB
VB.net
Executable File

Module Pepperbet
'This constant defines how RD increases over time, higher=faster
Const c = 0.6
'Minimum RD (to ensure liquidity)
Const RDmin = 30
'Defined as part of the Glicko system
Const q = 0.005756462732485
'Seconds between updates
Const updatedelay = 2
'Upset RD maximum increase factor (infinite matches, as a fraction of RD)
Const u = 0.5
'Upset RD increase fluke-factor, more matches creates less chance of a fluke
Const f = 0.5
'Upset RD exponent, steepens modification curve with confidence
Const e = 1.5
Const version As String = "1.9.12"
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
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)
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-2018 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 data.xml.", 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.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
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
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)
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 Class Glicko
Enum Tiers
Unknown
Potato
B
A
S
X
End Enum
Property K As Double
Private _RD As Double
Property RD As Double
Set(value As Double)
If value < RDmin Then
_RD = RDmin
Else
_RD = value
End If
End Set
Get
Return _RD
End Get
End Property
Property Name As String
Property LastMatch As Long
Property Tier As Tiers = Tiers.Unknown
ReadOnly Property TierString As String
Get
Select Case Me.Tier
Case Tiers.A
Return " A "
Case Tiers.B
Return " B "
Case Tiers.Potato
Return " P "
Case Tiers.S
Return " S"
Case Tiers.X
Return " X "
Case Tiers.Unknown
Return "U "
End Select
Return ""
End Get
End Property
ReadOnly Property TierLetter As String
Get
Select Case Me.Tier
Case Tiers.A
Return "A"
Case Tiers.B
Return "B"
Case Tiers.Potato
Return "P"
Case Tiers.S
Return "S"
Case Tiers.X
Return "X"
Case Tiers.Unknown
Return "U"
End Select
Return ""
End Get
End Property
''' <summary>
''' Updates this Glicko rating after a match. MAKE SURE TO COPY THE OPPONENT BEFORE UPDATING
''' </summary>
''' <param name="opp">Opponent that was faced</param>
''' <param name="win">Did this Glicko win? Draw=0.5</param>
''' <param name="t">Match number of this match</param>
''' <remarks></remarks>
Private Sub Update(opp() As Glicko, win() As Double, t As Long)
Dim E As Double = 0
Dim g As Double = 0
Dim dsum As Double = 0
Dim rsum As Double = 0
For i = 0 To opp.Count - 1
g = 1 / Math.Sqrt(1 + (3 * Math.Pow(q, 2) * Math.Pow(opp(i).RD, 2)) / Math.Pow(Math.PI, 2))
E = 1 / (1 + Math.Pow(10, (g * (Me.K - opp(i).K)) / -400))
dsum += Math.Pow(g, 2) * E * (1 - E)
rsum += g * (win(i) - E)
Next
Dim dsq As Double = Math.Pow(Math.Pow(q, 2) * dsum, -1)
Me.K = Me.K + (q / ((1 / Math.Pow(Me.RD, 2)) + (1 / dsq))) * rsum
Me.RD = Math.Max(Math.Sqrt(Math.Pow((1 / Math.Pow(Me.RD, 2)) + (1 / dsq), -1)), 30)
Me.LastMatch = t
End Sub
Public Shared Sub UpdateBatch(a As Glicko, b As Glicko, Acount As Integer, Bcount As Integer, t As Long, Optional Dcount As Integer = 0)
Dim total As Integer = Acount + Bcount + Dcount
Dim Aresults(total - 1) As Double
Dim aopps(total - 1) As Glicko
Dim Bresults(total - 1) As Double
Dim bopps(total - 1) As Glicko
Dim upset As Boolean = False
Dim confidence As Double = Conf(a, b)
Dim tempb As New Glicko("", -1)
tempb.K = b.K
tempb.RD = b.RD
For i = 0 To total - 1
aopps(i) = tempb
bopps(i) = a
Next
For i = 0 To Acount - 1
Aresults(i) = 1
Next
For i = Acount To Acount + Bcount - 1
Bresults(i) = 1
Next
For i = Acount + Bcount To total - 1
Aresults(i) = 0.5
Bresults(i) = 0.5
Next
If (Aresults.Average > 0.5 And b.K > a.K) Or (Bresults.Average > 0.5 And a.K > b.K) Then
upset = True
End If
b.Update(bopps, Bresults, t)
a.Update(aopps, Aresults, t)
'My custom RD-increasing function in case of upsets
'Note this increases after Glicko's decrease, so they oppose each other
'If upset = True Then
' 'U-factor is upset factor, the maximum possible increase in RD for a character if we trusted the results 100% accurately
' Dim aUfactor As Double = u * a.RD * (confidence ^ e)
' Dim bUfactor As Double = u * b.RD * (confidence ^ e)
' 'F-factor is the fluke factor, more rounds means it's less of a fluke and we should increase more
' Dim Ffactor As Double = 1 - (1 / (Aresults.Count + f))
' 'C-factor is the closeness factor, close matches are weighted less (5-0 more increase than 5-4)
' Dim Cfactor As Double = (Math.Max(Aresults.Average, Bresults.Average) - 0.5) * 2
' a.RD = Math.Min(350, a.RD + (aUfactor * Ffactor * Cfactor))
' b.RD = Math.Min(350, b.RD + (bUfactor * Ffactor * Cfactor))
'End If
End Sub
Public Shared Sub UpdateTiers(a As Glicko, b As Glicko)
If Now.DayOfWeek = DayOfWeek.Thursday And Now.Hour >= 18 And Now.Hour < 21 Then
'shaker classic
Exit Sub
End If
If a.Tier = Tiers.Unknown And b.Tier = Tiers.Unknown Then
Exit Sub
ElseIf a.Tier = Tiers.Unknown Then
a.Tier = b.Tier
ElseIf b.Tier = Tiers.Unknown Then
b.Tier = a.Tier
ElseIf b.Tier = a.Tier Then
Exit Sub
Else
a.Tier = Tiers.Unknown
b.Tier = Tiers.Unknown
End If
Save()
End Sub
''' <summary>
''' Time-decays RD in preperation for a match
''' </summary>
''' <param name="t">Current match number</param>
''' <remarks></remarks>
Public Sub Prep(t As Long)
Me.RD = Math.Min(350, Math.Sqrt(Math.Pow(Me.RD, 2) + Math.Pow(c, 2) * (t - Me.LastMatch)))
End Sub
Public Sub New(name As String, t As Long)
Me.K = 1500
Me.RD = 350
Me.Name = name
Me.LastMatch = t
End Sub
Public Function GenerateXMLItem() As XElement
Dim ret As New XElement("glicko")
ret.SetAttributeValue("name", Me.Name)
ret.SetAttributeValue("k", Me.K)
ret.SetAttributeValue("rd", Me.RD)
ret.SetAttributeValue("lastmatch", Me.LastMatch)
ret.SetAttributeValue("tier", CInt(Me.Tier))
Return ret
End Function
Private Shared Function erf(x As Double) As Double
'Erf(x) approximation, max error 3e-7
Dim a1 As Double = 0.0705230784
Dim a2 As Double = 0.0422820123
Dim a3 As Double = 0.0092705272
Dim a4 As Double = 0.0001520143
Dim a5 As Double = 0.0002765672
Dim a6 As Double = 0.0000430638
a1 = a1 * x
a2 = a2 * (x ^ 2)
a3 = a3 * (x ^ 3)
a4 = a4 * (x ^ 4)
a5 = a5 * (x ^ 5)
a6 = a6 * (x ^ 6)
Return 1 - (1 / ((1 + a1 + a2 + a3 + a4 + a5 + a6) ^ 16))
End Function
Private Shared Function CDF(x As Double, mu As Double, sigma As Double) As Double
Return 0.5 * (1 + erf((x - mu) / (sigma * Math.Sqrt(2))))
End Function
Private Shared Function StdNorm(x As Double) As Double
Return Math.Exp(-0.5 * (x ^ 2)) / (Math.Sqrt(2 * Math.PI))
End Function
Private Shared Function Norm(x As Double, mu As Double, sigma As Double) As Double
Return (1 / sigma) * StdNorm((x - mu) / sigma)
End Function
Public Shared Function Conf(a As Glicko, b As Glicko) As Double
Dim sum As Double
For i = 0 To 3000 Step 1
sum += Math.Max(Norm(i, a.K, a.RD) - Norm(i, b.K, b.RD), 0)
Next
Return sum
End Function
End Class
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))
xd.Save("data.xml")
End Sub
Private Sub Load()
If Not FileIO.FileSystem.FileExists("data.xml") Then
Exit Sub
End If
Dim xd As New XDocument
xd = XDocument.Load("data.xml")
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
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("[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