Mercurial > wow > ouroloot
comparison core.lua @ 147:e1a90e398231
Add unique seconds to history timestamp.
Rewrite :format_timestamp to suck less. Include seconds in the formatted
history timestamp, because preening fails horribly when the same person
has received multiple pieces of loot within the same "minute". Ensure the
timestamps are unique if needed; fast looting easily results in multiple
loot events per second.
Tweak wording of some GUI warnings.
author | Farmbuyer of US-Kilrogg <farmbuyer@gmail.com> |
---|---|
date | Tue, 30 Dec 2014 20:26:41 -0500 |
parents | 543fcf15add7 |
children | 113dd7c86222 |
comparison
equal
deleted
inserted
replaced
146:543fcf15add7 | 147:e1a90e398231 |
---|---|
26 | 26 |
27 Common g_loot entry indices: | 27 Common g_loot entry indices: |
28 - kind time/boss/loot | 28 - kind time/boss/loot |
29 - hour 0-23, on the *physical instance server*, not the realm server | 29 - hour 0-23, on the *physical instance server*, not the realm server |
30 - minute 0-59, ditto | 30 - minute 0-59, ditto |
31 - stamp time_t on the local computer | 31 - stamp time_t on the local computer, possibly tweaked for uniqueness |
32 | 32 |
33 Time specific g_loot indices: | 33 Time specific g_loot indices: |
34 - startday table with month/day/year/text fields from makedate() | 34 - startday table with month/day/year/text fields from makedate() |
35 text is always "dd Month yyyy" | 35 text is always "dd Month yyyy" |
36 | 36 |
177 --['heirloom'] = 7, | 177 --['heirloom'] = 7, |
178 } | 178 } |
179 local my_name = UnitName('player') | 179 local my_name = UnitName('player') |
180 local comm_cleanup_ttl = 4 -- seconds in the communications cache | 180 local comm_cleanup_ttl = 4 -- seconds in the communications cache |
181 local version_large = nil -- defaults to 1, possibly changed by version | 181 local version_large = nil -- defaults to 1, possibly changed by version |
182 local timestamp_fmt_unique = '%Y/%m/%dT%H:%M:%S' | |
183 local timestamp_fmt_history = '%Y/%m/%d %H:%M:%S' | |
182 local g_LOOT_ITEM_ss, g_LOOT_ITEM_MULTIPLE_sss, g_LOOT_ITEM_SELF_s | 184 local g_LOOT_ITEM_ss, g_LOOT_ITEM_MULTIPLE_sss, g_LOOT_ITEM_SELF_s |
183 local g_LOOT_ITEM_SELF_MULTIPLE_ss, g_LOOT_ITEM_WHILE_PLAYER_INELIGIBLE_ss | 185 local g_LOOT_ITEM_SELF_MULTIPLE_ss, g_LOOT_ITEM_WHILE_PLAYER_INELIGIBLE_ss |
184 | 186 |
185 | 187 |
186 ------ Addon member data | 188 ------ Addon member data |
1818 person = match(person,"|c%x%x%x%x%x%x%x%x(%S+)") or person | 1820 person = match(person,"|c%x%x%x%x%x%x%x%x(%S+)") or person |
1819 else | 1821 else |
1820 person = my_name -- UNIT_YOU / You | 1822 person = my_name -- UNIT_YOU / You |
1821 end | 1823 end |
1822 | 1824 |
1823 return _do_loot (self, --[[override=]]false, person, unique, | 1825 return _do_loot (self, --[[override=]]false, person, --[[unique=]]nil, |
1824 match(itemlink,"item[%-?%d:]+"), count) | 1826 match(itemlink,"item[%-?%d:]+"), count) |
1825 | 1827 |
1826 elseif event == "broadcast" then | 1828 elseif event == "broadcast" then |
1827 return _do_loot (self, --[[override=]]false, ...) | 1829 return _do_loot (self, --[[override=]]false, ...) |
1828 | 1830 |
2615 end | 2617 end |
2616 end | 2618 end |
2617 | 2619 |
2618 -- Adding entries to the loot record, and tracking the corresponding timestamp. | 2620 -- Adding entries to the loot record, and tracking the corresponding timestamp. |
2619 do | 2621 do |
2620 local rawget, setmetatable = rawget, setmetatable | 2622 local date, time, rawget, setmetatable = date, time, rawget, setmetatable |
2621 | 2623 |
2622 --@debug@ | 2624 --@debug@ |
2623 local tos = {} | 2625 local tos = {} |
2624 tos.time = function (e) | 2626 tos.time = function (e) |
2625 return e.startday.text | 2627 return e.startday.text |
2672 i = i - 1 | 2674 i = i - 1 |
2673 end | 2675 end |
2674 end | 2676 end |
2675 | 2677 |
2676 -- format_timestamp (["format_string"], Day, [Loot]) | 2678 -- format_timestamp (["format_string"], Day, [Loot]) |
2679 -- FORMAT_STRING may contain $x (x in TmdHMS) tokens, with the same | |
2680 -- meanings as in Lua/strftime but restricted formatting: | |
2681 -- Y year, 4 digit | |
2682 -- m month, 2 digit | |
2683 -- d day, 2 digit | |
2684 -- H hour, 2 digit, 24-hour clock | |
2685 -- M minute | |
2686 -- S second | |
2677 -- DAY is a loot entry with kind=='time', and controls the date printed. | 2687 -- DAY is a loot entry with kind=='time', and controls the date printed. |
2678 -- LOOT may be any kind of entry in the g_loot table. If present, it | 2688 -- LOOT may be any kind of entry in the g_loot table. If present, it |
2679 -- overrides the hour and minute printed; if absent, those values are | 2689 -- overrides the clock values printed; if absent, those values are |
2680 -- taken from the DAY entry. | 2690 -- taken from the DAY entry. |
2681 -- FORMAT_STRING may contain $x (x in Y/M/D/h/m) tokens. | |
2682 -- FIXME this is horribabble | |
2683 local format_timestamp_values, point2dee = {}, "%.2d" | 2691 local format_timestamp_values, point2dee = {}, "%.2d" |
2684 function addon:format_timestamp (fmt_opt, day_entry, time_entry_opt) | 2692 function addon:format_timestamp (fmt_opt, day_entry, time_entry_opt) |
2685 if not time_entry_opt then | 2693 if not time_entry_opt then |
2686 if type(fmt_opt) == 'table' then -- Two entries, default format | 2694 if type(fmt_opt) == 'table' then -- Two entries, default format |
2687 time_entry_opt, day_entry = day_entry, fmt_opt | 2695 time_entry_opt, day_entry = day_entry, fmt_opt |
2688 fmt_opt = "$Y/$M/$D $h:$m" | 2696 fmt_opt = "$Y/$m/$d $H:$M" |
2689 --elseif type(fmt_opt) == "string" then -- Day entry only, caller-specified format | 2697 --elseif type(fmt_opt) == "string" then -- Day entry only, caller-specified format |
2690 end | 2698 end |
2691 end | 2699 end |
2692 --format_timestamp_values.Y = point2dee:format (day_entry.startday.year % 100) | |
2693 format_timestamp_values.Y = ("%.4d"):format (day_entry.startday.year) | 2700 format_timestamp_values.Y = ("%.4d"):format (day_entry.startday.year) |
2694 format_timestamp_values.M = point2dee:format (day_entry.startday.month) | 2701 format_timestamp_values.m = ("%.2d"):format (day_entry.startday.month) |
2695 format_timestamp_values.D = point2dee:format (day_entry.startday.day) | 2702 format_timestamp_values.d = ("%.2d"):format (day_entry.startday.day) |
2696 format_timestamp_values.h = point2dee:format ((time_entry_opt or day_entry).hour) | 2703 format_timestamp_values.H = ("%.2d"):format ((time_entry_opt or day_entry).hour) |
2697 format_timestamp_values.m = point2dee:format ((time_entry_opt or day_entry).minute) | 2704 format_timestamp_values.M = ("%.2d"):format ((time_entry_opt or day_entry).minute) |
2698 return fmt_opt:gsub ('%$([YMDhm])', format_timestamp_values) | 2705 format_timestamp_values.S = date ("%S", (time_entry_opt or day_entry).stamp) |
2706 return fmt_opt:gsub ('%$([YmdHMS])', format_timestamp_values) | |
2699 end | 2707 end |
2700 | 2708 |
2701 local done_todays_date | 2709 local done_todays_date |
2702 function addon:_reset_timestamps() | 2710 function addon:_reset_timestamps() |
2703 done_todays_date = nil | 2711 done_todays_date = nil |
2731 function addon._addLootEntry (e) | 2739 function addon._addLootEntry (e) |
2732 setmetatable(e,loot_entry_mt) | 2740 setmetatable(e,loot_entry_mt) |
2733 | 2741 |
2734 if not done_todays_date then do_todays_date() end | 2742 if not done_todays_date then do_todays_date() end |
2735 | 2743 |
2744 -- All kinds of things go awry (especially history preening) if two | |
2745 -- entries share the exact same timestamp, and we can't get any better | |
2746 -- than one second resolution. | |
2747 -- | |
2748 -- Well, the only API in-game with finer precision is GetTime but the | |
2749 -- computer uptime doesn't help us. Stripping the fractional part off | |
2750 -- and gluing it to time_t would be too risky as they don't cycle at | |
2751 -- the same time. We could do something involving a count incrementing | |
2752 -- with the refresh rate, but... blech. | |
2753 -- | |
2754 -- So we sort of cheat. New entries are pushed into the future one | |
2755 -- second at a time, if needed, so that no two time_t's are equal. | |
2736 local h, m = GetGameTime() | 2756 local h, m = GetGameTime() |
2737 --local localuptime = math.floor(GetTime()) | |
2738 local time_t = time() | 2757 local time_t = time() |
2758 local index = #g_loot -- note, previous entry | |
2739 e.hour = h | 2759 e.hour = h |
2740 e.minute = m | 2760 e.minute = m |
2741 e.stamp = time_t --localuptime | 2761 if index > 0 and g_loot[index].stamp >= time_t then |
2742 local index = #g_loot + 1 | 2762 time_t = g_loot[index].stamp + 1 |
2763 addon.dprint('flow', "bumping timestamp to", time_t) | |
2764 end | |
2765 e.stamp = time_t | |
2766 | |
2767 index = index + 1 | |
2743 if e.kind == 'loot' then | 2768 if e.kind == 'loot' then |
2744 if (not e.unique) or (#e.unique==0) then | 2769 if (not e.unique) or (#e.unique==0) then |
2745 e.unique = e.id .. (e.disposition or e.person) .. date("%Y/%m/%d %H:%M",e.stamp) | 2770 e.unique = e.id .. (e.disposition or e.person) .. date (timestamp_fmt_unique, e.stamp) |
2746 end | 2771 end |
2747 addon:Fire ('NewLootEntry', e, index) | 2772 addon:Fire ('NewLootEntry', e, index) |
2748 end | 2773 end |
2749 g_loot[index] = e | 2774 g_loot[index] = e |
2750 g_gui.g_dloot[index] = nil | 2775 g_gui.g_dloot[index] = nil |
3160 -- ["name"] = "Farmbuyer", | 3185 -- ["name"] = "Farmbuyer", |
3161 -- ["person_class"] = "PRIEST", -- may be missing, used in display only | 3186 -- ["person_class"] = "PRIEST", -- may be missing, used in display only |
3162 -- -- sorted array: | 3187 -- -- sorted array: |
3163 -- ["unique"] = { most_recent_tag, previous_tag, .... }, | 3188 -- ["unique"] = { most_recent_tag, previous_tag, .... }, |
3164 -- -- these are indexed by unique tags, and 'count' may be missing: | 3189 -- -- these are indexed by unique tags, and 'count' may be missing: |
3165 -- ["when"] = { ["tag"] = "formatted timestamp for displaying loot" }, | 3190 -- ["when"] = { ["tag"] = "formatted timestamp for displaying loot history" }, |
3166 -- ["id"] = { ["tag"] = 11111 }, | 3191 -- ["id"] = { ["tag"] = 11111 }, |
3167 -- ["count"] = { ["tag"] = "x3", .... }, | 3192 -- ["count"] = { ["tag"] = "x3", .... }, |
3168 -- }, | 3193 -- }, |
3169 -- [2] = { | 3194 -- [2] = { |
3170 -- ["name"] = "OtherPlayer", | 3195 -- ["name"] = "OtherPlayer", |
3191 return L > R -- reverse of normal order, newest first | 3216 return L > R -- reverse of normal order, newest first |
3192 end | 3217 end |
3193 local function sort_player (p) | 3218 local function sort_player (p) |
3194 local new_uniques, uniques_bywhen, when_array = {}, new(), new() | 3219 local new_uniques, uniques_bywhen, when_array = {}, new(), new() |
3195 for u,tstamp in pairs(p.when) do | 3220 for u,tstamp in pairs(p.when) do |
3221 -- XXX multiple identical tstamps | |
3196 uniques_bywhen[tstamp] = u | 3222 uniques_bywhen[tstamp] = u |
3197 when_array[#when_array+1] = tstamp | 3223 when_array[#when_array+1] = tstamp |
3198 end | 3224 end |
3199 table.sort (when_array, compare_timestamps) | 3225 table.sort (when_array, compare_timestamps) |
3200 for i,tstamp in ipairs(when_array) do | 3226 for i,tstamp in ipairs(when_array) do |
3382 -- be the most recent entry). If g_today has not been set, then falls | 3408 -- be the most recent entry). If g_today has not been set, then falls |
3383 -- back on formatting LOOTINDEX's time_t 'stamp' field. | 3409 -- back on formatting LOOTINDEX's time_t 'stamp' field. |
3384 -- | 3410 -- |
3385 -- If RESORT_P is true-valued, then re-sorts the player's history based on | 3411 -- If RESORT_P is true-valued, then re-sorts the player's history based on |
3386 -- formatted timestmps, instead of leaving the new entry as the latest. | 3412 -- formatted timestmps, instead of leaving the new entry as the latest. |
3413 local tfmt_hist = timestamp_fmt_history:gsub('%%','$') | |
3387 function addon:_addHistoryEntry (lootindex, resort_p) | 3414 function addon:_addHistoryEntry (lootindex, resort_p) |
3388 local e = g_loot[lootindex] | 3415 local e = g_loot[lootindex] |
3389 if e.kind ~= 'loot' then return end | 3416 if e.kind ~= 'loot' then return end |
3390 | 3417 |
3391 if e.person_realm and opts.history_ignore_xrealm then | 3418 if e.person_realm and opts.history_ignore_xrealm then |
3394 | 3421 |
3395 local i,h = self:get_loot_history(e.person) | 3422 local i,h = self:get_loot_history(e.person) |
3396 -- If we've added anything at all into g_loot this session, g_today | 3423 -- If we've added anything at all into g_loot this session, g_today |
3397 -- will be set. If we've logged on simply to manipulate history, then | 3424 -- will be set. If we've logged on simply to manipulate history, then |
3398 -- try and fake a timestamp (it'll be "close enough"). | 3425 -- try and fake a timestamp (it'll be "close enough"). |
3399 local when = g_today and self:format_timestamp (g_today,e) | 3426 -- (WoD: This logic may be backwards now that loot entries track time_t.) |
3400 or date("%Y/%m/%d %H:%M",e.stamp) | 3427 local when = g_today |
3428 and self:format_timestamp (tfmt_hist, g_today, e) | |
3429 or date (timestamp_fmt_history, e.stamp) | |
3401 assert(h.name==e.person) | 3430 assert(h.name==e.person) |
3402 | 3431 |
3403 -- Should rarely happen anymore: | 3432 -- Should rarely happen anymore: |
3404 if (not e.unique) or (#e.unique==0) then | 3433 if (not e.unique) or (#e.unique==0) then |
3405 e.unique = e.id .. e.person .. when | 3434 e.unique = e.id .. e.person .. when |