annotate mleqdkp.lua @ 9:4fba9c6b5d3d

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