PDA

View Full Version : Sorting lists?



Insanity
September 8th, 2007, 15:31
I am in the process of creating lists similar to the d20 spells lists, for various parts of my ruleset;

i.e. skills, armor, weapons, etc...

After looking through the existing code in the d20 ruleset, I have made the appropriate changes to allow my lists to be created and displayed, except for one minor thing. The lists are, by default I'd imagine, sorted by name alphabetically. I would like to be able to sort the list by name alphabetically and by another value numerically, with the numerical being primarily sorted.

i.e. Helmets have a value called threshold, can range anywhere from 1-60, I want the various armors to be listed by Name and Threshold value. So that my list would maybe something like this:

Helmet A : Threshold 1
Helmet B : Threshold 1
Helmet C : Threshold 2
Helmet E : Threshold 2
Helmet F : Threshold 3
Helmet D: Threshold 4
Helmet G : Threshold 4
Helmet I : Threshold 5
Helmet J : Threshold 5
Helmet H : Threshold 6

I am not sure if sorting like this is possible, I'd imagine sorting by alphabetically is a default that really is not in the code, but with FG itself.

Any feedback is appreciated.

The code is virtually identical to the d20 spells, but if parts need to be posted I can do that.

Toadwart
September 8th, 2007, 23:29
Sorting is done within lua scripts.
If you create a script file for your windowlist you can implement whatever sorting you need within the onSortCompare event.

something like:


function onSortCompare(w1, w2, fieldname)
local returnValue = false;

local name1 = w1.Name.getValue();
local name2 = w2.Name.getValue();
local threshold1 = w1.threshold.getValue();
local threshold2 = w2.threshold.getValue();

if threshold1 == threshold2 then
returnValue = name1 > name2;
else
returnValue = threshold1 > threshold2;
end

return returnValue;
end

Insanity
September 9th, 2007, 00:36
Thanks Toadwart, however, I don't know where within the xml code to insert this or if I should create a separate lua file.:)

Toadwart
September 9th, 2007, 04:28
Create a separate .lua file with that function definition in it then 'link' it to your windowlist like so:



<windowlist name="mylist">
...
<script file = "scripts\mylistscript.lua>
</windowlist>


You will need a separate lua file for each windowlist. Unless they have exactly the same field names to be sorted by, in which case they can both point at the same .lua script file.

It's possible to do this in a more generic fashion but this is the easiest way to start out.
You may run into trouble if you are trying to change the existing spells page, can't recall exactly how it works but I do remember the code in there is quite confusing.

Also: the function definition should just be
function onSortCompare(w1, w2)
not
function onSortCompare(w1, w2, fieldname)

Insanity
September 9th, 2007, 04:55
Thanks, that works...almost.

It sorting it by name and threshold, except its sorting

1, 10, 11, 12, 2, 20, 21, 22, 3, 31, 32, etc.

and not

1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 12, 13, 14, etc.

Griogre
September 9th, 2007, 05:15
Your numbers are being sorted as if they are strings (letters). The easiest fix would be to input your number less than 10 with leading zeroes ie 3 should be 03, 4 as 04 etc.

I am not familar with the sort function but depending on your data you might want the values to be numbers.

Foen
September 9th, 2007, 06:09
The other thing you might try is to coerce the strings to numbers by adding zero to them:



local threshold1 = (w1.threshold.getValue() + 0);
local threshold2 = (w2.threshold.getValue() + 0);


Stuart

Insanity
September 10th, 2007, 15:36
Thanks Foen, it seems to work with one error.

I made that change to my helmet list, no problems.
I made the same change to my armor list and got the following error:

Script Error: [string "reference_armorgrouplistitem:armorlist"]:1: attempt to perform arithmetic on a string value

For both helmet and armor desc, I have thr (threshold) as type="string"
and use stringcontrol for the listing, yet get the error for one and not the error.

The only think I could think of is the fact I have two armors the have their thr value as 4/8 and 5/8, and one with no value, listed as "-". I will do some changes and see if thats it...

Insanity
September 10th, 2007, 15:51
The only think I could think of is the fact I have two armors the have their thr value as 4/8 and 5/8, and one with no value, listed as "-". I will do some changes and see if thats it...

Changing these values to 4, 5, and 0 resolved that error, but then the list is not quite how I want it, but I may have to accept that.

Thanks again Foen.

Toadwart
September 10th, 2007, 23:28
Another trick is to have a field in your data that is purely there for sorting: e.g.

<sortkey type="number">1</sortkey>

You could add an invisible numberfield to the windowlist
e.g.


<numberfield name="sortkey>
...
<script>
function onInit()
setVisible(false);
end
</script>
</numberfield>


However, it's simpler to just use the getdatabaseNode function to retrieve the value directly from the database.


function onSortCompare(w1, w2)
key1 = w1.getDatabaseNode().getChild("sortkey").getValue();
key2 = w2.getDatabaseNode().getChild("sortkey").getValue();

returnValue = key1 > key2;
end

Insanity
September 12th, 2007, 22:09
I've using this code for other sorting



local threshold1 = (w1.threshold.getValue() + 0);
local threshold2 = (w2.threshold.getValue() + 0);


and it seems to work fine if the "string" is a "number" less than 1,000

now my other sorting have values over 1,000. It will sort in the way I want it to, but I do get this error.



Script Error: [string "reference_weapongrouplistitem:weaponlist"]:1: attempt to perform arithmetic on a string value


The fact that it does work apparently, but still get this error seems odd.

joshuha
September 12th, 2007, 22:17
I realize I am coming into this late but does tonumber() function work for what you are doing or do you have values in there that sometimes aren't numbers? Even if thats the case, you could have a few if checks that assign those some default numbers...


EDIT:

Ok reading more this is a stringfield with numbers on the end so that wouldn't work. However, if everything is always Threshold XXXX you could just get a substring out past the word Threshold and conver that using tonumber() and sort that way.

Toadwart
September 12th, 2007, 23:06
I've using this code for other sorting



local threshold1 = (w1.threshold.getValue() + 0);
local threshold2 = (w2.threshold.getValue() + 0);


and it seems to work fine if the "string" is a "number" less than 1,000

now my other sorting have values over 1,000. It will sort in the way I want it to, but I do get this error.



Script Error: [string "reference_weapongrouplistitem:weaponlist"]:1: attempt to perform arithmetic on a string value


The fact that it does work apparently, but still get this error seems odd.

The numbers over 1000 don't have the comma in them do they?
Try debugging by printing the out the values to the console.. So you can see exactly which value(s) the error message is being raised for.


if w1.threshold.getValue() then
print("w1.threshold = " .. w1.threshold.getValue());
else
print("w1.threshold is nil");
end
if w2.threshold.getValue() then
print("w2.threshold = " .. w2.threshold.getValue());
else
print("w2.threshold is nil");
end
local threshold1 = (w1.threshold.getValue() + 0);
local threshold2 = (w2.threshold.getValue() + 0);

Insanity
September 12th, 2007, 23:25
yes, my values are as strings, as that is how I had learned to create the lists. So any value over 1000 is entered as 1,000 with a comma. I corrected it by simpy removing the comma from the string, but some values will be in the millions, and having commas would be nice.

Toadwart
September 13th, 2007, 04:19
The gsub function in the string library can be used to strip out the commas

e.g.



thresholdString1 = (w1.threshold.getValue() );
thresholdString2 = (w2.threshold.getValue() );
threshold1, count1 = string.gsub(thresholdString1, ",", "");
threshold2, count2 = string.gsub(thresholdString2, ",", "");

threshold1 = tonumber(threshold1);
threshold2 = tonumber(threshold2);


the count1 and count2 variables can be ignored - they just record how many commas were removed