Browse Source

项目合并流程及打分

zhangjinkun 6 years ago
parent
commit
bf42534204

+ 16 - 27
udpprojectset/src/cleareids.go

@@ -6,6 +6,7 @@ import (
 	"log"
 	"qfw/util"
 	"qfw/util/redis"
+	"sync"
 	"time"
 
 	"github.com/robfig/cron"
@@ -16,7 +17,7 @@ var (
 	projectcycle int64
 )
 
-func cleardis() {
+func clearedis() {
 	if credis, ok := Sysconfig["clearedis"].(map[string]interface{}); ok {
 		clearcron := util.ObjToString(credis["clearcron"])
 		projectcycle = util.Int64All(credis["projectcycle"])
@@ -32,37 +33,25 @@ func cleardis() {
 func clearPKey() {
 	log.Println("开始清理")
 	nowtime := time.Now().Unix()
-	go clearPNKey(nowtime)
-	//go clearPBKey(nowtime)
-	//go clearPCKey(nowtime)
-	log.Println("清理结束")
-}
-
-func clearPNKey(nowtime int64) {
-	delkey := clearIdsKeys(PNKey, nowtime)
-	PNKey.Lock.Lock()
-	for _, k := range delkey {
-		delete(PNKey.Map, k)
+	wg := sync.WaitGroup{}
+	for _, pncb := range []*KeyMap{PNKey, PCKey, PBKey} {
+		wg.Add(1)
+		go func() {
+			defer wg.Done()
+			clearPNCBKey(pncb, nowtime)
+		}()
 	}
-	PNKey.Lock.Unlock()
-}
-
-func clearPBKey(nowtime int64) {
-	delkey := clearIdsKeys(PBKey, nowtime)
-	PBKey.Lock.Lock()
-	for _, k := range delkey {
-		delete(PBKey.Map, k)
-	}
-	PBKey.Lock.Unlock()
+	wg.Wait()
+	log.Println("清理结束")
 }
 
-func clearPCKey(nowtime int64) {
-	delkey := clearIdsKeys(PCKey, nowtime)
-	PCKey.Lock.Lock()
+func clearPNCBKey(pncb *KeyMap, nowtime int64) {
+	delkey := clearIdsKeys(pncb, nowtime)
+	pncb.Lock.Lock()
 	for _, k := range delkey {
-		delete(PCKey.Map, k)
+		delete(pncb.Map, k)
 	}
-	PCKey.Lock.Unlock()
+	pncb.Lock.Unlock()
 }
 
 func clearIdsKeys(pKey *KeyMap, nowtime int64) []string {

+ 21 - 140
udpprojectset/src/compare.go

@@ -1,10 +1,6 @@
 package main
 
 import (
-	"encoding/json"
-	du "jy/util"
-	"log"
-	"math"
 	"qfw/util"
 	"qfw/util/redis"
 	"regexp"
@@ -50,43 +46,14 @@ type ProjectInfo struct {
 	Winnerorder []string //中标候选人
 }
 
-//抽取信息映射实体类
-type Info struct {
-	Id            string                 `json:"_id"`
-	Href          string                 `json:"href"`
-	Publishtime   int64                  `json:"publishtime"`
-	Title         string                 `json:"title"`
-	TopType       string                 `json:"toptype"`
-	SubType       string                 `json:"subtype"`
-	ProjectName   string                 `json:"projectname"`
-	ProjectCode   string                 `json:"projectcode"`
-	Buyer         string                 `json:"buyer"`
-	Buyerperson   string                 `json:"buyerperson"`
-	Buyertel      string                 `json:"buyertel"`
-	Agency        string                 `json:"agency"`
-	Area          string                 `json:"area"`
-	HasPackage    bool                   `json:"haspackage"`
-	Package       map[string]interface{} `json:"package"`
-	PNum          string                 `json:"pnum"`
-	Topscopeclass []string               `json:"topscopeclass"`
-	Subscopeclass []string               `json:"subscopeclass"`
-	Winners       []string
-	dealtype      int
-
-	Buyerclass  string `json:"buyerclass"`
-	Bidopentime int64  `json:"bidopentime"`
-	District    string `json:"district"`
-	Winnerorder []string
-}
-
 type CompareOne struct {
-	ProjectNameType int //项目名称对比结果分类 0未比较 1相等 2包含 3不相等
-	ProjectCodeType int //0未比较 1相等 2包含 3不相等
-	AreaType        int //0未比较 1相等 2不相等
-	PublistimeType  int //1在时间范围  2不在
-	BuyerType       int //0未比较 1相等 2包含 3不相等
-	AgencyType      int //0未比较 1相等 2包含 3不相等
-	PackageType     int //1都是多包 2都不是多包 3招标 4新信息是结果
+	ProjectNameType string //项目名称对比结果分类 A相等 B包含 C不相等 Dthis存在对比不存在 Ethis不存在
+	ProjectCodeType string //同上
+	BuyerType       string //同上
+	AreaType        string //同上
+	AgencyType      string //同上
+	PublistimeType  int    //1在时间范围  2不在
+	PackageType     int    //1都是多包 2都不是多包 3招标 4新信息是结果
 	Score           int
 	Parent          *CompareInfo
 	Pinfo           *ProjectInfo
@@ -120,104 +87,24 @@ var TitleReg = regexp.MustCompile("([一二三四五六七八九十0-9A-Za-zⅠ
 //对比打分程序
 func Compare(tmp map[string]interface{} /*新信息*/, pici int64) (sflag string) {
 	defer util.Catch()
-	/***********信息预处理开始***********/
-	//信息由map转换成Info对象
-	bys, _ := json.Marshal(tmp)
-	var thisinfo *Info
-	json.Unmarshal(bys, &thisinfo)
+	thisinfo := PreThisInfo(tmp) //信息预处理
 	if thisinfo == nil {
 		return
 	}
-	if len(thisinfo.Topscopeclass) == 0 {
-		thisinfo.Topscopeclass = []string{}
-	}
-	if len(thisinfo.Subscopeclass) == 0 {
-		thisinfo.Subscopeclass = []string{}
-	}
-	//去重
-	thisinfo.Subscopeclass = RemoveDup(thisinfo.Subscopeclass)
-
-	if len(thisinfo.Package) > 0 { //信息是否分包
-		thisinfo.HasPackage = true
-	} else if thisinfo.TopType == "结果" && TitleReg.MatchString(thisinfo.Title) {
-		//当信息类型是结果时,并且标题中包含分包字样,找到包号,用以后面比较打分
-		res := TitleReg.FindAllStringSubmatch(thisinfo.Title, -1)
-		pnum := du.PackageNumberConvert(res[0][0])
-		du.Debug(pnum, res)
-		thisinfo.PNum = pnum
-	}
-	if thisinfo.SubType == "变更" || strings.Index(thisinfo.Title, "变更公告") > -1 || strings.Index(thisinfo.Title, "更正公告") > -1 {
-		//当信息类型是变更或标题中含变更时
-		if thisinfo.TopType == "招标" {
-			//招标的变更公告过,不作处理
-			du.Debug(thisinfo.Id, thisinfo.Href, thisinfo.ProjectName, thisinfo.ProjectCode)
-			return
-		} else if thisinfo.TopType == "结果" {
-			thisinfo.SubType = "变更"
-		}
-	}
-
-	//计算中标人
-	winner, _ := tmp["winner"].(string)
-	m1 := map[string]bool{}
-	winners := []string{}
-	if winner != "" {
-		m1[winner] = true
-		winners = append(winners, winner)
-	}
-	if thisinfo.HasPackage {
-		packageM, _ := tmp["package"].(bson.M)
-		for _, p := range packageM {
-			pm, _ := p.(map[string]interface{})
-			pw, _ := pm["winner"].(string)
-			if pw != "" {
-				m1[pw] = true
-				winners = append(winners, pw)
-			}
-		}
-	}
-	thisinfo.Winners = winners
-	m1 = nil
-	//中标候选人
-	winnerorder := []string{}
-	if winorders, ok := tmp["winnerorder"].([]interface{}); ok {
-		for _, wins := range winorders {
-			if win, ok := wins.(map[string]interface{}); ok {
-				entname := util.ObjToString(win["entname"])
-				if entname != "" && len([]rune(entname)) > 6 {
-					winnerorder = append(winnerorder, entname)
-				}
-			}
-		}
-	}
-	thisinfo.Winnerorder = winnerorder
-	/***********信息预处理**结束***********/
-	updateid := ""
-
 	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)
 	}
-	//分值排序
-	tmpArr := []*CompareOne{}
 	repeatId := map[string]bool{}
 	IdLock.Lock()
 	//此处加id锁,会引进多线程的死锁,对比三个大map数组,找到key相同的项目id数组,并去重
@@ -238,13 +125,6 @@ func Compare(tmp map[string]interface{} /*新信息*/, pici int64) (sflag string
 				if !repeatId[id] {
 					newarr = append(newarr, id)
 					repeatId[id] = true
-					idlk := IdLockMap[id]
-					if idlk == nil {
-						idlk = &sync.Mutex{}
-						IdLockMap[id] = idlk
-					}
-					idlk.Lock()
-					defer idlk.Unlock()
 				}
 			}
 			PNCB.IdArr = newarr
@@ -252,16 +132,20 @@ func Compare(tmp map[string]interface{} /*新信息*/, pici int64) (sflag string
 	}
 	IdLock.Unlock()
 
+	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)
+				//PNCB.compute(thisinfo, PNCB.IdArr)
+				PNCB.ProcessInfo(thisinfo)
 				tmpArr = append(tmpArr, PNCB.Scores...)
 			}
 		}
 	}
+
 	//排序取出最大分值的对象,更新对象
+	updateid := ""
 	if len(tmpArr) > 0 {
 		sort.Slice(tmpArr, func(i, j int) bool {
 			return tmpArr[i].Score > tmpArr[j].Score
@@ -273,16 +157,12 @@ func Compare(tmp map[string]interface{} /*新信息*/, pici int64) (sflag string
 			updateid = updateinfo(thisinfo, tmp, max.Pinfo, pici)
 		}
 	}
-	/***********根据采购单位比对**结束***********/
+
 	if updateid == "" {
 		sflag = "normal"
 		updateid = InsertProject(new_pn, tmp, pici, thisinfo)
 		p1 := NewPinfo(updateid, thisinfo)
-		//PUT = append(PUT, []interface{}{updateid, p1})
 		redis.PutCKV(REDISIDS, updateid, p1)
-		//IdLock.Lock()
-		//IdLockMap[updateid] = &sync.Mutex{}
-		//IdLock.Unlock()
 	} else {
 		sflag = "repeat"
 	}
@@ -378,10 +258,10 @@ func NewPinfo(id string, thisinfo *Info) ProjectInfo {
 		Area:          thisinfo.Area,
 		HasPackage:    thisinfo.HasPackage,
 		Package:       map[string]interface{}{},
-		//		Buyerclass:    thisinfo.Buyerclass,
-		//		Bidopentime:   thisinfo.Bidopentime,
-		//		District:      thisinfo.District,
-		Winnerorder: thisinfo.Winnerorder,
+		Buyerclass:    thisinfo.Buyerclass,
+		Bidopentime:   thisinfo.Bidopentime,
+		District:      thisinfo.District,
+		Winnerorder:   thisinfo.Winnerorder,
 	}
 	for k4, _ := range thisinfo.Package {
 		p1.Package[k4] = ""
@@ -616,7 +496,8 @@ func EqInfoUpdate(thisinfo *Info, pInfo *ProjectInfo) {
 	//return pInfo
 }
 
-func (com *CompareInfo /*对比对象,分别含有项目名称、项目编号、采购单位*/) compute(thisinfo *Info /*新信息*/, ids []string) {
+/**
+func (com *CompareInfo) compute(thisinfo *Info, ids []string) {
 	//根据 com的key到redis中查找对应的值(如:项目名称的key为"pn_某某项目",值为一维对象数组 即:[]ProjectInfo)
 	//这些信息id上面已经加过锁
 	defer util.Catch()
@@ -752,7 +633,7 @@ func (com *CompareInfo /*对比对象,分别含有项目名称、项目编号
 		}
 	}
 }
-
+**/
 //二分字符串查找
 func BinarySearch(s []string, k string) int {
 	sort.Strings(s)

+ 1 - 8
udpprojectset/src/main.go

@@ -88,7 +88,6 @@ func NewKeyMap() *KeyMap {
 var PNKey, PCKey, PBKey = NewKeyMap(), NewKeyMap(), NewKeyMap()
 
 //id-lock
-var IdLockMap = map[string]*sync.Mutex{}
 var IdLock = &sync.Mutex{}
 
 func main() {
@@ -118,9 +117,6 @@ func main() {
 								var a1 []string
 								json.Unmarshal(v1.([]uint8), &a1)
 								pk.Map[arr[k1]] = &Key{&a1, &sync.Mutex{}} //pn_项目名称 id数组
-								for _, id := range a1 {
-									IdLockMap[id] = &sync.Mutex{}
-								}
 							}
 						}
 					}
@@ -135,9 +131,6 @@ func main() {
 							var a1 []string
 							json.Unmarshal(v1.([]uint8), &a1)
 							pk.Map[arr[k1]] = &Key{&a1, &sync.Mutex{}}
-							for _, id := range a1 {
-								IdLockMap[id] = &sync.Mutex{}
-							}
 						}
 					}
 				}
@@ -147,7 +140,7 @@ func main() {
 	}
 	log.Println("load data from redis finished.", n)
 	//清理redis
-	//cleardis()
+	//clearedis()
 	updport := Sysconfig["udpport"].(string)
 	udpclient = mu.UdpClient{Local: updport, BufSize: 1024}
 	udpclient.Listen(processUdpMsg)

+ 0 - 307
udpprojectset/src/main.go_idmemcheck

@@ -1,307 +0,0 @@
-package main
-
-import (
-	"encoding/json"
-	"log"
-	"math"
-	mu "mfw/util"
-	"net"
-	"os"
-	"qfw/util"
-	"qfw/util/mongodb"
-	"qfw/util/redis"
-	"sync"
-	"time"
-	du "util"
-
-	"gopkg.in/mgo.v2/bson"
-)
-
-/*
-从extract_result表中抽到projectset表中,根据3选2判断是不是同一条信息,抽取信息至少有两个字段。
-可以使用redis
-//对时间的判断
-*/
-var MultiThread chan bool
-var (
-	Sysconfig                map[string]interface{}
-	MQFW                     mongodb.MongodbSim
-	extractColl, projectColl string
-	lenprojectname           int
-	udpclient                mu.UdpClient             //udp对象
-	nextNode                 []map[string]interface{} //下节点数组
-	toaddr                   = []*net.UDPAddr{}       //下节点对象
-)
-
-const (
-	REDISIDS  = "ids"
-	REDISKEYS = "keys"
-)
-
-func init() {
-	initarea()
-	du.SetConsole(false)
-	du.SetRollingDaily("./", "extract.log")
-	du.SetLevel(du.DEBUG)
-	util.ReadConfig(&Sysconfig)
-	MultiThread = make(chan bool, util.IntAllDef(Sysconfig["thread"], 200))
-	lenprojectname = util.IntAllDef(Sysconfig["lenprojectname"], 20) - 1
-	redis.InitRedisBySize(Sysconfig["redisaddrs"].(string), util.IntAllDef(Sysconfig["redisPoolSize"], 100), 30, 300)
-	MQFW = mongodb.MongodbSim{
-		MongodbAddr: Sysconfig["mongodbServers"].(string),
-		Size:        util.IntAll(Sysconfig["mongodbPoolSize"]),
-		DbName:      Sysconfig["mongodbName"].(string),
-	}
-	MQFW.InitPool()
-	extractColl = Sysconfig["extractColl"].(string)
-	projectColl = Sysconfig["projectColl"].(string)
-	nextNode = util.ObjArrToMapArr(Sysconfig["nextNode"].([]interface{}))
-	for _, m := range nextNode {
-		toaddr = append(toaddr, &net.UDPAddr{
-			IP:   net.ParseIP(m["addr"].(string)),
-			Port: util.IntAll(m["port"]),
-		})
-	}
-}
-
-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 IdLockMap = map[string]*sync.Mutex{}
-var IdLock = &sync.Mutex{}
-var tmps = &struct{}{}
-var Infoids = map[string]*struct{}{}
-var InfoLock = &sync.Mutex{}
-
-func main() {
-	//从数据库加载
-	log.Println("loading infoids from mongodb..")
-	func() {
-		sess := MQFW.GetMgoConn()
-		defer MQFW.DestoryMongoConn(sess)
-		all := MQFW.Count(projectColl, nil)
-		log.Println("load all ids count:", all)
-		if all < 1 {
-			log.Println("load ids err!")
-			return
-		}
-		it := sess.DB(MQFW.DbName).C(projectColl).Find(nil).Select(&map[string]interface{}{
-			"list.infoid": 1,
-		}).Iter()
-		count := 0
-		mpool := make(chan bool, 10)
-		for tmp := make(map[string]interface{}); it.Next(tmp); {
-			count++
-			mpool <- true
-			go func(tmp map[string]interface{}) {
-				defer func() {
-					<-mpool
-				}()
-				list, _ := tmp["list"].([]interface{})
-				if len(list) > 0 {
-					for _, lv := range list {
-						m1 := lv.(map[string]interface{})
-						InfoLock.Lock()
-						Infoids[util.ObjToString(m1["infoid"])] = tmps
-						InfoLock.Unlock()
-					}
-				}
-			}(tmp)
-			if count%10000 == 0 {
-				log.Println("count:", count)
-			}
-			tmp = make(map[string]interface{})
-		}
-		if math.Abs(float64(all-len(Infoids))) < float64(5) {
-			log.Println("数据加载不完整,退出", all, len(Infoids))
-			os.Exit(0)
-		}
-	}()
-	log.Println("load infoids finished.", len(Infoids))
-	//先加载所有锁
-	log.Println("loading data from redis...")
-	n := 0
-	km := []*KeyMap{PNKey, PCKey, PBKey}
-	for pos, key := range []string{"pn_*", "pc_*", "pb_*"} {
-		res := redis.GetKeysByPattern(REDISKEYS, key)
-		pk := km[pos]
-		if res != nil {
-			//一次500条
-			num := 0
-			arr := []string{}
-			for _, v := range res {
-				n++
-				num++
-				k := string(v.([]uint8))
-				arr = append(arr, k)
-				if num == 500 {
-					num = 0
-					ret := redis.Mget(REDISKEYS, arr)
-					if len(ret) > 0 {
-						for k1, v1 := range ret {
-							if v1 != nil {
-								var a1 []string
-								json.Unmarshal(v1.([]uint8), &a1)
-								pk.Map[arr[k1]] = &Key{&a1, &sync.Mutex{}}
-								for _, id := range a1 {
-									IdLockMap[id] = &sync.Mutex{}
-								}
-							}
-						}
-					}
-					arr = []string{}
-				}
-			}
-			if num > 0 {
-				ret := redis.Mget(REDISKEYS, arr)
-				if len(ret) > 0 {
-					for k1, v1 := range ret {
-						if v1 != nil {
-							var a1 []string
-							json.Unmarshal(v1.([]uint8), &a1)
-							pk.Map[arr[k1]] = &Key{&a1, &sync.Mutex{}}
-							for _, id := range a1 {
-								IdLockMap[id] = &sync.Mutex{}
-							}
-						}
-					}
-				}
-				arr = []string{}
-			}
-		}
-	}
-	log.Println("load data from redis finished.", n)
-	updport := Sysconfig["udpport"].(string)
-	udpclient = mu.UdpClient{Local: updport, BufSize: 1024}
-	udpclient.Listen(processUdpMsg)
-	log.Println("Udp服务监听", updport)
-	time.Sleep(99999 * time.Hour)
-}
-
-func processUdpMsg(act byte, data []byte, ra *net.UDPAddr) {
-	switch act {
-	case mu.OP_TYPE_DATA: //上个节点的数据
-		var mapInfo map[string]interface{}
-		err := json.Unmarshal(data, &mapInfo)
-		log.Println("err:", err, "mapInfo:", mapInfo)
-		if err != nil {
-			udpclient.WriteUdp([]byte("err:"+err.Error()), mu.OP_NOOP, ra)
-		} else if mapInfo != nil {
-			udpclient.WriteUdp([]byte("ok,run"), mu.OP_NOOP, ra)
-			SingleThread <- true
-			go task(data, mapInfo)
-		}
-	case mu.OP_NOOP: //下个节点回应
-		log.Println("发送成功", string(data))
-	}
-}
-
-var SingleThread = make(chan bool, 1)
-
-func task(data []byte, mapInfo map[string]interface{}) {
-	defer func() {
-		<-SingleThread
-	}()
-	defer util.Catch()
-	q, _ := mapInfo["query"].(map[string]interface{})
-	if q == nil {
-		q = map[string]interface{}{
-			"_id": map[string]interface{}{
-				"$gt":  util.StringTOBsonId(mapInfo["gtid"].(string)),
-				"$lte": util.StringTOBsonId(mapInfo["lteid"].(string)),
-			},
-		}
-	}
-	sess := MQFW.GetMgoConn()
-	defer MQFW.DestoryMongoConn(sess)
-	//数据正序处理
-	it := sess.DB(MQFW.DbName).C(extractColl).Find(&q).Iter() //.Sort("publishtime")
-	count := 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); {
-		count++
-		thisid := util.BsonIdToSId(tmp["_id"])
-		InfoLock.Lock()
-		bexists := Infoids[thisid]
-		InfoLock.Unlock()
-		if bexists == nil && util.IntAll(tmp["infoformat"]) < 2 && tmp["detail"] != nil {
-			//增加判重逻辑,重复id不再生成
-			wg.Add(1)
-			idmap.Store(tmp["_id"], true)
-			MultiThread <- true
-			go func(tmp map[string]interface{}, thisid string) {
-				defer func() {
-					<-MultiThread
-					wg.Done()
-					idmap.Delete(tmp["_id"])
-				}()
-				sflag := Compare(tmp, pici)
-				InfoLock.Lock()
-				Infoids[thisid] = tmps
-				InfoLock.Unlock()
-				go IS.Add(sflag)
-			}(tmp, thisid)
-		}
-		if count%500 == 0 {
-			log.Println("count:", count)
-		}
-		tmp = make(map[string]interface{})
-	}
-	for {
-		time.Sleep(5 * time.Second)
-		n := 0
-		idmap.Range(func(key interface{}, v interface{}) bool {
-			n++
-			log.Println(key, v)
-			return true
-		})
-		if n < 1 {
-			break
-		}
-	}
-	wg.Wait()
-	log.Println("task over...")
-	//发送udp,调用生成项目索引
-	mapInfo["stype"] = "project"
-	mapInfo["query"] = map[string]interface{}{
-		"pici": pici,
-	}
-	datas, _ := json.Marshal(mapInfo)
-	for _, to := range toaddr {
-		udpclient.WriteUdp(datas, mu.OP_TYPE_DATA, to)
-	}
-}
-
-func NewPushInfo(tmp map[string]interface{}) bson.M {
-	return bson.M{
-		"comeintime":  tmp["comeintime"],
-		"publishtime": tmp["publishtime"],
-		"title":       tmp["title"],
-		"toptype":     tmp["toptype"],
-		"subtype":     tmp["subtype"],
-		"infoformat":  tmp["infoformat"],
-		"infoid":      util.BsonIdToSId(tmp["_id"]),
-		"href":        tmp["href"],
-	}
-}

+ 0 - 309
udpprojectset/src/main.go_nocheck

@@ -1,309 +0,0 @@
-package main
-
-import (
-	"encoding/json"
-	"log"
-	//"math"
-	mu "mfw/util"
-	"net"
-	//"os"
-	"qfw/util"
-	"qfw/util/mongodb"
-	"qfw/util/redis"
-	"sync"
-	"time"
-	du "util"
-
-	"gopkg.in/mgo.v2/bson"
-)
-
-/*
-从extract_result表中抽到projectset表中,根据3选2判断是不是同一条信息,抽取信息至少有两个字段。
-可以使用redis
-//对时间的判断
-*/
-var MultiThread chan bool
-var (
-	Sysconfig                map[string]interface{}
-	MQFW                     mongodb.MongodbSim
-	extractColl, projectColl string
-	lenprojectname           int
-	udpclient                mu.UdpClient             //udp对象
-	nextNode                 []map[string]interface{} //下节点数组
-	toaddr                   = []*net.UDPAddr{}       //下节点对象
-)
-
-const (
-	REDISIDS  = "ids"
-	REDISKEYS = "keys"
-)
-
-func init() {
-	initarea()
-	du.SetConsole(false)
-	du.SetRollingDaily("./", "extract.log")
-	du.SetLevel(du.DEBUG)
-	util.ReadConfig(&Sysconfig)
-	MultiThread = make(chan bool, util.IntAllDef(Sysconfig["thread"], 200))
-	lenprojectname = util.IntAllDef(Sysconfig["lenprojectname"], 20) - 1
-	redis.InitRedisBySize(Sysconfig["redisaddrs"].(string), util.IntAllDef(Sysconfig["redisPoolSize"], 100), 30, 300)
-	MQFW = mongodb.MongodbSim{
-		MongodbAddr: Sysconfig["mongodbServers"].(string),
-		Size:        util.IntAll(Sysconfig["mongodbPoolSize"]),
-		DbName:      Sysconfig["mongodbName"].(string),
-	}
-	MQFW.InitPool()
-	extractColl = Sysconfig["extractColl"].(string)
-	projectColl = Sysconfig["projectColl"].(string)
-	nextNode = util.ObjArrToMapArr(Sysconfig["nextNode"].([]interface{}))
-	for _, m := range nextNode {
-		toaddr = append(toaddr, &net.UDPAddr{
-			IP:   net.ParseIP(m["addr"].(string)),
-			Port: util.IntAll(m["port"]),
-		})
-	}
-}
-
-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 IdLockMap = map[string]*sync.Mutex{}
-var IdLock = &sync.Mutex{}
-
-//var tmps = &struct{}{}
-//var Infoids = map[string]*struct{}{}
-//var InfoLock = &sync.Mutex{}
-
-func main() {
-	//从数据库加载
-	//	log.Println("loading infoids from mongodb..")
-	//	func() {
-	//		sess := MQFW.GetMgoConn()
-	//		defer MQFW.DestoryMongoConn(sess)
-	//		all := MQFW.Count(projectColl, nil)
-	//		log.Println("load all ids count:", all)
-	//		if all < 1 {
-	//			log.Println("load ids err!")
-	//			return
-	//		}
-	//		it := sess.DB(MQFW.DbName).C(projectColl).Find(nil).Select(&map[string]interface{}{
-	//			"list.infoid": 1,
-	//		}).Iter()
-	//		count := 0
-	//		mpool := make(chan bool, 10)
-	//		for tmp := make(map[string]interface{}); it.Next(tmp); {
-	//			count++
-	//			mpool <- true
-	//			go func(tmp map[string]interface{}) {
-	//				defer func() {
-	//					<-mpool
-	//				}()
-	//				list, _ := tmp["list"].([]interface{})
-	//				if len(list) > 0 {
-	//					for _, lv := range list {
-	//						m1 := lv.(map[string]interface{})
-	//						InfoLock.Lock()
-	//						Infoids[util.ObjToString(m1["infoid"])] = tmps
-	//						InfoLock.Unlock()
-	//					}
-	//				}
-	//			}(tmp)
-	//			if count%10000 == 0 {
-	//				log.Println("count:", count)
-	//			}
-	//			tmp = make(map[string]interface{})
-	//		}
-	//		if math.Abs(float64(all-len(Infoids))) < float64(5) {
-	//			log.Println("数据加载不完整,退出", all, len(Infoids))
-	//			os.Exit(0)
-	//		}
-	//	}()
-	//	log.Println("load infoids finished.", len(Infoids))
-	//先加载所有锁
-	log.Println("loading data from redis...")
-	n := 0
-	km := []*KeyMap{PNKey, PCKey, PBKey}
-	for pos, key := range []string{"pn_*", "pc_*", "pb_*"} {
-		res := redis.GetKeysByPattern(REDISKEYS, key)
-		pk := km[pos]
-		if res != nil {
-			//一次500条
-			num := 0
-			arr := []string{}
-			for _, v := range res {
-				n++
-				num++
-				k := string(v.([]uint8))
-				arr = append(arr, k)
-				if num == 500 {
-					num = 0
-					ret := redis.Mget(REDISKEYS, arr)
-					if len(ret) > 0 {
-						for k1, v1 := range ret {
-							if v1 != nil {
-								var a1 []string
-								json.Unmarshal(v1.([]uint8), &a1)
-								pk.Map[arr[k1]] = &Key{&a1, &sync.Mutex{}}
-								for _, id := range a1 {
-									IdLockMap[id] = &sync.Mutex{}
-								}
-							}
-						}
-					}
-					arr = []string{}
-				}
-			}
-			if num > 0 {
-				ret := redis.Mget(REDISKEYS, arr)
-				if len(ret) > 0 {
-					for k1, v1 := range ret {
-						if v1 != nil {
-							var a1 []string
-							json.Unmarshal(v1.([]uint8), &a1)
-							pk.Map[arr[k1]] = &Key{&a1, &sync.Mutex{}}
-							for _, id := range a1 {
-								IdLockMap[id] = &sync.Mutex{}
-							}
-						}
-					}
-				}
-				arr = []string{}
-			}
-		}
-	}
-	log.Println("load data from redis finished.", n)
-	updport := Sysconfig["udpport"].(string)
-	udpclient = mu.UdpClient{Local: updport, BufSize: 1024}
-	udpclient.Listen(processUdpMsg)
-	log.Println("Udp服务监听", updport)
-	time.Sleep(99999 * time.Hour)
-}
-
-func processUdpMsg(act byte, data []byte, ra *net.UDPAddr) {
-	switch act {
-	case mu.OP_TYPE_DATA: //上个节点的数据
-		var mapInfo map[string]interface{}
-		err := json.Unmarshal(data, &mapInfo)
-		log.Println("err:", err, "mapInfo:", mapInfo)
-		if err != nil {
-			udpclient.WriteUdp([]byte("err:"+err.Error()), mu.OP_NOOP, ra)
-		} else if mapInfo != nil {
-			udpclient.WriteUdp([]byte("ok,run"), mu.OP_NOOP, ra)
-			SingleThread <- true
-			go task(data, mapInfo)
-		}
-	case mu.OP_NOOP: //下个节点回应
-		log.Println("发送成功", string(data))
-	}
-}
-
-var SingleThread = make(chan bool, 1)
-
-func task(data []byte, mapInfo map[string]interface{}) {
-	defer func() {
-		<-SingleThread
-	}()
-	defer util.Catch()
-	q, _ := mapInfo["query"].(map[string]interface{})
-	if q == nil {
-		q = map[string]interface{}{
-			"_id": map[string]interface{}{
-				"$gt":  util.StringTOBsonId(mapInfo["gtid"].(string)),
-				"$lte": util.StringTOBsonId(mapInfo["lteid"].(string)),
-			},
-		}
-	}
-	sess := MQFW.GetMgoConn()
-	defer MQFW.DestoryMongoConn(sess)
-	//数据正序处理
-	it := sess.DB(MQFW.DbName).C(extractColl).Find(&q).Iter() //.Sort("publishtime")
-	count := 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); {
-		count++
-		thisid := util.BsonIdToSId(tmp["_id"])
-		//		InfoLock.Lock()
-		//		bexists := Infoids[thisid]
-		//		InfoLock.Unlock()
-		//		if bexists == nil && util.IntAll(tmp["infoformat"]) < 2 && tmp["detail"] != nil {
-		if util.IntAll(tmp["infoformat"]) < 2 && tmp["detail"] != nil {
-			//增加判重逻辑,重复id不再生成
-			wg.Add(1)
-			idmap.Store(tmp["_id"], true)
-			MultiThread <- true
-			go func(tmp map[string]interface{}, thisid string) {
-				defer func() {
-					<-MultiThread
-					wg.Done()
-					idmap.Delete(tmp["_id"])
-				}()
-				sflag := Compare(tmp, pici)
-				//				InfoLock.Lock()
-				//				Infoids[thisid] = tmps
-				//				InfoLock.Unlock()
-				go IS.Add(sflag)
-			}(tmp, thisid)
-		}
-		if count%500 == 0 {
-			log.Println("count:", count)
-		}
-		tmp = make(map[string]interface{})
-	}
-	for {
-		time.Sleep(5 * time.Second)
-		n := 0
-		idmap.Range(func(key interface{}, v interface{}) bool {
-			n++
-			log.Println(key, v)
-			return true
-		})
-		if n < 1 {
-			break
-		}
-	}
-	wg.Wait()
-	log.Println("task over...")
-	//发送udp,调用生成项目索引
-	mapInfo["stype"] = "project"
-	mapInfo["query"] = map[string]interface{}{
-		"pici": pici,
-	}
-	datas, _ := json.Marshal(mapInfo)
-	for _, to := range toaddr {
-		udpclient.WriteUdp(datas, mu.OP_TYPE_DATA, to)
-	}
-}
-
-func NewPushInfo(tmp map[string]interface{}) bson.M {
-	return bson.M{
-		"comeintime":  tmp["comeintime"],
-		"publishtime": tmp["publishtime"],
-		"title":       tmp["title"],
-		"toptype":     tmp["toptype"],
-		"subtype":     tmp["subtype"],
-		"infoformat":  tmp["infoformat"],
-		"infoid":      util.BsonIdToSId(tmp["_id"]),
-		"href":        tmp["href"],
-	}
-}

+ 19 - 0
udpprojectset/src/main_test.go

@@ -1,6 +1,7 @@
 package main
 
 import (
+	"fmt"
 	"log"
 	"testing"
 )
@@ -37,3 +38,21 @@ func Test_main(t *testing.T) {
 	//arr := []string{"aa", "bb", "cc", "dd", "ee", "abdsfsdfsd"}
 	//log.Println("二分查找", binarySearch(arr, "bb"))
 }
+func Test_3t2(t *testing.T) {
+	pcb := [][]string{
+		[]string{"A", "B"},
+		[]string{"A", "B"},
+		[]string{"A", "B"},
+	}
+	for _, v1 := range pcb[0] {
+		tmp := []string{}
+		for _, v2 := range pcb[1] {
+			for _, v3 := range pcb[1] {
+				key := fmt.Sprintf("%s%s%s", v1, v2, v3)
+				tmp = append(tmp, key)
+			}
+		}
+		log.Println(tmp)
+	}
+
+}

+ 230 - 0
udpprojectset/src/scores.go

@@ -0,0 +1,230 @@
+// 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,
+	}
+	twos := [][][]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 _, two := range twos {
+		for _, v1 := range two[0] {
+			for _, v2 := range two[1] {
+				for _, v3 := range two[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) ComputeTwo(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,
+				}
+				fieldPCBScore(thisinfo.Buyer, info.Buyer, cone.BuyerType, cone.Score)
+				if hasbyer {
+					fieldPCBScore(thisinfo.ProjectName, info.ProjectName, cone.ProjectNameType, cone.Score)
+					fieldPCBScore(thisinfo.ProjectCode, info.ProjectCode, cone.ProjectCodeType, cone.Score)
+				} else { //无采购单位,打分考虑长度
+					if len([]rune(thisinfo.ProjectName)) > 5 {
+						fieldPCBScore(thisinfo.ProjectName, info.ProjectName, cone.ProjectNameType, cone.Score)
+					} else {
+						cone.ProjectNameType = "D"
+					}
+					if len([]rune(thisinfo.ProjectName)) > 6 {
+						fieldPCBScore(thisinfo.ProjectCode, info.ProjectCode, cone.ProjectCodeType, cone.Score)
+					} else {
+						cone.ProjectNameType = "D"
+					}
+				}
+				//省市打分
+				if thisinfo.Area != "A" && thisinfo.Area != "全国" && info.Area != "A" && info.Area != "全国" {
+					if thisinfo.Area == info.Area && thisinfo.District == info.District {
+						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) {
+	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"
+	}
+}

+ 243 - 0
udpprojectset/src/thisinfo.go

@@ -0,0 +1,243 @@
+// thisinfo
+package main
+
+import (
+	"encoding/json"
+	"fmt"
+	du "jy/util"
+	"qfw/util"
+	"strings"
+
+	"gopkg.in/mgo.v2/bson"
+)
+
+//抽取信息映射实体类
+type Info struct {
+	Id            string                 `json:"_id"`
+	Href          string                 `json:"href"`
+	Publishtime   int64                  `json:"publishtime"`
+	Title         string                 `json:"title"`
+	TopType       string                 `json:"toptype"`
+	SubType       string                 `json:"subtype"`
+	ProjectName   string                 `json:"projectname"`
+	ProjectCode   string                 `json:"projectcode"`
+	Buyer         string                 `json:"buyer"`
+	Buyerperson   string                 `json:"buyerperson"`
+	Buyertel      string                 `json:"buyertel"`
+	Agency        string                 `json:"agency"`
+	Area          string                 `json:"area"`
+	HasPackage    bool                   `json:"haspackage"`
+	Package       map[string]interface{} `json:"package"`
+	PNum          string                 `json:"pnum"`
+	Topscopeclass []string               `json:"topscopeclass"`
+	Subscopeclass []string               `json:"subscopeclass"`
+	Winners       []string
+	dealtype      int
+
+	Buyerclass  string `json:"buyerclass"`
+	Bidopentime int64  `json:"bidopentime"`
+	District    string `json:"district"`
+	Winnerorder []string
+}
+
+//pcb三选值
+type PCBV struct {
+	Val      int  //1一项有效值,2二项有效值,3三项有效值
+	Pname    bool //有项目名称
+	Cname    bool //有项目编号
+	Bname    bool //有采购单位
+	Area     bool //区域
+	District bool //市县
+	Agency   bool //代理机构
+
+	PnameLen int //值长度
+	CnameLen int //值长度
+	BnameLen int //值长度
+}
+
+func PreThisInfo(tmp map[string]interface{} /*新信息*/) *Info {
+	bys, _ := json.Marshal(tmp)
+	var thisinfo *Info
+	json.Unmarshal(bys, &thisinfo)
+	if thisinfo == nil {
+		return nil
+	}
+	if len(thisinfo.Topscopeclass) == 0 {
+		thisinfo.Topscopeclass = []string{}
+	}
+	if len(thisinfo.Subscopeclass) == 0 {
+		thisinfo.Subscopeclass = []string{}
+	}
+	//去重
+	thisinfo.Subscopeclass = RemoveDup(thisinfo.Subscopeclass)
+
+	if len(thisinfo.Package) > 0 { //信息是否分包
+		thisinfo.HasPackage = true
+	} else if thisinfo.TopType == "结果" && TitleReg.MatchString(thisinfo.Title) {
+		//当信息类型是结果时,并且标题中包含分包字样,找到包号,用以后面比较打分
+		res := TitleReg.FindAllStringSubmatch(thisinfo.Title, -1)
+		pnum := du.PackageNumberConvert(res[0][0])
+		du.Debug(pnum, res)
+		thisinfo.PNum = pnum
+	}
+	if thisinfo.SubType == "变更" || strings.Index(thisinfo.Title, "变更公告") > -1 || strings.Index(thisinfo.Title, "更正公告") > -1 {
+		//当信息类型是变更或标题中含变更时
+		if thisinfo.TopType == "招标" {
+			//招标的变更公告过,不作处理
+			du.Debug(thisinfo.Id, thisinfo.Href, thisinfo.ProjectName, thisinfo.ProjectCode)
+			return nil
+		} else if thisinfo.TopType == "结果" {
+			thisinfo.SubType = "变更"
+		}
+	}
+
+	//计算中标人
+	winner, _ := tmp["winner"].(string)
+	m1 := map[string]bool{}
+	winners := []string{}
+	if winner != "" {
+		m1[winner] = true
+		winners = append(winners, winner)
+	}
+	if thisinfo.HasPackage {
+		packageM, _ := tmp["package"].(bson.M)
+		for _, p := range packageM {
+			pm, _ := p.(map[string]interface{})
+			pw, _ := pm["winner"].(string)
+			if pw != "" {
+				m1[pw] = true
+				winners = append(winners, pw)
+			}
+		}
+	}
+	thisinfo.Winners = winners
+	m1 = nil
+	//中标候选人
+	winnerorder := []string{}
+	if winorders, ok := tmp["winnerorder"].([]interface{}); ok {
+		for _, wins := range winorders {
+			if win, ok := wins.(map[string]interface{}); ok {
+				entname := util.ObjToString(win["entname"])
+				if entname != "" && len([]rune(entname)) > 6 {
+					winnerorder = append(winnerorder, entname)
+				}
+			}
+		}
+	}
+	thisinfo.Winnerorder = winnerorder
+	return thisinfo
+}
+
+//流程处理
+func (com *CompareInfo) ProcessInfo(info *Info) {
+	pcbv := PCBValue(info)
+	if info.SubType == "变更" {
+		if pcbv.Val > 1 {
+			com.Process(info, pcbv)
+		} else {
+			//信息无效
+		}
+	} else { //非变更
+		com.Process(info, pcbv)
+	}
+}
+
+//流程
+func (com *CompareInfo) Process(info *Info, pcbv PCBV) {
+	if pcbv.Bname { //有采购单位
+		if pcbv.Pname || pcbv.Cname {
+			//三选二打分
+			scores := com.ComputeTwo(info, com.IdArr, true)
+			for _, v := range scores {
+				skey := fmt.Sprintf("%s%s%s", v.BuyerType, v.ProjectNameType, v.ProjectCodeType)
+				if ThreeToTow[skey] { //判断是否进入打分合并逻辑
+					com.Scores = append(com.Scores, v)
+				}
+			}
+		} else {
+			//生成项目,不参与后续对比
+		}
+	} else { //无采购单位
+		if pcbv.Pname {
+			if pcbv.Cname {
+				//三选二打分
+				scores := com.ComputeTwo(info, com.IdArr, false)
+				for _, v := range scores {
+					skey := fmt.Sprintf("%s%s%s", v.BuyerType, v.ProjectNameType, v.ProjectCodeType)
+					if ThreeToTow[skey] { //判断是否进入打分合并逻辑
+						com.Scores = append(com.Scores, v)
+					}
+				}
+			} else {
+				if pcbv.PnameLen > 5 {
+					if pcbv.Area && pcbv.District {
+						//三选一打分
+						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] { //判断是否进入打分合并逻辑
+								com.Scores = append(com.Scores, v)
+							}
+						}
+					} else {
+						//生成项目,不参与后续对比
+					}
+				} else {
+					//生成项目,不参与后续对比
+				}
+			}
+		} else {
+			if pcbv.Cname {
+				if pcbv.CnameLen > 8 {
+					if pcbv.Area && pcbv.District {
+						//三选一打分
+						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] { //判断是否进入打分合并逻辑
+								com.Scores = append(com.Scores, v)
+							}
+						}
+					} else {
+						//生成项目,不参与后续对比
+					}
+				} else {
+					//生成项目,不参与后续对比
+				}
+			} else {
+				//信息无效
+			}
+		}
+	}
+}
+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.District != "" {
+		pcbv.District = true
+	}
+	if info.Agency != "" {
+		pcbv.Agency = true
+	}
+	return pcbv
+}