package algo import ( "context" "encoding/json" "fmt" "github.com/go-redis/redis/v8" "github.com/golang/protobuf/proto" uuid "github.com/satori/go.uuid" "hilo-algoCenter/common" "hilo-algoCenter/common/config" "hilo-algoCenter/common/mylogrus" "hilo-algoCenter/cv" "hilo-algoCenter/protocol" "hilo-algoCenter/protocol/userCenter" "hilo-algoCenter/protocol/userProxy" "math/rand" "sort" "strconv" "strings" "time" ) /*const ( match_wait_duration = 10 )*/ //结果 type MatchResult struct { //channelId string User1Id uint64 user1External string //user1Token string User2Id uint64 user2External string //user2Token string Priority float64 //user2Id的质量分数 Excellen float64 //user1Id同user2Id的关系分数 Relation float64 ExcellentRelation float64 } func matchSuccess(c userCenter.UserClient, uids []uint64, msgType uint32, data []byte) error { ctx, cancel := context.WithTimeout(context.Background(), time.Second*3) defer cancel() rsp, err := c.Multicast(ctx, &userCenter.MulticastMessage{ Uids: uids, MsgType: msgType, PayLoad: data, }) if err != nil && rsp == nil { mylogrus.MyLog.Errorf("Multicast message failed %s", err.Error()) } if rsp != nil && len(rsp.FailedUids) > 0 { err = fmt.Errorf("%d users failed", len(rsp.FailedUids)) } return err } func Start(userClient userCenter.UserClient, rdb *redis.Client) { // 秒执行一次 ticker := time.NewTicker(time.Second * 1) go func() { for range ticker.C { go func() { joinNum, matchResults, matchFails, tradeUnionMap, cycleStr, flag := start() if flag { //匹配成功的 for i := 0; i < len(matchResults); i++ { go processMatchSuccess(userClient, matchResults[i], cycleStr, rdb) } //落单的 for i := 0; i < len(matchFails); i++ { go processMatchFail(userClient, matchFails[i], cycleStr, rdb) } //一次匹配中,没有匹配结果,落单的人中,过滤了工会用户,只剩下一个人, var tradeUnionBroadcast uint8 = 2 if len(matchResults) == 0 && len(matchFails) > 0 { mylogrus.MyLog.Infof("match cycle %v, check tradeUnionBroadcast", cycleStr) var n = 0 for i := 0; i < len(matchFails); i++ { if _, ok := tradeUnionMap[strconv.Itoa(int(matchFails[i].User1Id))]; !ok { n++ mylogrus.MyLog.Infof("match cycle %v, check tradeUnionBroadcast add n, n:%v", cycleStr, n) } } mylogrus.MyLog.Infof("match cycle %v, check tradeUnionBroadcast result, n:%v", cycleStr, n) if n == 1 { //redis广播 tradeUnionBroadcast = 1 } } go publishMatchCycle(rdb, protocol.MatchCycle{ MatchCycle: cycleStr, JoinNum: uint32(joinNum), SuccessNum: uint32(len(matchResults) * 2), FailNum: uint32(len(matchFails)), TradeUnionBroadcast: tradeUnionBroadcast, }) } }() } }() } func publishMatchResult(rdb *redis.Client, result protocol.MatchResult) { buf, err := json.Marshal(result) if err != nil { mylogrus.MyLog.Errorf("publishMatchResult json fail:%s", err.Error()) } else { val, err := rdb.Publish(context.Background(), protocol.MatchResultPubSubChannel, string(buf)).Result() if err != nil { mylogrus.MyLog.Errorf("Publish match failed,val:%v, err: %s", val, err.Error()) } else { mylogrus.MyLog.Infof("Publish match succeeded, val = %d", val) } } } func publishMatchCycle(rdb *redis.Client, result protocol.MatchCycle) { buf, err := json.Marshal(result) if err != nil { mylogrus.MyLog.Errorf("json fail:%v", err) } else { val, err := rdb.Publish(context.Background(), protocol.MatchCyclePubSubChannel, string(buf)).Result() if err != nil { mylogrus.MyLog.Errorf("Publish cycle failed,val:%v, err: %s", val, err.Error()) } else { mylogrus.MyLog.Infof("Publish cycle succeeded, val = %d", val) } } } //用户同分数 type UserAndScore struct { userId string score float64 excellen float64 relation float64 sex string isVip bool country string externalId string } type UserPriority struct { userId string score float64 sex string country string externalId string isVip bool } //开始 func start() (int, []MatchResult, []MatchResult, map[string]bool, string, bool) { cycle := (time.Now().Unix() - int64(config.GetMatchConfig().MATCH_CYCLE)) / int64(config.GetMatchConfig().MATCH_CYCLE) cycleStr := strconv.Itoa(int(cycle)) flag, err := SetCycle(cycle) if err != nil { mylogrus.MyLog.Errorf("match cycle %v start setNx err: %v", cycleStr, err) } if flag { mylogrus.MyLog.Infof("match cycle %v start match ", cycleStr) joinNum, matchResult, matchFails, tradeUnionMap := cal(cycle) return joinNum, matchResult, matchFails, tradeUnionMap, cycleStr, true } mylogrus.MyLog.Infof("match cycle %v start has exist", cycleStr) return 0, []MatchResult{}, []MatchResult{}, map[string]bool{}, cycleStr, false } //计算分数 func cal(cycle int64) (int, []MatchResult, []MatchResult, map[string]bool) { matchCycle := InitMatchCycle(cycle) //匹配的结果 var matchResults []MatchResult //已经被匹配的用户 hasMatch := map[string]bool{} //没有匹配到的用户 var noMatch []UserPriority //无序的工会用户 //tradeUnions, tradeUnionMap := initTradeUnion(matchCycle) _, tradeUnionMap := initTradeUnion(matchCycle) //推荐用户 manRecommend, womanRecommend := initRecommend(matchCycle) //Priority是升序排序 userAndScore, userPrioritys, err := initUserAndScore(matchCycle) priorityNum := len(userPrioritys) if err != nil { mylogrus.MyLog.Errorln("match cycle:%v, init userInfo and excellent score err:", matchCycle.GetCycle(), err) } //从高到低排序 sort.Slice(userAndScore, func(i, j int) bool { return userAndScore[i].score > userAndScore[j].score }) mylogrus.MyLog.Infof("match cycle:%v, init userInfo and excellent score success, start match", matchCycle.GetCycle()) //开始循环优先级分数 for i := len(userPrioritys) - 1; i >= 0; i-- { if _, ok := hasMatch[userPrioritys[i].userId]; ok { mylogrus.MyLog.Infof("match cycle:%v, priority userId: %v has bean matched", matchCycle.GetCycle(), userPrioritys[i].userId) continue } mylogrus.MyLog.Infof("match cycle:%v, priority userId: %v,score:%v finding user", matchCycle.GetCycle(), userPrioritys[i].userId, userPrioritys[i].score) // newUserAndScore := copyUserAndScore(userAndScore, userPrioritys) mylogrus.MyLog.Infof("match cycle:%v, priority userId: %v,copy init data", matchCycle.GetCycle(), userPrioritys[i].userId) addRelationScore(matchCycle, userPrioritys[i].userId, newUserAndScore) mylogrus.MyLog.Infof("match cycle:%v, priority userId: %v,cal relation score success", matchCycle.GetCycle(), userPrioritys[i].userId) //进行排序 sort.Slice(newUserAndScore, func(i, j int) bool { return newUserAndScore[i].score > newUserAndScore[j].score }) // var m *MatchResult = nil for j := 0; j < len(newUserAndScore); j++ { flag := matchUser(matchCycle, hasMatch, tradeUnionMap, userPrioritys[i], newUserAndScore[j]) if flag { m = initResult(userPrioritys[i].userId, userPrioritys[i].externalId, newUserAndScore[j].userId, newUserAndScore[j].externalId, userPrioritys[i].score, newUserAndScore[j].excellen, newUserAndScore[j].relation, newUserAndScore[j].score) mylogrus.MyLog.Infof("match cycle:%v, relation userId: %v,otherUserId:%v,match success", matchCycle.GetCycle(), m.User1Id, m.User2Id) break } else { continue } } if m == nil { //user164, _ := strconv.ParseUint(userPrioritys[i].userId, 10, 64) noMatch = append(noMatch, userPrioritys[i]) mylogrus.MyLog.Infof("match cycle:%v, relation userId: %v match fail alone", matchCycle.GetCycle(), userPrioritys[i].userId) } else { // hasMatch[strconv.Itoa(int(m.User1Id))] = true hasMatch[strconv.Itoa(int(m.User2Id))] = true matchResults = append(matchResults, *m) mylogrus.MyLog.Infof("match cycle:%v, relation userId: %v,otherUserId:%v,match success to record", matchCycle.GetCycle(), m.User1Id, m.User2Id) } //移除 userPrioritys = append(userPrioritys[0:i]) } mylogrus.MyLog.Infof("match cycle:%v, relation match end,join user num:%v succes num:%v,single num:%v", matchCycle.GetCycle(), priorityNum, len(matchResults), len(noMatch)) //落单的匹配 singleResults := toSingleMatch(matchCycle, hasMatch, tradeUnionMap, noMatch, manRecommend, womanRecommend) mylogrus.MyLog.Infof("match cycle:%v, all end,join user num:%v succes num:%v,single num:%v", matchCycle.GetCycle(), priorityNum, len(matchResults), len(singleResults)) return priorityNum, matchResults, singleResults, tradeUnionMap } func initResult(user1Id string, user1External string, user2Id string, user2External string, priority float64, excellen float64, relation float64, excellentRelation float64) *MatchResult { user164, _ := strconv.ParseUint(user1Id, 10, 64) user264, _ := strconv.ParseUint(user2Id, 10, 64) return &MatchResult{ User1Id: user164, user1External: user1External, User2Id: user264, user2External: user2External, Priority: priority, Excellen: excellen, Relation: relation, ExcellentRelation: excellentRelation, } } /** * @Description 初始化,推荐信息 * @return 男性用户信息, 女性用户信息 **/ func initRecommend(matchCycle *MatchCycle) ([]UserAndScore, []UserAndScore) { recommendCaches, err := GetRecommendCache() if err != nil { mylogrus.MyLog.Errorf("match cycle:%v, initRecommend fail,err:%v", matchCycle.GetCycle(), err) return []UserAndScore{}, []UserAndScore{} } var manUserAndScore []UserAndScore var womanUserAndScore []UserAndScore r := rand.New(rand.NewSource(time.Now().Unix())) perm := r.Perm(len(recommendCaches)) for _, randIndex := range perm { userAndScore := UserAndScore{ userId: strconv.Itoa(int(recommendCaches[randIndex].UserId)), sex: strconv.Itoa(int(recommendCaches[randIndex].Sex)), country: recommendCaches[randIndex].Country, externalId: recommendCaches[randIndex].ExternalId, } if recommendCaches[randIndex].Sex == 1 { //男性 manUserAndScore = append(manUserAndScore, userAndScore) } else { //女性 womanUserAndScore = append(womanUserAndScore, userAndScore) } } return manUserAndScore, womanUserAndScore } /** * @Description 初始化,工会用户 * @return map[string]bool。是为了防止两个工会用户匹配上 **/ func initTradeUnion(matchCycle *MatchCycle) ([]UserAndScore, map[string]bool) { matchTradeUnionCaches, err := GetMatchTradeUnionCache(matchCycle.GetCycle()) if err != nil { mylogrus.MyLog.Errorf("match cycle:%v, initTradeUnion fail,err:%v", matchCycle.GetCycle(), err) return []UserAndScore{}, map[string]bool{} } else { mylogrus.MyLog.Infof("match cycle:%v, initTradeUnion success, tradeUnionNum:%v", matchCycle.GetCycle(), len(matchTradeUnionCaches)) } userAndScores := make([]UserAndScore, len(matchTradeUnionCaches)) userMap := map[string]bool{} r := rand.New(rand.NewSource(time.Now().Unix())) perm := r.Perm(len(matchTradeUnionCaches)) for i, randIndex := range perm { userAndScores[i] = UserAndScore{ userId: strconv.Itoa(int(matchTradeUnionCaches[randIndex].UserId)), sex: strconv.Itoa(int(matchTradeUnionCaches[randIndex].Sex)), country: matchTradeUnionCaches[randIndex].Country, externalId: matchTradeUnionCaches[randIndex].ExternalId, } userMap[strconv.Itoa(int(matchTradeUnionCaches[randIndex].UserId))] = true } mylogrus.MyLog.Infof("match cycle:%v, initTradeUnion success, num:%v", matchCycle.GetCycle(), len(userAndScores)) return userAndScores, userMap } //初始化,用户同分数, func initUserAndScore(matchCycle *MatchCycle) ([]UserAndScore, []UserPriority, error) { mylogrus.MyLog.Infof("match cycle:%v, initUserAndScore userinfo, excellent score", matchCycle.GetCycle()) //优先级排队的人 zList, err := getPriorityData(matchCycle) if err != nil { mylogrus.MyLog.Errorf("match cycle:%v, initUserAndScore getPriorityData fail,err:%v", matchCycle.GetCycle(), err) return nil, nil, err } mylogrus.MyLog.Infof("match cycle:%v, initUserAndScore getPriorityData success,join num:%v", matchCycle.GetCycle(), len(zList)) mylogrus.MyLog.Infof("match cycle:%v, initUserAndScore print join user:%v", matchCycle.GetCycle(), zList) if len(zList) == 0 { return []UserAndScore{}, []UserPriority{}, nil } //优先级 var uPrioritys []UserPriority //分数 var uList []UserAndScore //用户Ids var userIds []string for i := 0; i < len(zList); i++ { userId := zList[i].Member.(string) uPrioritys = append(uPrioritys, UserPriority{ userId: userId, score: zList[i].Score, }) uList = append(uList, UserAndScore{ userId: userId, }) userIds = append(userIds, userId) } //构建用户性别同国籍 addSexAndCountryVip(matchCycle, uList, uPrioritys, userIds) mylogrus.MyLog.Infof("match cycle:%v, initUserAndScore add sex,country", matchCycle.GetCycle()) //构建质量分数 addExcellentScore(matchCycle, uList) mylogrus.MyLog.Infof("match cycle:%v, initUserAndScore addExcellentScore ", matchCycle.GetCycle()) return uList, uPrioritys, nil } //增加性别 func addSexAndCountryVip(matchCycle *MatchCycle, uList []UserAndScore, uPrioritys []UserPriority, userIds []string) { userCacheMap, err := matchCycle.GetUser(userIds) if err != nil { //打印错误,不处理错误,核心业务,接受容错 mylogrus.MyLog.Errorf("match cycle:%v, addSexAndCountry, err:%v", matchCycle.GetCycle(), err) } for i := 0; i < len(uList); i++ { userCache, ok := userCacheMap[uList[i].userId] if ok { uList[i].sex = strconv.Itoa(int(userCache.Sex)) uList[i].country = userCache.Country uList[i].externalId = userCache.ExternalId uList[i].isVip = userCache.IsVip mylogrus.MyLog.Infof("match cycle:%v, addSexAndCountry success,userId:%v, sex:%v, country:%v, isVip:%v", matchCycle.GetCycle(), uList[i].userId, uList[i].sex, uList[i].country, uList[i].isVip) } } for i := 0; i < len(uPrioritys); i++ { userCache, ok := userCacheMap[uPrioritys[i].userId] if ok { uPrioritys[i].sex = strconv.Itoa(int(userCache.Sex)) uPrioritys[i].country = userCache.Country uPrioritys[i].externalId = userCache.ExternalId uPrioritys[i].isVip = userCache.IsVip mylogrus.MyLog.Infof("match cycle:%v, addSexAndCountry detail,userId:%v, sex:%v, country:%v, isVip:%v", matchCycle.GetCycle(), uPrioritys[i].userId, uPrioritys[i].sex, uPrioritys[i].country, userCache.IsVip) } } } //构建质量分数 func addExcellentScore(matchCycle *MatchCycle, uList []UserAndScore) { zList, err := matchCycle.GetExcellentData() if err != nil { //打印错误,不处理错误,核心业务,接受容错 mylogrus.MyLog.Errorf("match cycle:%v, addExcellentScore, err:%v", matchCycle.GetCycle(), err) } mylogrus.MyLog.Infof("match cycle:%v, addExcellentScore success userNum:%v, joinNum:%v", matchCycle.GetCycle(), len(zList), len(uList)) excellentScoreMap := map[string]float64{} for _, v := range zList { excellentScoreMap[v.Member.(string)] = v.Score } // for i := 0; i < len(uList); i++ { f, ok := excellentScoreMap[uList[i].userId] if ok { uList[i].excellen = f uList[i].score = f mylogrus.MyLog.Infof("match cycle:%v, addExcellentScore detail,userId:%v, score:%v", matchCycle.GetCycle(), uList[i].userId, uList[i].score) } } } //计算,质量分数 + 关系分数 func addRelationScore(matchCycle *MatchCycle, userId string, u []UserAndScore) { if len(u) == 0 { return } relationScoreMap, err := getRelationData(matchCycle, userId) if err != nil { mylogrus.MyLog.Errorf("match cycle:%v, addRelationScore err:%v", matchCycle.GetCycle(), err) return } for i := 0; i < len(u); i++ { f, ok := relationScoreMap[u[i].userId] if ok { u[i].relation = f u[i].score = u[i].score + f mylogrus.MyLog.Infof("match cycle:%v, addRelationScore detail userId: %v, relation otherUserId:%v,score:%v", matchCycle.GetCycle(), userId, u[i].userId, f) } } } //落单,没有匹配成功的 func processMatchFail(userClient userCenter.UserClient, val MatchResult, matchCycle string, rdb *redis.Client) { user2Info, _ := cv.GetOtherUserInfo(val.User1Id, val.User2Id) msg := &userProxy.MatchSuccess{ LocalUserId: val.user1External, RemoteUserId: val.user2External, WaitDuration: config.GetMatchConfig().MATCH_SUCCESS_WAIT_DURATION, MatchUniqueId: strings.Replace(uuid.NewV4().String(), "-", "", -1), Status: false, SingleWaitTimeInSec: config.GetMatchConfig().MATCH_SUCCESS_SINGLE_WAIT_TIME_IN_SEC, DualWaitTimeInSec: config.GetMatchConfig().MATCH_SUCCESS_DUAL_WAIT_TIME_IN_SEC, RemoteUser: user2Info, } if buffer, err := proto.Marshal(msg); err == nil { rPcErr := "" matchSuccess(userClient, []uint64{val.User1Id}, common.MsgTypeMatchSuccess, buffer) // todo for updating if err = matchSuccess(userClient, []uint64{val.User1Id}, common.MsgTypeMatchV2Success, buffer); err == nil { mylogrus.MyLog.Infof("match cycle:%v, match result sent msg success, single LocalUserId:%v, RemoteUserId %v\n", matchCycle, msg.LocalUserId, msg.RemoteUserId) } else { mylogrus.MyLog.Errorf("match cycle:%v, match result sent msg fail, single LocalUserId:%v, RemoteUserId %v\n", matchCycle, msg.LocalUserId, msg.RemoteUserId) rPcErr = err.Error() } go publishMatchResult(rdb, protocol.MatchResult{ MatchCycle: matchCycle, MatchUniqueId: msg.MatchUniqueId, User1Id: val.User1Id, User2Id: val.User2Id, Status: false, Priority: val.Priority, Excellen: val.Excellen, Relation: val.Relation, ExcellentRelation: val.ExcellentRelation, RpcStatus: err == nil, RPcErr: rPcErr, }) } } //发布匹配成功 func processMatchSuccess(userClient userCenter.UserClient, val MatchResult, matchCycle string, rdb *redis.Client) { mylogrus.MyLog.Infof("Processing %v\n", val) uids := []uint64{val.User1Id} user1Info, _ := cv.GetOtherUserInfo(val.User2Id, val.User1Id) user2Info, _ := cv.GetOtherUserInfo(val.User1Id, val.User2Id) msg := &userProxy.MatchSuccess{ LocalUserId: val.user1External, RemoteUserId: val.user2External, WaitDuration: config.GetMatchConfig().MATCH_SUCCESS_WAIT_DURATION, MatchUniqueId: strings.Replace(uuid.NewV4().String(), "-", "", -1), Status: true, SingleWaitTimeInSec: config.GetMatchConfig().MATCH_SUCCESS_SINGLE_WAIT_TIME_IN_SEC, DualWaitTimeInSec: config.GetMatchConfig().MATCH_SUCCESS_DUAL_WAIT_TIME_IN_SEC, RemoteUser: user2Info, } ok1 := false ok2 := false if buffer, err := proto.Marshal(msg); err == nil { matchSuccess(userClient, uids, common.MsgTypeMatchSuccess, buffer) // todo for updating if err = matchSuccess(userClient, uids, common.MsgTypeMatchV2Success, buffer); err == nil { mylogrus.MyLog.Infof("match cycle:%v, match result sent msg begin LocalUserId:%v, RemoteUserId:%v, LocalUserId:%v, RemoteUserId:%v\n", matchCycle, msg.LocalUserId, msg.RemoteUserId, val.User1Id, val.User2Id) ok1 = true // 交换数据 uids[0] = val.User2Id msg.LocalUserId = val.user2External msg.RemoteUserId = val.user1External msg.RemoteUser = user1Info if buffer, err = proto.Marshal(msg); err == nil { matchSuccess(userClient, uids, common.MsgTypeMatchSuccess, buffer) // todo for updating if err = matchSuccess(userClient, uids, common.MsgTypeMatchV2Success, buffer); err == nil { ok2 = true mylogrus.MyLog.Infof("match cycle:%v, match result sent msg success LocalUserId:%v, RemoteUserId:%v, LocalUserId:%v, RemoteUserId:%v\n", matchCycle, msg.LocalUserId, msg.RemoteUserId, val.User1Id, val.User2Id) } } } rpcErr := "" if err != nil { rpcErr = err.Error() } //redis广播 go publishMatchResult(rdb, protocol.MatchResult{ MatchCycle: matchCycle, MatchUniqueId: msg.MatchUniqueId, User1Id: val.User1Id, User2Id: val.User2Id, Status: true, Priority: val.Priority, Excellen: val.Excellen, Relation: val.Relation, ExcellentRelation: val.ExcellentRelation, RpcStatus: ok1 && ok2, RPcErr: rpcErr, }) if !ok1 { mylogrus.MyLog.Errorf("match cycle:%v, match result sent msg fail user", val.User1Id) } if !ok2 { mylogrus.MyLog.Errorf("match cycle:%v, match result sent msg fail user", val.User2Id) } } } //获取匹配优先级 func getPriorityData(matchCycle *MatchCycle) ([]redis.Z, error) { zList, err := matchCycle.GetPriorityData() if err != nil { return nil, err } return zList, nil } //获取关系分数 func getRelationData(matchCycle *MatchCycle, userId string) (map[string]float64, error) { relations, err := matchCycle.GetRelationData(userId) if err != nil { return map[string]float64{}, err } m := map[string]float64{} for _, v := range relations { m[strconv.Itoa(int(v.RelationUserId))] = v.Score } return m, nil } //复制内容 func copyUserAndScore(list []UserAndScore, userPrioritys []UserPriority) []UserAndScore { userIdMap := map[string]bool{} for i := 0; i < len(userPrioritys); i++ { userIdMap[userPrioritys[i].userId] = true } var u []UserAndScore for i := 0; i < len(list); i++ { if _, ok := userIdMap[list[i].userId]; ok { u = append(u, list[i]) } } return u } //检查要匹配的用户 func matchUser(matchCycle *MatchCycle, hasMatch map[string]bool, tradeUnionMap map[string]bool, user UserPriority, otherUser UserAndScore) bool { if user.userId == otherUser.userId { mylogrus.MyLog.Infof("match cycle:%v, relation userId: %v,otherUserId:%v myself,skip", matchCycle.GetCycle(), user.userId, otherUser.userId) return false } //是否存在已匹配中 if _, ok := hasMatch[otherUser.userId]; ok { mylogrus.MyLog.Infof("match cycle:%v, relation userId: %v,otherUserId:%v has been match", matchCycle.GetCycle(), user.userId, otherUser.userId) return false } //是否均为工会用户 _, ok1 := tradeUnionMap[user.userId] _, ok2 := tradeUnionMap[otherUser.userId] if ok1 && ok2 { mylogrus.MyLog.Infof("match cycle:%v, relation userId: %v,otherUserId:%v both in tradeUnion", matchCycle.GetCycle(), user.userId, otherUser.userId) return false } //判断是否存在拉黑 flag, err := matchCycle.CheckBlock(user.userId, otherUser.userId) if err != nil { mylogrus.MyLog.Errorf("match cycle:%v, relation userId: %v,otherUserId:%v, check black ,err:%v", matchCycle.GetCycle(), user.userId, otherUser.userId, err) return false } //存在拉黑 if flag { mylogrus.MyLog.Infof("match cycle:%v, relation userId: %v,otherUserId:%v, has black, skip", matchCycle.GetCycle(), user.userId, otherUser.userId) return false } //存在条件搜索 sex1, err := matchCycle.GetConditionSex(user.userId) if err != nil { mylogrus.MyLog.Errorf("match cycle:%v, relation userId: %v,get match condition sex ,err:%v", matchCycle.GetCycle(), user.userId, err) return false } country1, err := matchCycle.GetConditionCountry(user.userId) if err != nil { mylogrus.MyLog.Errorf("match cycle:%v, relation userId: %v,get match condition country,err:%v", matchCycle.GetCycle(), user.userId, err) return false } //另一个人的条件刷选 sex2, err := matchCycle.GetConditionSex(otherUser.userId) if err != nil { mylogrus.MyLog.Errorf("match cycle:%v, relation userId: %v,get match condition sex,err:%v", matchCycle.GetCycle(), otherUser.userId, err) return false } country2, err := matchCycle.GetConditionCountry(otherUser.userId) if err != nil { mylogrus.MyLog.Errorf("match cycle:%v, relation userId: %v,get match condition country,err:%v", matchCycle.GetCycle(), otherUser.userId, err) return false } mylogrus.MyLog.Infof("match cycle:%v, relation userId: %v, tradeUnion:%v, isVip:%v, condition(sex:%v, country:%v) myself(:sex:%v, country:%v )"+ ",otherUserId:%v ,tradeUnion:%v, isVip:%v,condition(sex:%v, country:%v) otherUserSelf(:sex:%v, country:%v)", matchCycle.GetCycle(), user.userId, tradeUnionMap[user.userId], user.isVip, sex1, country1, user.sex, user.country, otherUser.userId, tradeUnionMap[otherUser.userId], otherUser.isVip, sex2, country2, otherUser.sex, otherUser.country) //需求,2022/03/07 需求增加公会用户只能与VIP用户进行匹配 /* if flag := tradeUnionMap[user.userId]; flag { //公会用户, 匹配上是非vip if !otherUser.isVip { mylogrus.MyLog.Infof("match cycle:%v, relation userId: %v,otherUserId:%v,condition tradeUnion not vip", matchCycle.GetCycle(), user.userId, otherUser.userId) return false } } if flag := tradeUnionMap[otherUser.userId]; flag { //公会用户, 匹配上是非vip if !user.isVip { mylogrus.MyLog.Infof("match cycle:%v, relation userId: %v,otherUserId:%v,condition tradeUnion not vip", matchCycle.GetCycle(), user.userId, otherUser.userId) return false } }*/ if sex1 == "" && country1 == "" && sex2 == "" && country2 == "" { // mylogrus.MyLog.Infof("match cycle:%v, relation userId: %v,otherUserId:%v,all not conditon, match success", matchCycle.GetCycle(), user.userId, otherUser.userId) //m = initResult(user.userId, user.externalId, otherUser.userId, otherUser.externalId) mylogrus.MyLog.Infof("match cycle:%v, relation userId: %v,otherUserId:%v,match success", matchCycle.GetCycle(), user.userId, otherUser.userId) return true } if sex1 != "" && sex1 != otherUser.sex { mylogrus.MyLog.Infof("match cycle:%v, relation userId: %v,otherUserId:%v,condition sex not match", matchCycle.GetCycle(), user.userId, otherUser.userId) return false } if sex2 != "" && sex2 != user.sex { mylogrus.MyLog.Infof("match cycle:%v, relation 用户userId: %v,otherUserId:%v,condition sex not match", matchCycle.GetCycle(), user.userId, otherUser.userId) return false } if country1 != "" && country1 != otherUser.country { mylogrus.MyLog.Infof("match cycle:%v, relation userId: %v,otherUserId:%v,condition country not match", matchCycle.GetCycle(), user.userId, otherUser.userId) return false } if country2 != "" && country2 != user.country { mylogrus.MyLog.Infof("match cycle:%v, relation userId: %v,otherUserId:%v,condition country not match", matchCycle.GetCycle(), user.userId, otherUser.userId) return false } return true } //func toSingleMatch(matchCycle *myredis.MatchCycle, hasMatch map[string]bool, tradeUnionMap map[string]bool, noMatch []UserPriority, tradeUnions []UserAndScore) []MatchResult { func toSingleMatch(matchCycle *MatchCycle, hasMatch map[string]bool, tradeUnionMap map[string]bool, noMatch []UserPriority, manRecommon []UserAndScore, womanRecommon []UserAndScore) []MatchResult { var singleResults []MatchResult for i := 0; i < len(noMatch); i++ { var singleM *MatchResult = nil //如果是公会用户,不能匹配离线用户 _, ok := tradeUnionMap[noMatch[i].userId] if !ok { //不断的遍历。利用hasMath来控制,重复匹配的 //如果是男性, 有限匹配女性 if noMatch[i].sex == "1" { for j := 0; j < len(womanRecommon); j++ { flag := matchUser(matchCycle, hasMatch, tradeUnionMap, noMatch[i], womanRecommon[j]) if flag { singleM = initResult(noMatch[i].userId, noMatch[i].externalId, womanRecommon[j].userId, womanRecommon[j].externalId, noMatch[i].score, 0, 0, 0) //找到了就退出 break } else { continue } } //找不到 if singleM == nil { for j := 0; j < len(manRecommon); j++ { flag := matchUser(matchCycle, hasMatch, tradeUnionMap, noMatch[i], manRecommon[j]) if flag { singleM = initResult(noMatch[i].userId, noMatch[i].externalId, manRecommon[j].userId, manRecommon[j].externalId, noMatch[i].score, 0, 0, 0) //找到了就退出 break } else { continue } } } } else { for j := 0; j < len(manRecommon); j++ { flag := matchUser(matchCycle, hasMatch, tradeUnionMap, noMatch[i], manRecommon[j]) if flag { singleM = initResult(noMatch[i].userId, noMatch[i].externalId, manRecommon[j].userId, manRecommon[j].externalId, noMatch[i].score, 0, 0, 0) //找到了就退出 break } else { continue } } if singleM == nil { for j := 0; j < len(womanRecommon); j++ { flag := matchUser(matchCycle, hasMatch, tradeUnionMap, noMatch[i], womanRecommon[j]) if flag { singleM = initResult(noMatch[i].userId, noMatch[i].externalId, womanRecommon[j].userId, womanRecommon[j].externalId, noMatch[i].score, 0, 0, 0) //找到了就退出 break } else { continue } } } } } /* for j := 0; j < len(tradeUnions); j++ { flag := matchUser(matchCycle, hasMatch, tradeUnionMap, noMatch[i], tradeUnions[j]) if flag { singleM = initResult(noMatch[i].userId, noMatch[i].externalId, tradeUnions[j].userId, tradeUnions[j].externalId, noMatch[i].score, 0, 0, 0) } else { continue } }*/ if singleM != nil { hasMatch[strconv.Itoa(int(singleM.User1Id))] = true hasMatch[strconv.Itoa(int(singleM.User2Id))] = true singleResults = append(singleResults, *singleM) mylogrus.MyLog.Infof("match cycle:%v, single userId: %v,otherUserId:%v,match success to record", matchCycle.GetCycle(), singleM.User1Id, singleM.User2Id) } else { user164, _ := strconv.ParseUint(noMatch[i].userId, 10, 64) singleM = &MatchResult{ User1Id: user164, user1External: noMatch[i].externalId, Priority: noMatch[i].score, } hasMatch[strconv.Itoa(int(singleM.User1Id))] = true singleResults = append(singleResults, *singleM) mylogrus.MyLog.Infof("match cycle:%v, singel userId: %v match fail alone", matchCycle.GetCycle(), singleM.User1Id) } } return singleResults }