fix
This commit is contained in:
@@ -73,13 +73,13 @@ func (g gameSettler) RecordGameResult(userID int64, won bool) {
|
||||
g.eco.RecordGameResult(context.Background(), userID, won)
|
||||
}
|
||||
|
||||
// PlayerProfile سکه و نشانِ رتبهی بازیکن را برای نمایش سرِ میز برمیگرداند.
|
||||
func (g gameSettler) PlayerProfile(userID int64) (int64, string) {
|
||||
// PlayerProfile سکه، نشانِ رتبه و آواتارِ بازیکن را برای نمایش سرِ میز برمیگرداند.
|
||||
func (g gameSettler) PlayerProfile(userID int64) (int64, string, string) {
|
||||
p, err := g.eco.GetProfile(context.Background(), userID)
|
||||
if err != nil || p == nil {
|
||||
return 0, ""
|
||||
return 0, "", ""
|
||||
}
|
||||
return p.Coins, p.RankTier
|
||||
return p.Coins, p.RankTier, p.Avatar
|
||||
}
|
||||
|
||||
// ChargeTicket یک بلیت برای بُرِ مجدد مصرف میکند (خطا اگر بلیت کافی نباشد).
|
||||
|
||||
@@ -11,18 +11,29 @@ cd "$(dirname "$0")"
|
||||
|
||||
echo "==> build linux/amd64 (CGO off, pure-Go sqlite)"
|
||||
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o /tmp/hakemsho-linux ./cmd/server
|
||||
LOCAL_SHA=$(shasum -a 256 /tmp/hakemsho-linux | cut -d' ' -f1)
|
||||
echo " sha256=$LOCAL_SHA"
|
||||
|
||||
echo "==> upload to $HOST"
|
||||
scp -i "$KEY" -o StrictHostKeyChecking=no /tmp/hakemsho-linux "$HOST:$REMOTE_DIR/hakemsho.new"
|
||||
|
||||
echo "==> swap in + restart (zero-config; data & env untouched)"
|
||||
ssh -i "$KEY" -o StrictHostKeyChecking=no "$HOST" '
|
||||
# چکسام را روی سرور تأیید کن و فقط در صورتِ سالمبودن باینری را جابهجا کن.
|
||||
# این از سناریوی «انتقالِ ناقص ⇒ باینریِ خراب ⇒ SEGV» جلوگیری میکند.
|
||||
echo "==> verify checksum + swap in + restart (data & env untouched)"
|
||||
ssh -i "$KEY" -o StrictHostKeyChecking=no "$HOST" "
|
||||
set -e
|
||||
REMOTE_SHA=\$(sha256sum ~/hakemsho/hakemsho.new | cut -d' ' -f1)
|
||||
if [ \"\$REMOTE_SHA\" != \"$LOCAL_SHA\" ]; then
|
||||
echo \"checksum mismatch (\$REMOTE_SHA != $LOCAL_SHA) — aborting, service untouched\"
|
||||
rm -f ~/hakemsho/hakemsho.new
|
||||
exit 1
|
||||
fi
|
||||
chmod +x ~/hakemsho/hakemsho.new
|
||||
mv ~/hakemsho/hakemsho.new ~/hakemsho/hakemsho
|
||||
chmod +x ~/hakemsho/hakemsho
|
||||
sudo systemctl reset-failed hakemsho || true
|
||||
sudo systemctl restart hakemsho
|
||||
sleep 2
|
||||
sleep 3
|
||||
systemctl is-active hakemsho
|
||||
curl -s -m5 http://127.0.0.1:8080/health && echo
|
||||
'
|
||||
"
|
||||
echo "==> done: https://hakem.approagency.ir/health"
|
||||
|
||||
@@ -60,21 +60,23 @@ type Profile struct {
|
||||
RankPoints int64 `json:"rank_points"`
|
||||
RankTier string `json:"rank_tier"` // bronze..king
|
||||
RankIndex int `json:"rank_index"` // ۰..۴
|
||||
Avatar string `json:"avatar"` // seed آواتار (برای نمایش سرِ میز)
|
||||
}
|
||||
|
||||
// GetProfile وضعیت اقتصادی کاربر را میخواند.
|
||||
func (s *Service) GetProfile(ctx context.Context, userID int64) (*Profile, error) {
|
||||
var p Profile
|
||||
var vipUntil sql.NullString
|
||||
var vipUntil, avatar sql.NullString
|
||||
err := s.db.QueryRowContext(ctx,
|
||||
`SELECT coins, tickets, xp, trophies, vip_until, selected_card, selected_carpet, rank_points FROM users WHERE id = ?`, userID).
|
||||
Scan(&p.Coins, &p.Tickets, &p.XP, &p.Trophies, &vipUntil, &p.SelectedCard, &p.SelectedCarpet, &p.RankPoints)
|
||||
`SELECT coins, tickets, xp, trophies, vip_until, selected_card, selected_carpet, rank_points, avatar FROM users WHERE id = ?`, userID).
|
||||
Scan(&p.Coins, &p.Tickets, &p.XP, &p.Trophies, &vipUntil, &p.SelectedCard, &p.SelectedCarpet, &p.RankPoints, &avatar)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.Avatar = avatar.String
|
||||
p.Level, p.XPInto, p.XPNeed = LevelInfo(p.XP)
|
||||
p.RankTier, p.RankIndex = RankTier(p.RankPoints)
|
||||
if vipUntil.Valid {
|
||||
|
||||
@@ -391,8 +391,10 @@ func (h *Hub) removeFromTable(t *pendingTable, c *Client) {
|
||||
func (h *Hub) broadcastLobby(t *pendingTable) {
|
||||
players := make([]lobbyPlayer, len(t.clients))
|
||||
for i, cl := range t.clients {
|
||||
_, _, avatar := h.settler.PlayerProfile(cl.UserID)
|
||||
players[i] = lobbyPlayer{
|
||||
Name: cl.Name,
|
||||
Avatar: avatar,
|
||||
Host: cl.UserID == t.host,
|
||||
Seat: t.seatOf(i),
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ type chatMsg struct {
|
||||
// lobbyPlayer یک بازیکن در اتاق انتظارِ میز خصوصی.
|
||||
type lobbyPlayer struct {
|
||||
Name string `json:"name"`
|
||||
Avatar string `json:"avatar"` // seed آواتارِ کاربر
|
||||
Host bool `json:"host"`
|
||||
Seat int `json:"seat"` // جایگاهِ مطلق (۰..۳)
|
||||
}
|
||||
@@ -64,6 +65,7 @@ type PlayerInfo struct {
|
||||
Connected bool `json:"connected"`
|
||||
Coins int64 `json:"coins"`
|
||||
RankTier string `json:"rank_tier"` // bronze..king (برای نشانِ رتبه)
|
||||
Avatar string `json:"avatar"` // seed آواتارِ کاربر
|
||||
}
|
||||
|
||||
// matchedMsg به کلاینت پس از تشکیل میز.
|
||||
|
||||
+3
-2
@@ -39,6 +39,7 @@ type seatInfo struct {
|
||||
left bool // خروج دائمی داوطلبانه (در تسویه از بازگشت ورودی محروم)
|
||||
coins int64 // برای نمایش سرِ میز
|
||||
rankTier string // نشانِ رتبه برای نمایش سرِ میز
|
||||
avatar string // seed آواتارِ انتخابیِ کاربر (برای نمایش سرِ میز)
|
||||
}
|
||||
|
||||
// auto مشخص میکند جایگاه باید خودکار بازی شود (بات یا قطعشده).
|
||||
@@ -143,7 +144,7 @@ func (r *Room) start() {
|
||||
if s.isBot || s.userID == 0 {
|
||||
continue
|
||||
}
|
||||
s.coins, s.rankTier = r.settler.PlayerProfile(s.userID)
|
||||
s.coins, s.rankTier, s.avatar = r.settler.PlayerProfile(s.userID)
|
||||
}
|
||||
for seat, s := range r.seats {
|
||||
if s.client != nil {
|
||||
@@ -567,7 +568,7 @@ func (r *Room) playersInfo() []PlayerInfo {
|
||||
out[i] = PlayerInfo{
|
||||
Seat: i, Name: s.name, Bot: s.isBot,
|
||||
Connected: s.isBot || s.connected,
|
||||
Coins: s.coins, RankTier: s.rankTier,
|
||||
Coins: s.coins, RankTier: s.rankTier, Avatar: s.avatar,
|
||||
}
|
||||
}
|
||||
return out
|
||||
|
||||
@@ -12,8 +12,8 @@ type Settler interface {
|
||||
RecordHand(userID int64, won, kot, asHakem bool) // پایان یک هَند
|
||||
RecordCut(userID int64) // بُرِش با حکم
|
||||
RecordGameResult(userID int64, won bool) // پایان بازی (برد/باخت)
|
||||
// PlayerProfile سکه و نشانِ رتبهی بازیکن را برای نمایش سرِ میز برمیگرداند.
|
||||
PlayerProfile(userID int64) (coins int64, rankTier string)
|
||||
// PlayerProfile سکه، نشانِ رتبه و seedِ آواتارِ بازیکن را برای نمایش سرِ میز برمیگرداند.
|
||||
PlayerProfile(userID int64) (coins int64, rankTier string, avatar string)
|
||||
// ChargeTicket یک بلیت برای بُرِ مجدد در فازِ انتخابِ حکم مصرف میکند.
|
||||
ChargeTicket(userID int64) error
|
||||
// ChargeCoins/AwardCoins برای شرطِ سکهایِ میزِ خصوصی (pot). Charge در صورتِ
|
||||
@@ -38,7 +38,7 @@ func (noopSettler) RecordGame(string, string, int, bool) {}
|
||||
func (noopSettler) RecordHand(int64, bool, bool, bool) {}
|
||||
func (noopSettler) RecordCut(int64) {}
|
||||
func (noopSettler) RecordGameResult(int64, bool) {}
|
||||
func (noopSettler) PlayerProfile(int64) (int64, string) { return 0, "" }
|
||||
func (noopSettler) PlayerProfile(int64) (int64, string, string) { return 0, "", "" }
|
||||
func (noopSettler) ChargeTicket(int64) error { return nil }
|
||||
func (noopSettler) ChargeCoins(int64, int64, string) error { return nil }
|
||||
func (noopSettler) AwardCoins(int64, int64, string) {}
|
||||
|
||||
@@ -481,7 +481,7 @@ func (s *recordingSettler) RecordGameResult(int64, bool) {
|
||||
s.mu.Unlock()
|
||||
}
|
||||
|
||||
func (s *recordingSettler) PlayerProfile(int64) (int64, string) { return 0, "" }
|
||||
func (s *recordingSettler) PlayerProfile(int64) (int64, string, string) { return 0, "", "" }
|
||||
func (s *recordingSettler) ChargeTicket(int64) error { return nil }
|
||||
func (s *recordingSettler) ChargeCoins(int64, int64, string) error { return nil }
|
||||
func (s *recordingSettler) AwardCoins(int64, int64, string) {}
|
||||
|
||||
Reference in New Issue
Block a user