map identity by checksum

This commit is contained in:
Not 2022-11-18 01:35:59 +01:00
parent 68e44e534b
commit cf74af8945
5 changed files with 91 additions and 69 deletions

View File

@ -12,6 +12,7 @@ local ModeSep
-- lb_common.lua -- lb_common.lua
local ZoneAct = lb_ZoneAct local ZoneAct = lb_ZoneAct
local TicsToTime = lb_TicsToTime local TicsToTime = lb_TicsToTime
local mapChecksum = lb_map_checksum
-- lb_store.lua -- lb_store.lua
local GetMapRecords = lb_get_map_records local GetMapRecords = lb_get_map_records
@ -50,7 +51,7 @@ local function updateMapIndex(n)
mapIndex = mapIndexOffset(n) mapIndex = mapIndexOffset(n)
scrollPos = 1 scrollPos = 1
MapRecords = GetMapRecords(maps[mapIndex], ModeSep) MapRecords = GetMapRecords(maps[mapIndex], mapChecksum(maps[mapIndex]), ModeSep)
updateModes() updateModes()
end end
@ -388,7 +389,7 @@ local function initBrowser(modeSep)
end end
-- initialize MapRecords -- initialize MapRecords
MapRecords = GetMapRecords(gamemap, ModeSep) MapRecords = GetMapRecords(gamemap, mapChecksum(gamemap), ModeSep)
scrollPos = 1 scrollPos = 1
updateModes() updateModes()

View File

@ -44,3 +44,23 @@ rawset(_G, "lb_comp", function(a, b)
local s = (a.flags & (F_SPBEXP | F_SPBBIG)) - (b.flags & (F_SPBEXP | F_SPBBIG)) local s = (a.flags & (F_SPBEXP | F_SPBBIG)) - (b.flags & (F_SPBEXP | F_SPBBIG))
return s > 0 or not(s < 0 or a.time >= b.time) return s > 0 or not(s < 0 or a.time >= b.time)
end) end)
local function djb2(message)
local digest = 5381
for c in message:gmatch(".") do
digest = (($ << 5) + $) + string.byte(c)
end
return digest
end
-- Produce a checksum by using the maps title, subtitle and zone
rawset(_G, "lb_map_checksum", function(mapnum)
local mh = mapheaderinfo[mapnum]
if not mh then
return nil
end
local digest = string.format("%04x", djb2(mh.lvlttl..mh.subttl..mh.zonttl))
return string.sub(digest, #digest - 3)
end)

View File

@ -5,6 +5,7 @@
-- lb_common.lua -- lb_common.lua
local stat_t = lb_stat_t local stat_t = lb_stat_t
local lbComp = lb_comp local lbComp = lb_comp
local mapChecksum = lb_map_checksum
---------------------------- ----------------------------
@ -24,18 +25,26 @@ local parseScore
-- Returns a list of all maps with records -- Returns a list of all maps with records
local function MapList() local function MapList()
local maps = {} local maps = {}
for map in pairs(ColdStore) do for mapid, checksums in pairs(ColdStore) do
maps[map] = true maps[mapid] = $ or {}
for checksum in pairs(checksums) do
maps[mapid][checksum] = true
end
end end
for map in pairs(LiveStore) do for mapid, checksums in pairs(LiveStore) do
maps[map] = true maps[mapid] = $ or {}
for checksum in pairs(checksums) do
maps[mapid][checksum] = true
end
end end
local maplist = {} local maplist = {}
for map in pairs(maps) do for mapid, checksums in pairs(maps) do
table.insert(maplist, map) for checksum in pairs(checksums) do
table.insert(maplist, {["id"] = mapid, ["checksum"] = checksum})
end
end end
table.sort(maplist) table.sort(maplist, function(a, b) return a.id < b.id end)
return maplist return maplist
end end
@ -45,7 +54,9 @@ rawset(_G, "lb_map_list", MapList)
-- Function for adding a single record from lua -- Function for adding a single record from lua
local function AddColdStore(record) local function AddColdStore(record)
ColdStore[record.map] = $ or {} ColdStore[record.map] = $ or {}
table.insert(ColdStore[record.map], record) ColdStore[record.map][record.checksum] = $ or {}
table.insert(ColdStore[record.map][record.checksum], record)
end end
rawset(_G, "lb_add_coldstore_record", AddColdStore) rawset(_G, "lb_add_coldstore_record", AddColdStore)
@ -57,11 +68,12 @@ end
rawset(_G, "lb_add_coldstore_record_string", AddColdStoreString) rawset(_G, "lb_add_coldstore_record_string", AddColdStoreString)
-- Insert mode separated records from the flat sourceTable into dest -- Insert mode separated records from the flat sourceTable into dest
local function insertRecords(dest, sourceTable, modeSep) local function insertRecords(dest, sourceTable, checksum, modeSep)
if not sourceTable then return end if not sourceTable then return end
if not sourceTable[checksum] then return end
local mode = nil local mode = nil
for _, record in ipairs(sourceTable) do for _, record in ipairs(sourceTable[checksum]) do
mode = record.flags & modeSep mode = record.flags & modeSep
dest[mode] = $ or {} dest[mode] = $ or {}
table.insert(dest[mode], record) table.insert(dest[mode], record)
@ -71,14 +83,14 @@ end
-- GLOBAL -- GLOBAL
-- Construct the leaderboard table of the supplied mapid -- Construct the leaderboard table of the supplied mapid
-- combines the ColdStore and LiveStore records -- combines the ColdStore and LiveStore records
local function GetMapRecords(map, modeSep) local function GetMapRecords(map, checksum, modeSep)
local mapRecords = {} local mapRecords = {}
-- Insert ColdStore records -- Insert ColdStore records
insertRecords(mapRecords, ColdStore[map], modeSep) insertRecords(mapRecords, ColdStore[map], checksum, modeSep)
-- Insert LiveStore records -- Insert LiveStore records
insertRecords(mapRecords, LiveStore[map], modeSep) insertRecords(mapRecords, LiveStore[map], checksum, modeSep)
-- Sort records -- Sort records
for _, records in pairs(mapRecords) do for _, records in pairs(mapRecords) do
@ -104,18 +116,20 @@ end
rawset(_G, "lb_get_map_records", GetMapRecords) rawset(_G, "lb_get_map_records", GetMapRecords)
local function insertOrReplaceRecord(map, score, modeSep) local function insertOrReplaceRecord(map, score, modeSep)
local checksum = mapChecksum(map)
LiveStore[map] = $ or {} LiveStore[map] = $ or {}
LiveStore[map][checksum] = $ or {}
for i, record in ipairs(LiveStore[map]) do for i, record in ipairs(LiveStore[map][checksum]) do
-- Replace the record -- Replace the record
if record.name == score.name if record.name == score.name
and (record.flags & modeSep) == (score.flags & modeSep) then and (record.flags & modeSep) == (score.flags & modeSep) then
LiveStore[map][i] = score LiveStore[map][checksum][i] = score
return return
end end
end end
table.insert(LiveStore[map], score) table.insert(LiveStore[map][checksum], score)
-- TODO: remove excess records -- TODO: remove excess records
end end
@ -130,26 +144,6 @@ local function stat_str(stat)
return "0" return "0"
end end
local function djb2(message)
local digest = 5381
for c in message:gmatch(".") do
digest = (($ << 5) + $) + string.byte(c)
end
return digest
end
-- Produce a checksum by using the maps title, subtitle and zone
local function mapChecksum(mapnum)
local mh = mapheaderinfo[mapnum]
if not mh then
return nil
end
local digest = string.format("%04x", djb2(mh.lvlttl..mh.subttl..mh.zonttl))
return string.sub(digest, #digest - 3)
end
-- GLOBAL -- GLOBAL
-- Save a record to the LiveStore and write to disk -- Save a record to the LiveStore and write to disk
-- SaveRecord will replace the record holders previous record but it will not compare any record times -- SaveRecord will replace the record holders previous record but it will not compare any record times
@ -167,24 +161,26 @@ local function SaveRecord(score, map, modeSep)
f:setvbuf("line") f:setvbuf("line")
for mapid, records in pairs(LiveStore) do for mapid, checksums in pairs(LiveStore) do
for _, record in ipairs(records) do for checksum, records in pairs(checksums) do
-- Insert checksum if missing for _, record in ipairs(records) do
if (not record.checksum) or record.checksum == "" then -- Insert checksum if missing
record.checksum = mapChecksum(mapid) if (not record.checksum) or record.checksum == "" then
end record.checksum = mapChecksum(mapid)
end
f:write( f:write(
mapid, "\t", mapid, "\t",
record.name, "\t", record.name, "\t",
record.skin, "\t", record.skin, "\t",
record.color, "\t", record.color, "\t",
record.time, "\t", record.time, "\t",
table.concat(record.splits, " "), "\t", table.concat(record.splits, " "), "\t",
record.flags, "\t", record.flags, "\t",
stat_str(record.stat), "\t", stat_str(record.stat), "\t",
record.checksum or "", "\n" record.checksum or "", "\n"
) )
end
end end
end end
@ -267,7 +263,8 @@ if isserver then
for l in f:lines() do for l in f:lines() do
local score = parseScore(l) local score = parseScore(l)
LiveStore[score.map] = $ or {} LiveStore[score.map] = $ or {}
table.insert(LiveStore[score.map], score) LiveStore[score.map][score.checksum] = $ or {}
table.insert(LiveStore[score.map][score.checksum], score)
end end
f:close() f:close()

View File

@ -92,6 +92,7 @@ local ticsToTime = lb_TicsToTime
local zoneAct = lb_ZoneAct local zoneAct = lb_ZoneAct
local stat_t = lb_stat_t local stat_t = lb_stat_t
local lbComp = lb_comp local lbComp = lb_comp
local mapChecksum = lb_map_checksum
-- browser.lua -- browser.lua
local InitBrowser = InitBrowser local InitBrowser = InitBrowser
@ -403,7 +404,7 @@ local function records(player, ...)
return return
end end
mapRecords = GetMapRecords(mapnum, ST_SEP) mapRecords = GetMapRecords(mapnum, mapChecksum(mapnum), ST_SEP)
end end
local map = mapheaderinfo[mapnum] local map = mapheaderinfo[mapnum]
@ -562,14 +563,14 @@ local function findRival(player, ...)
local totalDiff = 0 local totalDiff = 0
CONS_Printf(player, string.format("\x89%s's times:", rival)) CONS_Printf(player, string.format("\x89%s's times:", rival))
CONS_Printf(player, "MAP Time Diff Mode") CONS_Printf(player, "MAP CHCK Time Diff Mode")
local maplist = MapList() local maplist = MapList()
local mapRecords local mapRecords
local rivalScore local rivalScore
local yourScore local yourScore
for i = 1, #maplist do for i = 1, #maplist do
mapRecords = GetMapRecords(maplist[i], ST_SEP) mapRecords = GetMapRecords(maplist[i].id, maplist[i].checksum, ST_SEP)
for mode, records in pairs(mapRecords) do for mode, records in pairs(mapRecords) do
scores[mode] = $ or {} scores[mode] = $ or {}
@ -636,9 +637,10 @@ local function findRival(player, ...)
CONS_Printf( CONS_Printf(
player, player,
string.format( string.format(
"%s %8s %s%9s \x80%s", "%s %4s %8s %s%9s \x80%s",
G_BuildMapName(score["rival"]["map"]), G_BuildMapName(score.rival.map),
ticsToTime(score["rival"]["time"]), score.rival.checksum,
ticsToTime(score.rival.time),
color, color,
sym[diff<0] + ticsToTime(abs(diff)), sym[diff<0] + ticsToTime(abs(diff)),
modestr modestr
@ -648,9 +650,10 @@ local function findRival(player, ...)
CONS_Printf( CONS_Printf(
player, player,
string.format( string.format(
"%s %8s %9s %s", "%s %4s %8s %9s %s",
G_BuildMapName(score["rival"]["map"]), G_BuildMapName(score.rival.map),
ticsToTime(score["rival"]["time"]), score.rival.checksum,
ticsToTime(score.rival.time),
ticsToTime(0, true), ticsToTime(0, true),
modestr modestr
) )
@ -714,7 +717,7 @@ addHook("MapLoad", function()
allowJoin(true) allowJoin(true)
--printTable(lb) --printTable(lb)
MapRecords = GetMapRecords(gamemap, ST_SEP) MapRecords = GetMapRecords(gamemap, mapChecksum(gamemap), ST_SEP)
end end
) )
@ -1149,7 +1152,8 @@ local function saveTime(player)
TimeFinished, TimeFinished,
splits, splits,
Flags, Flags,
stat_t(player.HMRs or pskin.kartspeed, player.HMRw or pskin.kartweight) stat_t(player.HMRs or pskin.kartspeed, player.HMRw or pskin.kartweight),
mapChecksum(gamemap)
) )
-- Check if you beat your previous best -- Check if you beat your previous best
@ -1178,7 +1182,7 @@ local function saveTime(player)
FlashVFlags = YellowFlash FlashVFlags = YellowFlash
-- Reload the MapRecords -- Reload the MapRecords
MapRecords = GetMapRecords(gamemap, ST_SEP) MapRecords = GetMapRecords(gamemap, mapChecksum(gamemap), ST_SEP)
-- Set the updated ScoreTable -- Set the updated ScoreTable
ScoreTable = MapRecords[Flags] ScoreTable = MapRecords[Flags]

View File

@ -36,7 +36,7 @@ def CompareScore(a, b):
F_SEP = 0xF F_SEP = 0xF
def SameScore(a, b): def SameScore(a, b):
return a["name"] == b["name"] and (a["flags"] & F_SEP) == (b["flags"] & F_SEP) return a["name"] == b["name"] and a["checksum"] == b["checksum"] and (a["flags"] & F_SEP) == (b["flags"] & F_SEP)
def LoadRecordsFromFile(path): def LoadRecordsFromFile(path):
records = [] records = []