diff --git a/rule/public_platoon_double_network_relate_commission.go b/rule/public_platoon_double_network_relate_commission.go index 159c152..06b91f4 100644 --- a/rule/public_platoon_double_network_relate_commission.go +++ b/rule/public_platoon_double_network_relate_commission.go @@ -2,362 +2,14 @@ package rule import ( "code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/db" - "code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/db/model" - "code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/md" zhios_order_relate_utils "code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/utils" - zhios_order_relate_logx "code.fnuoos.com/go_rely_warehouse/zyos_go_order_relate_rule.git/utils/logx" "errors" "github.com/shopspring/decimal" - "math" - "math/rand" "strconv" - "strings" "time" "xorm.io/xorm" ) -// AddPublicPlatoonDoubleNetworkRelateCommission 新增公排用户关系记录 -func AddPublicPlatoonDoubleNetworkRelateCommission(engine *xorm.Engine, AddPublicPlatoonDoubleNetworkRelateCommissionReqList []*md.AddPublicPlatoonDoubleNetworkDoubleNetworkRelateCommissionReq) (map[string]*model.UserPublicPlatoonDoubleNetworkRelation, error) { - var resp = map[string]*model.UserPublicPlatoonDoubleNetworkRelation{} - //查找 `user_public_platoon_setting` 基础设置 - userPublicPlatoonDoubleNetworkSetting, err := db.UserPublicPlatoonDoubleNetworkSettingGetOneByParams(engine, map[string]interface{}{ - "key": "is_open", - "value": 1, - }) - if err != nil { - return nil, err - } - if userPublicPlatoonDoubleNetworkSetting == nil { - return nil, nil - } - for _, param := range AddPublicPlatoonDoubleNetworkRelateCommissionReqList { - //TODO::判断是否有uid为-1 (代表等待新用户填充) 的记录 - userPublicPlatoonDoubleNetworkRelation, err2 := db.UserPublicPlatoonDoubleNetworkRelationGetOneByParams(engine, map[string]interface{}{ - "key": "uid", - "value": -1, - }) - if err2 != nil { - return nil, err2 - } - if userPublicPlatoonDoubleNetworkRelation != nil { - now := time.Now() - uniqueIdentifier := strings.Split(userPublicPlatoonDoubleNetworkRelation.UniqueIdentifier, "-") - uniqueIdentifier[1] = param.Uid - - userPublicPlatoonDoubleNetworkRelation.Uid = zhios_order_relate_utils.StrToInt(param.Uid) - userPublicPlatoonDoubleNetworkRelation.UniqueIdentifier = strings.Join(uniqueIdentifier, "-") - userPublicPlatoonDoubleNetworkRelation.RecommendUid = zhios_order_relate_utils.StrToInt(param.RecommendUid) - userPublicPlatoonDoubleNetworkRelation.ReturnCommissionNum = 0 - userPublicPlatoonDoubleNetworkRelation.JoinAt = now - userPublicPlatoonDoubleNetworkRelation.CreateAt = now - userPublicPlatoonDoubleNetworkRelation.UpdateAt = now - updateAffected, err1 := db.UserPublicPlatoonDoubleNetworkRelationUpdate(engine.NewSession(), userPublicPlatoonDoubleNetworkRelation.Id, userPublicPlatoonDoubleNetworkRelation) - if err1 != nil { - return nil, err1 - } - if updateAffected == 0 { - err1 = errors.New("更新 user_public_platoon_double_network_relation 记录失败") - return nil, err1 - } else { - resp[param.Uid] = userPublicPlatoonDoubleNetworkRelation - } - continue - } - res, err1 := publicPlatoonDoubleNetwork(engine, zhios_order_relate_utils.StrToInt(param.Uid), zhios_order_relate_utils.StrToInt(param.RecommendUid), *userPublicPlatoonDoubleNetworkSetting) - if err1 != nil { - return nil, err1 - } - resp[param.Uid] = &res - } - return resp, nil -} - -/* - 公排方法 - TODO 相关公式: - 1: 每个等级的起始值(1+5^0+5^1+5^2+...+5^x-2), 每个等级的结束值(`5^0+5^1+5^2+...+5^x-1) - 2: 根据position查找父级position { (position-1)/5 } - 3: 根据position查找等级level {position-5^0-5^1-5^2-...-5^x 是否 <0 ? => x+1 } - 4: 根据最新自增`id` 逆向推导 position {levelFirstPosition + (position-1)%5} -*/ -func publicPlatoonDoubleNetwork(engine *xorm.Engine, uid, recommendUid int, userPublicPlatoonDoubleNetworkSetting model.UserPublicPlatoonDoubleNetworkSetting) (model.UserPublicPlatoonDoubleNetworkRelation, error) { - var userPublicPlatoonDoubleNetworkRelation model.UserPublicPlatoonDoubleNetworkRelation - - //1、 查找当前 user_public_platoon_double_network_relation 中 `position` 最大的记录 - var m model.UserPublicPlatoonDoubleNetworkRelation - has, err := engine.OrderBy("id desc").Get(&m) - if err != nil { - return userPublicPlatoonDoubleNetworkRelation, err - } - if has == false { - return userPublicPlatoonDoubleNetworkRelation, errors.New("查询 user_public_platoon_double_network_relation 记录失败") - } - - //TODO::判断 `position + userPublicPlatoonDoubleNetworkSetting.SeveralTimes(几乘)` OR `position + 1` - var position, position1, position2 int - position1 = m.Position + 1 - position2 = m.Position + userPublicPlatoonDoubleNetworkSetting.SeveralTimes - var level, level1, level2 float64 - makeSearchLevelDoubleNetwork(&position1, float64(userPublicPlatoonDoubleNetworkSetting.SeveralTimes), &level1) - makeSearchLevelDoubleNetwork(&position2, float64(userPublicPlatoonDoubleNetworkSetting.SeveralTimes), &level2) - level = level1 + 1 //TODO::根据公式需要 + 1 - if level > 2 { - if level1 != level2 { - position = reverseDeductionPositionDoubleNetwork(m.Position, getLevelForFirstPositionDoubleNetwork(int(level), userPublicPlatoonDoubleNetworkSetting.SeveralTimes), userPublicPlatoonDoubleNetworkSetting.SeveralTimes) - } else { - if position1 == getLevelForFirstPositionDoubleNetwork(int(level), userPublicPlatoonDoubleNetworkSetting.SeveralTimes) { - position = position1 - } else { - position = position2 - } - } - } else { - position = position1 - } - - pid := makeSearchPidDoubleNetwork(position, userPublicPlatoonDoubleNetworkSetting.SeveralTimes) - - //2、查找对应pid的 user_public_platoon_double_network_relation 记录 - var m1 model.UserPublicPlatoonDoubleNetworkRelation - if has, err := engine.Where("position=?", pid).Get(&m1); err != nil || has == false { - return userPublicPlatoonDoubleNetworkRelation, err - } - var fatherUid string - if m1.FatherUid == "" { - //TODO::顶级 - fatherUid = zhios_order_relate_utils.IntToStr(m1.Position) - } else { - fatherUids := strings.Split(m1.FatherUid, "-") - if len(fatherUids) > userPublicPlatoonDoubleNetworkSetting.SeveralRows { - fatherUid = zhios_order_relate_utils.IntToStr(m1.Position) + "-" + strings.Join(fatherUids[0:userPublicPlatoonDoubleNetworkSetting.SeveralRows:len(fatherUids)], "-") - } else { - fatherUid = zhios_order_relate_utils.IntToStr(m1.Position) + "-" + m1.FatherUid - } - } - - //唯一标识符(父级id-uid-等级-位置) - var uniqueIdentifier = zhios_order_relate_utils.IntToStr(pid) + "-" + zhios_order_relate_utils.IntToStr(uid) + "-" + zhios_order_relate_utils.IntToStr(int(level)) + "-" + zhios_order_relate_utils.IntToStr(position) - // 3、插入 user_public_platoon_double_network_relation 记录 - now := time.Now() - userPublicPlatoonDoubleNetworkRelation.Uid = uid - userPublicPlatoonDoubleNetworkRelation.FatherUid = fatherUid - userPublicPlatoonDoubleNetworkRelation.Pid = pid - userPublicPlatoonDoubleNetworkRelation.RecommendUid = recommendUid - userPublicPlatoonDoubleNetworkRelation.Level = int(level) - userPublicPlatoonDoubleNetworkRelation.Position = position - userPublicPlatoonDoubleNetworkRelation.UniqueIdentifier = uniqueIdentifier - userPublicPlatoonDoubleNetworkRelation.JoinAt = now - userPublicPlatoonDoubleNetworkRelation.CreateAt = now - userPublicPlatoonDoubleNetworkRelation.UpdateAt = now - _, err = db.UserPublicPlatoonDoubleNetworkRelationInsert(engine, &userPublicPlatoonDoubleNetworkRelation) - if err != nil { - return model.UserPublicPlatoonDoubleNetworkRelation{}, err - } - return userPublicPlatoonDoubleNetworkRelation, nil -} - -// reverseDeductionPositionDoubleNetwork 逆向推导 position -func reverseDeductionPositionDoubleNetwork(calcPosition, levelFirstPosition, severalTimes int) (position int) { - remainder := (calcPosition - 1) % severalTimes - position = levelFirstPosition + remainder - return -} - -// getLevelForFirstPositionDoubleNetwork 返回当前等级的起始值 -func getLevelForFirstPositionDoubleNetwork(level, severalTimes int) (position int) { - position = position + 1 - for n := 0; n <= (level - 2); n++ { - position += int(math.Pow(float64(severalTimes), float64(n))) - } - return -} - -// getLevelForLastPositionDoubleNetwork 每个等级的结束值 -func getLevelForLastPositionDoubleNetwork(level, severalTimes int) (position int) { - for n := 0; n <= (level - 1); n++ { - position += int(math.Pow(float64(severalTimes), float64(n))) - } - return -} - -//递归查找等级 -func makeSearchLevelDoubleNetwork(position *int, rows float64, times *float64) (level int) { - difference := *position - int(math.Pow(rows, *times)) - if difference <= 0 { - return int(*times) - } else { - position = &difference - *times++ - return makeSearchLevelDoubleNetwork(position, rows, times) - } -} - -//递归查找等级 -func makeSearchLevelDoubleNetworkByPosition(position *int, rows float64, times *float64) (level int) { - for { - level++ - positionStart := getLevelForFirstPositionDoubleNetwork(level, int(*times)) - positionEnd := getLevelForLastPositionDoubleNetwork(level, int(*times)) - if positionStart <= *position && *position <= positionEnd { - break - } - } - return -} - -//查找归属父级id -func makeSearchPidDoubleNetwork(position int, row int) (pid int) { - divisionValue := (position - 1) / row - if divisionValue == 0 { - pid = 1 - return - } else { - if (divisionValue*row + 1) == position { - pid = divisionValue - return - } else { - pid = divisionValue + 1 - return - } - } -} - -// JudgeUserBelowLevelDoubleNetwork 判断当前用户下几级排满 -func JudgeUserBelowLevelDoubleNetwork(engine *xorm.Engine, uid int) (level int, err error) { - //1、查找 `user_public_platoon_setting` 基础设置 - userPublicPlatoonDoubleNetworkSetting, err := db.UserPublicPlatoonDoubleNetworkSettingGetOneByParams(engine, map[string]interface{}{ - "key": "is_open", - "value": 1, - }) - if err != nil { - return - } - - //2、查找当前用户所在的公排记录 - var m model.UserPublicPlatoonDoubleNetworkRelation - has, err := engine.Where("uid =?", uid).Get(&m) - if err != nil { - return - } - if !has { - err = errors.New("未查询到当前用户的公排记录") - return - } - - //3、查找当前用户下最下级的层数 - var son model.UserPublicPlatoonDoubleNetworkRelation - hasSon, err := engine.Where("father_uid LIKE ?", "%-"+zhios_order_relate_utils.IntToStr(m.Id)). - Or("father_uid LIKE ?", zhios_order_relate_utils.IntToStr(m.Id)+"-%"). - Or("father_uid LIKE ?", "%-"+zhios_order_relate_utils.IntToStr(m.Id)+"-%"). - Or("father_uid = ?", m.Id). - OrderBy("id Desc").Get(&son) - if err != nil { - return - } - if !hasSon { - return - } - - level = son.Level - m.Level - var list []model.UserPublicPlatoonDoubleNetworkRelation - if err = engine.Where("father_uid =?", son.FatherUid). - Find(&list); err != nil { - return - } - - if len(list) == userPublicPlatoonDoubleNetworkSetting.SeveralTimes { - level++ - } - return -} - -// FindRandUserDoubleNetwork 随机查找指定数量用户 -func FindRandUserDoubleNetwork(engine *xorm.Engine, nums int) (resp []int64, err error) { - //1、查找最小、最大 位置的公排位置 - var minM, maxM model.UserPublicPlatoonDoubleNetworkRelation - has, err := engine.Asc("id").Get(&minM) - if err != nil { - return - } - if !has { - err = errors.New("未查询到最小公排记录") - return - } - - has, err = engine.Desc("id").Get(&maxM) - if err != nil { - return - } - if !has { - err = errors.New("未查询到最大公排记录") - return - } - var m model.UserPublicPlatoonDoubleNetworkRelation - count, err := engine.Count(&m) - if err != nil { - return - } - if int(count) < nums { - //TODO::直接查询所有的数据返回即可 - var list []model.UserPublicPlatoonDoubleNetworkRelation - if err1 := engine.Where("1=1"). - Find(&list); err1 != nil { - return nil, zhios_order_relate_logx.Warn(err1) - } - for _, v := range list { - resp = append(resp, int64(v.Uid)) - } - return - nums = int(count) - } - - var uniqueMap = map[int64]bool{} - var j = 0 - for { - ids := randSeedIntDoubleNetwork(int64(minM.Id), int64(maxM.Id), nums-len(resp), uniqueMap, &[]int64{}) - var list []model.UserPublicPlatoonDoubleNetworkRelation - if err1 := engine.In("id", ids). - Find(&list); err1 != nil { - return nil, zhios_order_relate_logx.Warn(err1) - } - - for _, v := range list { - resp = append(resp, int64(v.Uid)) - uniqueMap[int64(v.Id)] = true - } - - if len(resp) == nums { - break - } - - if j == 10 { - //TODO::避免出现死循环 - break - } - j++ - } - - return -} - -func randSeedIntDoubleNetwork(start, end int64, nums int, uniqueMap map[int64]bool, resp *[]int64) (res []int64) { - rand.Seed(time.Now().UnixNano()) - for { - result := rand.Int63n(end) + start - if !uniqueMap[result] { - *resp = append(*resp, result) - uniqueMap[result] = true - break - } - } - - if len(*resp) < nums { - randSeedIntDoubleNetwork(start, end, nums, uniqueMap, resp) - } - res = *resp - return res -} - /* EstimateUserPosition 预估用户位置 total 排名总数 @@ -369,14 +21,14 @@ diffValue 距离上一层级差值 */ func EstimateUserPosition(engine *xorm.Engine, uid int) (total, level, levelRank, rank, previousRow int, diffValue string, err error) { //1、查找 `user_public_platoon_setting` 基础设置 - userPublicPlatoonDoubleNetworkSetting, err := db.UserPublicPlatoonDoubleNetworkSettingGetOneByParams(engine, map[string]interface{}{ + userPublicPlatoonSetting, err := db.UserPublicPlatoonSettingGetOneByParams(engine, map[string]interface{}{ "key": "is_open", "value": 1, }) if err != nil { return } - if userPublicPlatoonDoubleNetworkSetting == nil { + if userPublicPlatoonSetting == nil { return } //2、查询排名 @@ -384,16 +36,16 @@ func EstimateUserPosition(engine *xorm.Engine, uid int) (total, level, levelRank if err != nil { return } - rows := float64(userPublicPlatoonDoubleNetworkSetting.SeveralRows) - times := float64(userPublicPlatoonDoubleNetworkSetting.SeveralTimes) - level = makeSearchLevelDoubleNetworkByPosition(&rank, rows, ×) - levelPosition1 := getLevelForFirstPositionDoubleNetwork(level, userPublicPlatoonDoubleNetworkSetting.SeveralTimes) + rows := float64(userPublicPlatoonSetting.SeveralRows) + times := float64(userPublicPlatoonSetting.SeveralTimes) + level = makeSearchLevelByPosition(&rank, rows, ×) + levelPosition1 := getLevelForFirstPosition(level, userPublicPlatoonSetting.SeveralTimes) levelRank = rank - levelPosition1 + 1 //3、计算与前排差距 previousRow = level - 1 if previousRow > 0 { - previousRowPosition1 := getLevelForLastPositionDoubleNetwork(previousRow, userPublicPlatoonDoubleNetworkSetting.SeveralTimes) + previousRowPosition1 := getLevelForLastPosition(previousRow, userPublicPlatoonSetting.SeveralTimes) previousRowAmount, err1 := GetUserRankAmount(engine, strconv.Itoa(previousRowPosition1)) if err1 != nil { err = err1 @@ -441,7 +93,7 @@ func GetUserRankAmount(engine *xorm.Engine, rank string) (amount string, err err } func ResetPublicPlatoonDoubleNetwork(engine *xorm.Engine, dbName string) (err error) { - //1、查找 `user_public_platoon_setting` 基础设置 + //1、查找 `user_public_platoon_double_network_setting` 基础设置 now := time.Now() userPublicPlatoonDoubleNetworkSetting, err := db.UserPublicPlatoonDoubleNetworkSettingGetOneByParams(engine, map[string]interface{}{ "key": "is_open", @@ -458,16 +110,16 @@ func ResetPublicPlatoonDoubleNetwork(engine *xorm.Engine, dbName string) (err er } //2、计算排名数据 - //sql := "SELECT id, uid, amount, @rank := @rank + 1 AS rank FROM `user_public_platoon_double_network_user_coin_record`, (SELECT @rank:=0) r ORDER BY amount DESC;" - //nativeString, _ := db.QueryNativeString(engine, sql) - //if len(nativeString) <= 0 { - // return errors.New("当前无排名数据") - //} + sql := "SELECT id, uid, amount, @rank := @rank + 1 AS rank FROM `user_public_platoon_double_network_user_coin_record`, (SELECT @rank:=0) r ORDER BY amount DESC;" + nativeString, _ := db.QueryNativeString(engine, sql) + if len(nativeString) <= 0 { + return errors.New("当前无排名数据") + } //for _, v := range nativeString { - // if rank == v["rank"] { - // amount = v["amount"] - // break - // } + // //if rank == v["rank"] { + // // amount = v["amount"] + // // break + // //} //} return } diff --git a/rule/public_platoon_relate_commission.go b/rule/public_platoon_relate_commission.go index a735df2..c5824e2 100644 --- a/rule/public_platoon_relate_commission.go +++ b/rule/public_platoon_relate_commission.go @@ -206,6 +206,19 @@ func makeSearchLevel(position *int, rows float64, times *float64) (level int) { } } +//递归查找等级 +func makeSearchLevelByPosition(position *int, rows float64, times *float64) (level int) { + for { + level++ + positionStart := getLevelForFirstPosition(level, int(*times)) + positionEnd := getLevelForLastPosition(level, int(*times)) + if positionStart <= *position && *position <= positionEnd { + break + } + } + return +} + //查找归属父级id func makeSearchPid(position int, row int) (pid int) { divisionValue := (position - 1) / row