Module:AchievementSystem: Difference between revisions
// via Wikitext Extension for VSCode |
// via Wikitext Extension for VSCode |
||
| Line 8: | Line 8: | ||
local Achievements = {} | local Achievements = {} | ||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
| Line 64: | Line 59: | ||
if success and result then | if success and result then | ||
return result | return result | ||
end | end | ||
end | end | ||
return nil | return nil | ||
end | end | ||
| Line 132: | Line 124: | ||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
function Achievements.loadData(frame) | function Achievements.loadData(frame) | ||
-- Use the request-level cache if we already loaded data once | -- Use the request-level cache if we already loaded data once | ||
if dataCache then | if dataCache then | ||
return dataCache | return dataCache | ||
end | end | ||
| Line 145: | Line 134: | ||
if frame and type(frame) == "table" and frame.preprocess then | if frame and type(frame) == "table" and frame.preprocess then | ||
-- Make sure frame is valid and has preprocess method | -- Make sure frame is valid and has preprocess method | ||
local preprocessSuccess, preprocessResult = pcall(function() | local preprocessSuccess, preprocessResult = pcall(function() | ||
return frame:preprocess('{{MediaWiki:AchievementData.json}}') | return frame:preprocess('{{MediaWiki:AchievementData.json}}') | ||
| Line 152: | Line 140: | ||
if preprocessSuccess and preprocessResult then | if preprocessSuccess and preprocessResult then | ||
jsonText = preprocessResult | jsonText = preprocessResult | ||
end | end | ||
end | end | ||
| Line 159: | Line 145: | ||
-- If we couldn't get JSON from frame:preprocess, fall back to direct content loading | -- If we couldn't get JSON from frame:preprocess, fall back to direct content loading | ||
if not jsonText then | if not jsonText then | ||
-- Try using mw.loadJsonData first (preferred method) | -- Try using mw.loadJsonData first (preferred method) | ||
if mw.loadJsonData then | if mw.loadJsonData then | ||
local loadJsonSuccess, jsonData = pcall(function() | local loadJsonSuccess, jsonData = pcall(function() | ||
return mw.loadJsonData(ACHIEVEMENT_DATA_PAGE) | return mw.loadJsonData(ACHIEVEMENT_DATA_PAGE) | ||
| Line 170: | Line 152: | ||
if loadJsonSuccess and jsonData and type(jsonData) == 'table' then | if loadJsonSuccess and jsonData and type(jsonData) == 'table' then | ||
return jsonData | return jsonData | ||
end | end | ||
end | end | ||
| Line 180: | Line 159: | ||
local pageTitle = mw.title.new(ACHIEVEMENT_DATA_PAGE) | local pageTitle = mw.title.new(ACHIEVEMENT_DATA_PAGE) | ||
if not pageTitle or not pageTitle.exists then | if not pageTitle or not pageTitle.exists then | ||
return DEFAULT_DATA | return DEFAULT_DATA | ||
end | end | ||
| Line 190: | Line 168: | ||
if contentSuccess and content and content ~= "" then | if contentSuccess and content and content ~= "" then | ||
-- Remove any BOM or leading whitespace that might cause issues | -- Remove any BOM or leading whitespace that might cause issues | ||
content = content:gsub("^%s+", "") | content = content:gsub("^%s+", "") | ||
if content:byte(1) == 239 and content:byte(2) == 187 and content:byte(3) == 191 then | if content:byte(1) == 239 and content:byte(2) == 187 and content:byte(3) == 191 then | ||
content = content:sub(4) | content = content:sub(4) | ||
end | end | ||
| Line 201: | Line 176: | ||
jsonText = content | jsonText = content | ||
else | else | ||
return DEFAULT_DATA | return DEFAULT_DATA | ||
end | end | ||
| Line 214: | Line 188: | ||
if jsonDecodeSuccess and jsonData then | if jsonDecodeSuccess and jsonData then | ||
return jsonData | return jsonData | ||
end | end | ||
| Line 224: | Line 197: | ||
if jsonDecodeSuccess and jsonData then | if jsonDecodeSuccess and jsonData then | ||
return jsonData | return jsonData | ||
end | end | ||
end | end | ||
-- As absolute last resort, use local default data | -- As absolute last resort, use local default data | ||
return DEFAULT_DATA | return DEFAULT_DATA | ||
end) | end) | ||
if not success or not data then | if not success or not data then | ||
data = DEFAULT_DATA | data = DEFAULT_DATA | ||
end | end | ||
| Line 257: | Line 218: | ||
function Achievements.getUserAchievements(pageId) | function Achievements.getUserAchievements(pageId) | ||
if not pageId or pageId == '' then | if not pageId or pageId == '' then | ||
return {} | return {} | ||
end | end | ||
| Line 263: | Line 223: | ||
local data = Achievements.loadData() | local data = Achievements.loadData() | ||
if not data or not data.user_achievements then | if not data or not data.user_achievements then | ||
return {} | return {} | ||
end | end | ||
local key = tostring(pageId) | local key = tostring(pageId) | ||
-- Try string key first | -- Try string key first | ||
local userAchievements = data.user_achievements[key] or {} | local userAchievements = data.user_achievements[key] or {} | ||
if #userAchievements > 0 then | if #userAchievements > 0 then | ||
return ensureArray(userAchievements) | return ensureArray(userAchievements) | ||
end | end | ||
| Line 280: | Line 237: | ||
local numKey = tonumber(key) | local numKey = tonumber(key) | ||
if numKey and data.user_achievements[numKey] then | if numKey and data.user_achievements[numKey] then | ||
return ensureArray(data.user_achievements[numKey]) | return ensureArray(data.user_achievements[numKey]) | ||
end | end | ||
| Line 288: | Line 244: | ||
local alt = "n" .. key | local alt = "n" .. key | ||
if data.user_achievements[alt] and #data.user_achievements[alt] > 0 then | if data.user_achievements[alt] and #data.user_achievements[alt] > 0 then | ||
return ensureArray(data.user_achievements[alt]) | return ensureArray(data.user_achievements[alt]) | ||
end | end | ||
| Line 296: | Line 251: | ||
for userId, achievements in pairs(data.user_achievements) do | for userId, achievements in pairs(data.user_achievements) do | ||
if tostring(userId) == key then | if tostring(userId) == key then | ||
return ensureArray(achievements) | return ensureArray(achievements) | ||
end | end | ||
end | end | ||
return {} | return {} | ||
end | end | ||
| Line 322: | Line 275: | ||
function Achievements.getAchievementName(achievementType) | function Achievements.getAchievementName(achievementType) | ||
if not achievementType or achievementType == '' then | if not achievementType or achievementType == '' then | ||
return 'Unknown' | return 'Unknown' | ||
end | end | ||
local data = Achievements.loadData() | local data = Achievements.loadData() | ||
if not data or not data.achievement_types then | if not data or not data.achievement_types then | ||
return achievementType | return achievementType | ||
end | end | ||
| Line 338: | Line 287: | ||
if typeData.id == achievementType then | if typeData.id == achievementType then | ||
if typeData.name and typeData.name ~= "" then | if typeData.name and typeData.name ~= "" then | ||
return typeData.name | return typeData.name | ||
else | else | ||
return achievementType | return achievementType | ||
end | end | ||
| Line 347: | Line 294: | ||
end | end | ||
return achievementType | return achievementType | ||
end | end | ||
| Line 362: | Line 303: | ||
function Achievements.getTitleClass(pageId) | function Achievements.getTitleClass(pageId) | ||
if not pageId or pageId == '' then | if not pageId or pageId == '' then | ||
return '', '' | return '', '' | ||
end | end | ||
| Line 368: | Line 308: | ||
local userAchievements = Achievements.getUserAchievements(pageId) | local userAchievements = Achievements.getUserAchievements(pageId) | ||
if #userAchievements == 0 then | if #userAchievements == 0 then | ||
return '', '' | return '', '' | ||
end | end | ||
| Line 378: | Line 317: | ||
for _, achievement in ipairs(userAchievements) do | for _, achievement in ipairs(userAchievements) do | ||
local achType = achievement.type | local achType = achievement.type | ||
for _, typeData in ipairs(data.achievement_types) do | for _, typeData in ipairs(data.achievement_types) do | ||
if typeData.id == achType then | if typeData.id == achType then | ||
local tier = typeData.tier or 999 | local tier = typeData.tier or 999 | ||
if tier < highestTier then | if tier < highestTier then | ||
highestTier = tier | highestTier = tier | ||
highestAchievement = typeData | highestAchievement = typeData | ||
end | end | ||
end | end | ||
| Line 394: | Line 330: | ||
if not highestAchievement or not highestAchievement.id then | if not highestAchievement or not highestAchievement.id then | ||
return '', '' | return '', '' | ||
end | end | ||
| Line 400: | Line 335: | ||
local cssClass = "achievement-" .. highestAchievement.id | local cssClass = "achievement-" .. highestAchievement.id | ||
local displayName = highestAchievement.name or highestAchievement.id or "Award" | local displayName = highestAchievement.name or highestAchievement.id or "Award" | ||
return cssClass, displayName | return cssClass, displayName | ||
| Line 471: | Line 404: | ||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
function Achievements.getSpecificAchievement(pageId, achievementType) | function Achievements.getSpecificAchievement(pageId, achievementType) | ||
if not pageId or not achievementType or pageId == '' then | if not pageId or not achievementType or pageId == '' then | ||
return nil | return nil | ||
end | end | ||
| Line 484: | Line 413: | ||
for _, achievement in ipairs(userAchievements) do | for _, achievement in ipairs(userAchievements) do | ||
if achievement.type == achievementType then | if achievement.type == achievementType then | ||
return achievement | return achievement | ||
end | end | ||
end | end | ||
return nil | return nil | ||
end | end | ||
| Line 498: | Line 425: | ||
function Achievements.getAchievementDefinition(achievementType) | function Achievements.getAchievementDefinition(achievementType) | ||
if not achievementType or achievementType == '' then | if not achievementType or achievementType == '' then | ||
return nil | return nil | ||
end | end | ||
| Line 504: | Line 430: | ||
local data = Achievements.loadData() | local data = Achievements.loadData() | ||
if not data or not data.achievement_types then | if not data or not data.achievement_types then | ||
return nil | return nil | ||
end | end | ||
| Line 511: | Line 436: | ||
for _, typeData in ipairs(data.achievement_types) do | for _, typeData in ipairs(data.achievement_types) do | ||
if typeData.id == achievementType then | if typeData.id == achievementType then | ||
return typeData | return typeData | ||
end | end | ||
end | end | ||
return nil | return nil | ||
end | end | ||
| Line 562: | Line 485: | ||
function Achievements.getTitleAchievement(pageId) | function Achievements.getTitleAchievement(pageId) | ||
if not pageId or pageId == '' then | if not pageId or pageId == '' then | ||
return '', '', '' | return '', '', '' | ||
end | end | ||
| Line 568: | Line 490: | ||
local userAchievements = Achievements.getUserAchievements(pageId) | local userAchievements = Achievements.getUserAchievements(pageId) | ||
if #userAchievements == 0 then | if #userAchievements == 0 then | ||
return '', '', '' | return '', '', '' | ||
end | end | ||
| Line 583: | Line 504: | ||
local highestTier = 999 | local highestTier = 999 | ||
local titleAchievement = nil | local titleAchievement = nil | ||
for _, achievement in ipairs(userAchievements) do | for _, achievement in ipairs(userAchievements) do | ||
local achType = achievement.type | local achType = achievement.type | ||
if achType then | if achType then | ||
local typeData = typeDefinitions[achType] | local typeData = typeDefinitions[achType] | ||
if typeData and typeData.type == "title" then | if typeData and typeData.type == "title" then | ||
local tier = typeData.tier or 999 | local tier = typeData.tier or 999 | ||
if tier < highestTier then | if tier < highestTier then | ||
highestTier = tier | highestTier = tier | ||
titleAchievement = typeData | titleAchievement = typeData | ||
end | end | ||
end | end | ||
| Line 605: | Line 520: | ||
if not titleAchievement or not titleAchievement.id then | if not titleAchievement or not titleAchievement.id then | ||
return '', '', '' | return '', '', '' | ||
end | end | ||
| Line 612: | Line 526: | ||
local displayName = titleAchievement.name or achievementId | local displayName = titleAchievement.name or achievementId | ||
return achievementId, displayName, achievementId | return achievementId, displayName, achievementId | ||
end | end | ||
return Achievements | return Achievements | ||