refill hearts like Duolingo: one every 5 hours, all of them after 24
Each heart used to take 24 hours, so a student who lost all five waited up to five days. Now one heart returns every 5 hours, and 24 hours after the first heart was lost they all come back at once (the owner's call). /api/user/hearts reports both times (nextRefillAt, fullRefillAt); an existing timer longer than 5 hours is shortened the first time it is read. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -129,3 +129,64 @@ class SummaryShowsTheActivePlanTests(TestCase):
|
||||
Subscription.objects.create(user_id=user.id, plan=plan, status='active')
|
||||
|
||||
self.assertEqual(self.client.get('/api/user/summary', **auth).json()['subscription'], 'طلایی')
|
||||
|
||||
|
||||
class HeartsLikeDuolingoTests(TestCase):
|
||||
"""هر ۵ ساعت یک قلب؛ ۲۴ ساعت بعد از اولین قلبِ ازدسترفته، همه پر."""
|
||||
|
||||
def _hearts_after_losing(self, n):
|
||||
from progress.models import UserHearts
|
||||
h = UserHearts.objects.create(user_id=1)
|
||||
for _ in range(n):
|
||||
h.lose_heart()
|
||||
h.save()
|
||||
return h
|
||||
|
||||
def _at(self, hours):
|
||||
from django.utils import timezone
|
||||
from datetime import timedelta
|
||||
return mock.patch('django.utils.timezone.now', return_value=timezone.now() + timedelta(hours=hours))
|
||||
|
||||
def test_one_heart_comes_back_every_five_hours(self):
|
||||
h = self._hearts_after_losing(5)
|
||||
with self._at(4.9):
|
||||
h.apply_regen()
|
||||
self.assertEqual(h.current_hearts, 0)
|
||||
with self._at(5.1):
|
||||
h.apply_regen()
|
||||
self.assertEqual(h.current_hearts, 1)
|
||||
with self._at(15.1):
|
||||
h.apply_regen()
|
||||
self.assertEqual(h.current_hearts, 3)
|
||||
|
||||
def test_everything_refills_24_hours_after_the_first_loss(self):
|
||||
h = self._hearts_after_losing(5)
|
||||
with self._at(24.1):
|
||||
h.apply_regen()
|
||||
self.assertEqual(h.current_hearts, 5)
|
||||
self.assertIsNone(h.next_refill_at)
|
||||
self.assertIsNone(h.full_refill_at)
|
||||
|
||||
def test_an_old_24_hour_timer_is_shortened_to_five(self):
|
||||
from datetime import timedelta
|
||||
from django.utils import timezone
|
||||
from progress.models import UserHearts
|
||||
h = UserHearts.objects.create(
|
||||
user_id=2, current_hearts=2, next_refill_at=timezone.now() + timedelta(hours=23),
|
||||
)
|
||||
h.apply_regen()
|
||||
self.assertLessEqual(h.next_refill_at, timezone.now() + timedelta(hours=5, seconds=1))
|
||||
self.assertIsNotNone(h.full_refill_at)
|
||||
|
||||
def test_api_reports_both_timers(self):
|
||||
user = User.objects.create(phone='09120000033')
|
||||
from progress.models import UserHearts
|
||||
h = UserHearts.objects.create(user_id=user.id)
|
||||
h.lose_heart()
|
||||
h.save()
|
||||
body = self.client.get(
|
||||
'/api/user/hearts', HTTP_AUTHORIZATION=f'Bearer {issue_access_token(user.id)}',
|
||||
).json()
|
||||
self.assertEqual(body['currentHearts'], 4)
|
||||
self.assertIsNotNone(body['nextRefillAt'])
|
||||
self.assertIsNotNone(body['fullRefillAt'])
|
||||
|
||||
Reference in New Issue
Block a user