Skip to content

Commit

Permalink
Implement (broken) live replay.
Browse files Browse the repository at this point in the history
  • Loading branch information
MikuAuahDark committed Nov 26, 2024
1 parent ef1ada9 commit bae9b7c
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 47 deletions.
2 changes: 1 addition & 1 deletion npps4/game/friend.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class FriendListFriendUserData(models.UserData):
class FriendListFriend(pydantic.BaseModel):
is_new: bool = False
user_data: FriendListFriendUserData
center_unit_info: models.CenterUnitInfo
center_unit_info: common.CenterUnitInfo
setting_award_id: int


Expand Down
11 changes: 9 additions & 2 deletions npps4/game/live.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import copy
import json
import math

import pydantic
Expand Down Expand Up @@ -420,7 +421,7 @@ async def live_partylist(context: idol.SchoolIdolUserParams, request: LivePartyL
)


@idol.register("live", "preciseScore")
@idol.register("live", "preciseScore", log_response_data=True)
async def live_precisescore(
context: idol.SchoolIdolUserParams, request: LivePreciseScoreRequest
) -> LivePreciseScoreResponse:
Expand Down Expand Up @@ -450,6 +451,7 @@ async def live_precisescore(
on_dict["has_record"] = True
on_dict["can_replay"] = True
on_dict["live_info"] = live_info_json
on_dict["update_date"] = util.timestamp_to_datetime(with_skill_record[2])

if without_skill_record is None:
off_dict = {"has_record": False, "can_replay": False, "live_info": live_info.model_dump(mode="json")}
Expand All @@ -460,6 +462,7 @@ async def live_precisescore(
off_dict["has_record"] = True
off_dict["can_replay"] = True
off_dict["live_info"] = live_info_json
off_dict["update_date"] = util.timestamp_to_datetime(without_skill_record[2])

return LivePreciseScoreResponse(
rank_info=[
Expand Down Expand Up @@ -524,7 +527,9 @@ async def live_play(context: idol.SchoolIdolUserParams, request: LivePlayRequest
)

# Register live in progress
await live.register_live_in_progress(context, current_user, guest, request.lp_factor, request.unit_deck_id)
await live.register_live_in_progress(
context, current_user, guest, request.lp_factor, request.unit_deck_id, stats.model_dump_json().encode("utf-8")
)

return LivePlayResponse(
rank_info=[
Expand Down Expand Up @@ -758,6 +763,8 @@ async def live_reward(context: idol.SchoolIdolUserParams, request: LiveRewardReq

# Store precise log score
if request.precise_score_log["live_setting"]["precise_score_auto_update_flag"]:
request.precise_score_log["deck_info"] = json.loads(live_in_progress.deck_data)
request.precise_score_log["max_combo"] = request.max_combo
await live.record_precise_score(
context,
current_user,
Expand Down
17 changes: 0 additions & 17 deletions npps4/game/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,3 @@ class UserData(pydantic.BaseModel):
user_id: int
name: str
level: int


class CenterUnitInfo(pydantic.BaseModel):
unit_id: int
level: int
love: int
rank: int
display_rank: int
smile: int
cute: int
cool: int
is_love_max: bool
is_rank_max: bool
is_level_max: bool
unit_skill_exp: int
removable_skill_ids: list[int]
unit_removable_skill_capacity: int
4 changes: 2 additions & 2 deletions npps4/game/ranking.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class RankingData(pydantic.BaseModel):
rank: int
score: int
user_data: models.UserData
center_unit_info: models.CenterUnitInfo
center_unit_info: common.CenterUnitInfo
setting_award_id: int


Expand Down Expand Up @@ -76,7 +76,7 @@ async def ranking_live(context: idol.SchoolIdolUserParams, request: RankingLiveR
rank=i,
score=score,
user_data=models.UserData(user_id=user_id, name=target_user.name, level=target_user.level),
center_unit_info=models.CenterUnitInfo(
center_unit_info=common.CenterUnitInfo(
unit_id=unit_data.unit_id,
level=unit_full_data.level,
rank=unit_data.rank,
Expand Down
85 changes: 63 additions & 22 deletions npps4/system/advanced.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,16 @@ class PartyInfo(pydantic.BaseModel):
friend_status: int


class LiveDeckUnitAttribute(pydantic.BaseModel):
smile: int
cute: int
cool: int
class LiveDeckUnitAttribute(common.CenterUnitInfo):
unit_skill_level: int
position: int


class LiveDeckStats(pydantic.BaseModel):
smile: int = 0
cute: int = 0
cool: int = 0
hp: int = 0


class LiveDeckInfo(pydantic.BaseModel):
Expand All @@ -96,6 +102,9 @@ class LiveDeckInfo(pydantic.BaseModel):
total_cool: int
total_hp: int
prepared_hp_damage: int = 0
total_status: LiveDeckStats
center_bonus: LiveDeckStats
si_bonus: LiveDeckStats
unit_list: list[LiveDeckUnitAttribute]


Expand Down Expand Up @@ -327,20 +336,24 @@ async def get_live_stats(
love_stats: list[tuple[int, int, int]] = []
sis_stats: list[tuple[int, int, int]] = []
unit_types: list[int] = []
max_hp = 0

total = LiveDeckStats()
leader = LiveDeckStats()
sis = LiveDeckStats()
sis_ids: list[list[int]] = []
unit_full: list[unit_model.UnitInfoData] = []

# Retrieve base stats
for unit_data in player_units:
unit_info = await self.get_unit_info(unit_data.unit_id)
unit_infos.append(unit_info)
unit_types.append(unit_info.unit_type_id)

unit_rarity = await self.get_unit_rarity(unit_info.rarity)
stats = await unit.get_unit_stats_from_unit_data(
self.context, unit.UnitStatsCalculationID.from_unit_data(unit_data)
)
unit_full_data, stats = await unit.get_unit_data_full_info(self.context, unit_data)
unit_full.append(unit_full_data)
sis_ids.append(await unit.get_unit_removable_skills(self.context, unit_data))
base_stats.append(stats)
max_hp = max_hp + stats.hp
total.hp = total.hp + stats.hp

# Apply bond stat
for i in range(9):
Expand Down Expand Up @@ -369,27 +382,55 @@ async def get_live_stats(
leader_stats = await self.calculate_leader_bonus(sis_stats, unit_types, player_units[4])
guest_stats = await self.calculate_leader_bonus(sis_stats, unit_types, guest)

smile = 0
pure = 0
cool = 0

final_stats: list[LiveDeckUnitAttribute] = []

for i in range(9):
sis.smile = sis.smile + sis_stats[i][0]
sis.cute = sis.cute + sis_stats[i][1]
sis.cool = sis.cool + sis_stats[i][2]
leader.smile = leader.smile + leader_stats[i][0]
leader.cute = leader.cute + leader_stats[i][1]
leader.cool = leader.cool + leader_stats[i][2]

current_smile = sis_stats[i][0] + leader_stats[i][0] + guest_stats[i][0]
current_pure = sis_stats[i][1] + leader_stats[i][1] + guest_stats[i][1]
current_cool = sis_stats[i][2] + leader_stats[i][2] + guest_stats[i][2]
smile = smile + current_smile
pure = pure + current_pure
cool = cool + current_cool
final_stats.append(LiveDeckUnitAttribute(smile=current_smile, cute=current_pure, cool=current_cool))
total.smile = total.smile + current_smile
total.cute = total.cute + current_pure
total.cool = total.cool + current_cool

unit_data = player_units[i]
unit_full_data = unit_full[i]
final_stats.append(
LiveDeckUnitAttribute(
unit_id=unit_data.unit_id,
level=unit_full_data.level,
love=unit_data.love,
rank=unit_data.rank,
display_rank=unit_data.display_rank,
smile=current_smile,
cute=current_pure,
cool=current_cool,
is_love_max=unit_full_data.is_love_max,
is_rank_max=unit_full_data.is_rank_max,
is_level_max=unit_full_data.is_level_max,
unit_skill_exp=unit_data.skill_exp,
unit_skill_level=unit_full_data.unit_skill_level,
unit_removable_skill_capacity=unit_data.unit_removable_skill_capacity,
removable_skill_ids=sis_ids[i],
position=i + 1,
)
)

return LiveDeckInfo(
unit_deck_id=unit_deck_id,
total_smile=smile,
total_cute=pure,
total_cool=cool,
total_hp=max_hp,
total_smile=total.smile,
total_cute=total.cute,
total_cool=total.cool,
total_hp=total.hp,
total_status=total,
center_bonus=leader,
si_bonus=sis,
unit_list=final_stats,
)

Expand Down
17 changes: 17 additions & 0 deletions npps4/system/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,23 @@ class TimestampMixin(pydantic.BaseModel):
server_timestamp: int = pydantic.Field(default_factory=util.time)


class CenterUnitInfo(pydantic.BaseModel):
unit_id: int
level: int
love: int
rank: int
display_rank: int
smile: int
cute: int
cool: int
is_love_max: bool
is_rank_max: bool
is_level_max: bool
unit_skill_exp: int
removable_skill_ids: list[int]
unit_removable_skill_capacity: int


async def get_cached[
T: Hashable, U
](
Expand Down
16 changes: 13 additions & 3 deletions npps4/system/live.py
Original file line number Diff line number Diff line change
Expand Up @@ -374,18 +374,28 @@ async def clean_live_in_progress(context: idol.BasicSchoolIdolContext, user: mai


async def register_live_in_progress(
context: idol.BasicSchoolIdolContext, user: main.User, party_user: main.User, lp_factor: int, unit_deck_id: int
context: idol.BasicSchoolIdolContext,
user: main.User,
party_user: main.User,
lp_factor: int,
unit_deck_id: int,
deck_data_bytes: bytes,
):
live_in_progress = await get_live_in_progress(context, user)
if live_in_progress is None:
wip = main.LiveInProgress(
user_id=user.id, party_user_id=party_user.id, lp_factor=lp_factor, unit_deck_id=unit_deck_id
user_id=user.id,
party_user_id=party_user.id,
lp_factor=lp_factor,
unit_deck_id=unit_deck_id,
deck_data=deck_data_bytes,
)
context.db.main.add(wip)
else:
live_in_progress.party_user_id = party_user.id
live_in_progress.lp_factor = lp_factor
live_in_progress.unit_deck_id = unit_deck_id
live_in_progress.deck_data = deck_data_bytes
await context.db.main.flush()


Expand Down Expand Up @@ -601,4 +611,4 @@ async def pull_precise_score_with_beatmap(
if notes_list is None:
return None

return json.loads(gzip.decompress(replay.precise_log)), notes_list
return json.loads(gzip.decompress(replay.precise_log)), notes_list, replay.timestamp

0 comments on commit bae9b7c

Please sign in to comment.