ChenyuRabbitLove commited on
Commit
4e6be8d
1 Parent(s): 1638084

feature: make unregistered user can show basic inof

Browse files
Files changed (3) hide show
  1. app.py +7 -2
  2. utils/mes_player_model.py +168 -5
  3. utils/utils.py +4 -3
app.py CHANGED
@@ -3,6 +3,7 @@ import json
3
  import gradio as gr
4
 
5
  from theme import Seafoam
 
6
  from utils.utils import (
7
  get_content,
8
  get_player_partners,
@@ -15,11 +16,15 @@ from utils.utils import (
15
 
16
  seafoam = Seafoam()
17
 
18
-
19
  def get_player_info(player_backend_user_id):
20
  with open("latest_player_data.json", "r", encoding="utf-8") as file:
21
  player_info = json.load(file)
22
- return player_info[player_backend_user_id]
 
 
 
 
 
23
 
24
 
25
  # start of gradio interface
 
3
  import gradio as gr
4
 
5
  from theme import Seafoam
6
+ from utils.mes_player_model import Player
7
  from utils.utils import (
8
  get_content,
9
  get_player_partners,
 
16
 
17
  seafoam = Seafoam()
18
 
 
19
  def get_player_info(player_backend_user_id):
20
  with open("latest_player_data.json", "r", encoding="utf-8") as file:
21
  player_info = json.load(file)
22
+ try:
23
+ player_info = player_info[player_backend_user_id]
24
+ return player_info
25
+ except KeyError:
26
+ player_info = Player(player_backend_user_id=player_backend_user_id, init=True)
27
+ return player_info.to_dict()
28
 
29
 
30
  # start of gradio interface
utils/mes_player_model.py CHANGED
@@ -1,8 +1,12 @@
1
- from dataclasses import dataclass, field
 
 
 
2
  from typing import List, Dict, Union
3
  from datetime import datetime, date
4
 
5
  import pandas as pd
 
6
 
7
 
8
  @dataclass
@@ -22,10 +26,154 @@ class Player:
22
  created_at_date: datetime.date = field(default_factory=date.today)
23
  updated_at_date: datetime.date = field(default_factory=date.today)
24
 
25
- def __post_init__(self):
26
- self.badges = self.badges.tolist()
27
- self.partners = self.partners.tolist()
28
- self.adventure_logs = self.adventure_logs.tolist()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
 
30
  @staticmethod
31
  def from_dict(series: pd.Series) -> "Player":
@@ -40,3 +188,18 @@ class Player:
40
  """
41
  data = series.copy()
42
  return Player(**data)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import logging
3
+ import hashlib
4
+ from dataclasses import dataclass, field, InitVar, asdict
5
  from typing import List, Dict, Union
6
  from datetime import datetime, date
7
 
8
  import pandas as pd
9
+ from google.cloud import bigquery
10
 
11
 
12
  @dataclass
 
26
  created_at_date: datetime.date = field(default_factory=date.today)
27
  updated_at_date: datetime.date = field(default_factory=date.today)
28
 
29
+ available_achievements: InitVar[list] = field(default=None)
30
+ init: InitVar[bool] = field(default=False)
31
+
32
+ def __post_init__(self, available_achievements: List, init: bool):
33
+ # If is_init is True, it means that the player is newly created
34
+ # and the rewards_status is not yet initialized
35
+ if init:
36
+ self.assign_group()
37
+ self.add_adventure_log(
38
+ "你開始了星空探險隊的冒險!, {date}".format(date=datetime.now().date())
39
+ )
40
+ if available_achievements is not None:
41
+ self.rewards_status.update(
42
+ {
43
+ achievement_key: {
44
+ "is_completed": False,
45
+ "is_issued": False,
46
+ }
47
+ for achievement_key in available_achievements
48
+ }
49
+ )
50
+ self.serialize_rewards_status()
51
+ else:
52
+ self.badges = self.badges.tolist()
53
+ self.partners = self.partners.tolist()
54
+ self.adventure_logs = self.adventure_logs.tolist()
55
+ self.assign_weekly_partner()
56
+
57
+ # Serialization and Deserialization is for content type of rewards_status
58
+ # rewards_status have to be serialized before inserting into BigQuery
59
+ def serialize_rewards_status(self):
60
+ self.rewards_status = json.dumps(self.rewards_status)
61
+
62
+ def deserialize_rewards_status(self):
63
+ self.rewards_status = json.loads(self.rewards_status)
64
+
65
+ def add_partner(self, partner: str):
66
+ if partner and partner not in self.partners:
67
+ self.partners.append(partner)
68
+ logging.info(
69
+ f"Player {self.player_backend_user_id} has a new partner: {partner}"
70
+ )
71
+
72
+ def add_badge(self, badge: str):
73
+ if badge and badge not in self.badges:
74
+ self.badges.append(badge)
75
+ logging.info(
76
+ f"Player {self.player_backend_user_id} earned a new badge: {badge}"
77
+ )
78
+
79
+ def add_adventure_log(self, log: str):
80
+ self.adventure_logs.append(log)
81
+ logging.info(
82
+ f"Player {self.player_backend_user_id} has a new adventure log: {log}"
83
+ )
84
+
85
+ def update_total_gained_scores(self, gained_scores: int):
86
+ self.total_gained_scores = gained_scores
87
+
88
+ def update_total_finished_contents(self, finished_contents_count: int):
89
+ self.total_finished_contents = finished_contents_count
90
+
91
+ def update_total_active_days(self, active_days: int):
92
+ self.total_active_days = active_days
93
+
94
+ def update_rewards_status(
95
+ self, key: str, value: bool, target=["is_completed", "is_issued"]
96
+ ):
97
+ self.deserialize_rewards_status()
98
+ self.rewards_status[key][target] = value
99
+ self.serialize_rewards_status()
100
+
101
+ def hash_user_id(self):
102
+ hashed = hashlib.sha256(self.player_backend_user_id.encode()).hexdigest()
103
+ hash_int = int(hashed, 16)
104
+ return hash_int % 40
105
+
106
+ def assign_group(self):
107
+ self.player_group = self.hash_user_id()
108
+ partner_group = self.player_group // 10
109
+ group_base_partners = {
110
+ 0: "phoenix_1",
111
+ 1: "pegasus_1",
112
+ 2: "dragon_1",
113
+ 3: "griffin_1",
114
+ }
115
+ self.add_partner(group_base_partners[partner_group])
116
+
117
+ def assign_weekly_partner(self):
118
+ event_start_date = datetime(2023, 12, 4).date()
119
+ current_date = datetime.now().date()
120
+ weeks_elapsed = (current_date - event_start_date).days // 7
121
+ if weeks_elapsed not in range(0, 4):
122
+ return
123
+
124
+ group_base_partners = {
125
+ 0: "phoenix",
126
+ 1: "pegasus",
127
+ 2: "dragon",
128
+ 3: "griffin",
129
+ }
130
+
131
+ base_partner = group_base_partners[self.player_group // 10]
132
+ stage_partner = (
133
+ f"{base_partner}_{weeks_elapsed + 1}" # +1 to start from stage 1
134
+ )
135
+
136
+ if stage_partner not in self.partners:
137
+ self.add_partner(stage_partner)
138
+
139
+ def display_player_info(self):
140
+ logging.info(f"Player Backend User ID: {self.player_backend_user_id}")
141
+ logging.info(f"Player Group: {self.player_group}")
142
+ logging.info(f"Partners: {self.partners}")
143
+ logging.info(f"Badges: {self.badges}")
144
+ logging.info(f"Adventure Logs: {self.adventure_logs}")
145
+ logging.info(f"Rewards Status: {self.rewards_status}")
146
+ logging.info(f"Total Gained Scores: {self.total_gained_scores}")
147
+ logging.info(f"Total Finished Contents: {self.total_finished_contents}")
148
+ logging.info(f"Total Active Days: {self.total_active_days}")
149
+ logging.info(f"Created At: {self.created_at_date}")
150
+ logging.info(f"Updated At: {self.updated_at_date}")
151
+
152
+ def get_incomplete_rewards(self):
153
+ self.deserialize_rewards_status()
154
+ incomplete_rewards = list(
155
+ {
156
+ k: v for k, v in self.rewards_status.items() if not v["is_completed"]
157
+ }.keys()
158
+ )
159
+ self.serialize_rewards_status()
160
+ return incomplete_rewards
161
+
162
+ @staticmethod
163
+ def get_big_query_schema():
164
+ return [
165
+ bigquery.SchemaField("player_backend_user_id", "STRING", mode="REQUIRED"),
166
+ bigquery.SchemaField("player_group", "INTEGER", mode="NULLABLE"),
167
+ bigquery.SchemaField("partners", "STRING", mode="REPEATED"),
168
+ bigquery.SchemaField("badges", "STRING", mode="REPEATED"),
169
+ bigquery.SchemaField("rewards_status", "STRING", mode="REQUIRED"),
170
+ bigquery.SchemaField("adventure_logs", "STRING", mode="REPEATED"),
171
+ bigquery.SchemaField("total_active_days", "INTEGER", mode="REQUIRED"),
172
+ bigquery.SchemaField("total_gained_scores", "INTEGER", mode="REQUIRED"),
173
+ bigquery.SchemaField("total_finished_contents", "INTEGER", mode="REQUIRED"),
174
+ bigquery.SchemaField("created_at_date", "DATE", mode="REQUIRED"),
175
+ bigquery.SchemaField("updated_at_date", "DATE", mode="REQUIRED"),
176
+ ]
177
 
178
  @staticmethod
179
  def from_dict(series: pd.Series) -> "Player":
 
188
  """
189
  data = series.copy()
190
  return Player(**data)
191
+
192
+ def to_dict(self) -> Dict:
193
+ """
194
+ Converts a Player instance to a dictionary.
195
+
196
+ Returns:
197
+ Dict: A dictionary representation of the Player instance.
198
+ """
199
+ data = asdict(self)
200
+ # Convert datetime.date objects to string
201
+ for date_field in ['created_at_date', 'updated_at_date']:
202
+ if data.get(date_field):
203
+ data[date_field] = data[date_field].strftime("%Y-%m-%d")
204
+
205
+ return data
utils/utils.py CHANGED
@@ -89,9 +89,10 @@ def get_player_achievements(player_info: gr.State) -> List[str]:
89
  "electronic_and_information_college_explorer_II": "電資學院探險家 II",
90
  "star_warrior": "星空艦長",
91
  }
92
- print(player_info["rewards_status"])
93
- rewards_status = json.loads(player_info["rewards_status"])
94
- # rewards_status rountine_achevement sholud be removed
 
95
  return [
96
  (
97
  achivement_name_map[achievement_key],
 
89
  "electronic_and_information_college_explorer_II": "電資學院探險家 II",
90
  "star_warrior": "星空艦長",
91
  }
92
+ if not isinstance(player_info["rewards_status"], dict):
93
+ rewards_status = json.loads(player_info["rewards_status"])
94
+ else:
95
+ rewards_status = player_info["rewards_status"]
96
  return [
97
  (
98
  achivement_name_map[achievement_key],