@quenty/experiencecalculator 2.0.2-canary.256.edbbcfc.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,7 +3,15 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
- ## [2.0.2-canary.256.edbbcfc.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/experiencecalculator@2.0.1...@quenty/experiencecalculator@2.0.2-canary.256.edbbcfc.0) (2022-03-27)
6
+ # [2.2.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/experiencecalculator@2.1.0...@quenty/experiencecalculator@2.2.0) (2022-06-21)
7
+
8
+ **Note:** Version bump only for package @quenty/experiencecalculator
9
+
10
+
11
+
12
+
13
+
14
+ # [2.1.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/experiencecalculator@2.0.1...@quenty/experiencecalculator@2.1.0) (2022-03-27)
7
15
 
8
16
  **Note:** Version bump only for package @quenty/experiencecalculator
9
17
 
package/LICENSE.md CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2014-2021 Quenty
3
+ Copyright (c) 2014-2022 Quenty
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quenty/experiencecalculator",
3
- "version": "2.0.2-canary.256.edbbcfc.0",
3
+ "version": "2.2.0",
4
4
  "description": "Calculate experience on an exponential curve and perform relevant calculations Uses formulas from stackoverflow.com/questions/6954874/php-game-formula-to-calculate-a-level-based-on-exp",
5
5
  "keywords": [
6
6
  "Roblox",
@@ -28,5 +28,5 @@
28
28
  "publishConfig": {
29
29
  "access": "public"
30
30
  },
31
- "gitHead": "edbbcfc38516772a791d50dc43cd6b304ffc4aff"
31
+ "gitHead": "c8732cc5dea767b3ff362db43137e2a16da7bc0d"
32
32
  }
@@ -0,0 +1,185 @@
1
+ --[=[
2
+ Calculate experience on an exponential curve and perform relevant calculations.
3
+
4
+ Uses formulas from https://stackoverflow.com/questions/6954874/php-game-formula-to-calculate-a-level-based-on-exp
5
+
6
+ ```lua
7
+ local config = ExperienceUtils.createExperienceConfig({
8
+ factor = 200;
9
+ })
10
+
11
+ local totalExperience = 2000
12
+ local level = ExperienceUtils.getLevel(config, totalExperience)
13
+ local percentDone = ExperienceUtils.percentLevelComplete(config, totalExperience)
14
+ ```
15
+ @class ExperienceUtils
16
+ ]=]
17
+
18
+ local ExperienceUtils = {}
19
+
20
+ --[=[
21
+ Creates a new experience configuration to be used
22
+
23
+ @param options ExperienceConfig
24
+ @return ExperienceConfig
25
+ ]=]
26
+ function ExperienceUtils.createExperienceConfig(options)
27
+ assert(type(options) == "table", "Bad options")
28
+
29
+ return {
30
+ factor = options.factor or 200;
31
+ maxLevel = options.maxLevel or math.huge;
32
+ }
33
+ end
34
+
35
+ --[=[
36
+ Returns whether a value is an experience config
37
+
38
+ @param value any
39
+ @return boolean
40
+ ]=]
41
+ function ExperienceUtils.isExperienceConfig(value)
42
+ return type(value) == "table"
43
+ and type(value.factor) == "number"
44
+ end
45
+
46
+ --[=[
47
+ Gets the current level from experience.
48
+
49
+ @param config ExperienceConfig
50
+ @param totalExperience number
51
+ @return number -- Level
52
+ ]=]
53
+ function ExperienceUtils.getLevel(config, totalExperience)
54
+ assert(ExperienceUtils.isExperienceConfig(config), "Bad experience config")
55
+ assert(type(totalExperience) == "number", "Bad totalExperience")
56
+
57
+ local factor = config.factor
58
+ local level = math.floor(
59
+ (factor
60
+ + math.sqrt(factor*factor - 4*factor*(-totalExperience)))
61
+ /(2*factor))
62
+ if level >= config.maxLevel then
63
+ return config.maxLevel
64
+ else
65
+ return level
66
+ end
67
+ end
68
+
69
+ --[=[
70
+ Gets experience required for a current level. Once the experience is
71
+ equal to this threshold, or greater, then the level is considered
72
+ earned.
73
+
74
+ @param config ExperienceConfig
75
+ @param level number
76
+ @return number -- Total experience required for a level
77
+ ]=]
78
+ function ExperienceUtils.experienceFromLevel(config, level)
79
+ assert(ExperienceUtils.isExperienceConfig(config), "Bad experience config")
80
+ assert(type(level) == "number", "Bad level")
81
+
82
+ return config.factor*level*(level - 1)
83
+ end
84
+
85
+ --[=[
86
+ For this level only, how much experience is earned.
87
+
88
+ @param config ExperienceConfig
89
+ @param totalExperience number
90
+ @return number
91
+ ]=]
92
+ function ExperienceUtils.levelExperienceEarned(config, totalExperience)
93
+ assert(ExperienceUtils.isExperienceConfig(config), "Bad experience config")
94
+ assert(type(totalExperience) == "number", "Bad totalExperience")
95
+
96
+ if totalExperience ~= totalExperience then -- math.huge
97
+ return 0
98
+ end
99
+
100
+ local currentLevel = ExperienceUtils.getLevel(config, totalExperience)
101
+ if currentLevel >= config.maxLevel then
102
+ return 0
103
+ end
104
+
105
+ local levelExperience = ExperienceUtils.experienceFromLevel(config, currentLevel)
106
+
107
+ return totalExperience - levelExperience
108
+ end
109
+
110
+ --[=[
111
+ For this level only, how much experience is left to earn.
112
+
113
+ @param config ExperienceConfig
114
+ @param totalExperience number
115
+ @return number
116
+ ]=]
117
+ function ExperienceUtils.levelExperienceLeft(config, totalExperience)
118
+ assert(ExperienceUtils.isExperienceConfig(config), "Bad experience config")
119
+ assert(type(totalExperience) == "number", "Bad totalExperience")
120
+
121
+ if totalExperience ~= totalExperience then -- math.huge
122
+ return 0
123
+ end
124
+
125
+ local currentLevel = ExperienceUtils.getLevel(config, totalExperience)
126
+ if currentLevel >= config.maxLevel then
127
+ return 0
128
+ end
129
+
130
+ local experienceRequired = ExperienceUtils.experienceFromLevel(config, currentLevel + 1)
131
+
132
+ return experienceRequired - totalExperience
133
+ end
134
+
135
+ --[=[
136
+ For this level only, how much experience is required
137
+
138
+ @param config ExperienceConfig
139
+ @param totalExperience number -- Current experience of player
140
+ @return number -- Total required for next level
141
+ ]=]
142
+ function ExperienceUtils.levelExperienceRequired(config, totalExperience)
143
+ assert(ExperienceUtils.isExperienceConfig(config), "Bad experience config")
144
+ assert(type(totalExperience) == "number", "Bad totalExperience")
145
+
146
+ if totalExperience ~= totalExperience then -- math.huge
147
+ return 0
148
+ end
149
+
150
+ local currentLevel = ExperienceUtils.getLevel(config, totalExperience)
151
+ if currentLevel >= config.maxLevel then
152
+ return 0
153
+ end
154
+
155
+ local thisLevelExperience = ExperienceUtils.experienceFromLevel(config, currentLevel)
156
+ local nextLevelExperience = ExperienceUtils.experienceFromLevel(config, currentLevel + 1)
157
+ return nextLevelExperience - thisLevelExperience
158
+ end
159
+
160
+ --[=[
161
+ Returns the percent of the level complete
162
+
163
+ @param config ExperienceConfig
164
+ @param totalExperience number
165
+ @return number
166
+ ]=]
167
+ function ExperienceUtils.percentLevelComplete(config, totalExperience)
168
+ assert(ExperienceUtils.isExperienceConfig(config), "Bad experience config")
169
+ assert(type(totalExperience) == "number", "Bad totalExperience")
170
+
171
+ if totalExperience ~= totalExperience then -- math.huge
172
+ return 0
173
+ end
174
+
175
+ local earned = ExperienceUtils.levelExperienceEarned(config, totalExperience)
176
+ local required = ExperienceUtils.levelExperienceRequired(config, totalExperience)
177
+
178
+ if required == 0 then
179
+ return 0
180
+ end
181
+
182
+ return earned/required
183
+ end
184
+
185
+ return ExperienceUtils
@@ -0,0 +1,37 @@
1
+ --[[
2
+ @class ExperienceUtils.spec.lua
3
+ ]]
4
+
5
+ local ExperienceUtils = require(script.Parent.ExperienceUtils)
6
+
7
+ return function()
8
+ local config = ExperienceUtils.createExperienceConfig({
9
+ factor = 200;
10
+ })
11
+
12
+ describe("ExperienceUtils.getLevel", function()
13
+ it("should return a level", function()
14
+ local level = ExperienceUtils.getLevel(config, 0)
15
+ expect(level).to.equal(1)
16
+
17
+ level = ExperienceUtils.getLevel(config, 399)
18
+ expect(level).to.equal(1)
19
+
20
+ level = ExperienceUtils.getLevel(config, 400)
21
+ expect(level).to.equal(2)
22
+ end)
23
+ end)
24
+
25
+ describe("ExperienceUtils.experienceFromLevel", function()
26
+ it("should return experience", function()
27
+ local experience = ExperienceUtils.experienceFromLevel(config, 1)
28
+ expect(experience).to.equal(0)
29
+
30
+ experience = ExperienceUtils.experienceFromLevel(config, 2)
31
+ expect(experience).to.equal(400)
32
+
33
+ experience = ExperienceUtils.experienceFromLevel(config, 3)
34
+ expect(experience).to.equal(1200)
35
+ end)
36
+ end)
37
+ end
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "ExperienceTest",
3
+ "tree": {
4
+ "$className": "DataModel",
5
+ "ServerScriptService": {
6
+ "experience": {
7
+ "$path": ".."
8
+ }
9
+ }
10
+ }
11
+ }
@@ -1,95 +0,0 @@
1
- --[=[
2
- Calculate experience on an exponential curve and perform relevant calculations.
3
-
4
- Uses formulas from https://stackoverflow.com/questions/6954874/php-game-formula-to-calculate-a-level-based-on-exp
5
-
6
- @class ExperienceCalculator
7
- ]=]
8
-
9
- local ExperienceCalculator = {}
10
- ExperienceCalculator._experienceFactor = 200
11
-
12
- --[=[
13
- Sets the global experience factor to be used across this library.
14
-
15
- :::tip
16
- This API is global, poorly designed and will be refactored at some point.
17
- :::
18
-
19
- @param factor number
20
- ]=]
21
- function ExperienceCalculator.setExperienceFactor(factor)
22
- ExperienceCalculator._experienceFactor = factor
23
- end
24
-
25
- --[=[
26
- Gets the current level from experience.
27
- @param experience number -- Current experience
28
- @return number -- The level the player should be
29
- ]=]
30
- function ExperienceCalculator.getLevel(experience)
31
- local factor = ExperienceCalculator._experienceFactor
32
- return math.floor(
33
- (factor
34
- + math.sqrt(factor*factor - 4*factor*(-experience)))
35
- /(2*factor))
36
- end
37
-
38
- --[=[
39
- Given a current level, return the experience required for the next one.
40
- @param currentLevel number -- The current level the player is
41
- @return number -- Experience required for next level
42
- ]=]
43
- function ExperienceCalculator.getExperienceRequiredForNextLevel(currentLevel)
44
- return ExperienceCalculator._experienceFactor*(currentLevel*(1+currentLevel))
45
- end
46
-
47
- --[=[
48
- Gets experience required for a current level.
49
- @param level number
50
- @return number -- Total experience required for a level
51
- ]=]
52
- function ExperienceCalculator.getExperienceRequiredForLevel(level)
53
- return ExperienceCalculator.getExperienceRequiredForNextLevel(level - 1)
54
- end
55
-
56
- --[=[
57
- Gets experience left to earn required for next level.
58
- @param currentExperience number -- Current experience of player
59
- @return number -- Experience points left to earn for the player
60
- ]=]
61
- function ExperienceCalculator.getExperienceForNextLevel(currentExperience)
62
- if currentExperience - 1 == currentExperience then -- math.huge
63
- return 0
64
- end
65
-
66
- local currentLevel = ExperienceCalculator.getLevel(currentExperience)
67
- local experienceRequired = ExperienceCalculator.getExperienceRequiredForNextLevel(currentLevel)
68
-
69
- return experienceRequired - currentExperience
70
- end
71
-
72
- --[=[
73
- Calculates subtotal experience.
74
- @param currentExperience number -- Current experience of player
75
- @return number -- Achieved of next level
76
- @return number -- Total required for next level
77
- ]=]
78
- function ExperienceCalculator.getSubExperience(currentExperience)
79
- if currentExperience - 1 == currentExperience then -- math.huge
80
- return 1, 1
81
- end
82
-
83
- local currentLevel = ExperienceCalculator.getLevel(currentExperience)
84
- local lastLevel = currentLevel-1
85
-
86
- local xpForCurrentLevel = ExperienceCalculator._experienceFactor*(lastLevel*(1+lastLevel))
87
- local experienceRequired = ExperienceCalculator._experienceFactor*(currentLevel*(1+currentLevel))
88
-
89
- local achievedOfNext = currentExperience - xpForCurrentLevel
90
- local subTotalRequired = experienceRequired - xpForCurrentLevel
91
-
92
- return achievedOfNext, subTotalRequired
93
- end
94
-
95
- return ExperienceCalculator