Bug fixes
This commit is contained in:
@@ -452,6 +452,8 @@ async def force_finish_marathon(
|
||||
db: DbSession,
|
||||
):
|
||||
"""Force finish a marathon. Admin only."""
|
||||
from app.services.coins import coins_service
|
||||
|
||||
require_admin_with_2fa(current_user)
|
||||
|
||||
result = await db.execute(select(Marathon).where(Marathon.id == marathon_id))
|
||||
@@ -465,6 +467,24 @@ async def force_finish_marathon(
|
||||
old_status = marathon.status
|
||||
marathon.status = MarathonStatus.FINISHED.value
|
||||
marathon.end_date = datetime.utcnow()
|
||||
|
||||
# Award coins for top 3 places (only in certified marathons)
|
||||
if marathon.is_certified:
|
||||
top_result = await db.execute(
|
||||
select(Participant)
|
||||
.options(selectinload(Participant.user))
|
||||
.where(Participant.marathon_id == marathon_id)
|
||||
.order_by(Participant.total_points.desc())
|
||||
.limit(3)
|
||||
)
|
||||
top_participants = top_result.scalars().all()
|
||||
|
||||
for place, participant in enumerate(top_participants, start=1):
|
||||
if participant.total_points > 0:
|
||||
await coins_service.award_marathon_place(
|
||||
db, participant.user, marathon, place
|
||||
)
|
||||
|
||||
await db.commit()
|
||||
|
||||
# Log action
|
||||
|
||||
@@ -353,6 +353,8 @@ async def start_marathon(marathon_id: int, current_user: CurrentUser, db: DbSess
|
||||
|
||||
@router.post("/{marathon_id}/finish", response_model=MarathonResponse)
|
||||
async def finish_marathon(marathon_id: int, current_user: CurrentUser, db: DbSession):
|
||||
from app.services.coins import coins_service
|
||||
|
||||
# Require organizer role
|
||||
await require_organizer(db, current_user, marathon_id)
|
||||
marathon = await get_marathon_or_404(db, marathon_id)
|
||||
@@ -362,6 +364,24 @@ async def finish_marathon(marathon_id: int, current_user: CurrentUser, db: DbSes
|
||||
|
||||
marathon.status = MarathonStatus.FINISHED.value
|
||||
|
||||
# Award coins for top 3 places (only in certified marathons)
|
||||
if marathon.is_certified:
|
||||
# Get top 3 participants by total_points
|
||||
top_result = await db.execute(
|
||||
select(Participant)
|
||||
.options(selectinload(Participant.user))
|
||||
.where(Participant.marathon_id == marathon_id)
|
||||
.order_by(Participant.total_points.desc())
|
||||
.limit(3)
|
||||
)
|
||||
top_participants = top_result.scalars().all()
|
||||
|
||||
for place, participant in enumerate(top_participants, start=1):
|
||||
if participant.total_points > 0: # Only award if they have points
|
||||
await coins_service.award_marathon_place(
|
||||
db, participant.user, marathon, place
|
||||
)
|
||||
|
||||
# Log activity
|
||||
activity = Activity(
|
||||
marathon_id=marathon_id,
|
||||
|
||||
@@ -206,7 +206,7 @@ async def use_consumable(
|
||||
effect_description = "Shield activated - next drop will be free"
|
||||
elif data.item_code == "boost":
|
||||
effect = await consumables_service.use_boost(db, current_user, participant, marathon)
|
||||
effect_description = f"Boost x{effect['multiplier']} activated until {effect['expires_at']}"
|
||||
effect_description = f"Boost x{effect['multiplier']} activated for next complete"
|
||||
elif data.item_code == "reroll":
|
||||
effect = await consumables_service.use_reroll(db, current_user, participant, marathon, assignment)
|
||||
effect_description = "Assignment rerolled - you can spin again"
|
||||
@@ -241,8 +241,10 @@ async def get_consumables_status(
|
||||
|
||||
participant = await require_participant(db, current_user.id, marathon_id)
|
||||
|
||||
# Get inventory counts
|
||||
# Get inventory counts for all consumables
|
||||
skips_available = await consumables_service.get_consumable_count(db, current_user.id, "skip")
|
||||
shields_available = await consumables_service.get_consumable_count(db, current_user.id, "shield")
|
||||
boosts_available = await consumables_service.get_consumable_count(db, current_user.id, "boost")
|
||||
rerolls_available = await consumables_service.get_consumable_count(db, current_user.id, "reroll")
|
||||
|
||||
# Calculate remaining skips for this marathon
|
||||
@@ -254,10 +256,11 @@ async def get_consumables_status(
|
||||
skips_available=skips_available,
|
||||
skips_used=participant.skips_used,
|
||||
skips_remaining=skips_remaining,
|
||||
shields_available=shields_available,
|
||||
has_shield=participant.has_shield,
|
||||
boosts_available=boosts_available,
|
||||
has_active_boost=participant.has_active_boost,
|
||||
boost_multiplier=participant.active_boost_multiplier if participant.has_active_boost else None,
|
||||
boost_expires_at=participant.active_boost_expires_at if participant.has_active_boost else None,
|
||||
boost_multiplier=consumables_service.BOOST_MULTIPLIER if participant.has_active_boost else None,
|
||||
rerolls_available=rerolls_available,
|
||||
)
|
||||
|
||||
|
||||
@@ -622,7 +622,7 @@ async def complete_assignment(
|
||||
ba.points_earned = int(ba.challenge.points * multiplier)
|
||||
|
||||
# Apply boost multiplier from consumable
|
||||
boost_multiplier = consumables_service.get_active_boost_multiplier(participant)
|
||||
boost_multiplier = consumables_service.consume_boost_on_complete(participant)
|
||||
if boost_multiplier > 1.0:
|
||||
total_points = int(total_points * boost_multiplier)
|
||||
|
||||
@@ -729,7 +729,7 @@ async def complete_assignment(
|
||||
print(f"[COMMON_ENEMY] bonus={common_enemy_bonus}, closed={common_enemy_closed}, winners={common_enemy_winners}")
|
||||
|
||||
# Apply boost multiplier from consumable
|
||||
boost_multiplier = consumables_service.get_active_boost_multiplier(participant)
|
||||
boost_multiplier = consumables_service.consume_boost_on_complete(participant)
|
||||
if boost_multiplier > 1.0:
|
||||
total_points = int(total_points * boost_multiplier)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user