Reputation: 25
I'm trying to create a rank system for my gaming group, similar in nature to Supercell's Trophy System in their Clash of Clans and Clash Royale games for android/iOS systems.
I have the layout of the ranks all figured out, and we already have a point system in place that works ... I just need to now program in the actual ranks.
The ranks work very simply: The individual's point balance falls within specific values, and the rank corresponding to that value is the person's rank. I created a simple table to show what I mean ... here's an excerpt of what it looks like:
Rank: Balance Range
Private: 0-500
Private I: 501-1000
Private II: 1001-1500
Private III: 1501-2500
Corporal: 2501-3000
...
So here's the simple rank system layout, it goes all the way up to Commander at 42,000 points. My question is this: How do I associate the Rank with the point value, without having to type out all the lines of code like this?
0 <= Private <= 500
501 <= PrivateI <= 1000
...
Upvotes: 2
Views: 137
Reputation: 59168
A slight improvement to Daniel Roseman's bisect
solution to would be to use a single list of 2-tuples:
from bisect import bisect_right
RANKS = [
# max balance, rank
(500, 'Private'),
(1000, 'Private I'),
(1500, 'Private II'),
(2500, 'Private III'),
(3000, 'Corporal'),
# ...
(42000, 'Commander')
]
def get_rank(balance):
index = bisect_right(RANKS, (balance, ''))
try:
return RANKS[index][1]
except IndexError:
return RANKS[-1][1]
The advantages here are that it's easier to read at a glance, and less prone to mistakes when editing your code to introduce new ranks, tweak limits, etc.
It also returns the highest rank when supplied a points balance higher than any accounted for in RANKS
(as specified in your comment), rather than raising an exception.
Example:
>>> for n in range(0,42001,500):
... print("%5d %s" % (n, get_rank(n)))
... print("%5d %s" % (n + 1, get_rank(n + 1)))
...
0 Private
1 Private
500 Private
501 Private I
1000 Private I
1001 Private II
1500 Private II
1501 Private III
2000 Private III
2001 Private III
2500 Private III
2501 Corporal
3000 Corporal
# ...
42000 Commander
42001 Commander
Upvotes: 0
Reputation: 599796
You can use bisect for this.
from bisect import bisect
def get_rank(score):
points = [500, 1000, 1500, 2500, 3000]
ranks = ["Private", "Private I", "Private II", "Private III", "Corporal"]
div = bisect(points, score)
return ranks[div]
Upvotes: 1