comparison mleqdkp.lua @ 1:822b6ca3ef89

Import of 2.15, moving to wowace svn.
author Farmbuyer of US-Kilrogg <farmbuyer@gmail.com>
date Sat, 16 Apr 2011 06:03:29 +0000
parents
children 67b8537e8432
comparison
equal deleted inserted replaced
0:0f14a1e5364d 1:822b6ca3ef89
1 if UnitName"player" ~= "Farmbuyer" then return end
2 local addon = select(2,...)
3
4 -- We keep some local state bundled up rather than trying to pass it around
5 -- as paramters (which would have entailed creating a ton of closures).
6 local state = {}
7 local tag_lookup_handlers = {}
8 local do_tag_lookup_handler
9
10
11 --[[
12 This is taken from CT_RaidTracker 1.7.32, reconstructing the output from
13 code inspection. No official format documents are available on the web
14 without downloading and installing the EQDKP webserver package. Bah.
15
16 Case of tag names shouldn't matter, but is preserved here from CT_RaidTracker
17 code for comparison of generated output.
18
19 There is some waste adding newlines between elements here only to strip them
20 out later, but it's worth the extra cycles for debugging and verification.
21
22 $TIMESTAMP,$ENDTIME MM/DD/YY HH:mm:ss except we don't have seconds available
23 $REALM GetRealmName()
24 $ZONE raw name, not snarky
25 $RAIDNOTE arbitrary text for the raid event
26 $PHAT_LEWTS all accumulated loot entries
27 ]]
28 local XML = ([====[
29 <RaidInfo>
30 <Version>1.4</Version> {In live output, this is missing due to scoping bug in ct_raidtracker.lua:3471}
31 <key>$TIMESTAMP</key>
32 <realm>$REALM</realm>
33 <start>$TIMESTAMP</start> {Same as the key, apparently?}
34 <end>$ENDTIME</end> {Set by the "end the raid" command in the raid tracker, here just the final entry time}
35 <zone>$ZONE</zone> {may be optional. first one on the list in case of multiple zones?}
36 {<difficulty>$DIFFICULTY</difficulty> {this scales badly in places like ICC. may be optional?}}
37
38 {<PlayerInfos>... {guh.}}
39
40 <BossKills>
41 $BOSS_KILLS
42 </BossKills>
43
44 {<Wipes> bleh}
45 {<NextBoss>Baron Steamroller</NextBoss> {only one "next boss" for the whole raid event? huh?}}
46
47 <note><![CDATA[$RAIDNOTE - Zone: $ZONE]]></note>
48
49 {<Join>...</Join><Leave>...</Leave> {specific timestamps per player. meh.}}
50
51 <Loot>
52 $PHAT_LEWTS
53 </Loot>
54 </RaidInfo>]====]):gsub('%b{}', "")
55
56 --[[
57 See the loot markup, next block.
58 ]]
59 local boss_kills_xml = ([====[
60 <key$N>
61 <name>$BOSS_NAME</name>
62 <time>$BOSS_TIME</time>
63 <attendees></attendees> {this is actually empty in the working example...}
64 <difficulty>$DIFFICULTY</difficulty>
65 </key$N>
66 ]====]):gsub('%b{}', "")
67
68 local function boss_kills_tag_lookup (tag)
69 if tag == 'N' then
70 return tostring(state.key)
71 elseif tag == 'BOSS_NAME' then
72 return state.entry.bosskill
73 elseif tag == 'BOSS_TIME' then
74 return do_tag_lookup_handler (state.index, state.entry, 'TIME')
75 else
76 return do_tag_lookup_handler (state.index, state.entry, tag) or 'NYI'
77 end
78 end
79
80 --[[
81 $N 1-based loop variable for key element
82 $ITEMNAME Without The Brackets
83 $ITEMID Not the ID, actually a full itemstring without the leading "item:"
84 $ICON Last component of texture path?
85 $CLASS,$SUBCLASS ItemType
86 $COLOR GetItemQualityColor, full 8-digit string
87 $COUNT,$BOSS,$ZONE,
88 $PLAYER all self-explanatory
89 $COSTS in DKP points... hmmm
90 $ITEMNOTE take the notes field for this one
91 $TIME another formatted timestamp
92 ]]
93 local phat_lewt_xml = ([====[
94 <key$N>
95 $LEWT_GRUNTWORK
96 <zone>$ZONE</zone> {may be optional}
97 <difficulty>$DIFFICULTY</difficulty> {this scales badly in places like ICC. may be optional?}
98 <Note><![CDATA[$ITEMNOTE - Zone: $ZONE - Boss: $BOSS - $COSTS DKP]]></Note> {zone can be followed by difficulty}
99 </key$N>
100 ]====]):gsub('%b{}', "")
101
102 local function phat_lewt_tag_lookup (tag)
103 if tag == 'N' then
104 return tostring(state.key)
105 elseif tag == 'COSTS'
106 then return '1'
107 else
108 return do_tag_lookup_handler (state.index, state.entry, tag) or 'NYI'
109 end
110 end
111
112 do
113 local gruntwork_tags = {
114 "ItemName", "ItemID", "Icon", "Class", "SubClass", "Color", "Count",
115 "Player", "Costs", "Boss", "Time",
116 }
117 for i,tag in ipairs(gruntwork_tags) do
118 gruntwork_tags[i] = (" <%s>$%s</%s>"):format(tag,tag:upper(),tag)
119 end
120 phat_lewt_xml = phat_lewt_xml:gsub('$LEWT_GRUNTWORK', table.concat(gruntwork_tags,'\n'))
121 end
122
123
124 local function format_EQDKP_timestamp (day_entry, time_entry)
125 --assert(day_entry.kind == 'time', day_entry.kind .. " passed to MLEQDKP timestamp")
126 return addon:format_timestamp ("$M/$D/$Y $h:$m:00", day_entry, time_entry)
127 end
128
129
130 -- Look up tag strings for a particular item, given index and entry table.
131 tag_lookup_handlers.ITEMNAME =
132 function (i, e)
133 return e.itemname
134 end
135
136 tag_lookup_handlers.ITEMID =
137 function (i, e)
138 return e.itemlink:match("^|c%x+|H(item[%d:]+)|h%[")
139 end
140
141 tag_lookup_handlers.ICON =
142 function (i, e)
143 local str = e.itexture
144 repeat
145 local s = str:find('\\')
146 if s then str = str:sub(s+1) end
147 until not s
148 return str
149 end
150
151 tag_lookup_handlers.CLASS =
152 function (i, e)
153 return state.class
154 end
155
156 tag_lookup_handlers.SUBCLASS =
157 function (i, e)
158 return state.subclass
159 end
160
161 tag_lookup_handlers.COLOR =
162 function (i, e)
163 local q = select(4, GetItemQualityColor(e.quality))
164 return q:sub(3) -- skip leading |c
165 end
166
167 tag_lookup_handlers.COUNT =
168 function (i, e)
169 return e.count and e.count:sub(2) or "1" -- skip the leading "x"
170 end
171
172 -- maybe combine these next two
173 tag_lookup_handlers.BOSS =
174 function (i, e)
175 while i > 0 and state.loot[i].kind ~= 'boss' do
176 i = i - 1
177 end
178 if i == 0 then return "No Boss Entry Found, Unknown Boss" end
179 return state.loot[i].bosskill
180 end
181
182 tag_lookup_handlers.ZONE =
183 function (i, e)
184 while i > 0 and state.loot[i].kind ~= 'boss' do
185 i = i - 1
186 end
187 if i == 0 then return "No Boss Entry Found, Unknown Zone" end
188 return state.loot[i].instance
189 end
190
191 tag_lookup_handlers.DIFFICULTY =
192 function (i, e)
193 local tag = tag_lookup_handlers.ZONE(i,e)
194 local N,h = tag:match("%((%d+)(h?)%)")
195 if not N then return "1" end -- maybe signal an error instead?
196 N = tonumber(N)
197 N = ( (N==10) and 1 or 2 ) + ( (h=='h') and 2 or 0 )
198 return tostring(N)
199 end
200
201 tag_lookup_handlers.PLAYER =
202 function (i, e)
203 return state.player
204 end
205
206 tag_lookup_handlers.ITEMNOTE =
207 function (i, e)
208 return state.itemnote
209 end
210
211 tag_lookup_handlers.TIME =
212 function (i, e)
213 local ti,tl = addon:find_previous_time_entry(i)
214 return format_EQDKP_timestamp(tl,e)
215 end
216
217
218 function do_tag_lookup_handler (index, entry, tag)
219 local h = tag_lookup_handlers[tag]
220 if h then
221 return h(index,entry)
222 else
223 error(("MLDKP tag lookup (index %d) on tag %s with no handler"):format(index,tag))
224 end
225 end
226
227 local function generator (ttype, loot, last_printed, generated, cache)
228 -- Because it's XML, generated text is "grown" by shoving more crap into
229 -- the middle instead of appending to the end. Only easy way of doing that
230 -- here is regenerating it from scratch each time.
231 generated[ttype] = nil
232
233 local _
234 local text = XML
235 state.loot = loot
236
237 -- TIMESTAMPs
238 do
239 local f,l -- first and last timestamps in the table
240 for i = 1, #loot do
241 if loot[i].kind == 'time' then
242 f = format_EQDKP_timestamp(loot[i])
243 break
244 end
245 end
246 _,l = addon:find_previous_time_entry(#loot) -- latest timestamp
247 l = format_EQDKP_timestamp(l,loot[#loot])
248 text = text:gsub('$TIMESTAMP', f):gsub('$ENDTIME', l)
249 end
250
251 -- Loot
252 do
253 local all_lewts = {}
254 local lewt_template = phat_lewt_xml
255
256 state.key = 1
257 for i,e in addon:filtered_loot_iter('loot') do
258 state.index, state.entry = i, e
259 -- no sense doing repeated getiteminfo calls
260 state.class, state.subclass = select(6, GetItemInfo(e.id))
261
262 -- similar logic as text_tabs.lua:
263 -- assuming nobody names a toon "offspec" or "gvault"
264 local P, N
265 local disp = e.disposition or e.person
266 if disp == 'offspec' then
267 P,N = e.person, "offspec"
268 elseif disp == 'gvault' then
269 P,N = "guild vault", e.person
270 else
271 P,N = disp, ""
272 end
273 if e.extratext_byhand then
274 N = N .. " -- " .. e.extratext
275 end
276 state.player, state.itemnote = P, N
277
278 all_lewts[#all_lewts+1] = lewt_template:gsub('%$([%w_]+)',
279 phat_lewt_tag_lookup)
280 state.key = state.key + 1
281 end
282
283 text = text:gsub('$PHAT_LEWTS', table.concat(all_lewts, '\n'))
284 end
285
286 -- Bosses
287 do
288 local all_bosses = {}
289 local boss_template = boss_kills_xml
290
291 state.key = 1
292 for i,e in addon:filtered_loot_iter('boss') do
293 if e.reason == 'kill' then -- oh, for a 'continue' statement...
294 state.index, state.entry = i, e
295 all_bosses[#all_bosses+1] = boss_template:gsub('%$([%w_]+)',
296 boss_kills_tag_lookup)
297 state.key = state.key + 1
298 end
299 end
300
301 text = text:gsub('$BOSS_KILLS', table.concat(all_bosses, '\n'))
302 end
303
304 -- In addition to doing the top-level zone, this will also catch any
305 -- leftover $ZONE tags. There could be multiple places in the raid, so
306 -- we default to the first one we saw.
307 do
308 local iter = addon:filtered_loot_iter() -- HACK
309 local first_boss = iter('boss',0)
310 local zone = first_boss and loot[first_boss].instance or "Unknown"
311 text = text:gsub('$ZONE', zone)
312 end
313
314 -- Misc
315 text = text:gsub('$REALM', (GetRealmName()))
316 --text = text:gsub('$DIFFICULTY', )
317 text = text:gsub('$RAIDNOTE', "")
318
319 cache[#cache+1] = "Formatted version (scroll down for unformatted):"
320 cache[#cache+1] = "==========================="
321 cache[#cache+1] = text
322 cache[#cache+1] = '\n'
323
324 cache[#cache+1] = "Unformatted version:"
325 cache[#cache+1] = "==========================="
326 text = text:gsub('>%s+<', "><")
327 cache[#cache+1] = text
328 cache[#cache+1] = '\n'
329
330 wipe(state)
331 return true
332 end
333
334 local function specials (_, editbox, container, mkbutton)
335 local hl = mkbutton("Highlight",
336 [[Highlight the unformatted copy for copy-and-pasting.]])
337 hl:SetFullWidth(true)
338 hl:SetCallback("OnClick", function(_hl)
339 local txt = editbox:GetText()
340 local _,start = txt:find("Unformatted version:\n=+\n")
341 local _,finish = txt:find("</RaidInfo>", start)
342 editbox.editBox:HighlightText(start,finish)
343 editbox.editBox:SetCursorPosition(start)
344 end)
345 container:AddChild(hl)
346 end
347
348 addon:register_text_generator ("mleqdkp", [[ML/EQ-DKP]], [[MLdkp 1.1 EQDKP format]], generator, specials)
349
350 -- vim:noet