views:

65

answers:

2

I'm trying to represent a scoreboard for a competition and am struggling with the best data structures to use.

I have a list of Player objects, a list of Round objects, and for each combination, I need to store a RoundScore object (there are various parts to the score for a round).

What I'd like is some overall Scoreboard object where the following holds:

1 - I can access a collection of RoundScore objects identified by Round keys by providing a Player object. For example, maybe something like:

public IDictionary<Round,RoundScore> PlayerScores(Player player) { ... }

2 - I can access a collection of RoundScore objects identified by Player keys by providing a Round object. e.g:

public IDictionary<Player,RoundScore> RoundScores(Round round) { ... }

3 - I can access a single RoundScore object by providing a Player and a Round

4 - I can add a new Round and all Players will get a new RoundScore for that round with default values

5 - Similarly, I can add a new Player and all Rounds will have a new RoundScore for that player with default values


I guess what I'm really looking for is a representation of a grid with Rounds on one axis, Players on the other, and RoundScores in the middle.

Is there any data structure (or combination of data structures) already in .Net that I can use for this or will I have to roll my own?

A: 

Why not model this the object oriented way?

Competition
-Games
--Game01
---Players
---Rounds
----Round1
-----Score
----Round2
-----Score
---Score (Game)

Another way to do this would be an ordinary array. For more on .Net colectios see http://dotnetperls.com/collections.

Burt
Using this, how do I get the score for a particular player in a particular round? Players seem to be completely separated from scores. Also, I don't have a concept of a Game in my model...
Damovisa
+1  A: 

I believe you'll have to roll your own. You could store your matrix of data in one of these:

List<List<RoundScore>>

Then in Round, add a field that stores the index of that Round's scores. Likewise, in Player, add a field for that player's scores.

If the rows are the scores for a round, then returning that list is trivial. To return the list of scores for a player, you could create a class that implements IList, which knows how to access the scores by index. By doing this, you don't have to copy the scores into a new list each time they are requested.

For example:

List<Player> Players;
List<Round> Rounds;
List<List<RoundScore>> Scores;


List<RoundScore> GetRoundScores(Round round)
{
    return Scores[round.Index];
}

IList<RoundScore> GetRoundScores(Player player)
{
    return new PlayerScoreList(Scores, player.Index); // or better yet, cache this
}


public class PlayerScoreList : IList<RoundScore>
{
    private List<List<RoundScore>> _scores;
    private int _playerIndex;

    public RoundScore this[int index]
    {
        get
        {
            return _scores[_playerIndex][index];
        }
        set
        {
            _scores[_playerIndex][index] = value;
        }
    }

    public PlayerScoreList(List<List<RoundScore>> scores, int playerIndex)
    {
        _scores = scores;
        _playerIndex = playerIndex;
    }

    public void Add(RoundScore item)
    {
        throw new NotSupportedException();
    }

    public void Clear()
    {
        throw new NotSupportedException();
    }

    public bool Contains(RoundScore item)
    {            
        for (int i = 0; i < Count; i++)
        {
            if (this[i].Equals(item))
            {
                return true;
            }
        }

        return false;
    }

    public int Count
    {
        get { return _scores[0].Count; }
    }

    public IEnumerator<RoundScore> GetEnumerator()
    {
        for (int i = 0; i < Count; i++)
        {
            yield return this[i];
        }
    }

    // ... more methods

}
Neil Whitaker
Thanks, I like what you're doing, but the return values I get back are just going to be a list of scores rather than a dictionary. It looks like your code should be easy to modify to get that for me. Thanks.
Damovisa
Yes. You could easily implement an IDictionary the same way as the IList.
Neil Whitaker