“模块:Standings”的版本间的差异
Onlyforyou(讨论 | 贡献) |
Onlyforyou(讨论 | 贡献) |
||
(未显示同一用户的9个中间版本) | |||
第7行: | 第7行: | ||
local video_col = 5 | local video_col = 5 | ||
local date_col = 6 | local date_col = 6 | ||
+ | |||
+ | -- .0 => .499, .5 => .999 | ||
+ | function expand_from_old_SR_time(score) | ||
+ | if score:len() == 6 then | ||
+ | if score:sub(-1) == '0' then | ||
+ | score = score:sub(1, -2) .. '499' | ||
+ | elseif score:sub(-1) == '5' then | ||
+ | score = score:sub(1, -2) .. '999' | ||
+ | end | ||
+ | end | ||
+ | return score | ||
+ | end | ||
+ | |||
+ | function score_less_SR(a, b) | ||
+ | a = expand_from_old_SR_time(a) | ||
+ | b = expand_from_old_SR_time(b) | ||
+ | return a > b | ||
+ | end | ||
+ | |||
+ | function score_less_HS(a, b) | ||
+ | return a < b | ||
+ | end | ||
+ | |||
+ | function remove_asterisk(score) | ||
+ | if score:sub(-1) == '*' then | ||
+ | score = score:sub(1, -2) | ||
+ | end | ||
+ | return score | ||
+ | end | ||
-- compare score, including HS and SR | -- compare score, including HS and SR | ||
function score_less(a, b) | function score_less(a, b) | ||
+ | a = remove_asterisk(a) | ||
+ | b = remove_asterisk(b) | ||
if string.find(a, ':') and string.find(b, ':') then | if string.find(a, ':') and string.find(b, ':') then | ||
− | return a | + | return score_less_SR(a, b) |
elseif not string.find(a, ':') and not string.find(b, ':') then | elseif not string.find(a, ':') and not string.find(b, ':') then | ||
− | return a | + | return score_less_HS(a, b) |
end | end | ||
end | end | ||
第23行: | 第54行: | ||
elseif a[level_col] ~= b[level_col] then | elseif a[level_col] ~= b[level_col] then | ||
return a[level_col] < b[level_col] | return a[level_col] < b[level_col] | ||
− | elseif a[score_col] ~= b[score_col] then | + | elseif remove_asterisk(a[score_col]) ~= remove_asterisk(b[score_col]) then |
− | return | + | return score_less(b[score_col], a[score_col]) |
else | else | ||
return a[date_col] < b[date_col] | return a[date_col] < b[date_col] | ||
第39行: | 第70行: | ||
return a[name_col] < b[name_col] | return a[name_col] < b[name_col] | ||
else | else | ||
− | return | + | return score_less(b[score_col], a[score_col]) |
end | end | ||
end | end | ||
第79行: | 第110行: | ||
local record = records[i] | local record = records[i] | ||
if record[mode_col] == mode and record[level_col] == level then | if record[mode_col] == mode and record[level_col] == level then | ||
− | if highest == nil or | + | if highest == nil or score_less(highest, record[score_col]) then |
table.insert(records_new, record) | table.insert(records_new, record) | ||
highest = record[score_col] | highest = record[score_col] | ||
第92行: | 第123行: | ||
end | end | ||
− | function | + | function get_records() |
local content = mw.title.new('Ballance个人纪录列表'):getContent() | local content = mw.title.new('Ballance个人纪录列表'):getContent() | ||
local records = {} | local records = {} | ||
第109行: | 第140行: | ||
end | end | ||
return records | return records | ||
+ | end | ||
+ | |||
+ | function get_score_limits(mode, level) | ||
+ | local score_limits = {} | ||
+ | local content | ||
+ | local found_level = false | ||
+ | if mode == '常规HS' then | ||
+ | content = mw.title.new('Ballance HS排行榜'):getContent() | ||
+ | elseif mode == '常规SR' or mode == '连打' then | ||
+ | content = mw.title.new('Ballance SR排行榜'):getContent() | ||
+ | else | ||
+ | return score_limits | ||
+ | end | ||
+ | |||
+ | for line in content:gmatch('[^\r\n]+') do | ||
+ | if string.sub(line, 1, string.len('| ')) == '| ' then | ||
+ | for element in line:gmatch("[^|]+") do | ||
+ | if element ~= '' then | ||
+ | element = trim(element) | ||
+ | if found_level then | ||
+ | table.insert(score_limits, element) | ||
+ | if #score_limits == 2 then | ||
+ | score_limits[1], score_limits[2] = score_limits[2], score_limits[1] | ||
+ | return score_limits | ||
+ | end | ||
+ | elseif element == level then | ||
+ | found_level = true | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | end | ||
+ | return score_limits | ||
+ | end | ||
+ | |||
+ | function get_score_limit_str(highest, score_limits) | ||
+ | local str = '' | ||
+ | local i, score_limit = next(score_limits) | ||
+ | if i ~= nil then | ||
+ | if highest == nil or score_less(highest, score_limit) then | ||
+ | local limit_str | ||
+ | if #score_limits == 1 then | ||
+ | limit_str = '上榜线' | ||
+ | elseif #score_limits == 2 then | ||
+ | limit_str = '精品线' | ||
+ | end | ||
+ | str = '|-\n|colspan="4" style="text-align: center;"|' .. limit_str .. ': ' .. score_limit .. '\n' | ||
+ | table.remove(score_limits, 1) | ||
+ | end | ||
+ | end | ||
+ | return str | ||
end | end | ||
function p.standings(frame) | function p.standings(frame) | ||
local args = frame.args[1] and frame.args or frame:getParent().args; | local args = frame.args[1] and frame.args or frame:getParent().args; | ||
− | local records = select_standing( | + | local records = select_standing(get_records(), args[1], args[2]) |
− | local | + | local score_limits = get_score_limits(args[1], args[2]) |
+ | local had_score_limits = (next(score_limits) ~= nil) | ||
local ranking = 0 | local ranking = 0 | ||
local ranking_hold = 0 | local ranking_hold = 0 | ||
local highest = nil | local highest = nil | ||
local wikitable_str = '{| class="wikitable" style="display: inline-block; vertical-align: top"\n' | local wikitable_str = '{| class="wikitable" style="display: inline-block; vertical-align: top"\n' | ||
− | wikitable_str = wikitable_str .. '|+ <h3> | + | if args[2]:len() == 2 then |
+ | title = '关卡 ' .. args[2] | ||
+ | else | ||
+ | title = args[2] | ||
+ | end | ||
+ | wikitable_str = wikitable_str .. '|+ <h3>' .. title .. '</h3>\n' | ||
wikitable_str = wikitable_str .. '! 名次 !! 分数 !! 纪录持有者 !! 视频链接\n' | wikitable_str = wikitable_str .. '! 名次 !! 分数 !! 纪录持有者 !! 视频链接\n' | ||
for key, record in ipairs(records) do | for key, record in ipairs(records) do | ||
ranking = ranking + 1 | ranking = ranking + 1 | ||
− | if highest == nil or highest ~= record[score_col] then | + | if highest == nil or highest ~= remove_asterisk(record[score_col]) then |
ranking_hold = ranking | ranking_hold = ranking | ||
+ | highest = remove_asterisk(record[score_col]) | ||
+ | wikitable_str = wikitable_str .. get_score_limit_str(highest, score_limits) | ||
+ | if next(score_limits) == nil and had_score_limits then | ||
+ | ranking_hold = '附' | ||
+ | end | ||
end | end | ||
wikitable_str = wikitable_str .. '|-\n' | wikitable_str = wikitable_str .. '|-\n' | ||
第133行: | 第226行: | ||
wikitable_str = wikitable_str .. '||' .. record[video_col] | wikitable_str = wikitable_str .. '||' .. record[video_col] | ||
wikitable_str = wikitable_str .. '\n' | wikitable_str = wikitable_str .. '\n' | ||
− | |||
− | |||
end | end | ||
− | + | while next(score_limits) do | |
− | + | wikitable_str = wikitable_str .. get_score_limit_str(nil, score_limits) | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
end | end | ||
wikitable_str = wikitable_str .. '|}\n' | wikitable_str = wikitable_str .. '|}\n' |
2022年12月11日 (日) 23:59的最新版本
此模块的文档可以在模块:Standings/doc创建
local p = {} --p stands for package local mode_col = 1 local level_col = 2 local score_col = 3 local name_col = 4 local video_col = 5 local date_col = 6 -- .0 => .499, .5 => .999 function expand_from_old_SR_time(score) if score:len() == 6 then if score:sub(-1) == '0' then score = score:sub(1, -2) .. '499' elseif score:sub(-1) == '5' then score = score:sub(1, -2) .. '999' end end return score end function score_less_SR(a, b) a = expand_from_old_SR_time(a) b = expand_from_old_SR_time(b) return a > b end function score_less_HS(a, b) return a < b end function remove_asterisk(score) if score:sub(-1) == '*' then score = score:sub(1, -2) end return score end -- compare score, including HS and SR function score_less(a, b) a = remove_asterisk(a) b = remove_asterisk(b) if string.find(a, ':') and string.find(b, ':') then return score_less_SR(a, b) elseif not string.find(a, ':') and not string.find(b, ':') then return score_less_HS(a, b) end end -- sort by mode, level, score and date function standing_less(a, b) if a[mode_col] ~= b[mode_col] then return a[mode_col] < b[mode_col] elseif a[level_col] ~= b[level_col] then return a[level_col] < b[level_col] elseif remove_asterisk(a[score_col]) ~= remove_asterisk(b[score_col]) then return score_less(b[score_col], a[score_col]) else return a[date_col] < b[date_col] end end -- sort by mode, level, name and score function unique_less(a, b) if a[mode_col] ~= b[mode_col] then return a[mode_col] < b[mode_col] elseif a[level_col] ~= b[level_col] then return a[level_col] < b[level_col] elseif a[name_col] ~= b[name_col] then return a[name_col] < b[name_col] else return score_less(b[score_col], a[score_col]) end end function unique(records) local records_new = {} local record_last = nil table.sort(records, unique_less) for key, record in ipairs(records) do if record_last == nil then table.insert(records_new, record) elseif record[mode_col] ~= record_last[mode_col] or record[level_col] ~= record_last[level_col] or record[name_col] ~= record_last[name_col] then table.insert(records_new, record) end record_last = record end return records_new end function select_standing(records, mode, level) local records_new = {} for key, record in ipairs(records) do if record[mode_col] == mode and record[level_col] == level then table.insert(records_new, record) end end records_new = unique(records_new) table.sort(records_new, standing_less) return records_new end function select_WR(records, mode, level) local records_new = {} local highest = nil table.sort(records, standing_less) for i = #records, 1, -1 do local record = records[i] if record[mode_col] == mode and record[level_col] == level then if highest == nil or score_less(highest, record[score_col]) then table.insert(records_new, record) highest = record[score_col] end end end return records_new end function trim(s) return s:match'^()%s*$' and '' or s:match'^%s*(.*%S)' end function get_records() local content = mw.title.new('Ballance个人纪录列表'):getContent() local records = {} for line in content:gmatch('[^\r\n]+') do if string.sub(line, 1, string.len('| ')) == '| ' then line = line:sub(2) record = {} for element in line:gmatch("[^|]+") do if element ~= '' then element = trim(element) table.insert(record, element) end end table.insert(records, record) end end return records end function get_score_limits(mode, level) local score_limits = {} local content local found_level = false if mode == '常规HS' then content = mw.title.new('Ballance HS排行榜'):getContent() elseif mode == '常规SR' or mode == '连打' then content = mw.title.new('Ballance SR排行榜'):getContent() else return score_limits end for line in content:gmatch('[^\r\n]+') do if string.sub(line, 1, string.len('| ')) == '| ' then for element in line:gmatch("[^|]+") do if element ~= '' then element = trim(element) if found_level then table.insert(score_limits, element) if #score_limits == 2 then score_limits[1], score_limits[2] = score_limits[2], score_limits[1] return score_limits end elseif element == level then found_level = true end end end end end return score_limits end function get_score_limit_str(highest, score_limits) local str = '' local i, score_limit = next(score_limits) if i ~= nil then if highest == nil or score_less(highest, score_limit) then local limit_str if #score_limits == 1 then limit_str = '上榜线' elseif #score_limits == 2 then limit_str = '精品线' end str = '|-\n|colspan="4" style="text-align: center;"|' .. limit_str .. ': ' .. score_limit .. '\n' table.remove(score_limits, 1) end end return str end function p.standings(frame) local args = frame.args[1] and frame.args or frame:getParent().args; local records = select_standing(get_records(), args[1], args[2]) local score_limits = get_score_limits(args[1], args[2]) local had_score_limits = (next(score_limits) ~= nil) local ranking = 0 local ranking_hold = 0 local highest = nil local wikitable_str = '{| class="wikitable" style="display: inline-block; vertical-align: top"\n' if args[2]:len() == 2 then title = '关卡 ' .. args[2] else title = args[2] end wikitable_str = wikitable_str .. '|+ <h3>' .. title .. '</h3>\n' wikitable_str = wikitable_str .. '! 名次 !! 分数 !! 纪录持有者 !! 视频链接\n' for key, record in ipairs(records) do ranking = ranking + 1 if highest == nil or highest ~= remove_asterisk(record[score_col]) then ranking_hold = ranking highest = remove_asterisk(record[score_col]) wikitable_str = wikitable_str .. get_score_limit_str(highest, score_limits) if next(score_limits) == nil and had_score_limits then ranking_hold = '附' end end wikitable_str = wikitable_str .. '|-\n' wikitable_str = wikitable_str .. '|' .. ranking_hold wikitable_str = wikitable_str .. '||' .. record[score_col] wikitable_str = wikitable_str .. '||' .. record[name_col] wikitable_str = wikitable_str .. '||' .. record[video_col] wikitable_str = wikitable_str .. '\n' end while next(score_limits) do wikitable_str = wikitable_str .. get_score_limit_str(nil, score_limits) end wikitable_str = wikitable_str .. '|}\n' mw.log(wikitable_str) return wikitable_str end return p