package main import ( "github.com/go-xweb/log" "go.mongodb.org/mongo-driver/bson/primitive" "math" qu "qfw/util" "reflect" "sort" "strings" ) func (p *ProjectTask) modifyUpdate(pInfoId string, index int, info *Info, tmp map[string]interface{}, tmpPro map[string]interface{}, modifyMap map[string]interface{}) { backupPro(tmpPro) infoList := []interface{}(tmpPro["list"].(primitive.A)) infoMap := infoList[index].(map[string]interface{}) infoList[index] = updateValue(infoMap, modifyMap) set := map[string]interface{}{ "$set": tmpPro, } err := MongoTool.UpdateById(ProjectColl, pInfoId, set) log.Println(err) } func (p *ProjectTask) mergeAndModify(pInfoId string, index int, info *Info, tmp map[string]interface{}, tmpPro map[string]interface{}, modifyMap map[string]interface{}) { p.AllIdsMapLock.Lock() currentPro := p.AllIdsMap[pInfoId] p.AllIdsMapLock.Unlock() merge, pId, i, comStr, mergePro := p.updateMerge(index, info, pInfoId, tmp, tmpPro) //招标信息在list中第1个 if index == 0 { log.Println("第1条合并", "------1------") //快照 backupPro(tmpPro) p.AllIdsMapLock.Lock() delete(p.AllIdsMap, pInfoId) p.AllIdsMapLock.Unlock() count := MongoTool.Delete(ProjectColl, pInfoId) log.Println(count) for _, infoId := range currentPro.P.Ids{ if infoId == info.Id { continue } tmp1 := MongoTool.FindById(ExtractColl, infoId) info1 := ParseInfo(tmp1) p.CommonMerge(tmp1, info1) } }else { log.Println("第n条合并", "------n------") //快照 招标信息所在的项目 backupPro(tmpPro) if merge { //跟原项目list第0条信息作对比,可以合并 if pId == pInfoId { //合并到当前项目 mergeProject(p, currentPro.P, info, tmpPro, index) p.AllIdsMapLock.Lock() p.AllIdsMap[currentPro.P.Id.Hex()].P = currentPro.P p.AllIdsMapLock.Unlock() infoList := []interface{}(tmpPro["list"].(primitive.A)) infoMap := infoList[index].(map[string]interface{}) infoList[index] = updateValue(infoMap, modifyMap) set := map[string]interface{}{ "$set": tmpPro, } MongoTool.UpdateById(ProjectColl, pInfoId, set) }else { //合并到的其它项目里边 //更新其它的项目 pro := MongoTool.FindById(ProjectColl, mergePro.Id.Hex()) backupPro(pro, ) choose, ex := CompareStatus(mergePro, info) if !choose { p.UpdateProject(tmp, info, mergePro, i, comStr, ex) }else { id, p1 := p.NewProject(tmp, info) p.AllIdsMapLock.Lock() p.AllIdsMap[id] = &ID{Id: id, P: p1} p.AllIdsMapLock.Unlock() } //内部合并 p.innerMerge(currentPro.P, info, tmp, tmpPro) } }else { //合并到新建的项目里边,原有项目内部合并 p.innerMerge(currentPro.P, info, tmp, tmpPro) } } } func (p *ProjectTask) updateMerge(index int, info *Info, pInfoId string, tmp map[string]interface{}, tmpPro map[string]interface{}) (bool, string, int, string, *ProjectInfo) { bpn, bpc, bptc, bpb, pids, _, IDArr := p.getCompareIds(info.ProjectName, info.ProjectCode, info.PTC, info.Buyer) defer p.wg.Done() for _, m := range pids { defer m.Lock.Unlock() } for _, id := range IDArr { defer id.Lock.Unlock() } bFindProject := false findPid := "" //获取完id,进行计算 //定义两组 comRes1 := []*ProjectInfo{} //优先级最高的对比结果数组 comRes2 := []*ProjectInfo{} //优化级其次 comRes3 := []*ProjectInfo{} for _, v := range IDArr { if index == 0 && pInfoId == v.P.Id.Hex() { //招标条目信息在原项目中是第0条时,忽略 continue } comStr := "" compareProject := v.P compareProject.score = 0 diffTime := int64(math.Abs(float64(info.Publishtime - compareProject.LastTime))) if diffTime <= p.validTime { //代理机构完全不相同,直接新建项目 if CheckContain(compareProject.Agency, info.Agency) == 3 { continue } //地区(省、市、区)不同,直接新建项目 if ComparePlace(compareProject, info) { continue } info.PNBH = 0 info.PCBH = 0 info.PTCBH = 0 compareStr, score := comparePNC(info, compareProject) resVal, pjVal := Select(compareStr, info, compareProject) if resVal > 0 { compareBuyer, compareCity, compareTime, compareAgency, compareBudget, compareBidmount, score2 := p.compareBCTABB(info, compareProject, diffTime, score) //项目名称、项目编号、标题项目编号、采购单位、省、市、发布时间、代理机构 comStr = compareStr + compareBuyer + compareCity + compareTime + compareAgency + compareBudget + compareBidmount compareProject.comStr = comStr compareProject.pjVal = pjVal compareProject.resVal = resVal eqV := compareResult(resVal, pjVal, score2, comStr, compareBuyer, compareCity, compareTime, compareAgency, compareBudget, compareBidmount) if eqV == 1 { comRes1 = append(comRes1, compareProject) } else if eqV == 2 { comRes2 = append(comRes2, compareProject) } else if eqV == 3 { comRes3 = append(comRes3, compareProject) } } } } //--------------------------------对比完成----------------------- k := -1 comStr := "" mergePro := &ProjectInfo{} for kv, resN := range [][]*ProjectInfo{comRes1, comRes2, comRes3} { if len(resN) > 0 { if len(resN) > 1 { sort.Slice(resN, func(i, j int) bool { return resN[i].score > resN[j].score }) } ex := 0 resArr := []*ProjectInfo{} for _, res := range resN{ choose, e := CompareStatus(resN[0], info) if !choose { ex = e resArr = append(resArr, res) } } if len(resArr) > 0 { bFindProject = true findPid = resArr[0].Id.Hex() for k2, bv := range []int{bpn, bpc, bptc, bpb} { if bv > -1 { pids[bv].Arr = append(pids[bv].Arr, findPid) if k2 == 0 { if resArr[0].ProjectName == "" { resArr[0].ProjectName = info.ProjectName } else { if resArr[0].MPN == nil { resArr[0].MPN = []string{info.ProjectName} } else { resArr[0].MPN = append(resArr[0].MPN, info.ProjectName) } } } else if k2 < 3 { if resArr[0].ProjectCode == "" { resArr[0].ProjectCode = qu.If(k2 == 1, info.ProjectCode, info.PTC).(string) } else { if resArr[0].MPC == nil { resArr[0].MPC = []string{qu.If(k2 == 1, info.ProjectCode, info.PTC).(string)} } else { resArr[0].MPC = append(resArr[0].MPC, qu.If(k2 == 1, info.ProjectCode, info.PTC).(string)) } } } else { if resArr[0].Buyer == "" { resArr[0].Buyer = info.Buyer } } } } if index != 0 { //招标条目信息在原项目中是第非0条时,返回对比结果 k = kv+1 comStr = resArr[0].comStr mergePro = resArr[0] bFindProject = false findPid = "" }else { mergePro = resArr[0] //如果有合并,合并之前备份(快照) backupPro(tmpPro) p.UpdateProject(tmp, info, resArr[0], kv+1, resArr[0].comStr, ex) } }else { bFindProject = false findPid = "" } break } } if !bFindProject { id, p1 := p.NewProject(tmp, info) p.AllIdsMapLock.Lock() p.AllIdsMap[id] = &ID{Id: id, P: p1} p.AllIdsMapLock.Unlock() for _, m := range pids { m.Arr = append(m.Arr, id) } } return bFindProject, findPid, k, comStr, mergePro } //内部合并 func (p *ProjectTask) innerMerge(pInfo *ProjectInfo, info *Info, tmp map[string]interface{}, tmpPro map[string]interface{}) { infoList := []interface{}(tmpPro["list"].(primitive.A)) for index, info1 := range infoList{ info2 := info1.(map[string]interface{}) if info2["infoid"] == info.Id { deleteSlice1(infoList, info1) continue } mergeProject(p, pInfo, info, tmpPro, index) } p.AllIdsMapLock.Lock() p.AllIdsMap[pInfo.Id.Hex()].P = pInfo p.AllIdsMapLock.Unlock() set := map[string]interface{}{ "$set": tmpPro, } MongoTool.UpdateById(ProjectColl, pInfo.Id.Hex(), set) } //合并字段到project func mergeProject(p *ProjectTask, pInfo *ProjectInfo, thisinfo *Info, set map[string]interface{}, index int) map[string]interface{} { //1--firsttime if thisinfo.Publishtime < pInfo.FirstTime && thisinfo.Publishtime > 0 { pInfo.FirstTime = thisinfo.Publishtime set["firsttime"] = thisinfo.Publishtime if thisinfo.TopType == "招标" { set["zbtime"] = thisinfo.Publishtime } } //2--lasttime if thisinfo.Publishtime > pInfo.LastTime { pInfo.LastTime = thisinfo.Publishtime set["lasttime"] = thisinfo.Publishtime bt := bidtype[thisinfo.SubType] if bt != "" { set["bidtype"] = bt } if thisinfo.SubType != "" { set["bidstatus"] = thisinfo.SubType if thisinfo.SubType != "预告" { set["jgtime"] = thisinfo.Publishtime } }else if thisinfo.Infoformat == 2 { set["bidstatus"] = "拟建" }else if thisinfo.SubType == "招标" { set["bidstatus"] = thisinfo.TopType }else { set["bidstatus"] = thisinfo.SubType } } //3\4\5--省、市、县 if thisinfo.Area != "全国" { //xt := true if pInfo.Area == "全国" { pInfo.Area = thisinfo.Area set["area"] = thisinfo.Area } else if pInfo.Area != thisinfo.Area { //xt = false } if pInfo.City == "" && thisinfo.City != "" { pInfo.City = thisinfo.City set["city"] = thisinfo.City } else if pInfo.City != thisinfo.City { //xt = false } if thisinfo.District != "" && pInfo.District == "" { pInfo.District = thisinfo.District set["district"] = thisinfo.District } } //6--项目名称 if (thisinfo.ProjectName != "" && pInfo.ProjectName == "") || (len([]rune(pInfo.ProjectName)) < 6 && thisinfo.LenPN > 6) { pInfo.ProjectName = thisinfo.ProjectName set["projectname"] = thisinfo.ProjectName } //7--项目编号 if (pInfo.ProjectCode == "" && thisinfo.ProjectCode != "") || (len([]rune(pInfo.ProjectCode)) < 6 && len([]rune(thisinfo.ProjectCode)) > 6) { pInfo.ProjectCode = thisinfo.ProjectCode set["projectcode"] = thisinfo.ProjectCode } //7--采购单位 if (pInfo.Buyer == "" && thisinfo.Buyer != "") || (len([]rune(pInfo.Buyer)) < 5 && len([]rune(thisinfo.Buyer)) > 5) { pInfo.Buyer = thisinfo.Buyer set["buyer"] = thisinfo.Buyer pInfo.Buyerclass = thisinfo.Buyerclass set["buyerclass"] = thisinfo.Buyerclass } if pInfo.Buyer == "" { set["buyerclass"] = "" } //8--代理机构 if (pInfo.Agency == "" && thisinfo.Agency != "") || (len([]rune(pInfo.Agency)) < 5 && len([]rune(thisinfo.Agency)) > 5) { pInfo.Agency = thisinfo.Agency set["agency"] = thisinfo.Agency } //9--采购单位联系人 if thisinfo.Buyerperson != "" && strings.Index(pInfo.Buyerperson, thisinfo.Buyerperson) < 0 { pInfo.Buyerperson = thisinfo.Buyerperson set["buyerperson"] = pInfo.Buyerperson } //10--采购单位電話 if thisinfo.Buyertel != "" && strings.Index(pInfo.Buyertel, thisinfo.Buyertel) < 0 { pInfo.Buyertel = thisinfo.Buyertel set["buyertel"] = pInfo.Buyertel } if thisinfo.Bidopentime > pInfo.Bidopentime { pInfo.Bidopentime = thisinfo.Bidopentime set["bidopentime"] = pInfo.Bidopentime } if thisinfo.Bidamount > 0 && pInfo.Bidamount < 1 { pInfo.Bidamount = thisinfo.Bidamount set["bidamount"] = pInfo.Bidamount } if thisinfo.Budget > 0 && pInfo.Budget < 1 { //多包的会有问题,没有进行合计。 pInfo.Budget = thisinfo.Budget set["budget"] = pInfo.Budget } if len(thisinfo.Topscopeclass) > 0 { sort.Strings(pInfo.Topscopeclass) for _, k := range thisinfo.Topscopeclass { if BinarySearch(pInfo.Topscopeclass, k) == -1 { pInfo.Topscopeclass = append(pInfo.Topscopeclass, k) sort.Strings(pInfo.Topscopeclass) } } set["topscopeclass"] = pInfo.Topscopeclass } if len(thisinfo.Subscopeclass) > 0 { sort.Strings(pInfo.Subscopeclass) for _, k := range thisinfo.Subscopeclass { if BinarySearch(pInfo.Subscopeclass, k) == -1 { pInfo.Subscopeclass = append(pInfo.Subscopeclass, k) sort.Strings(pInfo.Subscopeclass) } } set["subscopeclass"] = pInfo.Subscopeclass set["s_subscopeclass"] = strings.Join(pInfo.Subscopeclass, ",") } //winner if len(thisinfo.Winners) > 0 { sort.Strings(pInfo.Winners) for _, k := range thisinfo.Winners { if BinarySearch(pInfo.Winners, k) == -1 { pInfo.Winners = append(pInfo.Winners, k) sort.Strings(pInfo.Winners) } } //set["winners"] = pInfo.Winners set["s_winner"] = strings.Join(pInfo.Winners, ",") } if thisinfo.HasPackage { pkg, _, _ := PackageFormat(thisinfo, pInfo) pInfo.Package = pkg } set["mpn"] = pInfo.MPN set["mpc"] = pInfo.MPC set["pici"] = p.pici if thisinfo.HasPackage { set["multipackage"] = 1 } else { set["multipackage"] = 0 } return set } func deleteSlice1(arr []interface{}, v interface{}) []interface{} { for k, v1 := range arr { if reflect.DeepEqual(v1, v) { return append(arr[:k], arr[k+1:]...) } } return arr } func updateValue(info map[string]interface{}, tmp map[string]interface{}) map[string]interface{} { for k := range info{ for k1 := range tmp { if k == k1 && info[k] != tmp[k1] { info[k] = tmp[k] break } } } return info } //备份(快照) func backupPro(tmp map[string]interface{}) { tmp1 := make(map[string]interface{}) for k, v := range tmp{ tmp1[k] = v } if Sysconfig["backupFlag"].(bool) { tmp1["sourceprojectid"] = tmp1["_id"] delete(tmp1, "_id") MongoTool.Save(BackupColl, tmp1) } }