198 lines
4.7 KiB
Go
198 lines
4.7 KiB
Go
package psql
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"errors"
|
|
"math"
|
|
"time"
|
|
"ymgb/database"
|
|
|
|
"github.com/shopspring/decimal"
|
|
"github.com/vinovest/sqlx"
|
|
)
|
|
|
|
type User struct {
|
|
ID int
|
|
Balance decimal.Decimal
|
|
Name string
|
|
GroupID int `db:"group_id"`
|
|
Level int
|
|
Exp int
|
|
WorkID int `db:"work_id"`
|
|
WorkTime time.Time `db:"work_time"`
|
|
|
|
AutoID sql.NullInt32 `db:"auto_id"`
|
|
BusinessID sql.NullInt32 `db:"business_id"`
|
|
MaidID sql.NullInt32 `db:"maid_id"`
|
|
MinerID sql.NullInt32 `db:"miner_id"`
|
|
|
|
IncomeTime time.Time `db:"income_time"`
|
|
BTC decimal.Decimal
|
|
Invested decimal.Decimal
|
|
PairID sql.NullInt64 `db:"pair_id"`
|
|
Greeting string
|
|
Donat int
|
|
FractionID sql.NullInt32 `db:"fraction_id"`
|
|
|
|
MoneyIncome decimal.Decimal `db:"money_income"`
|
|
ExpIncome int `db:"exp_income"`
|
|
BtcIncome decimal.Decimal `db:"btc_income"`
|
|
|
|
WaifuSearchTime time.Time `db:"waifu_search_time"`
|
|
|
|
Group *Group
|
|
Work *Work
|
|
Auto *ShopAuto
|
|
Business *ShopBusiness
|
|
Maid *ShopMaid
|
|
Miner *ShopMiner
|
|
Pair *User
|
|
Fraction *Fraction
|
|
}
|
|
|
|
type UserRepository struct {
|
|
db *sqlx.DB
|
|
}
|
|
|
|
func newUserRepository(db *sqlx.DB) UserRepository { return UserRepository{db} }
|
|
func NewUserRepository(db *database.Context) UserRepository {
|
|
return newUserRepository(db.Postgres)
|
|
}
|
|
|
|
func (rep UserRepository) GetOrCreate(tgId int, name string) (*User, error) {
|
|
user, err := rep.GetById(tgId)
|
|
if errors.Is(err, sql.ErrNoRows) {
|
|
user, err = rep.Create(tgId, name)
|
|
}
|
|
return user, err
|
|
}
|
|
|
|
func (rep UserRepository) Create(id int, name string) (*User, error) {
|
|
user := new(User)
|
|
err := rep.db.Get(user, "INSERT INTO users (id, name) VALUES ($1, $2) RETURNING *;", id, name)
|
|
return user, err
|
|
}
|
|
|
|
func (rep UserRepository) GetById(telegramId int) (*User, error) {
|
|
user := new(User)
|
|
err := rep.db.Get(user, "SELECT * FROM users WHERE id=$1;", telegramId)
|
|
if err != nil {
|
|
return user, err
|
|
}
|
|
return rep.GetJoins(user)
|
|
}
|
|
|
|
func (rep UserRepository) GetJoins(user *User) (*User, error) {
|
|
err := sqlx.Transact(rep.db, func(ctx context.Context, db sqlx.Queryable) error {
|
|
user.Group = new(Group)
|
|
err := rep.db.Get(user.Group, "SELECT * FROM groups WHERE id=$1;", user.GroupID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
user.Work = new(Work)
|
|
err = rep.db.Get(user.Work, "SELECT * FROM works WHERE id=$1;", user.WorkID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
shopRep := newShopRepository(rep.db)
|
|
if user.AutoID.Valid {
|
|
auto, err := shopRep.GetAuto(user.AutoID.Int32)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
user.Auto = &auto
|
|
}
|
|
if user.BusinessID.Valid {
|
|
business, err := shopRep.GetBusiness(user.BusinessID.Int32)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
user.Business = &business
|
|
}
|
|
if user.MaidID.Valid {
|
|
maid, err := shopRep.GetMaid(user.MaidID.Int32)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
user.Maid = &maid
|
|
}
|
|
if user.MinerID.Valid {
|
|
miner, err := shopRep.GetMiner(user.MinerID.Int32)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
user.Miner = &miner
|
|
}
|
|
if user.PairID.Valid {
|
|
pair, err := rep.GetById(int(user.PairID.Int64))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
user.Pair = pair
|
|
}
|
|
if user.FractionID.Valid {
|
|
fractionRep := newFractionRepository(rep.db)
|
|
fraction, err := fractionRep.GetById(user.FractionID.Int32)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
user.Fraction = &fraction
|
|
}
|
|
return nil
|
|
})
|
|
return user, err
|
|
}
|
|
|
|
func (rep UserRepository) Update(user *User) (*User, error) {
|
|
_, err := rep.db.NamedExec(
|
|
`UPDATE users SET balance=:balance, name=:name, group_id=:group_id, level=:level, exp=:exp,
|
|
work_id=:work_id, work_time=:work_time, auto_id=:auto_id, business_id=:business_id,
|
|
maid_id=:maid_id, miner_id=:miner_id, income_time=:income_time, btc=:btc, invested=:invested,
|
|
pair_id=:pair_id, greeting=:greeting, donat=:donat, fraction_id=:fraction_id,
|
|
money_income=:money_income, exp_income=:exp_income, btc_income=:btc_income,
|
|
waifu_search_time=:waifu_search_time
|
|
WHERE id=:id;`,
|
|
user,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return rep.GetById(user.ID)
|
|
}
|
|
|
|
func (rep UserRepository) GetAll() ([]User, error) {
|
|
users := make([]User, 0)
|
|
err := rep.db.Select(&users, "SELECT * FROM users ORDER BY id;")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
outUsers := make([]User, len(users))
|
|
for i, user := range users {
|
|
u, err := rep.GetJoins(&user)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
outUsers[i] = *u
|
|
}
|
|
|
|
return outUsers, nil
|
|
}
|
|
|
|
func CountLevel(userXp int) (int, int) {
|
|
xp := 0
|
|
nextLevel := 2
|
|
for {
|
|
xp = int(math.Pow(float64(nextLevel), 3)) * (nextLevel * 3)
|
|
if xp > userXp {
|
|
break
|
|
}
|
|
if nextLevel == 200 {
|
|
break
|
|
}
|
|
nextLevel++
|
|
}
|
|
return nextLevel - 1, xp
|
|
}
|