-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSoftResJSON.lua
More file actions
223 lines (193 loc) · 7.17 KB
/
Copy pathSoftResJSON.lua
File metadata and controls
223 lines (193 loc) · 7.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
-- RT - Raid Tool | JSON Import Parser (RaidHelper + SoftRes)
-- Compatible Lua 5.0 (WoW 1.12)
-- ============================================================
-- string.match n'existe pas en Lua 5.0
local function strmatch(s, pattern)
if not s then return nil end
local _, _, cap = string.find(s, pattern)
return cap
end
-- Classes Discord a ignorer (absent du raid)
local RT_SKIP_CLASS = {
["Absence"] = true,
["Late"] = true,
}
-- Categories custom Discord (pas une vraie classe WoW)
local RT_CUSTOM_CLASS = {
["Tank"] = true,
["Bench"] = true,
["Tentative"] = true,
}
-- Extrait la valeur d'un champ "key":"value" dans un bloc JSON plat
local function RT_GetField(obj, key)
-- Champ texte : "key":"valeur"
local val = strmatch(obj, '"' .. key .. '":"([^"]*)"')
if val then return val end
-- Champ numerique : "key":123
val = strmatch(obj, '"' .. key .. '":(%d+)')
return val
end
-- Trouve le contenu entre le premier '[' apres arrayKey et son ']' correspondant
-- Retourne la sous-chaine (sans les crochets externes)
local function RT_FindArrayStr(jsonStr, arrayKey)
local keyPos = string.find(jsonStr, '"' .. arrayKey .. '"', 1, true)
if not keyPos then return nil end
-- Chercher le '[' qui suit la cle
local bracketPos = string.find(jsonStr, "[", keyPos, true)
if not bracketPos then return nil end
local depth = 1
local i = bracketPos + 1
local len = string.len(jsonStr)
while i <= len and depth > 0 do
local c = string.sub(jsonStr, i, i)
if c == "[" then depth = depth + 1
elseif c == "]" then depth = depth - 1 end
i = i + 1
end
if depth == 0 then
-- retourne le contenu entre [ et ]
return string.sub(jsonStr, bracketPos + 1, i - 2)
end
return nil
end
-- Extrait tous les objets {…} de premier niveau dans une chaine
-- (les objets imbriques sont inclus dans leur parent)
local function RT_ExtractObjects(str)
local objects = {}
local i = 1
local len = string.len(str)
while i <= len do
local startPos = string.find(str, "{", i, true)
if not startPos then break end
local depth = 1
local j = startPos + 1
while j <= len and depth > 0 do
local c = string.sub(str, j, j)
if c == "{" then depth = depth + 1
elseif c == "}" then depth = depth - 1 end
j = j + 1
end
if depth == 0 then
table.insert(objects, string.sub(str, startPos, j - 1))
i = j
else
break
end
end
return objects
end
local function RT_SoftResNormalizeRole(role)
if not role then return "?" end
local r = string.lower(role)
if string.find(r, "tank") then return "Tank" end
if string.find(r, "heal") then return "Heal" end
if string.find(r, "melee") then return "Melee" end
if string.find(r, "ranged") then return "Ranged" end
return "?"
end
local function RT_SoftResNormalizeClass(class)
if not class then return "" end
local classMap = {
["warrior"] = "Warrior", ["paladin"] = "Paladin",
["hunter"] = "Hunter", ["rogue"] = "Rogue",
["priest"] = "Priest", ["shaman"] = "Shaman",
["mage"] = "Mage", ["warlock"] = "Warlock",
["druid"] = "Druid",
}
return classMap[string.lower(class)] or class
end
-- Nettoie un nom Discord vers nom WoW :
-- "Appolonios/Benelda" -> "Appolonios"
-- "!ZiggZagg/Styg!" -> "ZiggZagg"
-- "#Slimou#-Cornichonne" -> "Slimou"
local function RT_CleanPlayerName(name)
if not name or name == "" then return name end
local part = strmatch(name, "^([^/|]+)") or name
part = string.gsub(part, "%s*%([^)]*%)%s*$", "")
local clean = strmatch(part, "([%a][%a%d]*)")
if clean and clean ~= "" then return clean end
return strmatch(part, "^%s*(.-)%s*$") or part
end
function RT_ImportSoftResJSON(jsonStr)
if not jsonStr or jsonStr == "" then
return false, "JSON vide"
end
-- Nettoyer sauts de ligne
jsonStr = string.gsub(jsonStr, "\r\n", " ")
jsonStr = string.gsub(jsonStr, "\r", " ")
jsonStr = string.gsub(jsonStr, "\n", " ")
jsonStr = string.gsub(jsonStr, "\t", " ")
-- Extraire les metadonnees globales
local date = RT_GetField(jsonStr, "date")
local title = RT_GetField(jsonStr, "displayTitle")
or RT_GetField(jsonStr, "title")
local isRaidHelper = string.find(jsonStr, '"cClassName"', 1, true) ~= nil
-- Localiser et extraire le contenu du tableau signUps
local signUpsStr = RT_FindArrayStr(jsonStr, "signUps")
if not signUpsStr or string.len(signUpsStr) < 5 then
return false, "Tableau signUps introuvable"
end
-- Extraire les objets individuels du tableau signUps
local rawObjects = RT_ExtractObjects(signUpsStr)
if table.getn(rawObjects) == 0 then
return false, "Aucun objet dans signUps"
end
RT_DB = RT_DB or {}
RT_DB.roster = RT_DB.roster or {}
RT_DB.signUps = RT_DB.signUps or {}
RT_DB.signUps.date = date or ""
RT_DB.signUps.title = title or "Import"
RT_DB.signUps.raidHelper = isRaidHelper
local imported = 0
local skipped = 0
for idx = 1, table.getn(rawObjects) do
local obj = rawObjects[idx]
local name = RT_GetField(obj, "name")
local rawClass = RT_GetField(obj, "cClassName") or RT_GetField(obj, "className") or ""
if not name or name == "" then
skipped = skipped + 1
elseif RT_SKIP_CLASS[rawClass] then
skipped = skipped + 1
else
local playerName = RT_CleanPlayerName(name)
if not playerName or playerName == "" then
playerName = name
end
local roleStr = RT_GetField(obj, "cRoleName") or RT_GetField(obj, "roleName") or ""
local role = RT_SoftResNormalizeRole(roleStr)
local class
if RT_CUSTOM_CLASS[rawClass] then
class = ""
if rawClass == "Tank" then role = "Tank" end
else
class = RT_SoftResNormalizeClass(rawClass)
end
local spec = RT_GetField(obj, "specName") or RT_GetField(obj, "cSpecName") or ""
local note = RT_GetField(obj, "note") or ""
RT_DB.roster[playerName] = {
class = class,
spec = spec,
role = role,
sr = 0,
status = RT_GetField(obj, "status") or "primary",
note = note,
}
imported = imported + 1
end
end
-- Auto-complétion : classe déduite de la spé (Holy1=Paladin...),
-- spé normalisée, rôle affiné Melee/Ranged.
local fixedCls = 0
if RT3_AutofixRoster then fixedCls = RT3_AutofixRoster() end
local msg = "Imported " .. imported .. " player(s)"
if skipped > 0 then
msg = msg .. " (" .. skipped .. " skipped)"
end
if fixedCls > 0 then
msg = msg .. ", " .. fixedCls .. " class(es) auto-detected from spec"
end
if isRaidHelper then
msg = msg .. " [RaidHelper]"
end
return true, msg
end