사이트 내의 점수로 레벨 업 구현

코변·2022년 8월 8일
0
post-thumbnail

프로젝트를 진행하면서 점수에 따라서 레벨을 바꿔줘야 할 필요가 있었다. 기준 점은 규칙성이 없는 숫자로 이루어져 있었고 현재의 점수를 업데이트 함과 동시에 어떤 범위에 점수가 있는지 확인하고 그 점수 값에 따라 레벨을 구하고 싶었다.

처음에 제일 먼저 떠오른 건 당연하게도 if 분기문이었으나 우리가 구현하려는 페이지의 레벨이 5단계인데 이 단계를 구현하기 위해서도 if문이 다섯 분기나 필요해진다.

그 모양새는 다음과 같을 것이다.

if 0 <= grade < 200:
...
elif 200 <= grade < 600:
...
elif 600 <= grade < 1200:
...
elif 1200 <= grade < 2500:
...
else:

편의상 내부 코드는 생략했지만 보기만 해도 어지러워진다. 그렇다면 이 문제를 어떻게 해결할 수 있을까? 0에서 200 사이 200에서 600사이 어떤 숫자들 사이의 인덱스 값을 구해야한다.

이분탐색! 파이썬의 내장모듈 bisect_left를 이용하면 지금 값이 어떤 값 사이에 들어가야 하는지 간단하게 구할 수 있다.
수정된 코드는 아래와 같다.

MONGLE_GRADE_RATE = {"review": 10, "letter": 100, "board": 5}
MONGLE_GRADES = [199, 599, 1199, 2499]


def update_mongle_grade(user: UserModel, grade: int, rate_type: str) -> None:
    MongleGrade.objects.filter(user=user).update(grade=F("grade") + (grade * MONGLE_GRADE_RATE[rate_type]))

    refreshed_user = UserModel.objects.select_related("monglegrade__mongle_level").get(id=user.id)
    cur_grade = refreshed_user.monglegrade.grade
    cur_level = update_mongle_level(cur_grade=cur_grade)

    if refreshed_user.monglegrade.mongle_level_id == cur_level:
        return
    refreshed_user.monglegrade.mongle_level = MongleLevel.objects.get(id=cur_level)
    refreshed_user.monglegrade.save()


def update_mongle_level(cur_grade: int) -> int:
    return bisect_left(MONGLE_GRADE_BISECTS, cur_grade) + 1

점수에 대한 rate 값이 각각 다르지만 이 또한 매직넘버를 쓰고 싶지 않았고 if 문을 쓰고 싶지 않았기에 dict 자료형을 활용하여 제어 하였다.

실제로 프로젝트에 적용이 되는 모습을 보니 알고리즘을 공부하는 재미가 더해지는 것 같다.

profile
내 것인 줄 알았으나 받은 모든 것이 선물이었다.

0개의 댓글