The December Project (The Grand Refactoring and The License)

Earlier this week I got a good/bad email from my HR department informing me that I needed to take X hours of vacation between now and the end of the year, or I would lose it.
This means that starting tomorrow (Dec2), I am now forced to take Thursdays and Fridays off. No doubt this will cause friction at home because now I will want to monopolize the computer for my own purposes.
So starting tomorrow, I will begin the changes to start putting the common bits of code in all the Guide addons (Leveling, Event, Dailies, Professions) into the base addon.
I'll do it a function/variable at a time, quest a bit and then move on. The basic idea is simple.
- WoWPro will become a "Library" which will support the "Embed" method
- Every function and method to be exported will be registered with WoWPro:Export("function"), which will add it to a list
- The Guide addons will call the WoWPro:Embed(WowPro_XXX) method at the start of loading, which will add all the "standard" methods and functions. The addon is free to redefine anything it wants to override.
That is it! Once this exercise is complete, we will be left with much less code in the addons. We can then work at migrating the leftover goodies in the guide addons back into the base addon to make functionality even across the guides.
Now, along the way, I may change the way some things work. Right now, for instance, the guide list code is bollixed up because each addon implements its own tab and tab management functions that do not have the right information at initialization time to do the right thing. I'll rewrite that code to make it data driven and provide functions in WowPro: for the addons to register functions to return the number of guides, the number of columns and the column labels and to provide a call back when the user selects a row. All of the window handling logic will be centralized and the guide specific information kept out of the core addon.
Oh, and as I go along, I will start adding copyright notices to all the files. This has been discussed on and off now for nearly a year and now we have settled on a bit of a compromise. We have opted to not try to write one of our own licenses (that way there be dragons), but to use a customizable license: the Creative Commons License.
They give us a nice little logo to use: which if you click it, leads to both a human readable and a lawyer readable license.
What does it boil down to:
- Under this license, users can redistribute the code, which we are not thrilled about, but is a minor annoyance.They would have to attribute the code to us (the WoW-Pro Community) and link back to our web site.
- Users can't use the code commercially.
- Users can't redistribute the code if they modify it (so our competitors can't take it and change a couple things and redistribute it).
The advantage of this license is that it's well recognized and has an infrastructure in place which explains decently.
- Login or register to post comments
- Ludovicus Maior's blog
del.icio.us
Digg
Technorati
Twitter

Comments
Progress Report for 12/27
So what could possibly take 17 calendar days?
Once I found the first, the second was obvious. I was nearly in tears this afternoon. Now I can get rid of all the debugging code and convert the rest of the addons to use the new GuideList.
Sooo painful. Writing an automatic way of generating the trial version of the Leveling addon was trivial in comparison.
But now everything scrolls smoothly!
—Ludovicus Maior
Progress Report for 1/1
I now have the other addons converted over. Testing and releasing on Wednesday, Jan 4!
—Ludovicus Maior
World Event Module
That's great news. Hopefully the changes I made to the World Event Module won't put much of a hamper into that plan. For the most part, they are pretty simple. Once you release the changes, I will see about putting in the changes I am making to the professions module. Those are bigger changes to eliminate all those steps and make it a little more user friendly.
Don't forget about the Lunar
Don't forget about the Lunar Festival Elder guides. http://wow-pro.com/wiki/lunar_festival_alliance and http://wow-pro.com/wiki/lunar_festival_horde
I really need to figure out Github more... Would probably make it a lot easier for you with me making new guides or updates.
Oh yea... I forgot Lunar
Oh yea... I forgot Lunar Festival doesn't begin until mid January. Sheesh I'm an idiot.
Progress Report for 12/10
So I got a bit distracted. The Guide List code had this annoying bug where the number of lines displayed was a fixed constant and depending on the size of the options window, it would either not use the whole window or overflow.
Fixing it has been a pain in the $%##! But I am now learning everything about the WoW windowing system that I have avoided for the past year.
But that was not the distraction. I started doing archeology on my current active toon, Agriotherium, and then realized that I had not been exploring everything as throughly as usual. So I added Exploration guides for every zone in Kalimdor and the Eastern Kingdoms that Twists had not already done.
But the Acheivement guides use the ACH tag, which takes an acheivement Id and a criteria number. How to get these? Write a program!
function WoWPro.Achievements:DumpInfo(achnum)
local count = GetAchievementNumCriteria(achnum)
WoWPro.Achievements.eBox = WoWPro.Achievements.eBox or CreateFrame("EditBox", nil,UIParent,ChatFrameEditBoxTemplate)
local eBox = WoWPro.Achievements.eBox
eBox:SetWidth(512)
eBox:SetHeight(128)
eBox:SetMultiLine(true)
eBox:SetAutoFocus(true)
eBox:SetFontObject(GameFontHighlight)
local text=""
for achitem=1, count do
local description, type, completed, quantity, requiredQuantity, characterName, flags, assetID, quantityString, criteriaID = GetAchievementCriteriaInfo(achnum, achitem)
local line = string.format("F %s|QID|%d|M|0.00,0.00|ACH|%d;%d|",description,900000000+10000*achnum+achitem,achnum,achitem)
-- self:Print(line)
text = text .. line .. "\n"
end
eBox:SetText(text)
eBox:SetPoint("CENTER")
eBox:Show()
eBox:SetScript("OnEscapePressed", function (self) self:Hide() end)
self:Print("Dumped %d items",count)
end
So if you "/run WoWPro.Achievements:DumpInfo(859)" this pops a window in the middle of the screen with a sketch for a guide for achievement 859, Explore Eversong Woods.
Now the fun part starts, write a program to order the flight points to minimize the travel time, assuming you can fly.
The classic shortest path problem, time to drag out Dijkstra's Algorithm!
—Ludovicus Maior
Obtaining objectives
This is alot easier then the way I was doing it. What I was doing was going to wowhead for the zone. The numbers are then layed out in rows going from the 1st one on the left (1) to the second on the right (2), then back to the left next (3), etc. It pretty much follows that pattern.
The hard part is the locations. Those are not always given in wowhead. I haven't really had time to tackle the rest of the explorations ones, but I am working hard on re-writing the code for the professions guide. Hope to have that one soon.
I really hate this captcha.
Obtaining objectives - First find a chump
I have a confession to make: I did not fill in the coordinates for the exploration guides.
I have slowly trained my spouse to do things like edit guides, cross reference things against wowhead and how to fill in the blanks.
So I offered to cook a fancy dinner and bribed him into doing >95% of them.
The first drafts are now checked in, and the release is cut. I need to do some quick checks and I will release it tomorrow.
I have this VERY beta change to the module that re-orders the exploration points according to your current position in the zone, triggered by a zone change. This means the guide will present you with the closest objective that you have not acheived yet. It needs to be sped up a bit and to have a better way of controlling which guides it gets applied to.
BUT I should really finish up the GuideList changes. Now I know I never want to do UI programming for a living.
—Ludovicus Maior
That is just too funny. Wish
That is just too funny. Wish I could do the same, but I can't cook. Not from lack of trying, I just don't have the knack for it (though I am good with desserts..). And my wife isn't very good with editing and cross referencing.
WoWPro Achievment module Error
Not sure what is going on, but getting this error.
Date: 2011-12-10 19:30:12
ID: 1
Error occured in: Global
Count: 1
Message: ...s\WoWPro_Achievements\WoWPro_Achievements_Parser.lua line 204:
attempt to index field 'ach' (a nil value)
Debug:
[C]: ?
...s\WoWPro_Achievements\WoWPro_Achievements_Parser.lua:204:
...s\WoWPro_Achievements\WoWPro_Achievements_Parser.lua:125
...s\WoWPro_Achievements\WoWPro_Achievements_Parser.lua:229: LoadGuide()
WoWPro\WoWPro_Broker.lua:66: LoadGuide()
WoWPro\WoWPro.lua:162:
WoWPro\WoWPro.lua:155
WoWPro Achievment module Error, -- patch
Yup! Got a patch for that:
diff --git a/WoWPro_Achievements/WoWPro_Achievements.lua b/WoWPro_Achievements/WoWPro_Achievements.lua index 320317f..6a6f5a5 100644 --- a/WoWPro_Achievements/WoWPro_Achievements.lua +++ b/WoWPro_Achievements/WoWPro_Achievements.lua @@ -17,7 +19,7 @@ function WoWPro.Achievements:OnEnable() WoWPro:dbp("|cff33ff33Enabled|r: Achievements Module") -- Achievements Tag Setup -- - WoWPro:RegisterTags({"QID", "questtext", "rep", "noncombat"}) + WoWPro:RegisterTags({"QID", "questtext", "rep", "noncombat","ach"}) -- Event Registration -- WoWPro.Achievements.Events = {"QUEST_LOG_UPDATE", "QUEST_COMPLETE", lfo@throne;69$—Ludovicus Maior
So this is addon code to help
So this is addon code to help make achievment guides? If so, what should the .lua file be named and located?
Dijkstra's Algorithm! Run away! Haven't seen that in ages, so long I forgot about it.
... I guess I ought to ...
It was a little thow-away code that I wrote.
I'll stick it in WoWPro_Achievements.lua for now and it will be out on Wednesday.
I was just thinking this morning that it would also help with many other types of acheivements, like the fishing or kill one of X ones.
—Ludovicus Maior
Yep, I agree.
Yep, I agree. Also if possible, maybe have the option to have it save to a txt document? If that is too much though don't worry about it.
WoW and Text Documents
WoW specifcally prohbits creating/reading/writing/deleting files in order to make it "safe".
Lord I wish you had access to web information!
But the window my snippet creates is an edit window and supports select all and copy paste, which makes it easy to plop into a text document yourself.
—Ludovicus Maior
I see, so that makes it just
I see, so that makes it just as good then, if not better.
The new GuideList.lua, a progress report for 12/3
So I decided to tackle the GuideLists as the first refactoring mini-project.
I cut down the code in the Leveling module to just the following blocks:
WoWPro.Leveling.GuideList = {} -- Creating a Table of Guides for the Guide List and sorting based on level -- local guides = {} for guidID,guide in pairs(WoWPro.Guides) do if guide.guidetype == "Leveling" then local progress = "" if guide.total and guide.progress then progress = guide.progress .. "/" .. guide.total end table.insert(guides, { GID = guidID, Zone = guide.zone, Author = guide.author, Range = "("..guide.startlevel.."-"..guide.endlevel..")", Progress = progress, startlevel = guide.startlevel, }) end end WoWPro.Leveling.GuideList.Guides = guides -- Sorting Functions -- local sorttype = "Default" local function authorSort() if sorttype == "AuthorAsc" then table.sort(guides, function(a,b) return a.author > b.author end) WoWPro.Leveling:UpdateGuideList() sorttype = "AuthorDesc" else table.sort(guides, function(a,b) return a.author < b.author end) WoWPro.Leveling.UpdateGuideList() sorttype = "AuthorAsc" end end local function zoneSort() ... end local function rangeSort() ... end rangeSort() -- Sort by range sorttype = "Default" -- and reset to Default -- Describe the table to the Core Module WoWPro.Leveling.GuideList.Format={{"Zone",0.35,zoneSort}, {"Range",0.15,rangeSort}, {"Author",0.30,authorSort}, {"Progess",0.20,nil}}The base module looks at the specification in GuideList.Format and builds the buttons and text boxes and uses the field names to extract the data out of GuideList.Guides . UpdateGuideList() is a generic method imported from the WoWPro module. The fractional numbers set the width of the field as a percent of the total width.
Once I get it functional (I am a terrible speller), it should be easy to get the other Guides converted. It should even handle the new muti-sized options window correctly.
—Ludovicus Maior
Err...?
Err...? I have no idea what this means. I can do simple stuff but you're kind of beyond my realm of current understanding.
the start of loading, which will add all the "standard" methods and
functions. The addon is free to redefine anything it wants to override.
I think I need to stick with dealing with PC hardware for the most part. XD
A Practical Example
The first function I ported was :Print().
In WowPro.Lua:
WoWPro.Name = "WoWPro"
...
WowPro:Export("Print")
function WoWPro:Print(message)
if message ~= nil then
print(string.format("|cffffff00%s|r: %s", self.Name or "Wow-Pro" , message))
end
end
In WowPro_Leveling.lua:
WoWPro.Leveling.Name = "WowProLeveling"WoWPro:Embed(WoWPro.Leveling)...WoWPro.Leveling:Print("|cff33ff33Enabled|r")Now when you call :Print, it gets passed as the self object either WoWPro.Leveling or WoWPro and can therefore prefix the message with the name of the module. Every function in WoWPro.Leveling that gets migrated, I need to decide if any variable or function references need to be changed to self: or pegged at WowPro: . Does that make it any clearer?
—Ludovicus Maior
Completed Zone Re-Selecting?
(For whatever reason I can't create a NEW post, so I'm sorry to do it this way, but I don't see another method...)
While you are working under the hood on wow-pro, is there a way to enable still being able to select a Zone even if every task in it is checfked off? The way it is now, if every task is checked as completed (or even skipped, I think), the interface no longer allows the User to select that Zone. It just jumps to the next one in the list. I've ran into several times when I really wanted to get to a specific step to remeber where I was (or how to get somewhere), but if the interface disallows re-selecting completed Zones, this isn't possible.
Thank you!
M.
Actually there is a way.
Actually there is a way. Reset the guide, shift+click it while in the Guide List.
Nope, but hazarding a guess I
Nope, but hazarding a guess I would say it is basically what it prints on the screen for us to read?
Sounds good! I'll wait before
Sounds good! I'll wait before messing with the Localization then.