Mischiefblog
I WATN 2 MAEK GAEM!

General

Four out of the box ideas for work

Posted by Chris Jones
On June 14th, 2010 at 11:48

Permalink | Trackback | Links In |

Comments Off
Posted in General

1. Use improv the illustrate process descriptions. You’ll be able to see and understand the process in a different way and can help identify errors and bottlenecks before going too deep into design.

2. Hire an artist to capture requirements and planning meetings. Artists interpret and capture meaning, unlike photographs.

3. Put a big HDTV in the team space for planning, tracking, and visualizing burndown, etc.

4. Extreme interviewing: bring in multiple candidates and make them work together. See if they have good kindergarten skills and if they will have the right team motivation and instincts to work with your current team.

The Halls of Reflection (Heroic) tax

Posted by Chris Jones
On December 27th, 2009 at 21:54

Permalink | Trackback | Links In |

Comments (1) |
Posted in General

After my, what, 30th wipe in Halls of Reflection Heroic, this time to a tank that wouldn’t pull waves back to the group but kept trying to fight on the altar, finally keeping Falric out of my healing range after I was feared in the opposite direction, I’m convinced Halls of Reflection is actually a gold tax on people using the random group tool.

I’ve run it successfully despite a lot of bad pugs but I much prefer doing it with a guild group. Becky saw how bad it was on normal mode today when she ran it with one of her Hunters. By comparison, Forge of Souls and Pit of Saron are cakewalks.

Maybe it’s because Halls of Reflection is a healing test, or maybe it’s because most pugs can’t seem to assist. When I ran it earlier today on Normal mode, I made sure everyone knew to assist off the main tank (a mediocre Death Knight, but it’s tough to be a good DK tank). At the least, a successful HoR group can pull 3k DPS per character, minus the healer and maybe the tank — any less and I’m out of mana or dead before I can keep the group’s health up. I feel like HoR was really built around the Holy Priest, even more so than the Tribunal encounter in Halls of Stone.

G13 WoW UI layout

Posted by Chris Jones
On December 25th, 2009 at 22:42

Permalink | Trackback | Links In |

Comments Off
Posted in General

Here’s my updated UI for World of Warcraft.

Buttons are laid out to match the Logitech G13 — the exact choice for each button is still being tweaked, but it’s pretty close to done. Main chat and Grid are next to each other to watch player health, discussion, and DBM warnings in the chat log.

Tanking is done using the same UI with different buttons (replacing the set by virtue of the extra bar groups with multiple talent specs).

(more…)

Notes on Spring development

Posted by Chris Jones
On August 15th, 2009 at 21:28

Permalink | Trackback | Links In |

Comments (3) |
Posted in General

3.0.0.M3 library problems
I haven’t tried 3.0.0.M4 with my new development environment yet, but I had missing class and Antlr problems with 3.0.0.M3. I ended up using 3.0.0.CI-319 at the time to get a working Spring framework.

Creating a logging bean
Create an annotation package with a Log interface:

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
  
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
  
/**
* Injects a logger of an appropriate type into beans.
*/
@Retention(RUNTIME)
@Target(FIELD)
@Documented
public @interface Log {
  
}

Create a logger injector:

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
  
import org.apache.log4j.Logger;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.ReflectionUtils.FieldCallback;
  
/**
* Auto injects the commons Log implementation into the bean when a field is annotated
* with Logger.
*/
public class LoggerInjector implements BeanPostProcessor {
  private static Map>String , Logger< loggers = new HashMap>String , Logger<();
  
  public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    return bean;
  }
  
  public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
    ReflectionUtils.doWithFields(bean.getClass(), new FieldCallback() {
      public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
        // make the field accessible if defined private
        ReflectionUtils.makeAccessible(field);
        if (field.getAnnotation(Log.class) != null) {
          String cls = bean.getClass().getName();
          field.setAccessible(true);
          Logger logger = null;
          if (loggers.containsKey(cls)) {
            logger = loggers.get(cls);
          } else {
            logger = Logger.getLogger(cls);
            loggers.put(cls, logger);
          }
          field.set(bean, logger);
        }
      }
    });
  
    return bean;
  }
}

Declare your logger bean in your application context:

<bean class="mypackage.annotation.LoggerInjector"/>

Attach the Logger to your class:

import org.apache.log4j.Logger;
 
import mypackage.annotation.Log;
 
// in your class fields
 
/**
* Logger
*/
@Log
private Logger logger;
 
// use it
logger.error("Invalid request type: " + requestType);

Interface-oriented design
Define your data objects and factories as interfaces (methods), then provide factory implementations to create or retrieve instances of your data objects:

<bean id="myDaoFactory" class="mypackage.factory.myDaoFactoryImpl"
  factory-method="getFactory" scope="singleton"/>

Autowiring
Use the Autowired annotation to automatically add beans to your consuming classes.

/**
* Storage engine.
*/
@Autowired
private Storage storage;

Non-SQL databases
Non-SQL databases should be handled through high level “use case” calls against a storage engine rather than direct puts and gets.

Heat

Posted by Chris Jones
On July 29th, 2009 at 18:39

Permalink | Trackback | Links In |

Comments (1) |
Posted in General

The Sound is evaporating away. I can barely see Kitsap, and the Olympics are lost in the haze.

I daresay, I may need to turn off my laptop. It’s running at about 110 F to the touch.

Seattle’s record 102 degrees is made that much worse by living in a house with air conditioning. “You won’t need it. It only gets hot a couple times a year, a week or two at the most, and it never goes above 90 and it’s never that humid.” Heh.

Tomorrow should be better.

Awww cute!

Posted by Chris Jones
On June 25th, 2009 at 13:05

Permalink | Trackback | Links In |

Comments Off
Posted in General

Becky got a baby raptor companion pet last night on the WoW 3.2 PTR. She said it was her fifth run through the instance, which means it’s about a 1 in 100 drop rate, similar to the Sprite Darter in Feralas.

Munchkin in the morning

Posted by Chris Jones
On June 25th, 2009 at 07:59

Permalink | Trackback | Links In |

Comments Off
Posted in General

My wife wanted to know if it was worth going Engineering on a Troll hunter and lose the +1% crit bonus to bows to use crafted shot instead.

Think about crit this way:
- For the sake of argument, you hit the mobs for 150 with a shot with
vendor ammo. You fire a shot every 2.7 seconds, and your hit is 2.2%,
meaning your miss rate is 3.7%, giving an effective hit of 144.45. Your
ideal DPS is 55.56, but with your miss, you’re really down to 53.5 DPS.
- 1% crit means one out of 100 shots will crit for up to double damage.
For the purpose of this discussion, we’ll assume it always does double
damage.
- In case A, we’ll say you have +3% crit for this discussion, or 8% crit
actual, which means your damage effective over 300 shots is (144.45 * 300
shots + 150 * 24 crits) or 43335 + 3600 = 46,935 damage, or effective
57.94 DPS
- In case B, we’ll say you have +2% crit, or 7% crit actual, which means
your damage effective over 300 shots is (21 crits) 43335 + 3150 = 46,485
damage or effective 57.39 DPS.

—-
So, as was said on Wowwiki:
What’s better, +to hit or +crit?

In principle they are equal. Which is better depends on circumstances. An
increase in hit rate will usually yield a constant level of damage,
whereas a high crit chance gives a spiky, more random damage distribution
over time.

(With the additional caveat that crits are sometimes dropped because the
attack table is full against a mob, and crits are rolled separately.)
—-

You can see when comparing 57.94 DPS versus 57.39 DPS that they’re almost
equal, and that the difference of .5 DPS from using crafted shot negates
the penalty for not using bows.

Totally worth being 30 minutes later for the bus…

She got King Krush!

Posted by Chris Jones
On June 1st, 2009 at 08:56

Permalink | Trackback | Links In |

Comments (1) |
Posted in General

Becky tamed King Krush Friday morning in Sholozar Basin on Amau, her Kirin Tor Hunter. She had to make a set of 24k HP armor, grab the right equipment and enchants, carry around haste potions, stamina scrolls, etc., but she got him!

The first tame attempt killed her as Krush got a series of critical hits on her. The second attempt was after Krush and a friendly group of Mammoths killed an Undead Mage who tried to get the rare mob, but this one succeeded.

She’s one of the first hunters on the server with the Dinosaur and she keeps getting looks from Horde and whispers from Alliance Hunters who can’t believe she managed to get such a difficult and rare tame.

Stackless Python mutex lock

Posted by Chris Jones
On May 20th, 2009 at 15:50

Permalink | Trackback | Links In |

Comments Off
Posted in General

Would anyone like to point out the problems in the following block of code? I’ve tested it and haven’t found any problems with it as a form of mutex locking between tasks in Stackless Python.


# locks
locks = {}
 
# waiting locks
queue = {}
 
# lock request channel    
lock_manager_channel = stackless.channel()
 
# controls lock manager
stopManager = Signal()
 
def acquire(caller, lck):
    """Acquire a lock from within a tasklet."""
    if not stopManager:
        lock_wait_channel = stackless.channel()
        lock_manager_channel.send((lck, lock_wait_channel, caller))
        # block until lock acquired
        lock_wait_channel.receive()
    else:
        raise LockManagerStoppedException("Lock manager stopped.")
    
def release(caller, lck):
    """Release a lock held by the calling tasklet.
    You can't release a lock you don't have.
    You can't remove a lock request that is enqueued.
    """
    lock_manager_channel.send((lck, None, caller))
 
def lock_manager():
    """Manage lock requests via a monitor task."""
    while queue or not stopManager:
        (lck, channel, caller) = lock_manager_channel.receive()
        if channel != None:
            # lock request
            if not locks.has_key(lck):
                # no lock held
                locks[lck] = caller
                # signal the requester
                channel.send(None)
            elif locks[lck] == caller:
                # reentrant lock
                channel.send(None)
            else:
                # append the request and block until lock released
                if queue.has_key(lck):
                    queue[lck].append((channel, caller))
                else:
                    queue[lck] = [(channel, caller)]
        else:
            # lock release
            if locks.has_key(lck) and locks[lck] == caller:
                # release the lock
                # get the next caller
                if queue.has_key(lck):
                    (channel, next_caller) = queue[lck].pop(0)
                    # remove empty wait queue                
                    if not len(queue[lck]):
                        del queue[lck]
                    # lock on the behalf of the requester
                    locks[lck] = next_caller
                    # notify the blocked requester
                    channel.send(None)
                else:
                    # remove the lock
                    del locks[lck]
            else:
                # no work needed to be done
 
                logger.debug("locks.has_key(" + str(lck) + ") " + str(locks.has_key(lck)))
        stackless.schedule()

(more…)

Incredibly Lucky

Posted by Chris Jones
On May 8th, 2009 at 11:11

Permalink | Trackback | Links In |

Comments Off
Posted in General

My wife decided to tame a spirit beast in Warcraft last night. Of course, at 9pm, even on a relatively dead server, she won’t find one and didn’t expect to: this was mostly a chance to scout out the locations where they spawn. This morning she was woken up at 4am, logged into Warcraft, and Gondria was waiting for her.

I’m afraid to roll against her in any dungeon groups.