Skip to content

Commit

Permalink
Goals: Implement collecting reward from goals.
Browse files Browse the repository at this point in the history
  • Loading branch information
MikuAuahDark committed Apr 15, 2024
1 parent 5d15a95 commit 651dca9
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 15 deletions.
112 changes: 112 additions & 0 deletions npps4/game/achievement.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
from .. import util
from ..system import achievement
from ..system import advanced
from ..system import common
from ..system import museum
from ..system import reward
from ..system import unit
from ..system import unit_model
from ..system import user


Expand All @@ -19,6 +24,23 @@ class AchievementUnaccomplishedResponse(pydantic.RootModel[list[AchievementUnacc
pass


class AchievementRewardOpenRequest(pydantic.BaseModel):
accomplish_id: int


class AchievementRewardOpenResponse(
achievement.AchievementMixin, common.TimestampMixin, user.UserDiffMixin, unit_model.SupporterListInfoResponse
):
reward_item_list: list[pydantic.SerializeAsAny[common.AnyItem]]
unit_support_list: list[unit_model.SupporterInfoResponse]
present_cnt: int


class AchievementRewardOpenAllResponse(AchievementRewardOpenResponse):
is_last: bool
opened_num: int


@idol.register("achievement", "unaccomplishList")
async def achievement_unaccomplishlist(context: idol.SchoolIdolUserParams) -> AchievementUnaccomplishedResponse:
current_user = await user.get_current(context)
Expand Down Expand Up @@ -52,3 +74,93 @@ async def achievement_initialaccomplishlist(context: idol.SchoolIdolUserParams)
)

return AchievementUnaccomplishedResponse.model_validate(result)


@idol.register("achievement", "rewardOpen")
async def achievement_rewardopen(
context: idol.SchoolIdolUserParams, request: AchievementRewardOpenRequest
) -> AchievementRewardOpenResponse:
current_user = await user.get_current(context)
achievement_id = int(request.accomplish_id)
ach = await achievement.get_achievement(context, current_user, achievement_id)
ach_info = await achievement.get_achievement_info(context, ach.achievement_id)
rewards = await achievement.get_achievement_rewards(context, ach)
await advanced.fixup_achievement_reward(context, current_user, [rewards])

before_user = await user.get_user_info(context, current_user)

for reward_item in rewards:
success = await advanced.add_item(context, current_user, reward_item)
if not bool(success):
reward_item.reward_box_flag = True
fallback_name = f"Achievement #{ach.achievement_id}"
await reward.add_item(
context,
current_user,
reward_item,
ach_info.title or fallback_name,
ach_info.title_en or ach_info.title or fallback_name,
)

# Mark claimed
ach.is_reward_claimed = True
await context.db.main.flush()
achievement_count = await achievement.get_achievement_count(context, current_user, False)

return AchievementRewardOpenResponse(
accomplished_achievement_list=[],
unaccomplished_achievement_cnt=achievement_count,
added_achievement_list=[],
new_achievement_cnt=achievement_count,
before_user_info=before_user,
after_user_info=await user.get_user_info(context, current_user),
reward_item_list=rewards,
unit_support_list=await unit.get_unit_support_list_response(context, current_user),
present_cnt=await reward.count_presentbox(context, current_user),
)


@idol.register("achievement", "rewardOpenAll")
async def achievement_rewardopenall(context: idol.SchoolIdolUserParams) -> AchievementRewardOpenAllResponse:
current_user = await user.get_current(context)
achievements = await achievement.get_unclaimed_achievements(context, current_user, True)
opened_count = 0
reward_item_list: list[common.AnyItem] = []
before_user = await user.get_user_info(context, current_user)

for ach in achievements:
ach_info = await achievement.get_achievement_info(context, ach.achievement_id)
rewards = await achievement.get_achievement_rewards(context, ach)
await advanced.fixup_achievement_reward(context, current_user, [rewards])

for reward_item in rewards:
success = await advanced.add_item(context, current_user, reward_item)
if not bool(success):
reward_item.reward_box_flag = True
fallback_name = f"Achievement #{ach.achievement_id}"
await reward.add_item(
context,
current_user,
reward_item,
ach_info.title or fallback_name,
ach_info.title_en or ach_info.title or fallback_name,
)
reward_item_list.append(reward_item)

ach.is_reward_claimed = True
opened_count = opened_count + 1

achievement_count = await achievement.get_achievement_count(context, current_user, False)
return AchievementRewardOpenAllResponse(
accomplished_achievement_list=[],
unaccomplished_achievement_cnt=achievement_count,
added_achievement_list=[],
new_achievement_cnt=achievement_count,
before_user_info=before_user,
after_user_info=await user.get_user_info(context, current_user),
reward_item_list=reward_item_list,
unit_support_list=await unit.get_unit_support_list_response(context, current_user),
present_cnt=await reward.count_presentbox(context, current_user),
is_last=True,
opened_num=opened_count,
)
23 changes: 18 additions & 5 deletions npps4/system/achievement.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ def from_sqlalchemy(ach: main.Achievement, info: achievement.Achievement, reward
is_new=ach.is_new,
for_display=bool(info.display_flag),
is_locked=False,
accomplish_id=str(ach.id) if ach.is_accomplished and (not ach.is_reward_claimed) else "",
reward_list=rewards,
)

Expand Down Expand Up @@ -138,6 +139,14 @@ async def init(context: idol.BasicSchoolIdolContext, user: main.User):
await context.db.main.flush()


async def get_achievement(context: idol.BasicSchoolIdolContext, /, user: main.User, ach_id: int):
ach = await context.db.main.get(main.Achievement, ach_id)
if ach is None or ach.user_id != user.id:
raise idol.error.IdolError(detail=f"invalid achievement id {ach_id}")

return ach


async def get_achievements(context: idol.BasicSchoolIdolContext, user: main.User, accomplished: bool | None = None):
if accomplished is not None:
q = sqlalchemy.select(main.Achievement).where(
Expand All @@ -149,11 +158,15 @@ async def get_achievements(context: idol.BasicSchoolIdolContext, user: main.User
return list(result.scalars())


async def get_unclaimed_achievements(context: idol.BasicSchoolIdolContext, user: main.User):
q = sqlalchemy.select(main.Achievement).where(
main.Achievement.user_id == user.id,
(main.Achievement.is_accomplished == False) | (main.Achievement.is_reward_claimed == False),
)
async def get_unclaimed_achievements(
context: idol.BasicSchoolIdolContext, /, user: main.User, accomplished_but_unclaimed_only: bool = False
):
q = sqlalchemy.select(main.Achievement).where(main.Achievement.user_id == user.id)

if accomplished_but_unclaimed_only:
q = q.where(main.Achievement.is_accomplished == True, main.Achievement.is_reward_claimed == False)
else:
q = q.where((main.Achievement.is_accomplished == False) | (main.Achievement.is_reward_claimed == False))
result = await context.db.main.execute(q)
return list(result.scalars())

Expand Down
23 changes: 13 additions & 10 deletions npps4/system/advanced.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,17 +116,20 @@ async def add_item(context: idol.BasicSchoolIdolContext, user: main.User, item:
user.free_sns_coin = user.free_sns_coin + item.amount
return AddResult(True)
case const.ADD_TYPE.UNIT:
unit_cnt = await unit.count_units(context, user, True)
if unit_cnt < user.unit_max:
unit_level = 1
if isinstance(item, unit_model.UnitItem):
unit_level = item.level
unit_data = await unit.add_unit(context, user, item.item_id, True, level=unit_level)
if isinstance(item, unit_model.UnitItem):
item.unit_owning_user_id = unit_data.id
return AddResult(True, extra_data=unit_data)
if await unit.is_support_member(context, item.item_id):
return AddResult(await unit.add_supporter_unit(context, user, item.item_id, item.amount))
else:
return AddResult(False, reason_unit_full=True)
unit_cnt = await unit.count_units(context, user, True)
if unit_cnt < user.unit_max:
unit_level = 1
if isinstance(item, unit_model.UnitItem):
unit_level = item.level
unit_data = await unit.add_unit(context, user, item.item_id, True, level=unit_level)
if isinstance(item, unit_model.UnitItem):
item.unit_owning_user_id = unit_data.id
return AddResult(True, extra_data=unit_data)
else:
return AddResult(False, reason_unit_full=True)
case const.ADD_TYPE.GAME_COIN:
user.game_coin = user.game_coin + item.amount
return AddResult(True)
Expand Down
4 changes: 4 additions & 0 deletions npps4/system/museum.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ class MuseumInfoData(pydantic.BaseModel):
contents_id_list: list[int]


class MuseumMixin(pydantic.BaseModel):
museum_info: MuseumInfoData


async def unlock(context: idol.BasicSchoolIdolContext, user: main.User, museum_contents_id: int):
if (await context.db.museum.get(museum.MuseumContents, museum_contents_id)) is None:
raise ValueError("invalid museum contents id")
Expand Down
5 changes: 5 additions & 0 deletions npps4/system/unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,11 @@ async def get_all_supporter_unit(context: idol.BasicSchoolIdolContext, user: mai
return supporters


async def get_unit_support_list_response(context: idol.BasicSchoolIdolContext, /, user: main.User):
supp_units = await get_all_supporter_unit(context, user)
return [unit_model.SupporterInfoResponse(unit_id=supp[0], amount=supp[1]) for supp in supp_units]


def get_unit_info(context: idol.BasicSchoolIdolContext, unit_id: int):
return db.get_decrypted_row(context.db.unit, unit.Unit, unit_id)

Expand Down

0 comments on commit 651dca9

Please sign in to comment.