203 lines
6.2 KiB
Go
203 lines
6.2 KiB
Go
package highwin
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"chatapp3-golang/internal/common"
|
|
"chatapp3-golang/internal/service/regionimgroup"
|
|
)
|
|
|
|
const (
|
|
SimulationKindLuckyGift = "LUCKY_GIFT"
|
|
SimulationKindGameWin = "GAME_WIN"
|
|
)
|
|
|
|
type BroadcastSimulationRequest struct {
|
|
SysOrigin string `json:"sysOrigin"`
|
|
RegionCode string `json:"regionCode"`
|
|
Kind string `json:"kind"`
|
|
SenderUserID string `json:"senderUserId"`
|
|
RoomID string `json:"roomId"`
|
|
Multiple string `json:"multiple"`
|
|
WinAmount string `json:"winAmount"`
|
|
|
|
AcceptUserID string `json:"acceptUserId"`
|
|
GiftID string `json:"giftId"`
|
|
GiftCandy string `json:"giftCandy"`
|
|
GiftQuantity string `json:"giftQuantity"`
|
|
GameID string `json:"gameId"`
|
|
GameRoundID string `json:"gameRoundId"`
|
|
GameURL string `json:"gameUrl"`
|
|
BetAmount string `json:"betAmount"`
|
|
ProviderOrder string `json:"providerOrderId"`
|
|
}
|
|
|
|
type BroadcastSimulationResponse struct {
|
|
SysOrigin string `json:"sysOrigin"`
|
|
RegionCode string `json:"regionCode"`
|
|
GroupID string `json:"groupId"`
|
|
Type string `json:"type"`
|
|
Data map[string]any `json:"data"`
|
|
}
|
|
|
|
func SendSimulationBroadcast(
|
|
ctx context.Context,
|
|
broadcaster RegionBroadcaster,
|
|
req BroadcastSimulationRequest,
|
|
) (*BroadcastSimulationResponse, error) {
|
|
if broadcaster == nil {
|
|
return nil, common.NewAppError(http.StatusInternalServerError, "region_broadcaster_missing", "region broadcaster is missing")
|
|
}
|
|
messageType, err := simulationMessageType(req.Kind)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
userID, err := parseRequiredInt64(req.SenderUserID, "senderUserId")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
roomID := strings.TrimSpace(req.RoomID)
|
|
if roomID == "" {
|
|
return nil, common.NewAppError(http.StatusBadRequest, "missing_room_id", "roomId is required")
|
|
}
|
|
amount, err := parseRequiredInt64(req.WinAmount, "winAmount")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
multiple, err := parseRequiredFloat64(req.Multiple, "multiple")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if !ShouldBroadcast(multiple, amount) {
|
|
return nil, common.NewAppError(http.StatusBadRequest, "broadcast_threshold_not_met", "multiple must be >= 10 and winAmount must be > 0")
|
|
}
|
|
|
|
data := simulationData(messageType, req, amount)
|
|
event := BroadcastEvent{
|
|
SysOrigin: req.SysOrigin,
|
|
RegionCode: req.RegionCode,
|
|
Type: messageType,
|
|
UserID: userID,
|
|
RoomID: roomID,
|
|
Multiple: multiple,
|
|
Amount: amount,
|
|
Data: data,
|
|
}
|
|
if err := SendRegionBroadcast(ctx, broadcaster, event); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
previewData := cloneData(data)
|
|
setRequired(previewData, "userId", strconv.FormatInt(userID, 10))
|
|
setRequired(previewData, "sendUserId", strconv.FormatInt(userID, 10))
|
|
setRequired(previewData, "senderUserId", strconv.FormatInt(userID, 10))
|
|
setRequired(previewData, "roomId", roomID)
|
|
setRequired(previewData, "multiple", normalizeMultiple(multiple))
|
|
setRequired(previewData, "winMultiple", normalizeMultiple(multiple))
|
|
setRequired(previewData, "winAmount", amount)
|
|
setRequired(previewData, "awardAmount", amount)
|
|
setRequired(previewData, "msg", highWinMessage(previewData, messageType, strconv.FormatInt(userID, 10), multiple, amount))
|
|
|
|
return &BroadcastSimulationResponse{
|
|
SysOrigin: strings.ToUpper(strings.TrimSpace(req.SysOrigin)),
|
|
RegionCode: strings.TrimSpace(req.RegionCode),
|
|
Type: messageType,
|
|
Data: previewData,
|
|
}, nil
|
|
}
|
|
|
|
func simulationMessageType(kind string) (string, error) {
|
|
switch strings.ToUpper(strings.TrimSpace(kind)) {
|
|
case SimulationKindLuckyGift:
|
|
return MessageTypeLuckyGift, nil
|
|
case SimulationKindGameWin:
|
|
return MessageTypeBaishunWin, nil
|
|
default:
|
|
return "", common.NewAppError(http.StatusBadRequest, "invalid_broadcast_kind", "kind must be LUCKY_GIFT or GAME_WIN")
|
|
}
|
|
}
|
|
|
|
func simulationData(messageType string, req BroadcastSimulationRequest, amount int64) map[string]any {
|
|
now := strconv.FormatInt(time.Now().UnixMilli(), 10)
|
|
switch messageType {
|
|
case MessageTypeLuckyGift:
|
|
data := map[string]any{
|
|
"businessId": firstNonBlank(req.ProviderOrder, "admin-sim-lucky-gift-"+now),
|
|
"orderId": firstNonBlank(req.ProviderOrder, "admin-sim-order-"+now),
|
|
"globalNews": true,
|
|
"multipleType": "WIN",
|
|
}
|
|
setOptional(data, "acceptUserId", req.AcceptUserID)
|
|
setOptional(data, "giftId", req.GiftID)
|
|
setOptionalInt64(data, "giftCandy", req.GiftCandy)
|
|
setOptionalInt64(data, "giftQuantity", req.GiftQuantity)
|
|
return data
|
|
default:
|
|
data := map[string]any{
|
|
"gameRoundId": firstNonBlank(req.GameRoundID, "admin-sim-game-round-"+now),
|
|
"currencyDiff": amount,
|
|
}
|
|
setOptional(data, "gameId", req.GameID)
|
|
setOptional(data, "gameUrl", req.GameURL)
|
|
setOptionalInt64(data, "betAmount", req.BetAmount)
|
|
return data
|
|
}
|
|
}
|
|
|
|
func setOptional(data map[string]any, key string, value string) {
|
|
if value = strings.TrimSpace(value); value != "" {
|
|
data[key] = value
|
|
}
|
|
}
|
|
|
|
func setOptionalInt64(data map[string]any, key string, value string) {
|
|
parsed, err := parseOptionalInt64(value)
|
|
if err == nil && parsed > 0 {
|
|
data[key] = parsed
|
|
}
|
|
}
|
|
|
|
func firstNonBlank(values ...string) string {
|
|
for _, value := range values {
|
|
if trimmed := strings.TrimSpace(value); trimmed != "" {
|
|
return trimmed
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func parseRequiredInt64(value string, field string) (int64, error) {
|
|
parsed, err := parseOptionalInt64(value)
|
|
if err != nil || parsed <= 0 {
|
|
return 0, common.NewAppError(http.StatusBadRequest, "invalid_"+field, fmt.Sprintf("%s must be a positive integer", field))
|
|
}
|
|
return parsed, nil
|
|
}
|
|
|
|
func parseOptionalInt64(value string) (int64, error) {
|
|
raw := strings.TrimSpace(value)
|
|
if raw == "" {
|
|
return 0, nil
|
|
}
|
|
return strconv.ParseInt(raw, 10, 64)
|
|
}
|
|
|
|
func parseRequiredFloat64(value string, field string) (float64, error) {
|
|
raw := strings.TrimSpace(value)
|
|
if raw == "" {
|
|
return 0, common.NewAppError(http.StatusBadRequest, "invalid_"+field, fmt.Sprintf("%s must be a positive number", field))
|
|
}
|
|
parsed, err := strconv.ParseFloat(raw, 64)
|
|
if err != nil || parsed <= 0 {
|
|
return 0, common.NewAppError(http.StatusBadRequest, "invalid_"+field, fmt.Sprintf("%s must be a positive number", field))
|
|
}
|
|
return parsed, nil
|
|
}
|
|
|
|
var _ RegionBroadcaster = (*regionimgroup.Service)(nil)
|