merge.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  1. package main
  2. import (
  3. "math"
  4. qu "qfw/util"
  5. "sort"
  6. //"strconv"
  7. "strings"
  8. "sync"
  9. )
  10. //单线程控制查找
  11. var findLock = sync.Mutex{}
  12. //从对应map中获取对比的项目id
  13. func getCompareIds(pn, pc, ptc, pb string) (bpn, bpc, bptc, bpb int, res []*Key, idArr []string, IDArr []*ID) {
  14. findLock.Lock()
  15. defer findLock.Unlock()
  16. wg.Add(1)
  17. res = []*Key{}
  18. //是否查找到,并标识位置。-1代表未查找到。
  19. bpn, bpc, bptc, bpb = -1, -1, -1, -1
  20. if pn != "" {
  21. ids := mapPn[pn]
  22. if ids == nil {
  23. ids = &Key{Arr: []string{}}
  24. mapPn[pn] = ids
  25. bpn = 0
  26. }
  27. ids.Lock.Lock()
  28. res = append(res, ids)
  29. }
  30. if pc != "" {
  31. ids := mapPc[pc]
  32. if ids == nil {
  33. ids = &Key{Arr: []string{}}
  34. mapPc[pc] = ids
  35. bpc = len(res)
  36. }
  37. ids.Lock.Lock()
  38. res = append(res, ids)
  39. }
  40. if ptc != "" {
  41. ids := mapPc[ptc]
  42. if ids == nil {
  43. ids = &Key{Arr: []string{}}
  44. mapPc[ptc] = ids
  45. bptc = len(res)
  46. }
  47. ids.Lock.Lock()
  48. res = append(res, ids)
  49. }
  50. if pb != "" {
  51. ids := mapPb[pb]
  52. if ids == nil {
  53. ids = &Key{Arr: []string{}}
  54. mapPb[pb] = ids
  55. bpb = len(res)
  56. }
  57. ids.Lock.Lock()
  58. res = append(res, ids)
  59. }
  60. repeatId := map[string]bool{}
  61. idArr = []string{} //项目id
  62. IDArr = []*ID{} //项目信息
  63. for _, m := range res {
  64. for _, id := range m.Arr {
  65. if !repeatId[id] {
  66. repeatId[id] = true
  67. //_, _ = strconv.ParseInt(id[0:8], 16, 64)
  68. AllIdsMapLock.Lock()
  69. Id := AllIdsMap2[id]
  70. AllIdsMapLock.Unlock()
  71. if Id != nil {
  72. Id.Lock.Lock()
  73. idArr = append(idArr, id)
  74. IDArr = append(IDArr, Id)
  75. }
  76. }
  77. }
  78. }
  79. return
  80. }
  81. //项目合并入口
  82. func startProjectMerge(info *Info, tmp map[string]interface{}) {
  83. //只有或没有采购单位的无法合并
  84. //bpn, bpc, bptc, bpb 是否查找到,并标识位置。-1代表未查找到。
  85. //pids 是项目id数组集合
  86. //IDArr,是单个项目ID对象集合
  87. defer wg.Done()
  88. bpn, bpc, bptc, bpb, pids, _, IDArr := getCompareIds(info.ProjectName, info.ProjectCode, info.PTC, info.Buyer)
  89. //map--k为pn,ptn,pc,ptc,buyer值 v为Id数组和lock
  90. for _, m := range pids {
  91. defer m.Lock.Unlock()
  92. }
  93. for _, id := range IDArr {
  94. defer id.Lock.Unlock()
  95. }
  96. bFindProject := false
  97. findPid := ""
  98. //获取完id,进行计算
  99. //定义两组
  100. comRes1 := []*ProjectInfo{} //优先级最高的对比结果数组
  101. comRes2 := []*ProjectInfo{} //优化级其次
  102. comRes3 := []*ProjectInfo{}
  103. for _, v := range IDArr {
  104. comStr := ""
  105. compareProject := v.P
  106. //问题出地LastTime!!!!!
  107. diffTime := math.Abs(float64(info.Publishtime - compareProject.LastTime))
  108. if diffTime < 360*86400 {
  109. //"A 相等 B 被包含 C 不相等 D不存在 E被包含
  110. compareStr, score := comparePNCB(info, compareProject)
  111. resVal := Select(compareStr, info, compareProject)
  112. //---------------------------------------
  113. if resVal > 0 {
  114. compareBuyer := "D"
  115. if info.Buyer != "" {
  116. if info.Buyer == compareProject.Buyer {
  117. compareBuyer = "A"
  118. score += 3
  119. } else if compareProject.Buyer != "" {
  120. if strings.Contains(info.Buyer, compareProject.Buyer) || strings.Contains(compareProject.Buyer, info.Buyer) {
  121. compareBuyer = "B"
  122. score += 1
  123. } else {
  124. compareBuyer = "C"
  125. }
  126. }
  127. }
  128. //---------------------------------------
  129. compareCity := ""
  130. if info.Area != "全国" && info.Area != "" && info.Area == compareProject.Area {
  131. compareCity += "A"
  132. score += 2
  133. } else if info.Area == "全国" || compareProject.Area == "全国" {
  134. compareCity += "B"
  135. score += 1
  136. } else {
  137. compareCity += "C"
  138. }
  139. if compareCity != "C" {
  140. if info.City != "" && info.City == compareProject.City {
  141. compareCity += "A"
  142. score += 2
  143. } else {
  144. if info.Area == "全国" || compareProject.Area == "全国" {
  145. compareCity += "B"
  146. } else if info.City == compareCity {
  147. compareCity += "B"
  148. } else {
  149. compareCity += "C"
  150. }
  151. }
  152. } else {
  153. compareCity += "C"
  154. }
  155. score2 := 0
  156. if compareCity == "AA" {
  157. if info.District != "" && info.District == compareProject.District {
  158. score2 = 1
  159. }
  160. }
  161. compareTime := "D"
  162. //diffTime := math.Abs(float64(info.Publishtime - compareProject.Publistime[len(compareProject.Publistime)-1]))
  163. if diffTime < 45*86400 {
  164. compareTime = "A"
  165. score += 2
  166. } else if diffTime < 90*86400 {
  167. compareTime = "B"
  168. score += 1
  169. }
  170. compareAgency := "D"
  171. if info.Agency != "" {
  172. if info.Agency == compareProject.Agency {
  173. compareAgency = "A"
  174. score += 2
  175. score2 += 1
  176. } else if compareProject.Agency != "" {
  177. if strings.Contains(info.Agency, compareProject.Agency) || strings.Contains(compareProject.Agency, info.Agency) {
  178. compareAgency = "B"
  179. score += 1
  180. score2 += 1
  181. } else {
  182. compareAgency = "C"
  183. }
  184. }
  185. }
  186. compareBudget := "C"
  187. if info.Budget > 0 && (info.Budget == compareProject.Budget || (compareProject.Bidamount > 0 && info.Budget > compareProject.Bidamount && (info.Budget-compareProject.Bidamount) < (0.1*info.Budget))) {
  188. compareBudget = "A"
  189. score += 1
  190. score2 += 1
  191. }
  192. compareBidmount := "C"
  193. if info.Bidamount > 0 && (info.Bidamount == compareProject.Bidamount || (compareProject.Budget > 0 && compareProject.Budget > info.Bidamount && (compareProject.Budget-info.Bidamount) < 0.1*compareProject.Budget)) {
  194. compareBidmount = "A"
  195. score += 1
  196. score2 += 1
  197. }
  198. //项目名称、项目编号、标题项目编号、采购单位、省、市、发布时间、代理机构
  199. comStr = compareStr + compareBuyer + compareCity + compareTime + compareAgency + compareBudget + compareBidmount
  200. compareProject.comStr = comStr
  201. eqV := 0
  202. switch resVal {
  203. case 3:
  204. if compareBuyer < "C" {
  205. eqV = 1
  206. } else if compareBuyer == "D" {
  207. if "AA" == compareCity && compareAgency != "C" && compareTime != "D" {
  208. eqV = 2
  209. } else if compareCity[1:1] != "C" && score2 > 0 && compareTime == "A" {
  210. eqV = 3
  211. } else if compareTime != "D" && compareAgency != "C" && score2 > 1 {
  212. eqV = 3
  213. }
  214. } else {
  215. if "AA" == compareCity && compareAgency != "C" && compareTime != "D" {
  216. eqV = 2
  217. } else if compareCity[1:1] != "C" && compareTime == "A" && score2 > 1 {
  218. eqV = 3
  219. }
  220. }
  221. case 2:
  222. if compareBuyer < "C" {
  223. if compareTime != "D" && "AA" == compareCity && compareAgency != "C" {
  224. eqV = 2
  225. } else if compareCity[1:1] != "C" && compareTime == "A" && score2 > 0 {
  226. eqV = 3
  227. }
  228. } else if compareBuyer == "D" {
  229. if "AA" == compareCity && compareTime != "D" && score2 > 1 {
  230. eqV = 3
  231. } else if score2 > 2 && compareTime == "A" {
  232. eqV = 3
  233. }
  234. } else {
  235. if "AA" == compareCity && (compareAgency == "A" || score2 > 1) && compareTime == "A" {
  236. eqV = 3
  237. }
  238. }
  239. case 1:
  240. if compareBuyer < "C" {
  241. if compareTime != "D" && "AA" == compareCity && score2 > 0 && compareAgency != "C" {
  242. eqV = 2
  243. } else if compareCity[1:1] != "C" && compareTime == "A" && score2 > 1 {
  244. eqV = 3
  245. }
  246. } else if compareBuyer == "D" {
  247. if "AA" == compareCity && compareTime != "D" && score2 > 1 && compareAgency != "C" {
  248. eqV = 3
  249. } else if compareCity[1:1] != "C" && score2 > 1 && compareTime == "A" && compareAgency != "C" {
  250. eqV = 3
  251. }
  252. } else {
  253. if "AA" == compareCity && score2 > 2 && compareTime == "A" {
  254. eqV = 3
  255. }
  256. }
  257. }
  258. if eqV == 1 {
  259. comRes1 = append(comRes1, compareProject)
  260. } else if eqV == 2 {
  261. comRes2 = append(comRes2, compareProject)
  262. } else if eqV == 3 {
  263. comRes3 = append(comRes3, compareProject)
  264. } else {
  265. //log.Println("+++++++++++", resVal, comStr, info, compareProject)
  266. }
  267. // compareBuyer := "D"
  268. // if info.Buyer != "" {
  269. // if info.Buyer == compareProject.Buyer {
  270. // compareBuyer += "A"
  271. // } else if compareProject.Buyer != "" {
  272. // if strings.Contains(info.Buyer, compareProject.Buyer) || strings.Contains(compareProject.Buyer, info.Buyer) {
  273. // compareBuyer += "B"
  274. // } else {
  275. // compareBuyer += "C"
  276. // }
  277. // }
  278. // }
  279. // //---------------------------------------
  280. // compareCity := ""
  281. // if info.Area != "全国" && info.Area != "" && info.Area == compareProject.Area {
  282. // compareCity += "A"
  283. // score += 2
  284. // } else if info.Area == "全国" || compareProject.Area == "全国" {
  285. // compareCity += "B"
  286. // score += 1
  287. // } else {
  288. // compareCity += "C"
  289. // }
  290. // if compareCity != "C" {
  291. // if info.City != "" && info.City == compareProject.City {
  292. // compareCity += "A"
  293. // score += 2
  294. // } else {
  295. // if info.Area == "全国" || compareProject.Area == "全国" {
  296. // compareCity += "B"
  297. // } else if info.City == compareCity {
  298. // compareCity += "B"
  299. // } else {
  300. // compareCity += "C"
  301. // }
  302. // }
  303. // } else {
  304. // compareCity += "C"
  305. // }
  306. // compareTime := "D"
  307. // //diffTime := math.Abs(float64(info.Publishtime - compareProject.Publistime[len(compareProject.Publistime)-1]))
  308. // if diffTime < 45*86400 {
  309. // compareTime += "A"
  310. // score += 2
  311. // } else if diffTime < 90*86400 {
  312. // compareTime += "B"
  313. // score += 1
  314. // }
  315. // compareAgency := "D"
  316. // if info.Agency != "" {
  317. // if info.Agency == compareProject.Agency {
  318. // compareAgency += "A"
  319. // score += 2
  320. // } else if compareProject.Agency != "" {
  321. // if strings.Contains(info.Agency, compareProject.Agency) || strings.Contains(compareProject.Agency, info.Agency) {
  322. // compareAgency += "B"
  323. // score += 1
  324. // } else {
  325. // compareAgency += "C"
  326. // }
  327. // }
  328. // }
  329. // compareBudget := "C"
  330. // if info.budget > 0 && float64(info.budget) == compareProject.Budget {
  331. // compareBudget = "A"
  332. // }
  333. // compareBidmount := "C"
  334. // if info.bidamount > 0 && float64(info.bidamount) == compareProject.Bidamount {
  335. // compareBidmount = "A"
  336. // }
  337. // //项目名称、项目编号、标题项目编号、采购单位、省、市、发布时间、代理机构
  338. // comStr = compareStr + compareBuyer + compareCity + compareTime + compareAgency + compareBudget + compareBidmount
  339. // compareProject.comStr = comStr
  340. // switch resVal {
  341. // case 3:
  342. // if compareBuyer == "A" || compareBuyer == "B" {
  343. // comRes1 = append(comRes1, compareProject)
  344. // } else if compareBuyer == "D" {
  345. // if "AA" == compareCity && compareAgency != "C" && compareTime != "D" {
  346. // comRes1 = append(comRes1, compareProject)
  347. // } else if compareCity[1:1] != "C" {
  348. // comRes2 = append(comRes2, compareProject)
  349. // }
  350. // } else {
  351. // if "AA" == compareCity && compareAgency != "C" && compareTime != "D" {
  352. // comRes2 = append(comRes2, compareProject)
  353. // } else if compareCity[1:1] != "C" && compareAgency != "C" && compareTime != "D" {
  354. // comRes3 = append(comRes3, compareProject)
  355. // } else if compareCity[1:1] != "C" && (compareBudget == "A" || compareBidmount == "A") {
  356. // comRes3 = append(comRes3, compareProject)
  357. // }
  358. // }
  359. // case 1, 2:
  360. // if compareBuyer == "A" && compareTime != "D" {
  361. // comRes2 = append(comRes2, compareProject)
  362. // } else if compareBuyer == "B" && compareTime != "D" && compareAgency != "C" {
  363. // comRes3 = append(comRes3, compareProject)
  364. // } else if compareBuyer == "D" {
  365. // if "AA" == compareCity && compareAgency != "C" && compareTime != "D" {
  366. // comRes2 = append(comRes2, compareProject)
  367. // } else {
  368. // comRes3 = append(comRes3, compareProject)
  369. // }
  370. // } else {
  371. // if "AA" == compareCity && compareAgency != "C" && compareTime != "D" {
  372. // comRes3 = append(comRes3, compareProject)
  373. // } else if "AA" == compareCity && (compareBudget == "A" || compareBidmount == "A") {
  374. // comRes3 = append(comRes3, compareProject)
  375. // }
  376. // }
  377. // }
  378. }
  379. }
  380. }
  381. //--------------------------------对比完成-----------------------
  382. //更新数组、更新项目
  383. for kv, resN := range [][]*ProjectInfo{comRes1, comRes2, comRes3} {
  384. if len(resN) > 0 {
  385. if len(resN) > 1 {
  386. sort.Slice(resN, func(i, j int) bool {
  387. return resN[i].score > resN[j].score
  388. })
  389. }
  390. bFindProject = true
  391. findPid = resN[0].Id.Hex()
  392. for k2, bv := range []int{bpn, bpc, bptc, bpb} {
  393. if bv > -1 {
  394. pids[bv].Arr = append(pids[bv].Arr, findPid)
  395. if k2 == 0 {
  396. if resN[0].ProjectName == "" {
  397. resN[0].ProjectName = info.ProjectName
  398. } else {
  399. if resN[0].MPN == nil {
  400. resN[0].MPN = []string{info.ProjectName}
  401. } else {
  402. resN[0].MPN = append(resN[0].MPN, info.ProjectName)
  403. }
  404. }
  405. } else if k2 < 3 {
  406. if resN[0].ProjectCode == "" {
  407. resN[0].ProjectCode = qu.If(k2 == 1, info.ProjectCode, info.PTC).(string)
  408. } else {
  409. if resN[0].MPC == nil {
  410. resN[0].MPC = []string{qu.If(k2 == 1, info.ProjectCode, info.PTC).(string)}
  411. } else {
  412. resN[0].MPC = append(resN[0].MPC, qu.If(k2 == 1, info.ProjectCode, info.PTC).(string))
  413. }
  414. }
  415. } else {
  416. if resN[0].Buyer == "" {
  417. resN[0].Buyer = info.Buyer
  418. }
  419. }
  420. }
  421. }
  422. UpdateProject(tmp, info, resN[0], kv+1, resN[0].comStr)
  423. //更新AllIdsMao中的时间
  424. break
  425. }
  426. }
  427. if !bFindProject {
  428. //没有找到
  429. id, p := NewProject(tmp, info)
  430. //_, _ = strconv.ParseInt(id[0:8], 16, 64)
  431. AllIdsMapLock.Lock()
  432. //AllIdsMap[int(t)%idsMapSize][id] = &ID{Id: id, lastTime: info.Publishtime}
  433. AllIdsMap2[id] = &ID{Id: id, lastTime: info.Publishtime, P: p}
  434. AllIdsMapLock.Unlock()
  435. for _, m := range pids {
  436. m.Arr = append(m.Arr, id)
  437. }
  438. }
  439. }
  440. //二分字符串查找
  441. func BinarySearch(s []string, k string) int {
  442. sort.Strings(s)
  443. lo, hi := 0, len(s)-1
  444. for lo <= hi {
  445. m := (lo + hi) >> 1
  446. if s[m] < k {
  447. lo = m + 1
  448. } else if s[m] > k {
  449. hi = m - 1
  450. } else {
  451. return m
  452. }
  453. }
  454. return -1
  455. }