123 lines
3.4 KiB
Go
123 lines
3.4 KiB
Go
package economy
|
|
|
|
import "context"
|
|
|
|
// Carpet یک فرشِ ایرانی که بهجای میزِ بازی استفاده میشود. Owned یعنی قابلِ انتخاب.
|
|
type Carpet struct {
|
|
ID string `json:"id"`
|
|
Title string `json:"title"`
|
|
PriceCoins int64 `json:"price_coins"`
|
|
VIP bool `json:"vip"`
|
|
Img string `json:"img"` // URL کاملِ تصویرِ فرش (خالی برای classic که تصویری ندارد)
|
|
Owned bool `json:"owned"`
|
|
}
|
|
|
|
// Carpets فرشهای فعال را با وضعیتِ مالکیتِ کاربر برمیگرداند.
|
|
func (s *Service) Carpets(ctx context.Context, userID int64) ([]Carpet, error) {
|
|
rows, err := s.db.QueryContext(ctx,
|
|
`SELECT id, title, price_coins, vip FROM carpets WHERE enabled = 1 ORDER BY sort`)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
var carpets []Carpet
|
|
for rows.Next() {
|
|
var c Carpet
|
|
var vip int
|
|
if err := rows.Scan(&c.ID, &c.Title, &c.PriceCoins, &vip); err != nil {
|
|
return nil, err
|
|
}
|
|
c.VIP = vip == 1
|
|
if c.ID != "classic" {
|
|
c.Img = s.imgURL("carpets", c.ID+".jpg")
|
|
}
|
|
carpets = append(carpets, c)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
owned, err := s.ownedCarpets(ctx, userID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
isVIP := s.isVIP(ctx, userID)
|
|
for i := range carpets {
|
|
c := &carpets[i]
|
|
c.Owned = (c.PriceCoins == 0 && !c.VIP) || (c.VIP && isVIP) || owned[c.ID]
|
|
}
|
|
return carpets, nil
|
|
}
|
|
|
|
func (s *Service) ownedCarpets(ctx context.Context, userID int64) (map[string]bool, error) {
|
|
rows, err := s.db.QueryContext(ctx,
|
|
`SELECT carpet_id FROM user_carpets WHERE user_id = ?`, userID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
owned := map[string]bool{}
|
|
for rows.Next() {
|
|
var id string
|
|
if err := rows.Scan(&id); err != nil {
|
|
return nil, err
|
|
}
|
|
owned[id] = true
|
|
}
|
|
return owned, rows.Err()
|
|
}
|
|
|
|
// BuyCarpet یک فرش را با سکه باز میکند.
|
|
func (s *Service) BuyCarpet(ctx context.Context, userID int64, carpetID string) error {
|
|
var price int64
|
|
var vip, enabled int
|
|
err := s.db.QueryRowContext(ctx,
|
|
`SELECT price_coins, vip, enabled FROM carpets WHERE id = ?`, carpetID).
|
|
Scan(&price, &vip, &enabled)
|
|
if err != nil || enabled != 1 {
|
|
return ErrNotFound
|
|
}
|
|
tx, err := s.db.BeginTx(ctx, nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer tx.Rollback()
|
|
|
|
var exists int
|
|
_ = tx.QueryRowContext(ctx,
|
|
`SELECT 1 FROM user_carpets WHERE user_id = ? AND carpet_id = ?`, userID, carpetID).Scan(&exists)
|
|
if exists == 1 {
|
|
return ErrAlreadyOwned
|
|
}
|
|
if price > 0 {
|
|
if err := adjustTx(ctx, tx, userID, CurrencyCoin, -price, "buy_carpet", carpetID); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if _, err := tx.ExecContext(ctx,
|
|
`INSERT INTO user_carpets (user_id, carpet_id) VALUES (?, ?)`, userID, carpetID); err != nil {
|
|
return err
|
|
}
|
|
return tx.Commit()
|
|
}
|
|
|
|
// SelectCarpet فرشِ انتخابیِ کاربر را تنظیم میکند (باید مالکش باشد یا رایگان/VIP).
|
|
func (s *Service) SelectCarpet(ctx context.Context, userID int64, carpetID string) error {
|
|
carpets, err := s.Carpets(ctx, userID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, c := range carpets {
|
|
if c.ID == carpetID {
|
|
if !c.Owned {
|
|
return ErrNotOwned
|
|
}
|
|
_, err := s.db.ExecContext(ctx,
|
|
`UPDATE users SET selected_carpet = ? WHERE id = ?`, carpetID, userID)
|
|
return err
|
|
}
|
|
}
|
|
return ErrNotFound
|
|
}
|