// Path: osuCelebrity-model/src/main/java/me/reddev/osucelebrity/core/QueuedPlayer.java
// public enum QueueSource {
//   TWITCH, OSU, AUTO
// }
// 
// Path: osuCelebrity-model/src/main/java/me/reddev/osucelebrity/osu/OsuUser.java
// @PersistenceCapable(detachable = "true")
// @Getter
// @ToString
// public class OsuUser {
//   @PrimaryKey
//   @UserId
//   @Getter(onMethod = @__(@UserId))
//   private int userId;
// 
//   @Index
//   private String userName;
// 
//   private long downloaded;
// 
//   @Setter
//   private Privilege privilege = Privilege.PLAYER;
// 
//   @Setter
//   @Column(defaultValue = "true")
//   private boolean allowsNotifications = true;
//   
//   @Setter
//   @Column(defaultValue = "true")
//   @Index
//   private boolean allowsSpectating = true;
//   
//   @Setter(onParam = @__(@GameMode))
//   @Getter(onMethod = @__(@GameMode))
//   @Column(defaultValue = "0")
//   @GameMode
//   private int gameMode = 0;
// 
//   @Setter
//   @Column(defaultValue = "-1")
//   private long timeOutUntil = -1;
// 
//   /**
//    * Creates a new user object copying all relevant data from the api user object.
//    * 
//    * @param user downloaded data.
//    * @param downloaded current time in millis.
//    */
//   public OsuUser(OsuApiUser user, long downloaded) {
//     this.userId = user.getUserId();
//     update(user, downloaded);
//   }
// 
//   /**
//    * updates this object with the downloaded data.
//    * 
//    * @param user downloaded data
//    * @param downloaded current time
//    */
//   public void update(OsuApiUser user, long downloaded) {
//     this.setUserName(user.getUserName());
//     this.setDownloaded(downloaded);
//   }
// 
//   @Override
//   public boolean equals(Object obj) {
//     if (obj instanceof OsuUser) {
//       return ((OsuUser) obj).userId == userId;
//     }
//     return false;
//   }
// 
//   @Override
//   public int hashCode() {
//     return userId;
//   }
// 
//   void setDownloaded(long downloaded) {
//     this.downloaded = downloaded;
//   }
// 
//   void setUserName(String userName) {
//     this.userName = userName;
//   }
// }


import static me.reddev.osucelebrity.osuapi.QApiUser.apiUser;
import com.querydsl.jdo.JDOQuery;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.reddev.osucelebrity.core.QueuedPlayer.QueueSource;
import me.reddev.osucelebrity.osu.Osu;
import me.reddev.osucelebrity.osu.Osu.PollStatusConsumer;
import me.reddev.osucelebrity.osu.OsuUser;
import me.reddev.osucelebrity.osu.PlayerStatus;
import me.reddev.osucelebrity.osu.PlayerStatus.PlayerStatusType;
import me.reddev.osucelebrity.osuapi.ApiUser;
import me.reddev.osucelebrity.osuapi.OsuApi;
import org.tillerino.osuApiModel.GameModes;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.function.ToDoubleFunction;
import javax.inject.Inject;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
        continue;
      }
      double prob = probability.applyAsDouble(user);
      distribution.put(sum, user);
      sum += prob;
    }
    if (sum == 0d) {
      lastDrawsAsSet.remove(lastDraws.removeFirst());
      return -1;
    }
    double rnd = Math.random() * sum;
    Entry<Double, ApiUser> floorEntry = distribution.floorEntry(rnd);
    if (floorEntry == null) {
      throw new RuntimeException(rnd + " in " + sum);
    }
    int userId = floorEntry.getValue().getUserId();
    if (lastDraws.size() >= 100) {
      lastDrawsAsSet.remove(lastDraws.removeFirst());
    }
    lastDraws.add(userId);
    lastDrawsAsSet.add(userId);
    return userId;
  }

  List<ApiUser> getTopPlayers(PersistenceManager pm) {
    try (JDOQuery<ApiUser> query = new JDOQuery<>(pm).select(apiUser).from(apiUser)) {
      return new ArrayList<>(query.where(apiUser.rank.loe(1000), apiUser.rank.goe(1)).fetch());
    }
  }

// Path: osuCelebrity-model/src/main/java/me/reddev/osucelebrity/core/QueuedPlayer.java
// public enum QueueSource {
//   TWITCH, OSU, AUTO
// }
// 
// Path: osuCelebrity-model/src/main/java/me/reddev/osucelebrity/osu/OsuUser.java
// @PersistenceCapable(detachable = "true")
// @Getter
// @ToString
// public class OsuUser {
//   @PrimaryKey
//   @UserId
//   @Getter(onMethod = @__(@UserId))
//   private int userId;
// 
//   @Index
//   private String userName;
// 
//   private long downloaded;
// 
//   @Setter
//   private Privilege privilege = Privilege.PLAYER;
// 
//   @Setter
//   @Column(defaultValue = "true")
//   private boolean allowsNotifications = true;
//   
//   @Setter
//   @Column(defaultValue = "true")
//   @Index
//   private boolean allowsSpectating = true;
//   
//   @Setter(onParam = @__(@GameMode))
//   @Getter(onMethod = @__(@GameMode))
//   @Column(defaultValue = "0")
//   @GameMode
//   private int gameMode = 0;
// 
//   @Setter
//   @Column(defaultValue = "-1")
//   private long timeOutUntil = -1;
// 
//   /**
//    * Creates a new user object copying all relevant data from the api user object.
//    * 
//    * @param user downloaded data.
//    * @param downloaded current time in millis.
//    */
//   public OsuUser(OsuApiUser user, long downloaded) {
//     this.userId = user.getUserId();
//     update(user, downloaded);
//   }
// 
//   /**
//    * updates this object with the downloaded data.
//    * 
//    * @param user downloaded data
//    * @param downloaded current time
//    */
//   public void update(OsuApiUser user, long downloaded) {
//     this.setUserName(user.getUserName());
//     this.setDownloaded(downloaded);
//   }
// 
//   @Override
//   public boolean equals(Object obj) {
//     if (obj instanceof OsuUser) {
//       return ((OsuUser) obj).userId == userId;
//     }
//     return false;
//   }
// 
//   @Override
//   public int hashCode() {
//     return userId;
//   }
// 
//   void setDownloaded(long downloaded) {
//     this.downloaded = downloaded;
//   }
// 
//   void setUserName(String userName) {
//     this.userName = userName;
//   }
// }


// Path: osuCelebrity-core/src/main/java/me/reddev/osucelebrity/core/AutoQueue.java
import static me.reddev.osucelebrity.osuapi.QApiUser.apiUser;
import com.querydsl.jdo.JDOQuery;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.reddev.osucelebrity.core.QueuedPlayer.QueueSource;
import me.reddev.osucelebrity.osu.Osu;
import me.reddev.osucelebrity.osu.Osu.PollStatusConsumer;
import me.reddev.osucelebrity.osu.OsuUser;
import me.reddev.osucelebrity.osu.PlayerStatus;
import me.reddev.osucelebrity.osu.PlayerStatus.PlayerStatusType;
import me.reddev.osucelebrity.osuapi.ApiUser;
import me.reddev.osucelebrity.osuapi.OsuApi;
import org.tillerino.osuApiModel.GameModes;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.function.ToDoubleFunction;
import javax.inject.Inject;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;

        continue;
      }
      double prob = probability.applyAsDouble(user);
      distribution.put(sum, user);
      sum += prob;
    }
    if (sum == 0d) {
      lastDrawsAsSet.remove(lastDraws.removeFirst());
      return -1;
    }
    double rnd = Math.random() * sum;
    Entry<Double, ApiUser> floorEntry = distribution.floorEntry(rnd);
    if (floorEntry == null) {
      throw new RuntimeException(rnd + " in " + sum);
    }
    int userId = floorEntry.getValue().getUserId();
    if (lastDraws.size() >= 100) {
      lastDrawsAsSet.remove(lastDraws.removeFirst());
    }
    lastDraws.add(userId);
    lastDrawsAsSet.add(userId);
    return userId;
  }

  List<ApiUser> getTopPlayers(PersistenceManager pm) {
    try (JDOQuery<ApiUser> query = new JDOQuery<>(pm).select(apiUser).from(apiUser)) {
      return new ArrayList<>(query.where(apiUser.rank.loe(1000), apiUser.rank.goe(1)).fetch());
    }
  }

  private void pollStatus(OsuUser user) {