FactionCapture! 12k records in 6 months

The other component to cf_armory, FactionCapture, is a mess!! A while ago I added the option to chose what factions to graph, and I just changed it to only store faction history for 6 months (filling up my database!), but the page is still so ugly. I'm thinking this is a good candidate for a Flex app. I love the idea of graphically seeing your faction values change over time, but the current conception of it that I have stinks.

So I played with some Flex and came up with this design mock up... The new mock up

UpgradeCentral gets JQuery Upgrade

After a year of ignoring it, I've finally gotten back to enhancing UpgradeCentral. I used JQuery to break up the data into tabs. Now you'll immediately notice the tabs are too much to fit on the screen, so go into a weird second line. That's because I don't know jack about JQuery ... yet.

Note, UpgradeCentral uses Armory to determine what is an upgrade, based on the character's current spec. And a lot of it is rubbish. It generally ignores items with a "chance on hit" sort of bonuses.

Next I need some check boxes to unselect locations. I don't care to see upgrades from Sunwell, Black Temple, or PVP with my hunter and nothing over Gruul's with my priest.

WoW Head popups in blogCFC

I'm not completely happy with my solution, but it works. It goes through Blizzard's armory to search for the item and get the item number, then uses wowhead.com to help make the popup.

Like yesterday's post, add a code block to blog.cfc to look for {item ...} code fragments. This is where I'm not happy, I wanted [wowitem ...] to work.

<!--- Check for wowitem blocks --->
<cfif findNoCase("{item ",arguments.string) and findNoCase("}",arguments.string)>
   <cfset armoryCFC=CreateObject("component","sandbox.wow.armory")>
   <cfset counter = findNoCase("{item ",arguments.string)>
   <cfloop condition="counter gte 1">
      <cfset codeblock = reFindNoCase("(?s)(.*)(\{item )(.*)(\})(.*)",arguments.string,1,1)>
      <cfif arrayLen(codeblock.len) gte 6>
         <cfset codeportion = mid(arguments.string, codeblock.pos[4], codeblock.len[4])>
         
         <cfset result = armoryCFC.getItemLinkFromName(codeportion)>
         <cfset newbody = mid(arguments.string, 1, codeblock.len[2]) & result & mid(arguments.string,codeblock.pos[6],codeblock.len[6])>

         <cfset arguments.string = newbody>
         <cfset counter = findNoCase("{item ",arguments.string,counter)>
      <cfelse>
         <cfset counter = 0>
      </cfif>
   </cfloop>
</cfif>

This references armory.cfc, so make it and add these two functions...

getItemLinkFromName

<cffunction name="getItemLinkFromName" access="remote" returntype="string">
   <cfargument name="itemName" default="War-Feathered Loop">
   <cfargument name="baseURL" required="false" default="http://armory.worldofwarcraft.com/">

   <cfset var url = arguments.baseURL
         & "search.xml?searchQuery=" & URLEncodedFormat(arguments.itemName)
         & "&searchType=Items">

   <cfset var itemsheet = makeHTTPCall(url)>
   <!--- initialize variables to be used --->
   <cfset var items = "">
   <cfset var ret = "">
            
   <cfif left(itemsheet.statuscode,3) neq "200">
      <cfreturn arguments.itemName/>
   </cfif>
   
   <cfset items = XMLParse(itemsheet.fileContent).page.armorySearch.searchResults.items>
   
   <cfif ArrayLen(items.XMLChildren) eq 0>
      <cfreturn arguments.itemName/>
   </cfif>
   
   <cfset ret = "<a href='http://www.wowhead.com/?item=#items.XMLChildren[1].XMLAttributes.id#'>#arguments.itemName#</a>">

   <cfreturn ret>   
</cffunction>

makeHTTPCall

<cffunction name="makeHTTPCall" returntype="struct">
   <cfargument name="url" required="true">
   <!---
   Store the user agent that I am using with my browser
   --->

   <cfset var strUserAgent = (
            "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; " &
            "rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3"
            ) />

            
   <cfhttp
      url="#arguments.url#"
      method="GET"
      result="armoryXML"
      useragent="#strUserAgent#"
      />

   
   <cfreturn armoryXML>
</cffunction>

Then add somewhere in your page, a script block for WOW Head ...

The magic in that script will add the popup to all links to wowhead.com, woo! If the item isn't found in the armory, it will just print the name of the item. Problem though, is if more than one item is found, it'll make a link to the first item. This is needed though. Boots of the Crimson Hawk is made from Pattern: Boots of the Crimson Hawk. Doing a search for the boots returns the pattern as well. I'm guessing armory returns items in alphabetical order.

So what happened with making a [wowitem ...]? It was fine when there was only one in the post, but could wrap the first "[wowitem" with the final "]" if there was more than one. If someone with better regex knowledge than I can solve this, please share!

cf_armory code

FactionCapture, phase 1

Try FactionCapture

I didn't upload the last version I was working on last night, so the graph is still small-ish and strange. But like the others, put in yourself and you'll have the option to start tracking faction. Reputation levels are gathered daily, at about 11pm EST. The factions on the graph are arbitrary ones that I'm currently interested in. I just haven't had a chance to try out making the chart with Flex2.

I made a main page for these cf_armory tools. The Heroic key lister requires some crunching on the server end. It runs longer than my host allows, so have to run it on my local machine. I'll post the full code files for all this once I clean them up more.

cf_armory : UpdateCentral phase 1 complete

For example, look up me, name: Castlereagh, realm: Bloodhoof

UpdateCentral

I'm blow away by the speed of this compared to if you were to click through each item slot on the armory character screen. This was my big chance to use ! The data comes back so quickly right now though.

I'm modularizing, moving more stuff to cfcs. There are three functions involved, and the page to call them all. I put one layer of error checking for the CFHTTP request function

[More]

cf_armory : UpgradeCentral, planning

Time to think about what to do with the new armory data available, item upgrades. I have a feeling those armory servers will need hardware upgrades soon if they keep adding usefulness to the site. There will be more and more developers writing stuff to pound that data.

  1. Get the person's character name and realm with a simple form
  2. Pull the character sheet, character-sheet.xml
  3. Pull out a list of current gear from the xml page/characterInfo/characterPage/items
  4. Loop over the items, requesting the xml of upgrades
  5. Remove any items you just wouldn't likely use, i.e. remove leather items if you're a warrior
  6. ?? Remove any items below the currently equipped one
  7. Display back the list of items, by slot

This project is the perfect place to try CF8's <cfthread> tag. After getting a list of equipped items, spawn a thread for each one send them on their way. Merge them back together before displaying. With 16-17 item slots (remove tabard and shirt, ignore off-hand if the character uses a 2 handed weapon), cfthread in theory would make the page come back maybe 15 times faster. If it really ends up being that much faster, it would be fine to create a list for an entire guild. You could created a "most wanted" list of bosses and instances, where the most people could possibly get an upgrade. This, like the heroic key builder, you still wouldn't want to run on demand when it's for an entire guild.

<filters>
<filter name="source" value="all"/>

<filter name="type" value="weapons"/>
<filter name="rrt" value="all"/>
<filter name="andor" value="or"/>
<filter name="slot" value="ranged"/>
<filter name="usbleBy" value="3"/>
<filter count="1" name="advOpt" value="attackPower_gteq_30"/>
<filter count="2" name="advOpt" value="agility_gt_0"/>
<filter count="3" name="advOpt" value="spellManaRegen_gt_0"/>
<filter name="recc" value="1"/>

<filter name="rqrMax" value="73"/>
</filters>

That's at the top of the upgrade page. Look at the "advOpt" filters, very cool. It figures those are my 3 top stats needed.

Armory updates, find an upgrade

Blizz just made some upgrades to the armory, very exciting stuff. You can now search for upgrades.

http://armory.worldofwarcraft.com/search.xml?searchType=items&pr=<;<realm>>&pn=<<charactername>>&pi=<<itemid>>

will now return a list of items that are an upgrade for the character for that item slot. So

http://armory.worldofwarcraft.com/search.xml?searchType=items&pr=Bloodhoof&pn=Castlereagh&pi=27423

Shows all the cloak upgrades I could get and where to get them. I'm seeing using this to build a list of locations and boss targets you need to go for upgrades. I'm not clear if it includes my current build for the calculations. But as a hunter, agility, crit, and attack power are what I need. It adds the "use" abilities of items to the rankings, that's cool. Unfortunately the gear you get by turning in tokens is listed as "vendor" instead of naming the boss that drops the token. And items that are created don't say by what profession (it's usually obvious, but like a leatherworker and a blacksmith can both make mail armor).

UPDATE: The armory upgrade finder DOES take spec (or current stats) into account. I looked up a 40/21/0 mage and the search modifiers were spellDamage, intellect, spellCritRating, stamina, spirit. A 0/0/61 mage was spellDamage, intellect, stamina.

cf_armory continued

I'd posted a first throw together of Blizzard Armory data a while ago here. Now I've completed phase one. It'll pull data for the guild from armory, save it to the database, pull reputations, and display is nicely (with a stolen CSS file).

Check it out

I have to thank Matt Shooks, his posts on the topic gave me some good ideas. From his code, I broke up the process so that it can happen more in smaller steps. First load all guild data, then load each character's reputation. If this were in CF8, I'd maybe want to run the reputation processing in blocks of ten characters in separate threads. That would be hot.

The next step will be to put filtering on the display page. Only show druids and priests that can go to heroic Mana Tombs, for example. How about some code first.

The page to load data to the database is pretty short and sweet.

<cfparam name="url.guild" default="Minions of the Night"/>
<cfparam name="url.realm" default="Bloodhoof"/>

<cfoutput>
(RE)LOADING GUILD ROSTER FOR #url.guild# - #url.realm#
</cfoutput>
...
<cfflush>
<cfset quickGuildRosterLoad(url.realm,url.guild,68)>
...
ROSTER LOADED<br/>
<br/>
STARTING REPUTATION UPDATE<br/>
<cfflush/>
<cfset loadGuildReputation(url.realm,url.guild)>
GUILD REP UPDATED

[More]

BlogCFC was created by Raymond Camden. This blog is running version 5.9.002. Contact Blog Owner