Skip to content

Instantly share code, notes, and snippets.

@jecsham
Created July 6, 2020 07:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jecsham/2807dc8c760863406be2e737efeef871 to your computer and use it in GitHub Desktop.
Save jecsham/2807dc8c760863406be2e737efeef871 to your computer and use it in GitHub Desktop.
/**
* This is a port from java to ts
* Original: https://github.com/HypixelDev/PublicAPI/blob/master/Java/src/main/java/net/hypixel/api/util/ILeveling.java
*/
export class Leveling {
static readonly EXP_FIELD: string = "networkExp";
static readonly LVL_FIELD: string = "networkLevel";
static readonly BASE: number = 10_000;
static readonly GROWTH: number = 2_500;
/* Constants to generate the total amount of XP to complete a level */
static readonly HALF_GROWTH: number = 0.5 * Leveling.GROWTH;
/* Constants to look up the level from the total amount of XP */
static readonly REVERSE_PQ_PREFIX: number = -(Leveling.BASE - 0.5 * Leveling.GROWTH) / Leveling.GROWTH;
static readonly REVERSE_CONST: number = Leveling.REVERSE_PQ_PREFIX * Leveling.REVERSE_PQ_PREFIX;
static readonly GROWTH_DIVIDES_2: number = 2 / Leveling.GROWTH;
/**
* This method returns the level of a player calculated by the current experience gathered. The result is
* a precise level of the player The value is not zero-indexed and represents the absolute visible level
* for the player.
* The result can't be smaller than 1 and negative experience results in level 1.
* <p>
* Examples:
* - 0 XP = 1.0
* - 5000 XP = 1.0
* - 10000 XP = 2.0
* - 50000 XP = 4.0
* - 79342431 XP = 249.0
*
* @param exp Total experience gathered by the player.
* @return Absolute level of player (Smallest value is 1.0)
*/
static getLevel(exp: number): number {
return exp < 0 ? 1 : Math.floor(1 + Leveling.REVERSE_PQ_PREFIX + Math.sqrt(Leveling.REVERSE_CONST + Leveling.GROWTH_DIVIDES_2 * exp));
}
/**
* This method returns the level of a player calculated by the current experience gathered. The result is
* a precise level of the player The value is not zero-indexed and represents the visible level
* for the player.
* The result can't be smaller than 1 and negative experience results in level 1.
* <p>
* Examples:
* - 0 XP = 1.0
* - 5000 XP = 1.5
* - 10000 XP = 2.0
* - 50000 XP = 4.71...
* - 79342431 XP = 249.46...
*
* @param exp Total experience gathered by the player.
* @return Exact level of player (Smallest value is 1.0)
*/
static getExactLevel(exp: number): number {
return Leveling.getLevel(exp) + Leveling.getPercentageToNextLevel(exp);
}
/**
* This method returns the amount of experience that is needed to progress from level to level + 1. (5 to 6)
* The levels passed must absolute levels with the smallest level being 1. Smaller values always return
* the BASE constant. The calculation is precise and if a decimal is passed it returns the XP from the
* progress of this level to the next level with the same progress. (5.5 to 6.5)
* <p>
* Examples:
* - 1 (to 2) = 10000.0 XP
* - 2 (to 3) = 12500.0 XP
* - 3 (to 4) = 15000.0 XP
* - 5 (to 6) = 20000.0 XP
* - 5.5 (to 6.5) = 21250.0 XP
* - 130 (to 131) = 332500.0 XP
* - 250 (to 251) = 632500.0 XP
*
* @param level Level from which you want to get the next level with the same level progress
* @return Experience to reach the next level with same progress
*/
static getExpFromLevelToNext(level: number): number {
return level < 1 ? Leveling.BASE : Leveling.GROWTH * (level - 1) + Leveling.BASE;
}
/**
* This method returns the experience it needs to reach that level. If you want to reach the given level
* you have to gather the amount of experience returned by this method. This method is precise, that means
* you can pass any progress of a level to receive the experience to reach that progress. (5.764 to get
* the experience to reach level 5 with 76.4% of level 6.
* <p>
* Examples:
* - 1.0 = 0.0 XP
* - 2.0 = 10000.0 XP
* - 3.0 = 22500.0 XP
* - 5.0 = 55000.0 XP
* - 5.764 = 70280.0 XP
* - 130.0 = 21930000.0 XP
* - 250.43 = 79951975.0 XP
*
* @param level The level and progress of the level to reach
* @return The experience required to reach that level and progress
*/
static getTotalExpToLevel(level: number): number {
let lv: number = Math.floor(level), x0 = Leveling.getTotalExpToFullLevel(lv);
if (level == lv) return x0;
return (Leveling.getTotalExpToFullLevel(lv + 1) - x0) * (level % 1) + x0;
}
/**
* Helper method that may only be called by full levels and has the same functionality as getTotalExpToLevel()
* but doesn't support progress and returns wrong values for progress due to perfect curve shape.
*
* @param level Level to receive the amount of experience to
* @return Experience to reach the given level
*/
static getTotalExpToFullLevel(level: number): number {
return (Leveling.HALF_GROWTH * (level - 2) + Leveling.BASE) * (level - 1);
}
/**
* This method returns the current progress of this level to reach the next level. This method is as
* precise as possible due to rounding errors on the mantissa. The first 10 decimals are totally
* accurate.
* <p>
* Examples:
* - 5000.0 XP (Lv. 1) = 0.5 (50 %)
* - 22499.0 XP (Lv. 2) = 0.99992 (99.992 %)
* - 5324224.0 XP (Lv. 62) = 0.856763076923077 (85.6763076923077 %)
* - 23422443.0 XP (Lv. 134) = 0.4304905109489051 (43.04905109489051 %)
*
* @param exp Current experience gathered by the player
* @return Current progress to the next level
*/
static getPercentageToNextLevel(exp: number): number {
let lv: number = Leveling.getLevel(exp), x0 = Leveling.getTotalExpToLevel(lv);
return (exp - x0) / (Leveling.getTotalExpToLevel(lv + 1) - x0);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment