When using the API to inspect ranking, it is not a numeric value and difficult to determine what the actual rank of the work item is. This article gives an example of how to interpret the 64 character value of DragAndDropRank into a numeric value.
Please note, the method described below is for information purposes only and is NOT supported. It demonstrates a rough approximation of the method Rally developers used to make the ranks consistent after the old numeric Rank attribute was replaced with the new alpha-numeric DragAndDropRank attribute. There are no guarantees that when this method is followed as described a complete match to the results of Rally's internal ranking algorithm can be achieved.
The rank values are base 94 values, using ASCII table but without the control characters (see the char[] digits array below). When we return WSAPI 1.x rank values we convert them to twelve digit decimals to simulate our old rank values. To do that we pull the 6 "most significant" characters from the left hand side and convert each value to long, much like hexadecimal conversion. The customer could use a larger number of significant digits, but we found you need several million artifacts in a workspace before you start hitting collisions in this space.
Let's say WSAPI 2.x rank is:
,~~t~Bj^iEn{qqS5!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
We would use first 6 "most significant" characters from the left hand side:
,~~t~B
and it converts to 88068394267
If you query the same User Story in 2.x and 1.x and compare the DragAndDropRank vs the Rank value you can double check your calculations.
Here are some java code snippets to give a sense of how it works. It won't compile because some tweaking was done to them to have it make sense in this context. This code serves as an illustration only.
The 6 character number above would become raw in the below method; essentially we calculate the numeric value of each letter then multiply it by the appropriate base.
public long convertToLong(String raw) {
long ret = 0L;
char[] chars = raw.toCharArray();
int power = 0;
for (int i = chars.length -1 ; i >=0; i--) {
long multiplier = (long) Math.pow(93, power);
long multiplicand = lookup.get(chars[i]);
ret +=(multiplicand * multiplier);
power++;
}
return ret;
}
protected static final char[] digits = {
'!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
':', ';', '<', '=', '>', '?', '@',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'[', '\\', ']', '^', '_', '`',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'{','|','}','~'
};
private static Map<Character, Integer> lookup;
static {
lookup = newHashMap();
for (int i = 0; i < digits.length; i++) {
lookup.put(digits[i], i);
}
}
EXAMPLE:
Let's say PortfolioItem/Feature query returns three objects. The query's fetch parameter included FromattedID and DragAndDropRank attributes:
Results:
[
{
FormattedID: F33,
DragAndDropRank: "P!!$(~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
},
{
FormattedID: F34,
DragAndDropRank: "P!!$)~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
},
{
FormattedID: F35,
DragAndDropRank: "P!!$*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
}
]