This commit is contained in:
lifestorm
2024-08-04 22:55:00 +03:00
parent 0e770b2b49
commit 94063e4369
7342 changed files with 1718932 additions and 14 deletions

174
lua/chess/cl_dermaboard.lua Normal file
View File

@@ -0,0 +1,174 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
local PanelCol = {
Main = Color(0,0,0,200), Hover = Color(0,255,0,50), Selected = Color(150,50,50,170),
Move = Color(10,25,150,150), HasMoved = Color(50,50,50,100), Text = Color(0,0,0,255),
GridWhite = Color(255, 248, 220), GridBlack = Color(210, 180, 140),
White = Color(180,180,180), Black = Color(0,0,0),
}
-- local ColText = Color(50,50,50,200)
-- local ColBlack,ColWhite = Color(0,0,0,120),Color(255,255,255,10)
local NumToLetter = {"a", "b", "c", "d", "e", "f", "g", "h", ["a"]=1, ["b"]=2, ["c"]=3, ["d"]=4, ["e"]=5, ["f"]=6, ["g"]=7, ["h"]=8} --Used extensively for conversions
surface.CreateFont( "ChessPieces", { font = "Arial", size = 64, weight = 300})
function Chess_Open2DBoard( board )
if not IsValid(board) then return end
if IsValid( Chess_2DDermaPanel ) then Chess_2DDermaPanel:Remove() end
Chess_2DDermaPanel = vgui.Create( "DFrame" )
local frame = Chess_2DDermaPanel
frame:SetTitle( "2D Game Board" )
frame:SetSize( 740, 760 )
frame:SetPos( (ScrW()/2)-370, (ScrH()/2)-380 )
frame.Paint = function( s,w,h )
if not IsValid(board) then
s:Remove()
end
draw.RoundedBox( 8, 0, 0, w, h, PanelCol.Main )
end
frame:MakePopup()
local pnlBoard = vgui.Create( "DPanel", frame )
pnlBoard:SetSize( 720, 720 )
pnlBoard:SetPos(10,30)
pnlBoard.Squares = {}
pnlBoard.Paint = function() end
local function DoTiles(swapped)
if pnlBoard.Squares then
for _,v in pairs(pnlBoard.Squares) do
for _,pnl in pairs(v) do
pnl:Remove()
end
end
end
for i=0,7 do
pnlBoard.Squares[i] = {}
for n=0,7 do
local pnl = vgui.Create( "DModelPanel", pnlBoard )
pnlBoard.Squares[i][n] = pnl
pnl:SetPos( (swapped and 7-i or i)*90, (swapped and 7-n or n)*90 )
pnl:SetSize(90,90)
pnl.GridCol = (((i+n)%2)==1) and PanelCol.GridBlack or PanelCol.GridWhite
pnl.GridPos = {i,n}
pnl.oPaint = pnl.Paint
pnl.Paint = function(s,w,h)
surface.SetDrawColor( s.GridCol )
surface.DrawRect( 0,0, w,h )
if not IsValid(board) then return end
if s:IsHovered() then
surface.SetDrawColor( PanelCol.Hover )
surface.DrawRect( 0,0, w,h )
end
if board.Selected and board.Selected[1]==s.GridPos[1] and board.Selected[2]==s.GridPos[2] then
surface.SetDrawColor( PanelCol.Selected )
surface.DrawRect( 0,0, w,h )
end
if board:GetTableGrid( board.Moves, s.GridPos[1], s.GridPos[2]) then
surface.SetDrawColor( PanelCol.Move )
surface.DrawRect( 0,0, w,h )
end
local col,square = board.Pieces[ NumToLetter[s.GridPos[1]+1] ]
if col then
square = col[8-s.GridPos[2]]
if square then
if not (square.Team and square.Class) then return end
if square.Moving then
surface.SetDrawColor( PanelCol.HasMoved )
surface.DrawRect( 0,0, w,h )
end
if board.Characters then
draw.SimpleText( board.Characters[square.Team .. square.Class], "ChessPieces", w/2, h/2, PanelCol.Text, TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER )
else
s:SetModel( board.Models[square.Team .. square.Class] )
return s.oPaint( s,w,h )
end
end
end
if cvars.Bool("chess_gridletters") then
local str = (NumToLetter[i+1]..tostring(8-n)):upper()
draw.SimpleText( str, "ChessTextSmall", 5, h-20, PanelCol.Black )
end
end
pnl.DoClick = function(s)
if not IsValid(board) then return end
if board.Selected and board:GetTableGrid( board.Moves, pnl.GridPos[1], pnl.GridPos[2] ) then
board:RequestMove( board.Selected[1], board.Selected[2], pnl.GridPos[1], pnl.GridPos[2] )
board:ResetHighlights()
elseif board.Selected and board.Selected[1]==s.GridPos[1] and board.Selected[2]==s.GridPos[2] then
board:ResetHighlights()
else
board:ResetHighlights()
board.Selected = {s.GridPos[1],s.GridPos[2]}
board.Moves = board:GetMove( NumToLetter[s.GridPos[1]+1], 8-s.GridPos[2] )
end
end
pnl.LayoutEntity = function( s, ent )
ent:SetPos( Vector(20,20,20) )
ent:SetAngles( Angle(0,-50,0) )
end
pnl:SetModel( board.Models["WhitePawn"] )
end
end
end
local swap = vgui.Create( "DButton", frame )
swap:SetImage( "icon16/arrow_rotate_clockwise.png" )
swap:SetSize( 18,18 )
swap:SetPos( 620,6 )
swap:SetText( "" )
swap.DoClick = function(s)
s.Swapped = not s.Swapped
DoTiles( s.Swapped )
end
swap.Paint = function() end
local toggleGridLetters = vgui.Create( "DCheckBox", frame )
toggleGridLetters:SetImage( "icon16/font.png" )
toggleGridLetters:SetSize( 18,18 )
toggleGridLetters:SetPos( 600,6 )
toggleGridLetters:SetText( "" )
toggleGridLetters:SetConVar( "chess_gridletters" )
toggleGridLetters.OnChange = function(s,newvalue)
s:SetAlpha( s:GetChecked() and 255 or 100 )
end
toggleGridLetters.Paint = function() end
toggleGridLetters.PerformLayout = function(s) -- DCheckBox overwrites DButton's PerformLayout, re-apply it
if IsValid(s.m_Image) then
s.m_Image:SetPos( 4, ( s:GetTall() - s.m_Image:GetTall() ) * 0.5 )
s:SetTextInset( s.m_Image:GetWide() + 16, 0 )
end
DLabel.PerformLayout( s )
end
swap.Swapped = false
DoTiles( swap.Swapped )
end

149
lua/chess/cl_top.lua Normal file
View File

@@ -0,0 +1,149 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
local Top10
local function ChessTop10( typ )
if IsValid(Top10) then Top10:Remove() end
typ = typ or "Chess"
Top10 = vgui.Create( "DFrame" )
Top10:SetSize( 450, 245 )
Top10:SetPos( (ScrW()/2)-150, (ScrH()/2)-100 )
Top10:SetTitle( "Top 10 Chess Elo ratings" )
Top10:MakePopup()
Top10.Column = "Elo"
local pnl = vgui.Create("DPanel", Top10)
pnl.Paint = function() end
pnl:SetTall(20)
pnl:Dock(BOTTOM)
Top10.Rank = vgui.Create( "DLabel", pnl )
Top10.Rank:Dock( LEFT )
Top10.Rank:SetTall( 20 )
Top10.Rank:SetWide( 150 )
Top10.Rank:SetText("")
Top10.Updated = vgui.Create( "DLabel", pnl )
Top10.Updated:Dock( RIGHT )
Top10.Updated:SetTall( 150 )
Top10.Updated:SetText("")
Top10.List = vgui.Create( "DListView", Top10 )
local List = Top10.List
List:Dock( FILL )
List:AddColumn( "Rank" )
List:AddColumn( "Name" )
List:AddColumn( "SteamID" )
List:AddColumn( "Elo" )
List:AddLine( "", "Loading..." )
-- PrintTable( List.Columns )
List:OnRequestResize( List.Columns[1], 10 )
List:OnRequestResize( List.Columns[2], 150 )
List:OnRequestResize( List.Columns[3], 100 )
List:OnRequestResize( List.Columns[4], 10 )
net.Start( "Chess Top10" ) net.WriteString( typ ) net.SendToServer()
end
local function DraughtsTop10()
ChessTop10( "Draughts" )
end
concommand.Add( "chess_top", function( p,c,a ) ChessTop10() end)
concommand.Add( "checkers_top", function( p,c,a ) DraughtsTop10() end)
local ChatCommands = {
["!chess"]=ChessTop10, ["!chesstop"]=ChessTop10, ["!topchess"]=ChessTop10,
["/chess"]=ChessTop10, ["/chesstop"]=ChessTop10, ["/topchess"]=ChessTop10,
["!draughts"]=DraughtsTop10, ["!draughtstop"]=DraughtsTop10, ["!topdraughts"]=DraughtsTop10,
["/draughts"]=DraughtsTop10, ["/draughtstop"]=DraughtsTop10, ["/topdraughts"]=DraughtsTop10,
["!checkers"]=DraughtsTop10, ["!checkerstop"]=DraughtsTop10, ["!topcheckers"]=DraughtsTop10,
["/checkers"]=DraughtsTop10, ["/checkerstop"]=DraughtsTop10, ["/topcheckers"]=DraughtsTop10,
}
hook.Add( "OnPlayerChat", "Chess Top10 PlayerChat", function( ply, str, tm, dead )
if ChatCommands[str:lower()] then
if ply==LocalPlayer() then
ChatCommands[str:lower()]()
end
return true
end
end)
local function SecondsToTime(num)
if updateTime>=86400 then
return ("%i day%s"):format( math.floor(updateTime/86400), updateTime>=172800 and "s" or "")
elseif updateTime>=3600 then
return ("%i hour%s"):format( math.floor(updateTime/3600), updateTime>=7200 and "s" or "")
elseif updateTime>=60 then
return ("%i minute%s"):format( math.floor(updateTime/60), updateTime>=120 and "s" or "")
else
return ("%i second%s"):format(updateTime, updateTime>=2 and "s" or "")
end
end
local lastTable = {}
local lastRank = {}
local lastUpdate = {}
net.Receive( "Chess Top10", function()
if not (IsValid(Top10) and IsValid(Top10.List)) then return end
Top10.List:Clear()
local typ = net.ReadString() or "[Error]"
Top10:SetTitle( "Top 10 "..typ.." Elo ratings" )
local tbl = net.ReadTable()
if (not tbl) or (#tbl==0) then -- Rate limit exceeded
if lastTable[typ] then
for i=1,#lastTable[typ] do
Top10.List:AddLine( tonumber(lastTable[typ][i].Rank), lastTable[typ][i].Username, lastTable[typ][i].SteamID, tonumber(lastTable[typ][i]["Elo" ]) )
end
Top10.Rank:SetText( "You are rank "..lastRank[typ] )
if lastUpdate[typ] then
updateTime = math.floor(CurTime() - lastUpdate[typ])
if updateTime>0 then
Top10.Updated:SetText( ("Updated %s ago."):format(SecondsToTime(updateTime)) )
end
Top10.Updated:SizeToContents()
end
else
Top10.List:AddLine( "", "ERROR: Rate limit exceeded." )
Top10.List:AddLine( "", "Please try again in a few minutes." )
end
return
end
for i=1,#tbl do
Top10.List:AddLine( tonumber(tbl[i].Rank), tbl[i].Username, tbl[i].SteamID, tonumber(tbl[i]["Elo" ]) )
end
local rank = (net.ReadString() or "N/A")
Top10.Rank:SetText( "You are rank "..rank )
lastUpdate[typ] = tonumber(net.ReadString())
if lastUpdate[typ] then
updateTime = math.floor(CurTime() - lastUpdate[typ])
if updateTime>0 then
Top10.Updated:SetText( ("Updated %s ago."):format(SecondsToTime(updateTime)) )
end
Top10.Updated:SizeToContents()
end
lastTable[typ] = tbl
lastRank[typ] = rank
end)

123
lua/chess/sh_player_ext.lua Normal file
View File

@@ -0,0 +1,123 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
local PLAYER = FindMetaTable( "Player" )
if not PLAYER then return end
function PLAYER:GetChessElo()
return self:GetNWInt( "ChessElo", 1400 ) or 1400
end
function PLAYER:GetDraughtsElo()
return self:GetNWInt( "DraughtsElo", 1400 ) or 1400
end
if CLIENT then return end
function PLAYER:SetChessElo( num )
self:SetNWInt( "ChessElo", num or Chess_GetElo(ply:SteamID()) or 1400 )
Chess_SetElo( self:SteamID(), num, false )
end
function PLAYER:SetDraughtsElo( num )
self:SetNWInt( "DraughtsElo", num or Chess_GetElo(ply:SteamID(), true) or 1400 )
Chess_SetElo( self:SteamID(), num, true )
end
function PLAYER:RefreshChessElo()
-- Convert old PData stuff
if self:GetPData("ChessElo") then
Chess_SetElo( self:SteamID(), self:GetPData("ChessElo"), false )
self:RemovePData("ChessElo")
end
if self:GetPData("DraughtsElo") then
Chess_SetElo( self:SteamID(), self:GetPData("DraughtsElo"), true )
self:RemovePData("DraughtsElo")
end
self:SetChessElo( Chess_GetElo(self:SteamID()) or 1400)
self:SetDraughtsElo( Chess_GetElo(self:SteamID(), true) or 1400)
end
hook.Add( "PlayerInitialSpawn", "Chess InitialSpawn InitElo", function(ply)
ply:RefreshChessElo()
end)
function PLAYER:ExpectedChessWin( against )
return (1/ (1+( 10^( (against:GetChessElo() - self:GetChessElo())/400 ) )) )
end
function PLAYER:ExpectedDraughtsWin( against )
return (1/ (1+( 10^( (against:GetDraughtsElo() - self:GetDraughtsElo())/400 ) )) )
end
function PLAYER:GetChessKFactor() --Imitating FIDE's K-factor ranges
local games = tonumber(self:GetPData( "ChessGamesPlayed", 0 )) or 0
if games<30 then
self:SetPData( "ChessEloKFactor", 15 )
return 30
end
local k = self:GetChessElo()>=2400 and 10 or self:GetPData( "ChessEloKFactor", 15 ) or 15
self:SetPData( "ChessEloKFactor", k )
return k
end
function PLAYER:GetDraughtsKFactor() --Imitating FIDE's K-factor ranges
local games = self:GetPData( "DraughtsGamesPlayed", 0 )
if games<30 then
self:SetPData( "DraughtsEloKFactor", 15 )
return 30
end
local k = self:GetDraughtsElo()>=2400 and 10 or self:GetPData( "DraughtsEloKFactor", 15 ) or 15
self:SetPData( "DraughtsEloKFactor", k )
return k
end
function PLAYER:DoChessElo( score, against )
local mod = math.ceil(self:GetChessKFactor() * (score - self:ExpectedChessWin(against)))
local NewElo = math.floor( self:GetChessElo() + mod )
self:SetChessElo( NewElo )
if IsValid(against) then
mod = mod*(-1)
local NewElo = math.floor( against:GetChessElo() + mod )
against:SetChessElo( NewElo )
local rank,count = Chess_GetRank(against)
against:ChatPrint( "Your chess Elo rating changed by "..tostring(mod).." to "..tostring(NewElo).."!" ..(rank and " You are #"..tostring(rank).." on this server." or "") )
end
local rank,count = Chess_GetRank(self)
self:ChatPrint( "Your chess Elo rating changed by "..tostring(mod).." to "..tostring(NewElo).."!" ..(rank and " You are #"..tostring(rank).." on this server." or "") )
Chess_UpdateElo( self )
end
function PLAYER:ChessWin( against )
if not IsValid(against) then return end
self:DoChessElo(1, against)
end
function PLAYER:ChessDraw( against ) self:DoChessElo(0.5, against) end
function PLAYER:DoDraughtsElo( score, against )
local mod = math.ceil(self:GetDraughtsKFactor() * (score - self:ExpectedDraughtsWin(against)))
local NewElo = math.floor( self:GetDraughtsElo() + mod )
self:SetDraughtsElo( NewElo )
if IsValid(against) then
mod = mod*(-1)
local NewElo = math.floor( against:GetDraughtsElo() + mod )
against:SetDraughtsElo( NewElo )
local rank = Chess_GetRank(self, "Draughts")
against:ChatPrint( "Your draughts Elo rating changed by "..tostring(mod).." to "..tostring(NewElo).."!" ..(rank and " You are #"..tostring(rank).." on this server." or "") )
end
local rank = Chess_GetRank(self, "Draughts")
self:ChatPrint( "Your draughts Elo rating changed by "..tostring(mod).." to "..tostring(NewElo).."!" ..(rank and " You are #"..tostring(rank).." on this server." or "") )
Chess_UpdateElo( self )
end
function PLAYER:DraughtsWin( against ) self:DoDraughtsElo(1, against) end
function PLAYER:DraughtsDraw( against ) self:DoDraughtsElo(0.5, against) end

212
lua/chess/sv_sql.lua Normal file
View File

@@ -0,0 +1,212 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
local nextTopUpdate = {}
local playerResults = {}
local function InitChessLeaderboard()
sql.Begin()
local query = sql.Query( [[CREATE TABLE ChessLeaderboard (SteamID varchar(255), Username varchar(255), Elo int, DraughtsElo int);]] )
sql.Commit()
if query==false then else print("Chess: Created Elo table") end
end
InitChessLeaderboard()
function Chess_UpdateElo( ply )
if not IsValid(ply) then return end
local SelStr = [[SELECT * FROM ChessLeaderboard WHERE SteamID==]].. sql.SQLStr(ply:SteamID()) ..[[;]]
sql.Begin()
local Select = sql.Query( SelStr )
sql.Commit()
local UpdateStr
if Select==false then
Error( "Chess: Save failed for player "..ply:Nick().." - Query error. "..sql.LastError().."\n" )
elseif Select==nil then
UpdateStr = [[INSERT INTO ChessLeaderboard (SteamID, Username, Elo, DraughtsElo) VALUES (]]..sql.SQLStr(ply:SteamID())..[[,]]..sql.SQLStr(ply:Nick())..[[,]]..sql.SQLStr(ply:GetChessElo())..[[,]]..sql.SQLStr(ply:GetDraughtsElo())..[[);]]
else
UpdateStr = [[UPDATE ChessLeaderboard SET Username=]]..sql.SQLStr(ply:GetName())..[[,Elo=]]..sql.SQLStr(ply:GetChessElo())..[[,DraughtsElo=]]..sql.SQLStr(ply:GetDraughtsElo())..[[ WHERE SteamID==]]..sql.SQLStr(ply:SteamID())..[[;]]
end
sql.Begin()
local Update = sql.Query( UpdateStr )
sql.Commit()
if Update==false then
Error( "Chess: Update failed for player "..ply:Nick().." - Query error. "..sql.LastError().."\n" )
end
nextTopUpdate = {}
playerResults = {}
end
function Chess_SetElo( steamID, newElo, isDraughts )
if not tonumber(newElo) then return false,"Elo must be a number." end
if type(steamID)=="Player" then
if not IsValid(steamID) then return end
steamID = steamID:SteamID()
end
local ply = player.GetBySteamID(steamID)
local SelStr = [[SELECT * FROM ChessLeaderboard WHERE SteamID==]].. sql.SQLStr(steamID) ..[[;]]
sql.Begin()
local Select = sql.Query( SelStr )
sql.Commit()
local UpdateStr
if Select==nil then
UpdateStr = [[INSERT INTO ChessLeaderboard (SteamID, Username, Elo, DraughtsElo) VALUES (]]..sql.SQLStr(steamID)..[[,]]..sql.SQLStr(IsValid(ply) and ply:Nick() or "N/A")..[[,]]..sql.SQLStr(IsValid(ply) and ply:GetChessElo() or 1400)..[[,]]..sql.SQLStr(IsValid(ply) and ply:GetDraughtsElo() or 1400)..[[);]]
end
if isDraughts then
UpdateStr = [[UPDATE ChessLeaderboard SET DraughtsElo=]]..sql.SQLStr(tonumber(newElo))..[[ WHERE SteamID==]]..sql.SQLStr(steamID)..[[;]]
else
UpdateStr = [[UPDATE ChessLeaderboard SET Elo=]]..sql.SQLStr(tonumber(newElo))..[[ WHERE SteamID==]]..sql.SQLStr(steamID)..[[;]]
end
sql.Begin()
local Update = sql.Query( UpdateStr )
sql.Commit()
if Update==false then
Error( "Chess: Update failed for player "..steamID.." - Query error. "..sql.LastError().."\n" )
return false
end
nextTopUpdate = {}
playerResults = {}
end
function Chess_GetElo( steamID, isDraughts )
if type(steamID)=="Player" then
if not IsValid(steamID) then return end
steamID = steamID:SteamID()
end
local SelStr = [[SELECT * FROM ChessLeaderboard WHERE SteamID==]].. sql.SQLStr(steamID) ..[[;]]
sql.Begin()
local Select = sql.Query( SelStr )
sql.Commit()
if Select==nil then
return false, "Player does not have an Elo rating"
end
if isDraughts then
return Select[1].DraughtsElo or 1400
else
return Select[1].Elo or 1400 -- Chess
end
end
function Chess_GetRank( ply, typ )
local query = string.gsub([[SELECT (
SELECT COUNT(*)+1
FROM ChessLeaderboard ordered
WHERE (ordered.{ELO}) > (uo.{ELO})
) AS Rank, (SELECT COUNT(*) FROM ChessLeaderboard) AS Count
FROM ChessLeaderboard uo WHERE SteamID==]]..sql.SQLStr(ply:SteamID())..[[;]], "{ELO}", (typ=="Draughts" and [[DraughtsElo]] or [[Elo]]) )
sql.Begin()
local rank = sql.Query( query )
sql.Commit()
if not (rank and rank[1] and rank[1].Rank and rank[1].Count) then return false end
return rank and rank[1] and rank[1].Rank, rank and rank[1] and rank[1].Count
end
util.AddNetworkString( "Chess Top10" )
local ValidType = {["Chess"] = true, ["Draughts"] = true}
local TopTable = {}
net.Receive( "Chess Top10", function( len, ply )
if not IsValid(ply) then return end
local typ = net.ReadString()
if not (typ and ValidType[typ]) then typ = "Chess" end
if not playerResults[typ] then playerResults[typ] = {} end
if playerResults[typ][ply] and (CurTime()<(playerResults[typ][ply].nextUpdate or 0)) then
net.Start( "Chess Top10" )
net.WriteString( typ )
net.Send( ply )
return
end
if CurTime()>(nextTopUpdate[typ] or 0) then
local query = string.gsub([[SELECT Username, SteamID, {ELO} as Elo, (
SELECT COUNT(*)+1
FROM ChessLeaderboard ordered
WHERE (ordered.{ELO}) > (uo.{ELO})
) AS Rank
FROM ChessLeaderboard uo ORDER BY {ELO} DESC LIMIT 10;]], "{ELO}", (typ=="Draughts" and [[DraughtsElo]] or [[Elo]]) )
sql.Begin()
local Top10 = sql.Query( query )
sql.Commit()
if Top10==false then
Error( "Chess: Top10 retrieval failed - Query error. "..sql.LastError().."\n" )
return
elseif Top10==nil then
Error( "Chess: Top10 retrieval failed - No data." )
return
end
TopTable = Top10
table.Empty(playerResults[typ])
nextTopUpdate[typ] = CurTime() + 120
end
local str = ""
if (not playerResults[typ][ply]) or CurTime()<(playerResults[typ][ply].nextUpdate) then
local rank,total = Chess_GetRank(ply, typ)
playerResults[typ][ply] = {rank = rank, total = total}
end
local res = playerResults[typ][ply]
str = (res.rank and res.total and res.rank.." of "..res.total) or res.rank or "N/A"
net.Start( "Chess Top10" )
net.WriteString( typ )
net.WriteTable( TopTable )
net.WriteString( str )
net.WriteString(math.floor(nextTopUpdate[typ] - 120))
net.Send( ply )
playerResults[typ][ply].nextUpdate = CurTime() + 30
end)
-- function TestElo()
-- local typ = ""
-- local query = string.gsub([[SELECT *,(
-- SELECT COUNT(*)+1
-- FROM ChessLeaderboard ordered
-- WHERE (ordered.{ELO}) > (uo.{ELO})
-- ) AS Rank, (SELECT COUNT(*) FROM ChessLeaderboard) AS Count
-- FROM ChessLeaderboard uo ORDER BY {ELO} DESC;]], "{ELO}", (typ=="Draughts" and [[DraughtsElo]] or [[Elo]]) )
-- sql.Begin()
-- local Top10 = sql.Query( query )
-- sql.Commit()
-- if Top10 then
-- print( Top10 )
-- PrintTable( Top10 )
-- print( Top10[1].Rank, type(Top10[1].Rank) )
-- else
-- print( sql.LastError() )
-- end
-- end