浏览代码

Merge branch 'dev3.2' of ssh://192.168.3.207:10022/qmx/jy-data-extract into dev3.2

wcj 6 年之前
父节点
当前提交
3decc0b667

+ 3 - 254
udpprojectset/src/compare.go

@@ -1,13 +1,11 @@
 package main
 
 import (
-	"log"
 	"qfw/util"
 	"qfw/util/redis"
 	"regexp"
 	"sort"
 	"strings"
-	"sync"
 	"time"
 
 	"gopkg.in/mgo.v2/bson"
@@ -65,9 +63,8 @@ type CompareOne struct {
 }
 
 type CompareInfo struct {
-	Field string //对比属性 pn/pc/pb
-	Key   string //存放rediskey
-	//Pinfo  []ProjectInfo //存放redis对象
+	Field  string        //对比属性 pn/pc/pb
+	Key    string        //存放rediskey
 	Scores []*CompareOne //对比分值 pinfo索引对应分值
 	Bfind  bool          //是否查找到
 	IdArr  []string
@@ -88,110 +85,6 @@ func NewCompareInfo(field, key string, KeyMap *KeyMap) *CompareInfo {
 var numreg2 = regexp.MustCompile("^[0-9]+$")
 var TitleReg = regexp.MustCompile("([一二三四五六七八九十0-9A-Za-zⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ、\\-~至]+(子|合同|分|施工|监理|标)?[包标段][号段]?[、]?)+|((子|合同|分|施工|监理|标)?[包标段][号段]?[一二三四五六七八九十0-9A-Za-zⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ、\\-~至]+[、]?)+|(子|合同|分|施工|监理|标)?[包标段][号段]?[a-zA-Z0-9]+[\\-~-至、](子|合同|分|施工|监理|标)?[包标段][号段]?[a-zA-Z0-9]+")
 
-//对比打分程序
-func Compare(tmp map[string]interface{} /*新信息*/, pici int64) (sflag string) {
-	defer util.Catch()
-	thisinfo := PreThisInfo(tmp) //信息预处理
-	if thisinfo == nil {
-		return
-	}
-	var PN, PC, PB *CompareInfo
-	new_pn, _ := handleprojectname(thisinfo.ProjectName, thisinfo.Buyer, thisinfo.TopType) //作为判断依据
-	if thisinfo.ProjectName != "" {
-		KEY := "pn_" + new_pn
-		PN = NewCompareInfo("pn", KEY, PNKey)
-	}
-	if len(thisinfo.ProjectCode) > 5 && !numreg.MatchString(thisinfo.ProjectCode) { //大于5且不是纯数字bfind
-		KEY := "pc_" + thisinfo.ProjectCode
-		PC = NewCompareInfo("pc", KEY, PCKey)
-	}
-	if len([]rune(thisinfo.Buyer)) > 4 {
-		KEY := "pb_" + thisinfo.Buyer
-		PB = NewCompareInfo("pb", KEY, PBKey)
-	}
-	repeatId := map[string]bool{}
-	IdLock.Lock()
-	//此处加id锁,会引进多线程的死锁,对比三个大map数组,找到key相同的项目id数组,并去重
-	for _, PNCB := range []*CompareInfo{PN, PC, PB} {
-		if PNCB != nil {
-			PNCB.KeyMap.Lock.Lock()
-			K := PNCB.KeyMap.Map[PNCB.Key]
-			if K == nil {
-				K = &Key{&[]string{}, &sync.Mutex{}}
-				PNCB.KeyMap.Map[PNCB.Key] = K
-			}
-			PNCB.K = K
-			PNCB.K.Lock.Lock()
-			PNCB.KeyMap.Lock.Unlock()
-			defer PNCB.K.Lock.Unlock()
-			newarr := []string{}
-			for _, id := range *K.Arr {
-				if !repeatId[id] {
-					newarr = append(newarr, id)
-					repeatId[id] = true
-				}
-			}
-			PNCB.IdArr = newarr
-		}
-	}
-	IdLock.Unlock()
-	updateid, ncid := "", ""
-	tmpArr := []*CompareOne{}
-	//三个对比对象分别和thisinfo比较,打完分的对象放入scores,合并放入tempArr
-	for _, PNCB := range []*CompareInfo{PN, PC, PB} {
-		if PNCB != nil {
-			if len(PNCB.IdArr) > 0 {
-				//PNCB.compute(thisinfo, PNCB.IdArr)
-				ncid = PNCB.ProcessInfo(new_pn, tmp, pici, thisinfo)
-				tmpArr = append(tmpArr, PNCB.Scores...)
-			}
-		}
-	}
-	if ncid == "" {
-		//排序取出最大分值的对象,更新对象
-		if len(tmpArr) > 0 {
-			sort.Slice(tmpArr, func(i, j int) bool {
-				return tmpArr[i].Score > tmpArr[j].Score
-			})
-			max := tmpArr[0]
-			if max.Score > 0 {
-				//获取到对象
-				max.Parent.Bfind = true
-				tmp["cresult"] = max.Cresult
-				updateid = updateinfo(thisinfo, tmp, max.Pinfo, pici)
-				//log.Println("更新项目", updateid)
-			}
-		}
-		if updateid == "" {
-			sflag = "normal"
-			updateid = InsertProject(new_pn, tmp, nil, pici, thisinfo)
-			p1 := NewPinfo(updateid, thisinfo)
-			redis.PutCKV(REDISIDS, updateid, p1)
-			//log.Println("生成项目", updateid)
-		} else {
-			sflag = "repeat"
-		}
-		//更新redis中存入的三大map对象中的id
-		if updateid != "" {
-			PUT := []interface{}{}
-			for _, PNCB := range []*CompareInfo{PN, PC, PB} {
-				if PNCB != nil && !PNCB.Bfind {
-					if BinarySearch(*PNCB.K.Arr, updateid) == -1 {
-						*(PNCB.K.Arr) = append(*(PNCB.K.Arr), updateid)
-						PUT = append(PUT, []interface{}{PNCB.Key, *(PNCB.K.Arr)})
-					}
-				}
-			}
-			if len(PUT) > 0 {
-				redis.BulkPut(REDISKEYS, 0, PUT...)
-			}
-		}
-	} else {
-		log.Println("无效项目", ncid)
-	}
-	return
-}
-
 //没有在redis中查找到,新增项目
 func InsertProject(new_pn string, tmp, mess map[string]interface{}, pici int64, thisinfo *Info) string {
 	e := InitEL("")
@@ -225,14 +118,8 @@ func InsertProject(new_pn string, tmp, mess map[string]interface{}, pici int64,
 		set["winnerorder"] = thisinfo.Winnerorder
 	}
 	s_subscopeclass := strings.Join(thisinfo.Subscopeclass, ",")
-	//	if len(s_subscopeclass) > 0 {
-	//		s_subscopeclass = "," + s_subscopeclass + ","
-	//	}
 	set["s_subscopeclass"] = s_subscopeclass
 	s_winner := strings.Join(thisinfo.Winners, ",")
-	//	if len(s_winner) > 0 {
-	//		s_winner = "," + s_winner + ","
-	//	}
 	set["s_winner"] = s_winner
 	if tmp["package"] != nil {
 		set["package"] = tmp["package"] //没定义优先级
@@ -246,7 +133,7 @@ func InsertProject(new_pn string, tmp, mess map[string]interface{}, pici int64,
 	set["list"] = []bson.M{
 		push,
 	}
-	if mess != nil { //不参与对比项目标识
+	if mess != nil { //项目标识
 		for k, v := range mess {
 			set[k] = v
 		}
@@ -509,144 +396,6 @@ func EqInfoUpdate(thisinfo *Info, pInfo *ProjectInfo) {
 	//return pInfo
 }
 
-/**
-func (com *CompareInfo) compute(thisinfo *Info, ids []string) {
-	//根据 com的key到redis中查找对应的值(如:项目名称的key为"pn_某某项目",值为一维对象数组 即:[]ProjectInfo)
-	//这些信息id上面已经加过锁
-	defer util.Catch()
-	res := redis.Mget(REDISIDS, ids)
-	//redis.GetInterface("other", com.Key, &com.Pinfo)
-	//redispush := false
-	if len(res) > 0 { //找到项目名称、项目编号或采购单位相同时
-		for _, b1 := range res { //遍历对象数组
-			if b1 != nil {
-				var info ProjectInfo
-				err := json.Unmarshal(b1.([]byte), &info)
-				if err != nil {
-					log.Println(err)
-				}
-				cone := &CompareOne{
-					Parent: com,
-					Pinfo:  &info,
-				}
-				if com.Field != "pn" { //比较字段不是项目名称时,对项目名称要素的打分逻辑
-					//新信息和对比信息的项目名称长度都大于5时
-					if len([]rune(thisinfo.ProjectName)) > 5 && len([]rune(info.ProjectName)) > 5 {
-						if thisinfo.ProjectName == info.ProjectName { //绝对相等加5分
-							cone.ProjectNameType = 1
-							cone.Score += 5
-						} else if strings.Index(info.ProjectName, thisinfo.ProjectName) > -1 || strings.Index(thisinfo.ProjectName, info.ProjectName) > -1 { //包含或被包含关系不加分不减分
-							cone.ProjectNameType = 2
-							//cone.Score += 3
-						} else { //不相等且不包含减5分
-							cone.ProjectNameType = 3
-							cone.Score -= 10
-						}
-					}
-				}
-				if com.Field != "pc" { //比较字段不是项目编号时,对项目编号要素的打分逻辑
-					//新信息和对比信息和项目编号长度大于5
-					if len(thisinfo.ProjectCode) > 5 && len(info.ProjectCode) > 5 {
-						if thisinfo.ProjectCode == info.ProjectCode { //项目编号相等加5分
-							cone.ProjectCodeType = 1
-							cone.Score += 5
-						} else if strings.Index(info.ProjectCode, thisinfo.ProjectCode) > -1 || strings.Index(thisinfo.ProjectCode, info.ProjectCode) > -1 { //包含或被包含关系加3分
-							cone.ProjectCodeType = 2
-							cone.Score += 3
-						} else {
-							//不相等减5分
-							cone.ProjectCodeType = 3
-							cone.Score -= 5
-							if len(thisinfo.ProjectCode) == len(info.ProjectCode) { //值不相等但长度相等减20分
-								cone.Score -= 20
-							}
-						}
-					}
-				}
-				if com.Field != "pb" { //比较字段不是采购单位时,对采购单位要素的打分逻辑
-					//采购单位大于4个字时做比较
-					if len(thisinfo.Buyer) > 12 && len(info.Buyer) > 12 {
-						if thisinfo.Buyer == info.Buyer { //相等加5分
-							cone.BuyerType = 1
-							cone.Score += 5
-						} else if strings.Index(thisinfo.Buyer, info.Buyer) > -1 || strings.Index(info.Buyer, thisinfo.Buyer) > -1 { //包含与被包含加3分
-							cone.BuyerType = 2
-							cone.Score += 3
-						} else { //不相等减5分
-							cone.BuyerType = 3
-							cone.Score -= 5
-						}
-					}
-				}
-				//对发布时间打分,两者信息发布时间在120天以内加2分
-				if math.Abs(float64(thisinfo.Publishtime-info.Publistime[0])) < 120*86400 && math.Abs(float64(thisinfo.Publishtime-info.Publistime[len(info.Publistime)-1])) < 120*86400 {
-					cone.PublistimeType = 1
-					//cone.Score += 2
-				} else { //发布时间相差超过120天减5分
-					cone.PublistimeType = 2
-					cone.Score -= 5
-				}
-
-				//对招标机构进行打分
-				//招标机构长度大于4分字时做比较
-				if len(thisinfo.Agency) > 12 && len(info.Agency) > 12 {
-					if thisinfo.Agency == info.Agency { //相等加3分
-						cone.AgencyType = 1
-						cone.Score += 3
-					} else if strings.Index(thisinfo.Agency, info.Agency) > -1 || strings.Index(info.Agency, thisinfo.Agency) > -1 { //包含关系不加分
-						cone.AgencyType = 2
-					} else { //不相等减5分
-						cone.AgencyType = 3
-						cone.Score -= 5
-					}
-				}
-				//对地区进行打分,地区都不为空,且范围都不是全国时做比较
-				if thisinfo.Area != "" && info.Area != "" && thisinfo.Area != "A" && thisinfo.Area != "全国" && info.Area != "A" && info.Area != "全国" {
-					if thisinfo.Area == info.Area { //地区相同不加分
-						cone.AreaType = 1
-					} else { //地区不同减5分
-						cone.AreaType = 2
-						cone.Score -= 5
-					}
-				}
-				//分包类型相同时
-				if thisinfo.HasPackage == info.HasPackage {
-					if thisinfo.HasPackage {
-						cone.PackageType = 1
-					} else { //都不是多包
-						cone.PackageType = 2
-					}
-					//都是分包或都不是分包加4分
-					cone.Score += 4
-				} else { //分包不一致时
-					if thisinfo.TopType == "招标" { //新信息类型为招标时
-						if thisinfo.HasPackage && len(thisinfo.Package) == 1 { //当前信息是招标类,且是一个包,对比信息不是分包,认为它们都不是分包,加2分
-							cone.PackageType = 3
-							cone.Score += 2
-						} else if !thisinfo.HasPackage { //当前信息不是分包,合并信息是分包(要从标题中查找),不加分不减分
-							cone.PackageType = 31
-						} else { //当前信息是分包,合并信息不是分包,不加减分
-							cone.PackageType = 32
-						}
-					} else if thisinfo.TopType == "结果" { //新信息类型为结果时
-						if thisinfo.HasPackage && len(thisinfo.Package) == 1 { //从标题中查找有没有分包 ,当前信息结果类是一个分包,合并信息不是分包,加2分
-							cone.PackageType = 4
-							cone.Score += 2
-						} else if !thisinfo.HasPackage { //当前信息是结果,不是分包,而合并信息是分包,不加分
-							cone.PackageType = 41
-						} else {
-							cone.PackageType = 42 //当前信息是分包,而合并信息不是分包,不加减分
-						}
-					}
-				}
-				//cone.Pos = k
-				//放入打分数组中
-				com.Scores = append(com.Scores, cone)
-			}
-		}
-	}
-}
-**/
 //二分字符串查找
 func BinarySearch(s []string, k string) int {
 	sort.Strings(s)

+ 11 - 7
udpprojectset/src/config.json

@@ -1,22 +1,26 @@
 {
     "mongodbServers": "192.168.3.207:27082",
-    "mongodbPoolSize": 100,
-    "mongodbName": "qfw",
+    "mongodbPoolSize": 10,
+    "mongodbName": "extract_v3",
     "jkmail": {
-        "to": "renzheng@topnet.net.cn",
+        "to": "zhangjinkun@topnet.net.cn",
         "api": "http://10.171.112.160:19281/_send/_mail"
     },
-    "thread": 300,
-    "extractColl": "extract_v2.0",
+    "thread": 30,
+    "extractColl": "bidding20190423",
     "projectColl": "projectset",
     "lenprojectname": 18,
-    "redisPoolSize": 300,
-    "redisaddrs": "ids=192.168.3.207:3379,keys=192.168.3.207:3378,info=192.168.3.207:3378",
+    "redisPoolSize": 60,
+    "redisaddrs": "ids=127.0.0.1:6379,keys=127.0.0.1:6379,info=127.0.0.1:6379",
     "clearedis": {
         "open": true,
         "clearcron": "0 10 15 ? * 4",
         "projectcycle": 180
     },
+    "megerfields": {
+        "projectlen": 5,
+        "projectcodelen": 8
+    },
     "udpport": ":1482",
     "nextNode": [
         {

+ 54 - 54
udpprojectset/src/main.go

@@ -3,12 +3,10 @@ package main
 import (
 	"encoding/json"
 	"fmt"
+	du "jy/util"
 	"log"
-	//"math"
 	mu "mfw/util"
 	"net"
-	//"os"
-	du "jy/util"
 	"qfw/util"
 	"qfw/util/mongodb"
 	"qfw/util/redis"
@@ -18,12 +16,13 @@ import (
 	"gopkg.in/mgo.v2/bson"
 )
 
-/*
-从extract_result表中抽到projectset表中,根据3选2判断是不是同一条信息,抽取信息至少有两个字段。
-可以使用redis
-//对时间的判断
-*/
-var MultiThread chan bool
+const (
+	REDISIDS    = "ids"
+	REDISKEYS   = "keys"
+	INFOID      = "info"
+	INFOTIMEOUT = 86400 * 30
+)
+
 var (
 	Sysconfig                map[string]interface{}
 	MQFW                     mongodb.MongodbSim
@@ -32,14 +31,36 @@ var (
 	udpclient                mu.UdpClient             //udp对象
 	nextNode                 []map[string]interface{} //下节点数组
 	toaddr                   = []*net.UDPAddr{}       //下节点对象
+	MultiThread              chan bool
+	SingleThread             = make(chan bool, 1) //udp调用
+	IdLock                   = &sync.Mutex{}
+	PncbMayLock              = &sync.Mutex{}
+	MegerFieldsLen           *MegerFields
+	//三组lock,对应的(PNKey)key为项目名称,值对应的是此项目名称对应的项目id数组
+	PNKey, PCKey, PBKey          = NewKeyMap(), NewKeyMap(), NewKeyMap()
+	PNKeyMap, PCKeyMap, PBKeyMap = sync.Map{}, sync.Map{}, sync.Map{}
 )
 
-const (
-	REDISIDS    = "ids"
-	REDISKEYS   = "keys"
-	INFOID      = "info"
-	INFOTIMEOUT = 86400 * 30
-)
+type MegerFields struct {
+	ProjectNamelen int
+	ProjectCodelen int
+}
+
+type KeyMap struct {
+	Lock sync.Mutex
+	Map  map[string]*Key
+}
+
+type Key struct {
+	Arr  *[]string
+	Lock *sync.Mutex
+}
+
+func NewKeyMap() *KeyMap {
+	return &KeyMap{
+		Map: map[string]*Key{},
+	}
+}
 
 func init() {
 	initarea()
@@ -49,6 +70,11 @@ func init() {
 	util.ReadConfig(&Sysconfig)
 	MultiThread = make(chan bool, util.IntAllDef(Sysconfig["thread"], 200))
 	lenprojectname = util.IntAllDef(Sysconfig["lenprojectname"], 20) - 1
+	megerfields, _ := Sysconfig["megerfields"].(map[string]interface{})
+	MegerFieldsLen = &MegerFields{
+		ProjectNamelen: util.IntAllDef(megerfields["projectlen"], 5),
+		ProjectCodelen: util.IntAllDef(megerfields["projectcodelen"], 8),
+	}
 	redis.InitRedisBySize(Sysconfig["redisaddrs"].(string), util.IntAllDef(Sysconfig["redisPoolSize"], 100), 30, 300)
 	MQFW = mongodb.MongodbSim{
 		MongodbAddr: Sysconfig["mongodbServers"].(string),
@@ -67,29 +93,6 @@ func init() {
 	}
 }
 
-type KeyMap struct {
-	Lock sync.Mutex
-	Map  map[string]*Key
-}
-
-type Key struct {
-	Arr  *[]string
-	Lock *sync.Mutex
-}
-
-func NewKeyMap() *KeyMap {
-	//k:=&Key{[]string{}}
-	return &KeyMap{
-		Map: map[string]*Key{},
-	}
-}
-
-//三组lock,对应的(PNKey)key为项目名称,值对应的是此项目名称对应的项目id数组
-var PNKey, PCKey, PBKey = NewKeyMap(), NewKeyMap(), NewKeyMap()
-
-//id-lock
-var IdLock = &sync.Mutex{}
-
 func main() {
 	go checkMapJob()
 	//先加载所有锁
@@ -99,8 +102,7 @@ func main() {
 	for pos, key := range []string{"pn_*", "pc_*", "pb_*"} {
 		res := redis.GetKeysByPattern(REDISKEYS, key)
 		pk := km[pos]
-		if res != nil {
-			//一次500条
+		if res != nil { //一次500条
 			num := 0
 			arr := []string{}
 			for _, v := range res {
@@ -174,8 +176,6 @@ func processUdpMsg(act byte, data []byte, ra *net.UDPAddr) {
 	}
 }
 
-var SingleThread = make(chan bool, 1)
-
 func task(data []byte, mapInfo map[string]interface{}) {
 	defer func() {
 		<-SingleThread
@@ -196,14 +196,9 @@ func task(data []byte, mapInfo map[string]interface{}) {
 	it := sess.DB(MQFW.DbName).C(extractColl).Find(&q).Iter() //.Sort("publishtime")
 	count, index := 0, 0
 	pici := time.Now().Unix()
-	//log.Println(q, MQFW.DbName, extractColl)
 	wg := &sync.WaitGroup{}
 	idmap := &sync.Map{}
 	for tmp := make(map[string]interface{}); it.Next(tmp); {
-		//		if util.IntAll(tmp["extracttype"]) == -1 {
-		//			tmp = make(map[string]interface{})
-		//			continue
-		//		}
 		if index%10000 == 0 {
 			log.Println(index, tmp["_id"])
 		}
@@ -218,10 +213,9 @@ func task(data []byte, mapInfo map[string]interface{}) {
 		if err != nil {
 			log.Println("checkid err", err.Error())
 		}
-		if !b { // && util.IntAll(tmp["infoformat"]) < 2 && tmp["detail"] != nil {
-			//增加判重逻辑,重复id不再生成
+		if !b {
 			wg.Add(1)
-			idmap.Store(tmp["_id"], true)
+			idmap.Store(tmp["_id"], true) //增加判重逻辑,重复id不再生成
 			MultiThread <- true
 			go func(tmp map[string]interface{}, thisid string) {
 				defer func() {
@@ -229,9 +223,13 @@ func task(data []byte, mapInfo map[string]interface{}) {
 					wg.Done()
 					idmap.Delete(tmp["_id"])
 				}()
-				sflag := Compare(tmp, pici)
-				redis.Put(INFOID, thisid, 1, INFOTIMEOUT)
-				go IS.Add(sflag)
+				info := PreThisInfo(tmp)
+				if info != nil {
+					lockPNCBMap(info)
+					startProjectMerge(info, tmp)
+					redis.Put(INFOID, thisid, 1, INFOTIMEOUT)
+					unlockPNCBMap(info)
+				}
 			}(tmp, thisid)
 		}
 		if count%500 == 0 {
@@ -282,6 +280,8 @@ func NewPushInfo(tmp map[string]interface{}) bson.M {
 		"href":        tmp["href"],
 		"area":        tmp["area"],
 		"city":        tmp["city"],
-		"cresult":     tmp["cresult"],
+
+		"cresult": tmp["cresult"],
+		"score":   tmp["score"],
 	}
 }

+ 598 - 0
udpprojectset/src/projectmeger.go

@@ -0,0 +1,598 @@
+// projectmeger
+package main
+
+import (
+	"encoding/json"
+	"fmt"
+	du "jy/util"
+	"log"
+	qu "qfw/util"
+	"qfw/util/redis"
+	"sort"
+	"strings"
+	"sync"
+	"time"
+)
+
+//有效值三选一、三选二
+var ThreeToTow, ThreeToOne map[string]bool
+
+func init() {
+	ThreeToTow = map[string]bool{}
+	ThreeToOne = map[string]bool{
+		"AAA": true,
+		"AAB": true,
+	}
+	tows := [][][]string{
+		[][]string{
+			[]string{"A", "B"},
+			[]string{"A", "B"},
+			[]string{"A", "B"},
+		},
+		[][]string{
+			[]string{"A", "B"},
+			[]string{"D", "E"},
+			[]string{"A", "B"},
+		},
+		[][]string{
+			[]string{"A", "B"},
+			[]string{"A", "B"},
+			[]string{"D", "E"},
+		},
+		[][]string{
+			[]string{"D", "E"},
+			[]string{"A", "B"},
+			[]string{"A", "B"},
+		},
+	}
+	for _, tow := range tows {
+		for _, v1 := range tow[0] {
+			for _, v2 := range tow[1] {
+				for _, v3 := range tow[2] {
+					key := fmt.Sprintf("%s%s%s", v1, v2, v3)
+					ThreeToTow[key] = true
+				}
+			}
+		}
+	}
+}
+
+func startProjectMerge(thisinfo *Info, tmp map[string]interface{}) {
+	bNormalScore := false
+	pcbv := PCBVal(tmp)
+	if checkInfoAlter(tmp) { //进入变更信息流程
+		if pcbv.Val > 1 { //判断三项至少包含两项
+			bNormalScore = true
+		} else {
+			extInfoTag("invalid", qu.BsonIdToSId(tmp["_id"])) //无效信息,打标记
+			go IS.Add("invalid")                              //数据统计使用
+			return
+		}
+	} else {
+		bNormalScore = true
+	}
+	//合并流程
+	if bNormalScore {
+		PNKeyMap.Store(thisinfo.PNKey, true)
+		PBKeyMap.Store(thisinfo.PBKey, true)
+		PCKeyMap.Store(thisinfo.PCKey, true)
+		if pcbv.Buyer { //有采购单位
+			hasBuyer(pcbv, thisinfo, tmp)
+		} else { //无采购单位
+			noBuyer(pcbv, thisinfo, tmp)
+		}
+	}
+}
+
+//判断信息是否是变更
+func checkInfoAlter(tmp map[string]interface{} /*新信息*/) bool {
+	toptype := qu.ObjToString(tmp["toptype"])
+	subtype := qu.ObjToString(tmp["subtype"])
+	title := qu.ObjToString(tmp["title"])
+	if subtype == "变更" || strings.Index(title, "变更公告") > -1 || strings.Index(title, "更正公告") > -1 {
+		//当信息类型是变更或标题中含变更时
+		if toptype == "招标" {
+			//招标的变更公告,不作处理
+		} else if toptype == "结果" {
+			subtype = "变更"
+		}
+	}
+	return subtype == "变更"
+}
+
+//有采购单位
+func hasBuyer(p PCBV, thisinfo *Info, tmp map[string]interface{}) {
+	var pncb []*CompareInfo
+	var res []interface{}
+	sflag := ""
+	pici := time.Now().Unix()
+	if p.Pname || p.Pcode { //有项目名称或项目编号
+		//获取对比项目数组
+		res, pncb = getComeperProjects(p, thisinfo)
+		//三选二打分
+		scores := score3Select2(p, thisinfo, tmp, res, pncb)
+		//项目合并
+		sflag = mergeProject(tmp, thisinfo, scores, pncb)
+	} else {
+		//生成项目,不参与后续对比
+		sflag = "alone"
+		mess := map[string]interface{}{
+			"meger_mess":  "有采购单位,不满足三选二",
+			"meger_sflag": sflag,
+		}
+		newProject(tmp, mess, pici, thisinfo)
+	}
+	extInfoTag(sflag, thisinfo.Id)
+	go IS.Add(sflag) //数据统计使用
+}
+
+//无采购单位
+func noBuyer(p PCBV, thisinfo *Info, tmp map[string]interface{}) {
+	var pncb []*CompareInfo
+	var res []interface{}
+	sflag := ""
+	pici := time.Now().Unix()
+	if p.Pname { //有项目名称
+		//获取对比项目数组
+		res, pncb = getComeperProjects(p, thisinfo)
+		if p.Pcode { //有项目编号
+			//三选二打分
+			scores := score3Select2(p, thisinfo, tmp, res, pncb)
+			//项目合并
+			sflag = mergeProject(tmp, thisinfo, scores, pncb)
+		} else { //无项目编号
+			if p.PnameLen > MegerFieldsLen.ProjectNamelen {
+				//三选一打分
+				scores := score3Select1(p, thisinfo, tmp, res, pncb)
+				//项目合并
+				sflag = mergeProject(tmp, thisinfo, scores, pncb)
+			} else {
+				//生成项目,不参与后续对比
+				sflag = "alone"
+				mess := map[string]interface{}{
+					"meger_mess":  "无采购单位,不满足三选一",
+					"meger_sflag": sflag,
+				}
+				newProject(tmp, mess, pici, thisinfo)
+			}
+		}
+	} else { //无项目名称
+		if p.Pcode {
+			//获取对比项目数组
+			res, pncb = getComeperProjects(p, thisinfo)
+			if p.PcodeLen > MegerFieldsLen.ProjectCodelen {
+				if p.Area && p.City && p.Agency { //有省市代理机构
+					//三选一打分
+					scores := score3Select1(p, thisinfo, tmp, res, pncb)
+					//项目合并
+					sflag = mergeProject(tmp, thisinfo, scores, pncb)
+				} else {
+					//生成项目,不参与后续对比
+					sflag = "alone"
+					mess := map[string]interface{}{
+						"meger_mess":  "无采购单位,不满足三选一",
+						"meger_sflag": sflag,
+					}
+					newProject(tmp, mess, pici, thisinfo)
+				}
+			} else {
+				//生成项目,不参与后续对比
+				sflag = "alone"
+				mess := map[string]interface{}{
+					"meger_mess":  "无采购单位,不满足三选一",
+					"meger_sflag": sflag,
+				}
+				newProject(tmp, mess, pici, thisinfo)
+			}
+		} else {
+			//信息无效,打标记
+			sflag = "invalid"
+		}
+	}
+	extInfoTag(sflag, thisinfo.Id)
+	go IS.Add(sflag) //数据统计使用
+}
+
+//3选2打分
+func score3Select2(p PCBV, thisinfo *Info, tmp map[string]interface{}, res []interface{}, pncb []*CompareInfo) (scores []*CompareOne) {
+	defer qu.Catch()
+	if len(res) > 0 {
+		//对比打分
+		for k, tmps := range res { //遍历对象数组
+			if tmp, ok := tmps.([]interface{}); ok {
+				for _, b1 := range tmp {
+					if b1 != nil {
+						var info ProjectInfo
+						err := json.Unmarshal(b1.([]byte), &info)
+						if err != nil {
+							log.Println(err)
+						}
+						cone := &CompareOne{
+							Parent: pncb[k],
+							Pinfo:  &info,
+						}
+						cone.BuyerType, cone.Score = fieldPCBScore(thisinfo.Buyer, info.Buyer, cone.BuyerType, cone.Score)
+						if p.Buyer {
+							cone.ProjectNameType, cone.Score = fieldPCBScore(thisinfo.ProjectName, info.ProjectName, cone.ProjectNameType, cone.Score)
+							cone.ProjectCodeType, cone.Score = fieldPCBScore(thisinfo.ProjectCode, info.ProjectCode, cone.ProjectCodeType, cone.Score)
+						} else { //无采购单位,打分考虑长度
+							if len([]rune(thisinfo.ProjectName)) > MegerFieldsLen.ProjectNamelen {
+								cone.ProjectNameType, cone.Score = fieldPCBScore(thisinfo.ProjectName, info.ProjectName, cone.ProjectNameType, cone.Score)
+							} else {
+								cone.ProjectNameType = "D"
+							}
+							if len(thisinfo.ProjectCode) > MegerFieldsLen.ProjectCodelen {
+								cone.ProjectCodeType, cone.Score = fieldPCBScore(thisinfo.ProjectCode, info.ProjectCode, cone.ProjectCodeType, cone.Score)
+							} else {
+								cone.ProjectCodeType = "D"
+							}
+						}
+						//省市打分
+						if thisinfo.Area != "A" && thisinfo.Area != "全国" && info.Area != "A" && info.Area != "全国" {
+							if thisinfo.Area == info.Area && thisinfo.City == info.City {
+								cone.Score += 2
+							} else {
+								cone.Score -= 1
+							}
+						} else {
+							cone.Score += 1
+						}
+						//代理机构打分
+						if len([]rune(info.Agency)) > 0 {
+							if thisinfo.Agency == info.Agency { //A
+								cone.Score += 2
+							} else if strings.Index(info.Agency, thisinfo.Agency) > -1 || strings.Index(thisinfo.Agency, info.Agency) > -1 { //B
+								cone.Score += 1
+							} else {
+								if len(thisinfo.Agency) < 1 { //E
+									cone.Score -= 1
+								} else { //C
+									cone.Score -= 2
+								}
+							}
+						} else { //D不计分
+							//
+						}
+						skey := fmt.Sprintf("%s%s%s", cone.BuyerType, cone.ProjectNameType, cone.ProjectCodeType)
+						cone.Cresult = skey
+						if ThreeToTow[skey] {
+							scores = append(scores, cone)
+						}
+					}
+				}
+			}
+		}
+	}
+	return
+}
+
+//3选1打分
+func score3Select1(p PCBV, thisinfo *Info, tmp map[string]interface{}, res []interface{}, pncb []*CompareInfo) (scores []*CompareOne) {
+	defer qu.Catch()
+	//对比打分
+	if len(res) > 0 { //找到项目名称、项目编号或采购单位相同时
+		for k, tmps := range res { //遍历对象数组
+			if tmp, ok := tmps.([]interface{}); ok {
+				for _, b1 := range tmp {
+					if b1 != nil {
+						var info ProjectInfo
+						err := json.Unmarshal(b1.([]byte), &info)
+						if err != nil {
+							log.Println(err)
+						}
+						cone := &CompareOne{
+							Parent: pncb[k],
+							Pinfo:  &info,
+						}
+						if pncb[k].Field == "pn" { //比较字段项目名称
+							if len(info.ProjectName) > 0 {
+								if thisinfo.ProjectName == info.ProjectName { //A
+									cone.Score += 2
+									cone.ProjectNameType = "A"
+								} else if strings.Index(info.ProjectName, thisinfo.ProjectName) > -1 || strings.Index(thisinfo.ProjectName, info.ProjectName) > -1 { //B
+									cone.Score += 1
+									cone.ProjectNameType = "B"
+								} else { //C
+									cone.Score -= 2
+									cone.ProjectNameType = "C"
+								}
+							} else { //D不计分
+								cone.ProjectNameType = "D"
+							}
+						}
+						if pncb[k].Field == "pc" { //比较字段项目编号
+							if len(info.ProjectCode) > 0 {
+								if thisinfo.ProjectCode == info.ProjectCode { //A
+									cone.Score += 2
+									cone.ProjectCodeType = "A"
+								} else if strings.Index(info.ProjectCode, thisinfo.ProjectCode) > -1 || strings.Index(thisinfo.ProjectCode, info.ProjectCode) > -1 { //B
+									cone.Score += 1
+									cone.ProjectCodeType = "B"
+								} else { //C
+									cone.Score -= 2
+									cone.ProjectCodeType = "C"
+								}
+							} else { //D不计分
+								cone.ProjectCodeType = "D"
+							}
+						}
+						if thisinfo.Area != "A" && thisinfo.Area != "全国" && info.Area != "A" && info.Area != "全国" {
+							if thisinfo.Area == info.Area && thisinfo.City == info.City {
+								cone.Score += 2
+								cone.AreaType = "A"
+							} else {
+								cone.Score -= 1
+								cone.AreaType = "C"
+							}
+						} else {
+							cone.Score += 1
+							cone.AreaType = "B"
+						}
+						if len([]rune(info.Agency)) > 0 {
+							if thisinfo.Agency == info.Agency { //A
+								cone.Score += 2
+								cone.AgencyType = "A"
+							} else if strings.Index(info.Agency, thisinfo.Agency) > -1 || strings.Index(thisinfo.Agency, info.Agency) > -1 { //B
+								cone.Score += 1
+								cone.AgencyType = "B"
+							} else {
+								if len(thisinfo.Agency) < 1 { //E
+									cone.Score -= 1
+									cone.AgencyType = "E"
+								} else { //C
+									cone.Score -= 2
+									cone.AgencyType = "C"
+								}
+							}
+						} else { //D不计分
+							cone.AgencyType = "D"
+						}
+						skey := fmt.Sprintf("%s%s%s", cone.BuyerType, cone.ProjectNameType, cone.ProjectCodeType)
+						cone.Cresult = skey
+						if ThreeToOne[skey] {
+							scores = append(scores, cone)
+						}
+					}
+				}
+			}
+		}
+	}
+	return
+}
+
+//获取对比项目数组
+func getComeperProjects(p PCBV, thisinfo *Info) (res []interface{}, pncb []*CompareInfo) {
+	if p.PnameLen > 0 {
+		pn := NewCompareInfo("pn", thisinfo.PNKey, PNKey)
+		pncb = append(pncb, pn)
+	}
+	if p.PcodeLen > 0 {
+		pc := NewCompareInfo("pc", thisinfo.PCKey, PCKey)
+		pncb = append(pncb, pc)
+	}
+	if p.BuyerLen > 0 {
+		pb := NewCompareInfo("pb", thisinfo.PBKey, PBKey)
+		pncb = append(pncb, pb)
+	}
+	repeatId := map[string]bool{}
+	IdLock.Lock() //此处加id锁,会引进多线程的死锁,对比三个大map数组,找到key相同的项目id数组,并去重
+	for _, pv := range pncb {
+		if pv != nil {
+			pv.KeyMap.Lock.Lock()
+			K := pv.KeyMap.Map[pv.Key]
+			if K == nil {
+				K = &Key{&[]string{}, &sync.Mutex{}}
+				pv.KeyMap.Map[pv.Key] = K
+			}
+			pv.K = K
+			pv.K.Lock.Lock()
+			pv.KeyMap.Lock.Unlock()
+			defer pv.K.Lock.Unlock()
+			newarr := []string{}
+			for _, id := range *K.Arr {
+				if !repeatId[id] {
+					newarr = append(newarr, id)
+					repeatId[id] = true
+				}
+			}
+			pv.IdArr = newarr
+		}
+	}
+	IdLock.Unlock()
+	for _, pv := range pncb {
+		if len(pv.IdArr) > 0 {
+			res = append(res, redis.Mget(REDISIDS, pv.IdArr))
+		}
+	}
+	return
+}
+
+//合并项目
+func mergeProject(tmp map[string]interface{}, thisinfo *Info, scores []*CompareOne, pncb []*CompareInfo) (sflag string) {
+	var id = ""
+	//分值排序
+	sort.Slice(scores, func(i, j int) bool {
+		return scores[i].Score > scores[j].Score
+	})
+	if len(scores) > 0 {
+		//分值排序
+		sort.Slice(scores, func(i, j int) bool {
+			return scores[i].Score > scores[j].Score
+		})
+		max := scores[0]
+		if max.Score > 0 {
+			sflag = "repeat"
+			max.Parent.Bfind = true
+			tmp["cresult"] = max.Cresult
+			tmp["score"] = max.Score
+			id = updateinfo(thisinfo, tmp, max.Pinfo, time.Now().Unix())
+			//log.Println(sflag, id, max.Cresult)
+			if len(scores) > 1 && (scores[0].Score == scores[1].Score) {
+				//通知检查,异常数据存库
+				checkNotice(thisinfo.Id, id, scores)
+			}
+		} else {
+			sflag = "invalidscore"
+		}
+	} else {
+		//生成项目
+		sflag = "normal"
+		mess := map[string]interface{}{
+			"meger_sflag": sflag,
+		}
+		id = newProject(tmp, mess, time.Now().Unix(), thisinfo)
+	}
+	if id != "" { //更新REDISKEYS redis
+		put := []interface{}{}
+		for _, pv := range pncb {
+			if pv != nil && !pv.Bfind {
+				if BinarySearch(*pv.K.Arr, id) == -1 {
+					*(pv.K.Arr) = append(*(pv.K.Arr), id)
+					put = append(put, []interface{}{pv.Key, *(pv.K.Arr)})
+				}
+			}
+		}
+		if len(put) > 0 {
+			redis.BulkPut(REDISKEYS, 0, put...)
+		}
+	}
+	return sflag
+}
+
+//新增项目
+func newProject(tmp, mess map[string]interface{}, pipc int64, thisinfo *Info) (id string) {
+	id = InsertProject(thisinfo.NewPNKey, tmp, mess, pipc, thisinfo)
+	sflag := qu.ObjToString(mess["meger_sflag"])
+	if sflag != "alone" {
+		p1 := NewPinfo(id, thisinfo)
+		redis.PutCKV(REDISIDS, id, p1)
+	} else {
+		du.Debug("新增项目,不参与对比", id)
+	}
+	return id
+}
+
+//抽取信息打标记
+func extInfoTag(sflag, id string) {
+	MQFW.UpdateById(extractColl, id,
+		map[string]interface{}{
+			"$set": map[string]interface{}{
+				"meger_sflag": sflag,
+			},
+		})
+}
+
+//检查通知
+func checkNotice(infoid, pid string, scores []*CompareOne) {
+	MQFW.Update("project_unusual", `{"project_id":"`+pid+`"}`,
+		map[string]interface{}{
+			"$set": map[string]interface{}{
+				"project_id": pid,
+				"pici":       time.Now().Unix(),
+			},
+			"$push": map[string]interface{}{
+				"list": map[string]interface{}{
+					"infoid": infoid,
+					"pinfo1": scores[0].Pinfo.Id,
+					"pinfo2": scores[1].Pinfo.Id,
+				},
+			},
+		}, true, false)
+	du.Debug("通知检查,异常数据存库", infoid, pid)
+}
+
+//属性判断组
+func PCBVal(tmp map[string]interface{}) PCBV {
+	pcbv := PCBV{}
+	projectName := qu.ObjToString(tmp["projectname"])
+	if len([]rune(projectName)) > 1 {
+		pcbv.Val += 1
+		pcbv.Pname = true
+		pcbv.PnameLen = len([]rune(projectName))
+	}
+	projectCode := qu.ObjToString(tmp["projectcode"])
+	if len([]rune(projectCode)) > 1 {
+		pcbv.Val += 1
+		pcbv.Pcode = true
+		pcbv.PcodeLen = len(projectCode)
+	}
+	buyer := qu.ObjToString(tmp["buyer"])
+	if len([]rune(buyer)) > 1 {
+		pcbv.Val += 1
+		pcbv.Buyer = true
+		pcbv.BuyerLen = len([]rune(buyer))
+	}
+	//省市代理机构
+	if qu.ObjToString(tmp["area"]) != "" {
+		pcbv.Area = true
+	}
+	if qu.ObjToString(tmp["city"]) != "" {
+		pcbv.City = true
+	}
+	if qu.ObjToString(tmp["agency"]) != "" {
+		pcbv.Agency = true
+	}
+	return pcbv
+}
+
+//项目名称、项目编号、采购单位打分
+func fieldPCBScore(this, info, ctype string, score int) (string, int) {
+	if len(info) > 0 {
+		if this == info { //A
+			score += 5
+			ctype = "A"
+		} else if strings.Index(info, this) > -1 || strings.Index(this, info) > -1 { //B
+			score += 2
+			ctype = "B"
+		} else {
+			if len(this) < 1 { //E
+				score -= 1
+				ctype = "E"
+			} else { //C
+				score -= 2
+				ctype = "C"
+			}
+		}
+	} else { //D不计分
+		ctype = "D"
+	}
+	return ctype, score
+}
+
+//pncbMap加锁
+func lockPNCBMap(thisinfo *Info) {
+	for { //等待其他任务完成
+		ok := true
+		if len(thisinfo.PNKey) > 3 {
+			if _, b := PNKeyMap.Load(thisinfo.PNKey); b {
+				ok = false
+			}
+		}
+		if len(thisinfo.PCKey) > 3 {
+			if _, b := PCKeyMap.Load(thisinfo.PCKey); b {
+				ok = false
+			}
+		}
+		if len(thisinfo.PBKey) > 3 {
+			if _, b := PBKeyMap.Load(thisinfo.PBKey); b {
+				ok = false
+			}
+		}
+		if ok {
+			break
+		}
+	}
+}
+
+//pncbMap解锁
+func unlockPNCBMap(thisinfo *Info) {
+	if len(thisinfo.PNKey) > 3 {
+		PNKeyMap.Delete(thisinfo.PNKey)
+	}
+	if len(thisinfo.PCKey) > 3 {
+		PCKeyMap.Delete(thisinfo.PCKey)
+	}
+	if len(thisinfo.PBKey) > 3 {
+		PBKeyMap.Delete(thisinfo.PBKey)
+	}
+}

+ 0 - 231
udpprojectset/src/scores.go

@@ -1,231 +0,0 @@
-// scores
-package main
-
-import (
-	"encoding/json"
-	"fmt"
-	"log"
-	"qfw/util"
-	"qfw/util/redis"
-	"strings"
-)
-
-//有效值三选一、三选二
-var ThreeToTow, ThreeToOne map[string]bool
-
-func init() {
-	ThreeToTow = map[string]bool{}
-	ThreeToOne = map[string]bool{
-		"AAA": true,
-		"AAB": true,
-	}
-	tows := [][][]string{
-		[][]string{
-			[]string{"A", "B"},
-			[]string{"A", "B"},
-			[]string{"A", "B"},
-		},
-		[][]string{
-			[]string{"A", "B"},
-			[]string{"D", "E"},
-			[]string{"A", "B"},
-		},
-		[][]string{
-			[]string{"A", "B"},
-			[]string{"A", "B"},
-			[]string{"D", "E"},
-		},
-		[][]string{
-			[]string{"D", "E"},
-			[]string{"A", "B"},
-			[]string{"A", "B"},
-		},
-	}
-	for _, tow := range tows {
-		for _, v1 := range tow[0] {
-			for _, v2 := range tow[1] {
-				for _, v3 := range tow[2] {
-					key := fmt.Sprintf("%s%s%s", v1, v2, v3)
-					ThreeToTow[key] = true
-				}
-			}
-		}
-	}
-}
-
-//三选一打分
-func (com *CompareInfo) ComputeOne(thisinfo *Info, ids []string) []*CompareOne {
-	defer util.Catch()
-	res := redis.Mget(REDISIDS, ids)
-	scores := []*CompareOne{}
-	if len(res) > 0 { //找到项目名称、项目编号或采购单位相同时
-		for _, b1 := range res { //遍历对象数组
-			if b1 != nil {
-				var info ProjectInfo
-				err := json.Unmarshal(b1.([]byte), &info)
-				if err != nil {
-					log.Println(err)
-				}
-				cone := &CompareOne{
-					Parent: com,
-					Pinfo:  &info,
-				}
-				if com.Field == "pn" { //比较字段项目名称
-					if len(info.ProjectName) > 0 {
-						if thisinfo.ProjectName == info.ProjectName { //A
-							cone.Score += 2
-							cone.ProjectNameType = "A"
-						} else if strings.Index(info.ProjectName, thisinfo.ProjectName) > -1 || strings.Index(thisinfo.ProjectName, info.ProjectName) > -1 { //B
-							cone.Score += 1
-							cone.ProjectNameType = "B"
-						} else { //C
-							cone.Score -= 2
-							cone.ProjectNameType = "C"
-						}
-					} else { //D不计分
-						cone.ProjectNameType = "D"
-					}
-				}
-				if com.Field == "pc" { //比较字段项目编号
-					if len(info.ProjectCode) > 0 {
-						if thisinfo.ProjectCode == info.ProjectCode { //A
-							cone.Score += 2
-							cone.ProjectCodeType = "A"
-						} else if strings.Index(info.ProjectCode, thisinfo.ProjectCode) > -1 || strings.Index(thisinfo.ProjectCode, info.ProjectCode) > -1 { //B
-							cone.Score += 1
-							cone.ProjectCodeType = "B"
-						} else { //C
-							cone.Score -= 2
-							cone.ProjectCodeType = "C"
-						}
-					} else { //D不计分
-						cone.ProjectCodeType = "D"
-					}
-				}
-				if thisinfo.Area != "A" && thisinfo.Area != "全国" && info.Area != "A" && info.Area != "全国" {
-					if thisinfo.Area == info.Area && thisinfo.District == info.District {
-						cone.Score += 2
-						cone.AreaType = "A"
-					} else {
-						cone.Score -= 1
-						cone.AreaType = "C"
-					}
-				} else {
-					cone.Score += 1
-					cone.AreaType = "B"
-				}
-				if len([]rune(info.Agency)) > 0 {
-					if thisinfo.Agency == info.Agency { //A
-						cone.Score += 2
-						cone.AgencyType = "A"
-					} else if strings.Index(info.Agency, thisinfo.Agency) > -1 || strings.Index(thisinfo.Agency, info.Agency) > -1 { //B
-						cone.Score += 1
-						cone.AgencyType = "B"
-					} else {
-						if len(thisinfo.Agency) < 1 { //E
-							cone.Score -= 1
-							cone.AgencyType = "E"
-						} else { //C
-							cone.Score -= 2
-							cone.AgencyType = "C"
-						}
-					}
-				} else { //D不计分
-					cone.AgencyType = "D"
-				}
-				scores = append(scores, cone)
-			}
-		}
-	}
-	return scores
-}
-
-//三选二打分
-func (com *CompareInfo) ComputeTow(thisinfo *Info, ids []string, hasbyer bool) []*CompareOne {
-	defer util.Catch()
-	res := redis.Mget(REDISIDS, ids)
-	scores := []*CompareOne{}
-	if len(res) > 0 { //找到项目名称、项目编号或采购单位相同时
-		for _, b1 := range res { //遍历对象数组
-			if b1 != nil {
-				var info ProjectInfo
-				err := json.Unmarshal(b1.([]byte), &info)
-				if err != nil {
-					log.Println(err)
-				}
-				cone := &CompareOne{
-					Parent: com,
-					Pinfo:  &info,
-				}
-				cone.BuyerType, cone.Score = fieldPCBScore(thisinfo.Buyer, info.Buyer, cone.BuyerType, cone.Score)
-				if hasbyer {
-					cone.ProjectNameType, cone.Score = fieldPCBScore(thisinfo.ProjectName, info.ProjectName, cone.ProjectNameType, cone.Score)
-					cone.ProjectCodeType, cone.Score = fieldPCBScore(thisinfo.ProjectCode, info.ProjectCode, cone.ProjectCodeType, cone.Score)
-				} else { //无采购单位,打分考虑长度
-					if len([]rune(thisinfo.ProjectName)) > 5 {
-						cone.ProjectNameType, cone.Score = fieldPCBScore(thisinfo.ProjectName, info.ProjectName, cone.ProjectNameType, cone.Score)
-					} else {
-						cone.ProjectNameType = "D"
-					}
-					if len(thisinfo.ProjectCode) > 6 {
-						cone.ProjectCodeType, cone.Score = fieldPCBScore(thisinfo.ProjectCode, info.ProjectCode, cone.ProjectCodeType, cone.Score)
-					} else {
-						cone.ProjectCodeType = "D"
-					}
-				}
-				//省市打分
-				if thisinfo.Area != "A" && thisinfo.Area != "全国" && info.Area != "A" && info.Area != "全国" {
-					if thisinfo.Area == info.Area && thisinfo.City == info.City {
-						cone.Score += 2
-					} else {
-						cone.Score -= 1
-					}
-				} else {
-					cone.Score += 1
-				}
-				//代理机构打分
-				if len([]rune(info.Agency)) > 0 {
-					if thisinfo.Agency == info.Agency { //A
-						cone.Score += 2
-					} else if strings.Index(info.Agency, thisinfo.Agency) > -1 || strings.Index(thisinfo.Agency, info.Agency) > -1 { //B
-						cone.Score += 1
-					} else {
-						if len(thisinfo.Agency) < 1 { //E
-							cone.Score -= 1
-						} else { //C
-							cone.Score -= 2
-						}
-					}
-				} else { //D不计分
-					//
-				}
-				scores = append(scores, cone)
-			}
-		}
-	}
-	return scores
-}
-
-//项目名称、项目编号、采购单位打分
-func fieldPCBScore(this, info, ctype string, score int) (string, int) {
-	if len(info) > 0 {
-		if this == info { //A
-			score += 5
-			ctype = "A"
-		} else if strings.Index(info, this) > -1 || strings.Index(this, info) > -1 { //B
-			score += 2
-			ctype = "B"
-		} else {
-			if len(this) < 1 { //E
-				score -= 1
-				ctype = "E"
-			} else { //C
-				score -= 2
-				ctype = "C"
-			}
-		}
-	} else { //D不计分
-		ctype = "D"
-	}
-	return ctype, score
-}

+ 22 - 194
udpprojectset/src/thisinfo.go

@@ -2,10 +2,11 @@
 package main
 
 import (
+	"crypto/sha1"
 	"encoding/json"
 	"fmt"
+	"io"
 	du "jy/util"
-	"log"
 	"qfw/util"
 	"strings"
 
@@ -40,21 +41,26 @@ type Info struct {
 	Bidopentime int64  `json:"bidopentime"`
 	District    string `json:"district"`
 	Winnerorder []string
+
+	NewPNKey string
+	PNKey    string
+	PCKey    string
+	PBKey    string
 }
 
 //pcb三选值
 type PCBV struct {
 	Val    int  //1一项有效值,2二项有效值,3三项有效值
 	Pname  bool //有项目名称
-	Cname  bool //有项目编号
-	Bname  bool //有采购单位
+	Pcode  bool //有项目编号
+	Buyer  bool //有采购单位
 	Area   bool //区域
 	City   bool //市
 	Agency bool //代理机构
 
 	PnameLen int //值长度
-	CnameLen int //值长度
-	BnameLen int //值长度
+	PcodeLen int //值长度
+	BuyerLen int //值长度
 }
 
 func PreThisInfo(tmp map[string]interface{} /*新信息*/) *Info {
@@ -127,196 +133,18 @@ func PreThisInfo(tmp map[string]interface{} /*新信息*/) *Info {
 		}
 	}
 	thisinfo.Winnerorder = winnerorder
-	return thisinfo
-}
-
-//流程处理
-func (com *CompareInfo) ProcessInfo(new_pn string, tmp map[string]interface{}, pici int64, info *Info) (id string) {
-	pcbv := PCBValue(info)
-	if info.SubType == "变更" {
-		if pcbv.Val > 1 {
-			id = com.Process(new_pn, tmp, pici, info, pcbv)
-		} else {
-			//信息无效
-			MQFW.UpdateById(extractColl, info.Id,
-				map[string]interface{}{
-					"$set": map[string]interface{}{
-						"ext_mess": info.SubType + ",不满足三选二",
-					},
-				})
-			du.Debug("信息无效", info.Id)
-		}
-	} else { //非变更
-		id = com.Process(new_pn, tmp, pici, info, pcbv)
-	}
-	return id
-}
 
-//流程
-func (com *CompareInfo) Process(new_pn string, tmp map[string]interface{}, pici int64, info *Info, pcbv PCBV) (id string) {
-	if pcbv.Bname { //有采购单位
-		if pcbv.Pname || pcbv.Cname {
-			//三选二打分
-			scores := com.ComputeTow(info, com.IdArr, true)
-			for _, v := range scores {
-				skey := fmt.Sprintf("%s%s%s", v.BuyerType, v.ProjectNameType, v.ProjectCodeType)
-				if ThreeToTow[skey] { //判断是否进入打分合并逻辑
-					log.Println(info.Id, skey)
-					v.Cresult = skey
-					com.Scores = append(com.Scores, v)
-				}
-			}
-			if len(scores) < 1 {
-				//新建项目,(Compare方法中创建)不在此创建,其他同理
-				//du.Debug("有采购单位,新建项目")
-			}
-		} else {
-			//生成项目,不参与后续对比
-			id = InsertProject(new_pn, tmp,
-				map[string]interface{}{
-					"ext_mess": map[string]interface{}{
-						"type": "有采购单位,不满足三选二",
-						"mess": "项目名称或项目编号不满足",
-					},
-				}, pici, info)
-			//du.Debug("生成项目,不参与后续对比", id)
-		}
-	} else { //无采购单位
-		if pcbv.Pname {
-			if pcbv.Cname {
-				//三选二打分
-				scores := com.ComputeTow(info, com.IdArr, false)
-				for _, v := range scores {
-					skey := fmt.Sprintf("%s%s%s", v.BuyerType, v.ProjectNameType, v.ProjectCodeType)
-					if ThreeToTow[skey] { //判断是否进入打分合并逻辑
-						v.Cresult = skey
-						com.Scores = append(com.Scores, v)
-					}
-				}
-				if len(scores) < 1 {
-					//新建项目
-					//du.Debug("无采购单位,新建项目")
-				}
-			} else {
-				if pcbv.PnameLen > 5 {
-					if pcbv.Area && pcbv.City {
-						//三选一打分
-						scores := com.ComputeOne(info, com.IdArr)
-						for _, v := range scores { // v.ProjectNameType, v.ProjectCodeType二者有其一
-							skey := fmt.Sprintf("%s%s%s%s", v.ProjectNameType, v.ProjectCodeType, v.AreaType, v.AgencyType)
-							if ThreeToOne[skey] { //判断是否进入打分合并逻辑
-								v.Cresult = skey
-								com.Scores = append(com.Scores, v)
-							}
-						}
-						if len(scores) < 1 {
-							//新建项目
-							du.Debug("新建项目")
-						}
-					} else {
-						//生成项目,不参与后续对比
-						id = InsertProject(new_pn, tmp,
-							map[string]interface{}{
-								"ext_mess": map[string]interface{}{
-									"type": "无采购单位,不满足三选一",
-									"mess": "省市不满足",
-								},
-							},
-							pici, info)
-						//du.Debug("生成项目,不参与后续对比", id)
-					}
-				} else {
-					//生成项目,不参与后续对比
-					id = InsertProject(new_pn, tmp,
-						map[string]interface{}{"ext_mess": map[string]interface{}{
-							"type": "无采购单位,不满足三选一",
-							"mess": "项目名称不满足",
-						},
-						}, pici, info)
-					//du.Debug("生成项目,不参与后续对比", id)
-				}
-			}
-		} else {
-			if pcbv.Cname {
-				if pcbv.CnameLen > 8 {
-					if pcbv.Area && pcbv.City {
-						//三选一打分
-						scores := com.ComputeOne(info, com.IdArr)
-						for _, v := range scores { // v.ProjectNameType, v.ProjectCodeType二者有其一
-							skey := fmt.Sprintf("%s%s%s%s", v.ProjectNameType, v.ProjectCodeType, v.AreaType, v.AgencyType)
-							if ThreeToOne[skey] { //判断是否进入打分合并逻辑
-								v.Cresult = skey
-								com.Scores = append(com.Scores, v)
-							}
-						}
-						if len(scores) < 1 {
-							//新建项目
-							//du.Debug("无采购单位,新建项目")
-						}
-					} else {
-						//生成项目,不参与后续对比
-						id = InsertProject(new_pn, tmp,
-							map[string]interface{}{
-								"ext_mess": map[string]interface{}{
-									"type": "无采购单位,不满足三选一",
-									"mess": "省市不满足",
-								},
-							}, pici, info)
-						//du.Debug("生成项目,不参与后续对比", id)
-					}
-				} else {
-					//生成项目,不参与后续对比
-					id = InsertProject(new_pn, tmp,
-						map[string]interface{}{
-							"ext_mess": map[string]interface{}{
-								"type": "无采购单位,不满足三选一",
-								"mess": "项目编号不满足",
-							},
-						}, pici, info)
-					//du.Debug("生成项目,不参与后续对比", id)
-				}
-			} else {
-				//信息无效
-				MQFW.UpdateById(extractColl, info.Id,
-					map[string]interface{}{
-						"$set": map[string]interface{}{
-							"ext_mess": info.SubType + ",不满足三选一",
-						},
-					})
-				//du.Debug("信息无效", info.Id)
-			}
-		}
-	}
-	return id
+	new_pn, _ := handleprojectname(thisinfo.ProjectName, thisinfo.Buyer, thisinfo.TopType) //作为判断依据
+	thisinfo.NewPNKey = new_pn
+	thisinfo.PNKey = "pn_" + new_pn
+	thisinfo.PCKey = "pc_" + thisinfo.ProjectCode
+	thisinfo.PBKey = "pb_" + thisinfo.Buyer
+	return thisinfo
 }
-func PCBValue(info *Info) PCBV {
-	pcbv := PCBV{}
-	if len([]rune(info.ProjectName)) > 1 {
-		pcbv.Val += 1
-		pcbv.Pname = true
-		pcbv.PnameLen = len([]rune(info.ProjectName))
 
-	}
-	if len([]rune(info.ProjectCode)) > 1 {
-		pcbv.Val += 1
-		pcbv.Cname = true
-		pcbv.CnameLen = len([]rune(info.ProjectCode))
-
-	}
-	if len([]rune(info.Buyer)) > 1 {
-		pcbv.Val += 1
-		pcbv.Bname = true
-		pcbv.BnameLen = len([]rune(info.Buyer))
-	}
-	//省市代理机构
-	if info.Area != "" {
-		pcbv.Area = true
-	}
-	if info.City != "" {
-		pcbv.City = true
-	}
-	if info.Agency != "" {
-		pcbv.Agency = true
-	}
-	return pcbv
+//获取hascode
+func GetHas1(key string) string {
+	t := sha1.New()
+	io.WriteString(t, key)
+	return fmt.Sprintf("%x", t.Sum(nil))
 }