Nobility listing

06/05/2011 22:54 Iron~Man#1
I really don't want to look up into other messy public sources, so I'd like you to help me.
I cannot figure out nobility listing.. I have something in my head that goes like this..
When Somebody donates ->
Code:
[U]ulong[] Donations = new ulong[50];[/U]
for (int i = 0; i < 50; i++)
{
if (Char.Donation < Donations[i])
        Char.NobleRank = i;
}
But what is next?

It's really hard for me to realize, anybody willing to help me for REAL, or willing to code a part for me please add me on my msn [Only registered and activated users can see links. Click Here To Register...]
06/05/2011 23:12 BaussHacker#2
Use Array.Sort();
06/06/2011 01:51 pro4never#3
Or LINQ.


LINQ is my new overlord.

It will do what array.sort will but won't have any annoying issues you might normally have with an array (non dynamic size, etc). I'd simply use a link query to pull all valid donations (above X value or w/e), sort them by donation, limit how many I want to pull (top 60 or w/e for the list) and then .ToList() the returned collection and you're good to go.
06/06/2011 02:26 CptSky#4
It's not a really good way to do it, but it's working...

Code:
           public static void ResetPosition()
            {
                lock (World.NobilityRank)
                {
                    if (World.NobilityRank.Count < 1)
                        return;

                    Nobility.Info[] Infos = new Nobility.Info[World.NobilityRank.Count];
                    World.NobilityRank.Values.CopyTo(Infos, 0);

                    List<Int32> Sorted = new List<Int32>();
                    Int64 LastDonation = Int64.MaxValue;
                    Int32 LastUID = 0;
                    Int64 tmp1 = 0;
                    for (Int32 i = 0; i < Infos.Length; i++)
                    {
                        for (Int32 x = 0; x < Infos.Length; x++)
                        {
                            if (Sorted.Contains(Infos[x].UniqId))
                                continue;

                            if (Infos[x].Donation > tmp1 && Infos[x].Donation <= LastDonation)
                            {
                                Infos[x].Position = i;
                                tmp1 = Infos[x].Donation;
                                LastUID = Infos[x].UniqId;
                            }
                        }
                        LastDonation = tmp1;
                        LastDonation++;
                        tmp1 = 0;
                        Sorted.Add(LastUID);
                        LastUID = 0;
                    }

                    World.NobilityRank.Clear();
                    for (Int32 i = 0; i < Infos.Length; i++)
                    {
                        Infos[i].Rank = 0;
                        if (Infos[i].Position >= _MAX_KING + _MAX_PRINCE + _MAX_DUKE)
                        {
                            if (Infos[i].Donation >= _DONATION_KNIGHT)
                                Infos[i].Rank = _RANK_KNIGHT;

                            if (Infos[i].Donation >= _DONATION_BARON)
                                Infos[i].Rank = _RANK_BARON;

                            if (Infos[i].Donation >= _DONATION_EARL)
                                Infos[i].Rank = _RANK_EARL;
                        }
                        else
                        {
                            if (Infos[i].Position < _MAX_KING + _MAX_PRINCE + _MAX_DUKE)
                                Infos[i].Rank = _RANK_DUKE;

                            if (Infos[i].Position < _MAX_KING + _MAX_PRINCE)
                                Infos[i].Rank = _RANK_PRINCE;

                            if (Infos[i].Position < _MAX_KING)
                                Infos[i].Rank = _RANK_KING;
                        }

                        World.NobilityRank.Add(Infos[i].UniqId, Infos[i]);

                        Player Player = null;
                        if (World.AllPlayers.TryGetValue(Infos[i].UniqId, out Player))
                            Player.Send(MsgNoble.Create(Player));
                    }
                }
            }
06/06/2011 04:55 pro4never#5
Code:
  public static void ReSortRankings()
        {
             var results = from I in NobilityRecords orderby I.Value.Donation descending select I;
           sbyte pos = 0;
           foreach (KeyValuePair<uint, Packet.NobilityRankingInfo> rank in results)
           {
              
               rank.Value.NobilityType = (byte)GetNobilityType(rank.Value.Donation);
               if (Kernel.Clients.ContainsKey(rank.Key))
                   rank.Value.Online = 1;
               else
                   rank.Value.Online = 0;
               if (rank.Value.Rank != pos)
               {
                   rank.Value.Rank = pos;
                   Kernel.Clients[rank.Key].Send(Packet.Nobility.CreateIcon(Kernel.Clients[rank.Key]));
               }
               pos++;
           }
           NobilityRecords = results.ToDictionary(b=>b.Key, b=>b.Value);
        }
Not perfect but a handy little Linq version I wrote up.
06/06/2011 10:12 { Angelius }#6
i wold do it this way though idk its just another way to do the ranking :)


PHP Code:
public static List<Struct.NoblilityStatusNobilityBoard = new List<Struct.NoblilityStatus>(); 

PHP Code:
Monitor.Enter(Dictionary.NobilityBoard);
try
{
Struct.NoblilityStatus ID Dictionary.NobilityBoard.Where(=> p.UID == Status.UID).FirstOrDefault();
if (
ID == null) { Dictionary.NobilityBoard.Add(Status); } 
else { 
Dictionary.NobilityBoard[Dictionary.NobilityBoard.IndexOf(ID)] = Status; }

var 
NobilityCount from DV in Dictionary.ThreadSafeDictionary(Dictionary.NobilityBoardwhere DV.Donation Status.Donation && DV.UID != Status.UID select DV;
if (
NobilityCount.Count() > 0)
{
int Rank = (Dictionary.NobilityBoard.Count() - NobilityCount.Count()) - 1;
if (
Dictionary.NobilityBoard[Rank].UID != Status.UID)
{
Dictionary.NobilityBoard.Remove(Status);
Dictionary.NobilityBoard.Insert(RankStatus); 
/*Update the db table*/
}
}
else { 
/*Update the db table*/}
}
finally Monitor.Exit(Dictionary.NobilityBoard); } 
06/06/2011 20:49 _DreadNought_#7
@Array.Sort, Use a better algorithm to do what array.sort does.
06/07/2011 01:27 .Kinshi#8
Use LINQ or grab the values straight from the database.

Code:
SELECT * FROM nobility ORDER BY donation DESC LIMIT 0, 9
Will get you the top 10 nobility donations.
06/07/2011 01:48 pro4never#9
Quote:
Originally Posted by .Kinshi View Post
Use LINQ or grab the values straight from the database.

Code:
SELECT * FROM nobility ORDER BY donation DESC LIMIT 0, 9
Will get you the top 10 nobility donations.
Code:
 var results =
                (from I in NobilityRecords.Values orderby I.Donation descending select I)
                .Skip((int)page * NOBILITY_PAGE_SIZE)
                .Take(NOBILITY_PAGE_SIZE);
That's what I do in my source. I store all of the nobility rankings inside the source just cause I haven't bothered converting to our nhibrinate db system yet. Works perfectly and supports multiple pages.
06/07/2011 02:27 _tao4229_#10
Quote:
Originally Posted by _DreadNought_ View Post
@Array.Sort, Use a better algorithm to do what array.sort does.
Array.Sort runs in O(n log n) time iirc. Not going to write a much faster algorithm to sort an array.


Edit: Uses quicksort, so I guess you could implement a better algorithm.
06/07/2011 10:01 Korvacs#11
It should be noted that using LINQ impacts performance greatly, and that while as significantly less elegant as a for loop is, they are significantly faster.
06/07/2011 13:36 { Angelius }#12
Quote:
Originally Posted by Korvacs View Post
It should be noted that using LINQ impacts performance greatly, and that while as significantly less elegant as a for loop is, they are significantly faster.
yep but ... I would personally still use linq when it comes to such stuff ranking/localClients/in range mobs as it doesent really impact performance when it comes to 600/700 items (few millisec's)
06/07/2011 13:42 Korvacs#13
When your developing for a server a few milliseconds whenever you do anything that involves the clients, rankings, mobs builds up. Its the server, you shouldn't be sacrificing time for readability, what kind of approach to server development is that?
06/07/2011 16:06 { Angelius }#14
i thought that you were the one that is talking about threadpooling, calling things on different threads, queues /w.e

however its less than few milliseconds using linq with a dictionary that contains 1k items
D---H ---S ---MS
00:00:00.0160000

nothing to mention thought correct me if im wrong.

EDIT: Well Lets Face It a for Loop did the same job in a way better amount of time
D---H ---S ---MS
00:00:00.0050000
06/07/2011 17:00 Korvacs#15
Yes my argument is that if you can save time by improving performance through your source then you should, so use threadpooling where possible (and necessary) use code that is faster, not more elegant.