184 lines
4.4 KiB
Go

package storage
import (
"fmt"
"strconv"
"strings"
"time"
"github.com/shopspring/decimal"
"go.mongodb.org/mongo-driver/v2/bson"
"dashboard-cdc-worker/internal/dashboard"
)
func mergeMongoGiftRows(rows map[string]*giftMetricRow, metrics []mongoGiftAmount, anchorShare bool) {
for _, item := range metrics {
key := giftMetricKey(item.day, "", item.userID)
row := rows[key]
if row == nil {
row = &giftMetricRow{day: item.day, luckyGiftUsers: make(map[int64]struct{})}
rows[key] = row
}
if anchorShare {
row.luckyGiftAnchorShare = row.luckyGiftAnchorShare.Add(item.amount)
} else {
row.giftConsume = row.giftConsume.Add(item.amount)
}
}
}
func mergeSQLLuckyGiftRows(rows map[string]*giftMetricRow, metrics []sqlLuckyGiftRow) {
for _, item := range metrics {
key := giftMetricKey(item.day, item.country.Code, 0)
row := rows[key]
if row == nil {
row = &giftMetricRow{
day: item.day,
sysOrigin: item.sysOrigin,
country: item.country,
luckyGiftUsers: make(map[int64]struct{}),
}
rows[key] = row
}
row.sysOrigin = item.sysOrigin
row.country = item.country
row.luckyGiftTotalFlow = row.luckyGiftTotalFlow.Add(item.payAmount)
row.luckyGiftPayout = row.luckyGiftPayout.Add(item.payout)
row.luckyGiftUsers[item.userID] = struct{}{}
}
}
func applyGiftUserCountries(rows map[string]*giftMetricRow, users map[int64]dashboard.UserCountry, unknownCountry string) {
for key, row := range rows {
if row.country.Code != "" {
continue
}
parts := strings.Split(key, "|")
if len(parts) != 3 {
continue
}
userID := parseInt64(parts[2])
user, ok := users[userID]
if !ok {
delete(rows, key)
continue
}
row.sysOrigin = user.SysOrigin
row.country = user.Country
countryKey := giftMetricKey(row.day, row.country.Code, 0)
countryRow := rows[countryKey]
if countryRow == nil {
countryRow = &giftMetricRow{
day: row.day,
sysOrigin: row.sysOrigin,
country: row.country,
luckyGiftUsers: make(map[int64]struct{}),
}
rows[countryKey] = countryRow
}
countryRow.giftConsume = countryRow.giftConsume.Add(row.giftConsume)
countryRow.luckyGiftAnchorShare = countryRow.luckyGiftAnchorShare.Add(row.luckyGiftAnchorShare)
delete(rows, key)
}
}
func (row *giftMetricRow) empty() bool {
return row.giftConsume.IsZero() &&
row.luckyGiftAnchorShare.IsZero() &&
row.luckyGiftTotalFlow.IsZero() &&
row.luckyGiftPayout.IsZero() &&
len(row.luckyGiftUsers) == 0
}
func giftMetricKey(day, countryCode string, userID int64) string {
return fmt.Sprintf("%s|%s|%d", day, countryCode, userID)
}
func int64SetToSlice(values map[int64]struct{}) []int64 {
out := make([]int64, 0, len(values))
for value := range values {
out = append(out, value)
}
return out
}
func bsonInt64(value interface{}) int64 {
switch typed := value.(type) {
case int64:
return typed
case int32:
return int64(typed)
case int:
return int64(typed)
case float64:
return int64(typed)
case string:
return parseInt64(typed)
default:
return parseInt64(fmt.Sprint(typed))
}
}
func bsonDecimal(value interface{}) decimal.Decimal {
switch typed := value.(type) {
case decimal.Decimal:
return typed
case bson.Decimal128:
parsed, err := decimal.NewFromString(typed.String())
if err == nil {
return parsed
}
case int64:
return decimal.NewFromInt(typed)
case int32:
return decimal.NewFromInt(int64(typed))
case int:
return decimal.NewFromInt(int64(typed))
case float64:
return decimal.NewFromFloat(typed)
case string:
parsed, err := decimal.NewFromString(typed)
if err == nil {
return parsed
}
}
parsed, err := decimal.NewFromString(fmt.Sprint(value))
if err != nil {
return decimal.Zero
}
return parsed
}
func parseInt64(value string) int64 {
parsed, _ := strconv.ParseInt(strings.TrimSpace(value), 10, 64)
return parsed
}
func defaultSysOrigin(values []string) string {
if len(values) == 0 {
return ""
}
return strings.TrimSpace(values[0])
}
func timezoneOffset(timezone string) string {
location, err := time.LoadLocation(timezone)
if err != nil {
return "+00:00"
}
_, offset := time.Now().In(location).Zone()
sign := "+"
if offset < 0 {
sign = "-"
offset = -offset
}
hours := offset / 3600
minutes := (offset % 3600) / 60
return fmt.Sprintf("%s%02d:%02d", sign, hours, minutes)
}
func quoteIdent(value string) string {
return "`" + strings.ReplaceAll(value, "`", "``") + "`"
}