merge.go 11 KB

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