getting the largest number in a hashmap

Discussion in 'Plugin Development' started by nitrousspark, Nov 25, 2012.

Thread Status:
Not open for further replies.
  1. Offline

    nitrousspark

    i have a hashmap with <String, Double> and im putting the players name then their amount of kills, want to rank people in a list that puts them in order of most kills to least, or at least get the person with the most kills.
     
  2. Offline

    Zidkon

    I think the best way is that whenever you update your Hashmap you do the comparison on the list, so you keep the Ranking List, at least the names in order, and the Hashmap
     
  3. Offline

    kyran_

    If you just need the largest number you can iterate through and store a variable of the highest number of kills so far. If you need to sort the whole map by value there's a few ways to do that. You could also exchange the map for a list of objects of a custom type that you define, implementing the comparable interface, and containing the player name and player kills. Then you could just do a collections.sort() on the list and it would compare the number of kills to perform the sorting (as defined in the compareTo method).


    For example, you'd have a List<PlayerRecord>:
    Code:
    public class PlayerRecord  implements Comparable<PlayerRecord>{
        private String playerName;
        private int kills;
     
        public String getName(){
            return playerName;
        }
     
        public int getKills(){
            return kills;
        }
     
        public void addKill(){
            kills++;
        }
     
        public int compareTo(PlayerRecord record){
            this.getKills.compareTo(record.getKills);
        }
    }
    
    You would store these record objects in a list and allow you to sort them at any time based upon kills as you defined in the compareTo method. It would be really easy to get rankings because the data structure the objects are contained in is just a list. This approach may be a bit much for what you want but it leaves you open to expansion as you can add more fields to a player record down the road.

    (also note this is off the top of my head and untested so there may be some errors in the example code)
     
    Zidkon likes this.
  4. Offline

    nitrousspark

    PlayerRecord is an error, not sure what to do with it
     
  5. Offline

    kyran_

    You need to actually make the PlayerRecord class yourself similar to how I outlined above. You'll also need to add in a constructor that takes a player name and possibly a number of kills if you want to migrate your current records over to the new format.

    So add this into the PlayerRecord class above.
    Code:
        public PlayerRecord (String playerName) {
            this.playerName = playerName;
        }
     
        public PlayerRecord (String playerName, int kills) {
            this.playerName = playerName;
            this.kills = kills;
        }
    
     
  6. Offline

    nitrousspark

    this is just getting the highest one, what about in a list, so i can put a number before everybodys name that says their rank for how many kills they have.

    ive been thinkning and i might be able to use hashmaps for it :/ maybe
     
  7. Offline

    kyran_

    That's why I made that suggestion. You can iterate through the list of PlayerRecord objects and print out their rank (the index in the list after you sort it)
    Here's an updated class that has that extra functionality built right in, no need for an external list.
    Code:
    public class PlayerRecord  implements Comparable<PlayerRecord>{
        private String playerName;
        private int kills;
        private static List<PlayerRecord> rankingList;
     
        public PlayerRecord(String playerName){
            this.playerName = playerName;
            PlayerRecord.addPlayer(this);
        }
     
        public PlayerRecord(String playerName, int kills) {
            this.playerName = playerName;
            this.kills = kills;
            PlayerRecord.addPlayer(this);
        }
     
        public String getName(){
            return playerName;
        }
     
        public int getKills(){
            return kills;
        }
     
        public static void addPlayer(PlayerRecord playerRecord){
            if (rankingList == null) {
                rankingList = new ArrayList<PlayerRecord>();
                rankingList.add(playerRecord);
            }
            else if (!rankingList.contains(playerRecord) {
                rankingList.add(playerRecord);
            }
        }
     
        public static PlayerRecord getRecord(String playerName){
            for (PlayerRecord p : rankingList) {
                if (p.getName().equals(playerName) {
                    return p;
                }
            }
            return null;
        }
     
        public static void addKill(String playerName) {
            PlayerRecord record = PlayerRecord.getRecord(playerName);
            if (record != null) {
                record.addKill();
            }
            else {
                new PlayerRecord(playerName, 1);
            }
        }
     
        public void addKill(){
            kills++;
        }
     
        public String toString(){
            return ("Rank: " + (rankingList.indexOf(this) + 1) + " Player: " + playerName + ", Kills: " + kills + ".");
        }
     
        public String getPlayerStats(String playerName){
            PlayerRecord.sortRankings();
            return PlayerRecord.getRecord(playerName).toString();
        }
     
        public static String[] getTopRankings(int top){
            PlayerRecord.sortRankings();
            String[] rankings = new String[top];
            for (int i = 0; i < top; i++){
                rankings[i] = rankingList.get(i);
            }
            return rankings;
        }
     
        public static String[] getTopRankings(){
            PlayerRecord.sortRankings();
            int totalRecords = rankingList.length();
            String[] rankings = new String[totalRecords];
            for (int i = 0; i < totalRecords; i++){
                rankings[i] = rankingList.get(i);
            }
            return rankings;
        }
     
        public static void sortRankings(){
            collections.sort(rankingList);
        }
     
        public int compareTo(PlayerRecord record){
            this.getKills.compareTo(record.getKills);
        }
    }
    

    That should do it. You can get the rankings with getTopRankings, with an optional parameter to limit how many results you get. You can create a new record by passing a player name into the constructor, get an individual player's ranking with getPlayerStats, and add kills to a player's record with the addKill(String playerName) method.

    I typed all this into the reply box so it's quite possible there's some errors. If you have any issues or are unsure of method functions just ask and I or someone else should be able to help. Don't forget to import java.util.arrayList.


    (Edited to tighten up the addKill method to handle if the player doesn't already have a record in the list.)
     
  8. Offline

    nitrousspark

    errors



    this.getKills().compareTo(record.getKills());
    ---------------
    Cannot invoke compareTo(double) on the primitive type double
    ---------------
    rankingList.get(i);
    ---------------
    Type mismatch: cannot convert from PlayerRecord to String

    ok i got this and it just counts, the player says something it says #1 and then someone else says something its #2 and no matter who says what it just counts :/

    public int getRank() {
    PlayerRecord.sortRankings();
    return rankingList.indexOf(this) + 1;
    }

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 30, 2016
  9. Offline

    kyran_

    I threw it into eclipse to do the error checking, there were lots of small ones, missed parentheses and such.
    Here's the working class:
    Code:
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    
    public class PlayerRecord  implements Comparable<PlayerRecord>{
        private String playerName;
        private int kills;
        private static List<PlayerRecord> rankingList;
     
        public PlayerRecord(String playerName){
            this.playerName = playerName;
            PlayerRecord.addPlayer(this);
        }
     
        public PlayerRecord(String playerName, int kills) {
            this.playerName = playerName;
            this.kills = kills;
            PlayerRecord.addPlayer(this);
        }
     
        private String getName(){
            return playerName;
        }
     
        private int getKills(){
            return kills;
        }
     
        private static void addPlayer(PlayerRecord playerRecord){
            if (rankingList == null) {
                rankingList = new ArrayList<PlayerRecord>();
                rankingList.add(playerRecord);
            }
            else if (!rankingList.contains(playerRecord)) {
                rankingList.add(playerRecord);
            }
        }
     
        private static PlayerRecord getRecord(String playerName){
            for (PlayerRecord p : rankingList) {
                if (p.getName().equals(playerName)) {
                    return p;
                }
            }
            return null;
        }
     
        public static void addKill(String playerName) {
            PlayerRecord record = PlayerRecord.getRecord(playerName);
            if (record != null) {
                record.addKill();
            }
            else {
                new PlayerRecord(playerName, 1);
            }
        }
     
        private void addKill(){
            kills++;
        }
     
        public String toString(){
            return ("Rank: " + (rankingList.indexOf(this) + 1) + " Player: " + playerName + ", Kills: " + kills + ".");
        }
     
        public String getPlayerStats(String playerName){
            PlayerRecord.sortRankings();
            return PlayerRecord.getRecord(playerName).toString();
        }
     
        public static String[] getTopRankings(int top){
            PlayerRecord.sortRankings();
            String[] rankings = new String[top];
            for (int i = 0; i < top; i++){
                rankings[i] = rankingList.get(i).toString();
            }
            return rankings;
        }
     
        public static String[] getTopRankings(){
            PlayerRecord.sortRankings();
            int totalRecords = rankingList.size();
            String[] rankings = new String[totalRecords];
            for (int i = 0; i < totalRecords; i++){
                rankings[i] = rankingList.get(i).toString();
            }
            return rankings;
        }
     
        private static void sortRankings(){
            Collections.sort(rankingList);
        }
     
        public int compareTo(PlayerRecord record){
            return (new Integer(record.getKills())).compareTo(new Integer(this.getKills()));
        }
    }
    
    Tested working perfectly.

    I don't know what you want to do with the information it gives you and I'm not gonna write your whole plugin for you. The getTopRankings method returns an array of strings, you should be able to iterate through them and print them out or store them in some other object. If you only want to be able to print them to the chat, pass in the server as a parameter and print from within the top rankings method. The only other methods you should need to touch are the constructor to add a record, the static addKill(String playerName) method, and the getPlayerStats method. I've set most of the internal methods to be private so as to avoid confusion. The compareTo method and the toString method are both public but don't need to be called by you.
     
  10. Offline

    Zidkon

    I'm not sure why are you doing the class for him? the main class idea that you gave was great, he could do the class by himself....
     
  11. Offline

    nitrousspark

    ok now when you kill someone, i have the PlayerRecord.addKill(player), and sometimes it works, but sometimes it does nothing, like you will kill someone and your kills wont go up
     
  12. Offline

    kyran_

    You should be passing in a String of the player name, not an actual player object. It could be a problem in your event listeners, I dunno I don't have all your code remember.

    As Zidkon said, I shouldn't be writing your code for you. If you can't debug and figure out problems, then maybe programming isn't for you. I know some people manage to make plugins without getting too deep into java but you're really just making it harder for yourself and wasting time on what could otherwise be spent learning general object oriented programming. That's not what you want to hear when you just want to make things for minecraft right away but in the long run you'll be better off. Plenty of tutorial videos on youtube and written ones all over the place. I learned more in a month of watching video tutorials than I did in my first 2 years of computer science.

    All I can say is, check the console for errors and print out checks in between each step to see where it's going wrong. Once you figure out where the problem is occurring, it shouldn't be too hard to fix.
     
    Zidkon likes this.
Thread Status:
Not open for further replies.

Share This Page