datamap.go 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337
  1. package main
  2. import (
  3. "fmt"
  4. "log"
  5. "math"
  6. qutil "qfw/util"
  7. "regexp"
  8. "strings"
  9. "sync"
  10. "time"
  11. )
  12. type Info struct {
  13. id string //id
  14. title string //标题
  15. area string //省份
  16. city string //城市
  17. subtype string //信息类型
  18. buyer string //采购单位
  19. agency string //代理机构
  20. winner string //中标单位
  21. budget float64 //预算金额
  22. bidamount float64 //中标金额
  23. projectname string //项目名称
  24. projectcode string //项目编号
  25. contractnumber string //合同编号
  26. publishtime int64 //发布时间
  27. comeintime int64 //入库时间
  28. bidopentime int64 //开标时间
  29. bidopenaddress string //开标地点
  30. site string //站点
  31. href string //正文的url
  32. repeatid string //重复id
  33. titleSpecialWord bool //标题特殊词
  34. specialWord bool //再次判断的特殊词
  35. mergemap map[string]interface{} //合并记录
  36. is_site bool //是否站点城市
  37. }
  38. var datelimit = float64(432000) //五天
  39. var sitelock sync.Mutex //锁
  40. //一般数据判重
  41. type datamap struct {
  42. lock sync.Mutex //锁
  43. days int //保留几天数据
  44. data map[string][]*Info
  45. keymap []string
  46. areakeys []string
  47. keys map[string]bool
  48. }
  49. func TimedTaskDatamap(days int,lasttime int64) *datamap {
  50. log.Println("数据池开始重新构建")
  51. datelimit = qutil.Float64All(days * 86400)
  52. dm := &datamap{sync.Mutex{}, days, map[string][]*Info{}, []string{}, []string{},map[string]bool{}}
  53. if lasttime <0 {
  54. log.Println("数据池空数据")
  55. return dm
  56. }
  57. start := int(time.Now().Unix())
  58. sess := mgo.GetMgoConn()
  59. defer mgo.DestoryMongoConn(sess)
  60. query := map[string]interface{}{"publishtime": map[string]interface{}{
  61. "$lt": lasttime,
  62. }}
  63. log.Println("query", query)
  64. it := sess.DB(mgo.DbName).C(extract_back).Find(query).Sort("-publishtime").Iter()
  65. n, continuSum := 0, 0
  66. for tmp := make(map[string]interface{}); it.Next(&tmp); n++ {
  67. //qutil.IntAll(tmp["dataging"]) == 1
  68. if qutil.IntAll(tmp["repeat"]) == 1 || qutil.IntAll(tmp["repeat"]) == -1 {
  69. } else {
  70. pt := tmp["publishtime"]
  71. pt_time := qutil.Int64All(pt)
  72. if qutil.Float64All(lasttime-pt_time) < datelimit {
  73. continuSum++
  74. info := NewInfo(tmp)
  75. dkey := qutil.FormatDateWithObj(&pt, qutil.Date_yyyyMMdd)
  76. k := fmt.Sprintf("%s_%s_%s", dkey, info.subtype, info.area)
  77. data := dm.data[k]
  78. if data == nil {
  79. data = []*Info{}
  80. }
  81. data = append(data, info)
  82. dm.data[k] = data
  83. dm.keys[dkey] = true
  84. //添加省
  85. isAreaExist :=false
  86. for _,v:= range dm.areakeys {
  87. if v==info.area {
  88. isAreaExist = true
  89. }
  90. }
  91. if !isAreaExist {
  92. areaArr := dm.areakeys
  93. areaArr = append(areaArr,info.area)
  94. dm.areakeys = areaArr
  95. }
  96. } else {
  97. break
  98. }
  99. }
  100. if n%50000 == 0 {
  101. log.Println("当前数据池:", n, continuSum)
  102. }
  103. tmp = make(map[string]interface{})
  104. }
  105. log.Printf("数据池构建完成::%d秒,%d个\n", int(time.Now().Unix())-start, n)
  106. return dm
  107. }
  108. func NewDatamap(days int, lastid string) *datamap {
  109. datelimit = qutil.Float64All(days * 86400 * 2)
  110. dm := &datamap{sync.Mutex{}, days, map[string][]*Info{}, []string{},[]string{}, map[string]bool{}}
  111. if lastid == "" {
  112. return dm
  113. }
  114. //初始化加载数据
  115. sess := mgo.GetMgoConn()
  116. defer mgo.DestoryMongoConn(sess)
  117. query := map[string]interface{}{"_id": map[string]interface{}{
  118. "$lte": StringTOBsonId(lastid),
  119. }}
  120. log.Println("query", query)
  121. sortName := "-_id"
  122. if Is_Sort {
  123. sortName = "-publishtime"
  124. }
  125. it := sess.DB(mgo.DbName).C(extract).Find(query).Sort(sortName).Iter()
  126. now1 := int64(0)
  127. n, continuSum := 0, 0
  128. for tmp := make(map[string]interface{}); it.Next(&tmp); n++ {
  129. if qutil.IntAll(tmp["repeat"]) == 1 || qutil.IntAll(tmp["repeat"]) == -1{
  130. } else {
  131. pt := tmp["comeintime"]
  132. if Is_Sort {
  133. pt = tmp["publishtime"]
  134. }
  135. pt_time := qutil.Int64All(pt)
  136. if pt_time <= 0 {
  137. continue
  138. }
  139. if now1 == 0 {
  140. now1 = pt_time
  141. }
  142. if qutil.Float64All(now1-pt_time) < datelimit {
  143. continuSum++
  144. info := NewInfo(tmp)
  145. dkey := qutil.FormatDateWithObj(&pt, qutil.Date_yyyyMMdd)
  146. k := fmt.Sprintf("%s_%s_%s", dkey, info.subtype, info.area)
  147. data := dm.data[k]
  148. if data == nil {
  149. data = []*Info{}
  150. }
  151. data = append(data, info)
  152. dm.data[k] = data
  153. dm.keys[dkey] = true
  154. //添加省
  155. isAreaExist :=false
  156. for _,v:= range dm.areakeys {
  157. if v==info.area {
  158. isAreaExist = true
  159. }
  160. }
  161. if !isAreaExist {
  162. areaArr := dm.areakeys
  163. areaArr = append(areaArr,info.area)
  164. dm.areakeys = areaArr
  165. }
  166. } else {
  167. break
  168. }
  169. }
  170. if n%5000 == 0 {
  171. log.Println("当前 n:", n,"数量:" ,continuSum)
  172. }
  173. tmp = make(map[string]interface{})
  174. }
  175. log.Println("load data:", n,"总数:",continuSum)
  176. return dm
  177. }
  178. func NewInfo(tmp map[string]interface{}) *Info {
  179. subtype := qutil.ObjToString(tmp["subtype"])
  180. area := qutil.ObjToString(tmp["area"])
  181. if area == "A" {
  182. area = "全国"
  183. }
  184. info := &Info{}
  185. if IdType {
  186. info.id = qutil.ObjToString(tmp["_id"])
  187. }else {
  188. info.id = BsonTOStringId(tmp["_id"])
  189. }
  190. info.title = qutil.ObjToString(tmp["title"])
  191. info.area = area
  192. info.subtype = subtype
  193. info.buyer = qutil.ObjToString(tmp["buyer"])
  194. info.projectname = qutil.ObjToString(tmp["projectname"])
  195. info.contractnumber = qutil.ObjToString(tmp["contractnumber"])
  196. info.projectcode = qutil.ObjToString(tmp["projectcode"])
  197. info.city = qutil.ObjToString(tmp["city"])
  198. info.agency = qutil.ObjToString(tmp["agency"])
  199. info.winner = qutil.ObjToString(tmp["winner"])
  200. info.budget = qutil.Float64All(tmp["budget"])
  201. info.bidamount = qutil.Float64All(tmp["bidamount"])
  202. info.publishtime = qutil.Int64All(tmp["publishtime"])
  203. info.comeintime = qutil.Int64All(tmp["comeintime"])
  204. info.bidopentime = qutil.Int64All(tmp["bidopentime"])
  205. info.bidopenaddress = qutil.ObjToString(tmp["bidopenaddress"])
  206. info.site = qutil.ObjToString(tmp["site"])
  207. info.href = qutil.ObjToString(tmp["href"])
  208. info.repeatid = qutil.ObjToString(tmp["repeatid"])
  209. info.specialWord = FilterRegTitle.MatchString(info.title)
  210. info.titleSpecialWord = FilterRegTitle_0.MatchString(info.title) ||FilterRegTitle_1.MatchString(info.title) || FilterRegTitle_2.MatchString(info.title)
  211. info.mergemap = *qutil.ObjToMap(tmp["merge_map"])
  212. if info.mergemap == nil {
  213. info.mergemap = make(map[string]interface{}, 0)
  214. }
  215. info.is_site = false
  216. return info
  217. }
  218. //判重方法
  219. func (d *datamap) check(info *Info) (b bool, source *Info, reasons string) {
  220. reason := ""
  221. keys := []string{}
  222. d.lock.Lock()
  223. for k, _ := range d.keys { //不同时间段
  224. if info.area=="全国" {
  225. //匹配所有省
  226. for _,v := range d.areakeys{
  227. keys = append(keys, fmt.Sprintf("%s_%s_%s", k, info.subtype, v))
  228. }
  229. }else {
  230. //匹配指定省
  231. keys = append(keys, fmt.Sprintf("%s_%s_%s", k, info.subtype, info.area))
  232. }
  233. keys = append(keys, fmt.Sprintf("%s_%s_%s", k, info.subtype, "全国"))
  234. }
  235. d.lock.Unlock()
  236. L:
  237. for _, k := range keys {
  238. d.lock.Lock()
  239. data := d.data[k]
  240. d.lock.Unlock()
  241. if len(data) > 0 { //对比v 找到同类型,同省或全国的数据作对比
  242. for _, v := range data {
  243. reason = ""
  244. if v.id == info.id { //正常重复
  245. return false, v, ""
  246. }
  247. //buyer 优先级高,有值且不相等过滤
  248. if info.buyer!=""&&v.buyer!=""&&info.buyer!=v.buyer {
  249. continue
  250. }
  251. if info.site != "" {//站点临时赋值
  252. sitelock.Lock()
  253. dict := SiteMap[info.site]
  254. sitelock.Unlock()
  255. if dict != nil {
  256. if (info.area == "全国" && dict["area"] != "")||
  257. (info.city == "" && dict["city"] != ""){
  258. info.is_site = true
  259. info.area = qutil.ObjToString(dict["area"])
  260. info.city = qutil.ObjToString(dict["city"])
  261. }
  262. }
  263. }
  264. //前置条件 - 站点相关
  265. if info.site != "" && info.site == v.site {
  266. if info.href != "" && info.href == v.href {
  267. reason = "同站点-href相同"
  268. b = true
  269. source = v
  270. reasons = reason
  271. break L
  272. }
  273. if info.href != "" && info.href != v.href {
  274. if v.title==info.title&&len([]rune(info.title)) >10 && isTheSameDay(info.publishtime,v.publishtime){
  275. if !againHrefRepeat(v, info) {//进行同站点二次判断
  276. reason = "同站点-href不同-标题相同等"
  277. b = true
  278. source = v
  279. reasons = reason
  280. break L
  281. }else {
  282. continue
  283. }
  284. }else {
  285. continue
  286. }
  287. }
  288. }
  289. specialNum:= dealWithSpecialWordNumber(info,v)
  290. //前置条件 - 标题相关,有且一个关键词
  291. if specialNum==1 {
  292. if info.title != v.title && v.title != "" && info.title != "" {
  293. continue
  294. }
  295. }
  296. //前置条件3 - 标题相关,均含有关键词
  297. if specialNum==2 {
  298. if len([]rune(v.title)) > 10 && len([]rune(info.title)) > 10 &&
  299. v.title != "" && info.title != "" {
  300. letter1,letter2:=v.title,info.title
  301. res, _ := regexp.Compile("[0-9a-zA-Z]+");
  302. if res.MatchString(letter1)||res.MatchString(letter2) {
  303. letter1=convertArabicNumeralsAndLetters(letter1)
  304. letter2=convertArabicNumeralsAndLetters(letter2)
  305. }
  306. if strings.Contains(letter1,"重新招标")|| strings.Contains(letter2,"重新招标"){
  307. letter1,letter2=dealWithSpecialPhrases(letter1,letter2)
  308. }
  309. if letter1==letter2 {
  310. reason = reason + "标题关键词相等关系"
  311. if !againRepeat(v, info) {//进行二级金额判断
  312. b = true
  313. source = v
  314. reasons = reason
  315. break L
  316. }
  317. }else {
  318. if !(strings.Contains(letter1, letter2) || strings.Contains(letter2, letter1)) {
  319. //无包含关系-即不相等
  320. continue
  321. }
  322. }
  323. }
  324. }
  325. //前置条件-五要素均相等
  326. if leadingElementSame(v,info) {
  327. reason = "五要素-相同-满足"
  328. b = true
  329. source = v
  330. reasons = reason
  331. break L
  332. }
  333. //新增快速数据过少判重
  334. if LowHeavy {
  335. repeat := false
  336. if repeat, reason = fastLowQualityHeavy(v, info, reason); repeat {
  337. b = true
  338. source = v
  339. reasons = reason
  340. break L
  341. }
  342. }
  343. //代理机构相同-非空相等
  344. if v.agency != "" && info.agency != "" && v.agency == info.agency {
  345. reason = reason + "同机构-"
  346. repeat := false
  347. if repeat, reason = quickHeavyMethodTwo(v, info, reason); repeat {
  348. b = true
  349. source = v
  350. reasons = reason
  351. break L
  352. }
  353. } else {
  354. reason = reason + "非同机构-"
  355. if info.city != "" && info.city == v.city {
  356. reason = reason + "同城-"
  357. repeat := false
  358. if repeat, reason = quickHeavyMethodTwo(v, info, reason); repeat {
  359. b = true
  360. source = v
  361. reasons = reason
  362. break L
  363. }
  364. } else {
  365. reason = reason + "不同城-"
  366. repeat := false
  367. if repeat, reason = quickHeavyMethodOne(v, info, reason); repeat {
  368. b = true
  369. source = v
  370. reasons = reason
  371. break L
  372. }
  373. }
  374. }
  375. }
  376. }
  377. }
  378. //往预存数据 d 添加
  379. if !b {
  380. ct := info.comeintime
  381. if Is_Sort ||TimingTask{
  382. ct = info.publishtime
  383. }
  384. dkey := qutil.FormatDateByInt64(&ct, qutil.Date_yyyyMMdd)
  385. k := fmt.Sprintf("%s_%s_%s", dkey, info.subtype, info.area)
  386. d.lock.Lock()
  387. data := d.data[k]
  388. if data == nil {
  389. data = []*Info{info}
  390. d.data[k] = data
  391. if !d.keys[dkey] {
  392. d.keys[dkey] = true
  393. d.update(ct)
  394. }
  395. } else {
  396. data = append(data, info)
  397. d.data[k] = data
  398. }
  399. //添加省
  400. isAreaExist :=false
  401. for _,v:= range d.areakeys {
  402. if v==info.area {
  403. isAreaExist = true
  404. }
  405. }
  406. if !isAreaExist {
  407. areaArr := d.areakeys
  408. areaArr = append(areaArr,info.area)
  409. d.areakeys = areaArr
  410. }
  411. d.lock.Unlock()
  412. }
  413. return
  414. }
  415. //替换原始数据池
  416. func (d *datamap) replaceSourceData(newData *Info, oldData *Info) {
  417. //删除数据池的老数据
  418. ct_old := oldData.comeintime
  419. if Is_Sort||TimingTask {
  420. ct_old = oldData.publishtime
  421. }
  422. dkey_old := qutil.FormatDateByInt64(&ct_old, qutil.Date_yyyyMMdd)
  423. k_old := fmt.Sprintf("%s_%s_%s", dkey_old, oldData.subtype, oldData.area)
  424. data_old := d.data[k_old]
  425. for k, v := range data_old {
  426. if v.id == oldData.id {//删除对应当前的老数据
  427. data_old = append(data_old[:k], data_old[k+1:]...)
  428. break
  429. }
  430. }
  431. d.data[k_old] = data_old
  432. //添加新的
  433. ct := newData.comeintime
  434. if Is_Sort ||TimingTask{
  435. ct = newData.publishtime
  436. }
  437. dkey := qutil.FormatDateByInt64(&ct, qutil.Date_yyyyMMdd)
  438. k := fmt.Sprintf("%s_%s_%s", dkey, newData.subtype, newData.area)
  439. d.lock.Lock()
  440. data := d.data[k]
  441. if data == nil {
  442. data = []*Info{newData}
  443. d.data[k] = data
  444. if !d.keys[dkey] {
  445. d.keys[dkey] = true
  446. d.update(ct)
  447. }
  448. } else {
  449. data = append(data, newData)
  450. d.data[k] = data
  451. }
  452. //添加省
  453. isAreaExist :=false
  454. for _,v:= range d.areakeys {
  455. if v==newData.area {
  456. isAreaExist = true
  457. }
  458. }
  459. if !isAreaExist {
  460. areaArr := d.areakeys
  461. areaArr = append(areaArr,newData.area)
  462. d.areakeys = areaArr
  463. }
  464. d.lock.Unlock()
  465. }
  466. func (d *datamap) update(t int64) {
  467. if TimingTask {
  468. d.keymap = d.GetLatelyFiveDay(t)
  469. }else {
  470. //d.keymap = d.GetLatelyFiveDay(t)//测试数据采用
  471. d.keymap = d.GetLatelyFiveDayDouble(t)
  472. }
  473. m := map[string]bool{}
  474. for _, v := range d.keymap {
  475. m[v] = true
  476. }
  477. all, all1 := 0, 0
  478. for k, v := range d.data {
  479. all += len(v)
  480. if !m[k[:8]] {
  481. delete(d.data, k)
  482. }
  483. }
  484. for k, _ := range d.keys {
  485. if !m[k] {
  486. delete(d.keys, k)
  487. }
  488. }
  489. for _, v := range d.data {
  490. all1 += len(v)
  491. }
  492. //log.Println("更新前后数据:", all, all1)
  493. }
  494. func (d *datamap) GetLatelyFiveDay(t int64) []string {
  495. array := make([]string, d.days)
  496. now := time.Unix(t, 0)
  497. for i := 0; i < d.days; i++ {
  498. array[i] = now.Format(qutil.Date_yyyyMMdd)
  499. now = now.AddDate(0, 0, -1)
  500. }
  501. return array
  502. }
  503. func (d *datamap) GetLatelyFiveDayDouble(t int64) []string {//增量-两倍
  504. array := make([]string, d.days*2)
  505. now := time.Now()
  506. for i := 0; i < d.days*2; i++ {
  507. array[i] = now.Format(qutil.Date_yyyyMMdd)
  508. now = now.AddDate(0, 0, -1)
  509. }
  510. return array
  511. }
  512. /*
  513. **************************
  514. ******** 以下为判重 ********
  515. **************************
  516. */
  517. //完善判重数据监测-前置条件
  518. func convertArabicNumeralsAndLetters(data string) string {
  519. newData :=data
  520. res1, _ := regexp.Compile("[a-zA-Z]+");
  521. if res1.MatchString(data) {
  522. newData = res1.ReplaceAllStringFunc(data, strings.ToUpper);
  523. }
  524. res2, _ := regexp.Compile("[0-9]+");
  525. if res2.MatchString(newData) {
  526. arr1:=[]string {"0","1","2","3","4","5","6","7","8","9"}
  527. arr2:=[]string {"零","一","二","三","四","五","六","七","八","九"}
  528. for i:=0 ;i<len(arr1) ;i++ {
  529. resTemp ,_:=regexp.Compile(arr1[i])
  530. newData= resTemp.ReplaceAllString(newData, arr2[i]);
  531. }
  532. }
  533. return newData
  534. }
  535. func dealWithSpecialPhrases(str1 string,str2 string) (string,string) {
  536. newStr1:=str1
  537. newStr2:=str2
  538. res, _ := regexp.Compile("重新招标");
  539. if res.MatchString(newStr1) {
  540. newStr1 = res.ReplaceAllString(newStr1,"重招");
  541. }
  542. if res.MatchString(newStr2) {
  543. newStr2 = res.ReplaceAllString(newStr2,"重招");
  544. }
  545. return newStr1,newStr2
  546. }
  547. //关键词数量v
  548. func dealWithSpecialWordNumber(info*Info,v*Info) int {
  549. okNum:=0
  550. if info.titleSpecialWord || info.specialWord {
  551. okNum++
  552. }
  553. if v.titleSpecialWord || v.specialWord {
  554. okNum++
  555. }
  556. return okNum
  557. }
  558. //快速低质量数据判重
  559. func fastLowQualityHeavy(v *Info, info *Info, reason string) (bool, string) {
  560. //首先判定是否为低质量数据 info目标数据
  561. if info.agency==v.agency&&info.title!=""&&
  562. info.title==v.title &&
  563. info.projectname==""&&info.projectcode==""&&info.contractnumber==""&&info.buyer=="" {
  564. isValue:=0//五要素判断
  565. if info.budget != 0 {//预算
  566. isValue++
  567. }
  568. if info.bidopentime != 0{//开标时间
  569. isValue++
  570. }
  571. if info.bidopenaddress!=""{//开标地点
  572. isValue++
  573. }
  574. if info.winner != ""{//中标单位
  575. isValue++
  576. }
  577. if info.bidamount != 0 {//中标金额
  578. isValue++
  579. }
  580. if isValue==0 {
  581. reason = reason + "---低质量-要素均为空,标题包含关系"
  582. return true, reason
  583. }else if isValue==1 {
  584. isMeet := false
  585. if isMeet, reason = judgeLowQualityData(v, info, reason); isMeet {
  586. reason = reason + "---低质量-有且一个要素组合"
  587. return true, reason
  588. }
  589. }else {
  590. }
  591. }
  592. return false,reason
  593. }
  594. //类别细节原因记录
  595. func judgeLowQualityData(v *Info, info *Info, reason string) (bool, string) {
  596. if info.subtype == "招标" || info.subtype == "邀标" || info.subtype == "询价" ||
  597. info.subtype == "竞谈" || info.subtype == "单一" || info.subtype == "竞价" ||
  598. info.subtype == "变更" || info.subtype == "其他" {
  599. //招标结果
  600. if info.budget != 0 && info.budget == v.budget{//预算
  601. reason = reason + "---招标类:预算"
  602. return true,reason
  603. }
  604. if info.bidopentime != 0 && info.bidopentime==v.bidopentime{//开标时间
  605. reason = reason + "---招标类:开标时间"
  606. return true,reason
  607. }
  608. if info.bidopenaddress!="" && info.bidopenaddress == v.bidopenaddress{//开标地点
  609. reason = reason + "---招标类:开标地点"
  610. return true,reason
  611. }
  612. } else if info.subtype == "中标" || info.subtype == "成交" || info.subtype == "废标" || info.subtype == "流标" {
  613. //中标结果
  614. if v.winner != "" && info.winner == v.winner{//中标单位
  615. reason = reason + "---中标类:中标单位"
  616. return true,reason
  617. }
  618. if v.bidamount != 0 && info.bidamount == v.bidamount{//中标金额
  619. reason = reason + "---中标类:中标金额"
  620. return true,reason
  621. }
  622. } else if info.subtype == "合同" || info.subtype == "验收" || info.subtype == "违规" {
  623. //合同
  624. if info.budget != 0 && info.budget == v.budget{//预算
  625. reason = reason + "---合同类:预算"
  626. return true,reason
  627. }
  628. if info.bidopentime != 0 && info.bidopentime==v.bidopentime{//开标时间
  629. reason = reason + "---合同类:开标时间"
  630. return true,reason
  631. }
  632. if info.bidopenaddress!="" && info.bidopenaddress == v.bidopenaddress{//开标地点
  633. reason = reason + "---合同类:开标地点"
  634. return true,reason
  635. }
  636. if v.winner != "" && info.winner == v.winner{//中标单位
  637. reason = reason + "---合同类:中标单位"
  638. return true,reason
  639. }
  640. if v.bidamount != 0 && info.bidamount == v.bidamount{//中标金额
  641. reason = reason + "---合同类:中标金额"
  642. return true,reason
  643. }
  644. } else {
  645. //招标结果
  646. if info.budget != 0 && info.budget == v.budget{//预算
  647. reason = reason + "---类别空-招标类:预算"
  648. return true,reason
  649. }
  650. if info.bidopentime != 0 && info.bidopentime==v.bidopentime{//开标时间
  651. reason = reason + "---类别空-招标类:开标时间"
  652. return true,reason
  653. }
  654. if info.bidopenaddress!="" && info.bidopenaddress == v.bidopenaddress{//开标地点
  655. reason = reason + "---类别空-招标类:开标地点"
  656. return true,reason
  657. }
  658. }
  659. return false,reason
  660. }
  661. //判重方法1
  662. func quickHeavyMethodOne(v *Info, info *Info, reason string) (bool, string) {
  663. isMeet := false
  664. if info.subtype == "招标" || info.subtype == "邀标" || info.subtype == "询价" ||
  665. info.subtype == "竞谈" || info.subtype == "单一" || info.subtype == "竞价" ||
  666. info.subtype == "变更" || info.subtype == "其他" {
  667. //招标结果
  668. if isMeet, reason = tenderRepeat_A(v, info, reason); isMeet {
  669. if tenderRepeat_C(v, info) {
  670. return false, reason
  671. } else {
  672. reason = reason + "---招标类"
  673. return true, reason
  674. }
  675. } else {
  676. return false, reason
  677. }
  678. } else if info.subtype == "中标" || info.subtype == "成交" || info.subtype == "废标" || info.subtype == "流标" {
  679. //中标结果
  680. if isMeet, reason = winningRepeat_A(v, info, reason); isMeet {
  681. if winningRepeat_C(v, info) {
  682. return false, reason
  683. } else {
  684. reason = reason + "---中标类"
  685. return true, reason
  686. }
  687. } else {
  688. return false, reason
  689. }
  690. } else if info.subtype == "合同" || info.subtype == "验收" || info.subtype == "违规" {
  691. //合同
  692. if isMeet, reason = contractRepeat_A(v, info, reason); isMeet {
  693. if contractRepeat_C(v, info) {
  694. return false, reason
  695. } else {
  696. reason = reason + "---合同类"
  697. return true, reason
  698. }
  699. } else {
  700. return false, reason
  701. }
  702. } else {
  703. //招标结果
  704. if isMeet, reason = tenderRepeat_A(v, info, reason); isMeet {
  705. if tenderRepeat_C(v, info) {
  706. return false, reason
  707. } else {
  708. reason = reason + "---类别空-招标类"
  709. return true, reason
  710. }
  711. } else {
  712. return false, reason
  713. }
  714. }
  715. return false, reason
  716. }
  717. //判重方法2
  718. func quickHeavyMethodTwo(v *Info, info *Info, reason string) (bool, string) {
  719. isMeet := false
  720. if v.agency == info.agency && v.agency != "" && info.agency != "" {
  721. if info.subtype == "招标" || info.subtype == "邀标" || info.subtype == "询价" ||
  722. info.subtype == "竞谈" || info.subtype == "单一" || info.subtype == "竞价" ||
  723. info.subtype == "变更" || info.subtype == "其他" {
  724. //招标结果
  725. if isMeet, reason = tenderRepeat_B(v, info, reason); isMeet {
  726. if tenderRepeat_C(v, info) { //有不同
  727. return false, reason
  728. } else {
  729. reason = reason + "---招标类"
  730. return true, reason
  731. }
  732. } else {
  733. return false, reason
  734. }
  735. } else if info.subtype == "中标" || info.subtype == "成交" || info.subtype == "废标" || info.subtype == "流标" {
  736. //中标结果
  737. if isMeet, reason = winningRepeat_B(v, info, reason); isMeet {
  738. if winningRepeat_C(v, info) { //有不同
  739. return false, reason
  740. } else {
  741. reason = reason + "---中标类"
  742. return true, reason
  743. }
  744. } else {
  745. return false, reason
  746. }
  747. } else if info.subtype == "合同" || info.subtype == "验收" || info.subtype == "违规" {
  748. //合同
  749. if isMeet, reason = contractRepeat_B(v, info, reason); isMeet {
  750. if contractRepeat_C(v, info) { //有不同
  751. return false, reason
  752. } else {
  753. reason = reason + "---合同类"
  754. return true, reason
  755. }
  756. } else {
  757. return false, reason
  758. }
  759. } else {
  760. //招标结果
  761. if isMeet, reason = tenderRepeat_B(v, info, reason); isMeet {
  762. if tenderRepeat_C(v, info) { //有不同
  763. return false, reason
  764. } else {
  765. reason = reason + "---类别空-招标类"
  766. return true, reason
  767. }
  768. } else {
  769. return false, reason
  770. }
  771. }
  772. }
  773. //不同
  774. if v.agency != info.agency && v.agency != "" && info.agency != "" {
  775. return false, reason
  776. }
  777. //机构最少一个为空
  778. if v.agency == "" || info.agency == "" {
  779. var repeat = false
  780. if repeat, reason = quickHeavyMethodOne(v, info, reason); repeat {
  781. reason = reason + "---机构最少一个空"
  782. return true, reason
  783. } else {
  784. return false, reason
  785. }
  786. }
  787. return false, reason
  788. }
  789. //招标_A
  790. func tenderRepeat_A(v *Info, info *Info, reason string) (bool, string) {
  791. var ss string
  792. p1, p2, p3, p4, p9, p10, p11 := false, false, false, false, false, false, false
  793. if v.projectname != "" && v.projectname == info.projectname {
  794. ss = ss + "p1-名称-"
  795. p1 = true
  796. }
  797. if v.buyer != "" && v.buyer == info.buyer {
  798. ss = ss + "p2-单位-"
  799. p2 = true
  800. }
  801. if (v.projectcode != "" && v.projectcode == info.projectcode && len(v.projectcode) >= 5) ||
  802. (v.contractnumber != "" && v.contractnumber == info.contractnumber && len(v.contractnumber) >= 5) {
  803. ss = ss + "p3-编号组-"
  804. p3 = true
  805. }
  806. if v.budget != 0 && v.budget == info.budget {
  807. ss = ss + "p4-预算-"
  808. p4 = true
  809. }
  810. if v.bidopentime != 0 && v.bidopentime == info.bidopentime {
  811. ss = ss + "p9-开标时间相同-"
  812. p9 = true
  813. }
  814. if v.bidopenaddress != "" && v.bidopenaddress == info.bidopenaddress {
  815. ss = ss + "p10-开标地点-"
  816. p10 = true
  817. }
  818. if len([]rune(v.title)) > 10 && len([]rune(info.title)) > 10 &&
  819. (strings.Contains(v.title, info.title) || strings.Contains(info.title, v.title)) {
  820. ss = ss + "p11-标题-"
  821. p11 = true
  822. }
  823. if (p1 && p2 && p3) || (p1 && p2 && p4) || (p1 && p2 && p9) || (p1 && p2 && p10) ||
  824. (p1 && p2 && p11) || (p1 && p3 && p9) || (p1 && p3 && p10) ||
  825. (p1 && p4 && p9) || (p1 && p4 && p10) || (p2 && p3 && p4) ||
  826. (p2 && p3 && p9) || (p2 && p3 && p10) || (p2 && p3 && p11) ||
  827. (p2 && p4 && p9) || (p2 && p4 && p10) || (p2 && p4 && p11) ||
  828. (p3 && p4 && p9) || (p3 && p4 && p10) || (p3 && p4 && p11) ||
  829. (p4 && p9 && p10) || (p4 && p9 && p11) || (p9 && p10 && p11) {
  830. reason = reason + "满足招标A,3要素组合-" + ss + ","
  831. return true, reason
  832. }
  833. return false, reason
  834. }
  835. //招标_B
  836. func tenderRepeat_B(v *Info, info *Info, reason string) (bool, string) {
  837. m, n := 0, 0
  838. if v.projectname != "" && v.projectname == info.projectname {
  839. m++
  840. n++
  841. }
  842. if v.buyer != "" && v.buyer == info.buyer {
  843. m++
  844. }
  845. if (v.projectcode != "" && v.projectcode == info.projectcode && len(v.projectcode) >= 5) ||
  846. (v.contractnumber != "" && v.contractnumber == info.contractnumber && len(v.contractnumber) >= 5) {
  847. m++
  848. }
  849. if v.budget != 0 && v.budget == info.budget {
  850. m++
  851. }
  852. if v.bidopentime != 0 && v.bidopentime == info.bidopentime {
  853. m++
  854. }
  855. //if v.bidopenaddress != "" && v.bidopenaddress == info.bidopenaddress {
  856. // m++
  857. //}
  858. if len([]rune(v.title)) > 10 && len([]rune(info.title)) > 10 &&
  859. (strings.Contains(v.title, info.title) || strings.Contains(info.title, v.title)) {
  860. m++
  861. n++
  862. }
  863. if m >= 2 {
  864. if n == 2 && m == 2 {
  865. return false, reason
  866. } else {
  867. reason = reason + "满足招标B,六选二,"
  868. return true, reason
  869. }
  870. }
  871. return false, reason
  872. }
  873. //招标_C
  874. func tenderRepeat_C(v *Info, info *Info) bool {
  875. if v.budget != 0 && info.budget != 0 && v.budget != info.budget {
  876. return true
  877. }
  878. //原始地址...
  879. //if v.buyer != "" && info.buyer != "" && v.buyer != info.buyer {
  880. // return true
  881. //}
  882. if v.bidopentime != 0 && info.bidopentime != 0 && isBidopentimeInterval(info.bidopentime,v.bidopentime) {
  883. return true
  884. }
  885. //if v.bidopenaddress != "" && info.bidopenaddress != "" && v.bidopenaddress != info.bidopenaddress {
  886. // return true
  887. //}
  888. return false
  889. }
  890. //中标_A
  891. func winningRepeat_A(v *Info, info *Info, reason string) (bool, string) {
  892. var ss string
  893. p1, p2, p3, p5, p6, p11 := false, false, false, false, false, false
  894. if v.projectname != "" && v.projectname == info.projectname {
  895. ss = ss + "p1-项目名称-"
  896. p1 = true
  897. }
  898. if v.buyer != "" && v.buyer == info.buyer {
  899. ss = ss + "p2-单位-"
  900. p2 = true
  901. }
  902. if (v.projectcode != "" && v.projectcode == info.projectcode && len(v.projectcode) >= 5) ||
  903. (v.contractnumber != "" && v.contractnumber == info.contractnumber && len(v.contractnumber) >= 5) {
  904. ss = ss + "p3-编号组--"
  905. p3 = true
  906. }
  907. if v.bidamount != 0 && !isBidWinningAmount(v.bidamount,info.bidamount) {
  908. ss = ss + "p5-中标金-"
  909. p5 = true
  910. }
  911. if v.winner != "" && deleteExtraSpace(v.winner) == deleteExtraSpace(info.winner) {
  912. ss = ss + "p6-中标人-"
  913. p6 = true
  914. }
  915. if len([]rune(v.title)) > 10 && len([]rune(info.title)) > 10 &&
  916. (strings.Contains(v.title, info.title) || strings.Contains(info.title, v.title)) {
  917. ss = ss + "p11-标题-"
  918. p11 = true
  919. }
  920. if (p1 && p2 && p3) || (p1 && p2 && p5) || (p1 && p2 && p6) ||
  921. (p1 && p3 && p5) || (p1 && p3 && p6) || (p1 && p5 && p6) ||
  922. (p2 && p3 && p5) || (p2 && p3 && p6) || (p2 && p3 && p11) ||
  923. (p2 && p5 && p6) || (p2 && p5 && p11) || (p2 && p6 && p11) ||
  924. (p3 && p5 && p6) || (p3 && p5 && p11) || (p3 && p6 && p11) ||
  925. (p5 && p6 && p11) {
  926. reason = reason + "满足中标A,3要素组合-" + ss + ","
  927. return true, reason
  928. }
  929. return false, reason
  930. }
  931. //中标_B
  932. func winningRepeat_B(v *Info, info *Info, reason string) (bool, string) {
  933. m, n := 0, 0
  934. if v.projectname != "" && v.projectname == info.projectname {
  935. m++
  936. n++
  937. }
  938. if v.buyer != "" && v.buyer == info.buyer {
  939. m++
  940. }
  941. if (v.projectcode != "" && v.projectcode == info.projectcode && len(v.projectcode) >= 5) ||
  942. (v.contractnumber != "" && v.contractnumber == info.contractnumber && len(v.contractnumber) >= 5) {
  943. m++
  944. }
  945. if v.bidamount != 0 && !isBidWinningAmount(v.bidamount,info.bidamount) {
  946. m++
  947. }
  948. if v.winner != "" && deleteExtraSpace(v.winner) == deleteExtraSpace(info.winner) {
  949. m++
  950. }
  951. if len([]rune(v.title)) > 10 && len([]rune(info.title)) > 10 &&
  952. (strings.Contains(v.title, info.title) || strings.Contains(info.title, v.title)) {
  953. m++
  954. n++
  955. }
  956. if m >= 2 {
  957. if n == 2 && m == 2 {
  958. return false, reason
  959. } else {
  960. reason = reason + "满足中标B.六选二,"
  961. return true, reason
  962. }
  963. }
  964. return false, reason
  965. }
  966. //中标_C
  967. func winningRepeat_C(v *Info, info *Info) bool {
  968. if v.bidamount != 0 && info.bidamount != 0 && isBidWinningAmount(v.bidamount,info.bidamount) {
  969. return true
  970. }
  971. //
  972. if v.winner != "" && info.winner != "" && deleteExtraSpace(v.winner) != deleteExtraSpace(info.winner) {
  973. return true
  974. }
  975. //原始地址...
  976. //if v.buyer != "" && info.buyer != "" && v.buyer != info.buyer {
  977. // return true
  978. //}
  979. return false
  980. }
  981. //合同_A
  982. func contractRepeat_A(v *Info, info *Info, reason string) (bool, string) {
  983. isMeet_1 := false
  984. if isMeet_1, reason = tenderRepeat_A(v, info, reason); isMeet_1 {
  985. return true, reason
  986. }
  987. isMeet_2 := false
  988. if isMeet_2, reason = winningRepeat_A(v, info, reason); isMeet_2 {
  989. return true, reason
  990. }
  991. return false, reason
  992. }
  993. //合同_B
  994. func contractRepeat_B(v *Info, info *Info, reason string) (bool, string) {
  995. isMeet_1 := false
  996. if isMeet_1, reason = tenderRepeat_B(v, info, reason); isMeet_1 {
  997. return true, reason
  998. }
  999. isMeet_2 := false
  1000. if isMeet_2, reason = winningRepeat_B(v, info, reason); isMeet_2 {
  1001. return true, reason
  1002. }
  1003. return false, reason
  1004. }
  1005. //合同_C
  1006. func contractRepeat_C(v *Info, info *Info) bool {
  1007. if tenderRepeat_C(v, info) {
  1008. return true
  1009. }
  1010. if winningRepeat_C(v, info) {
  1011. return true
  1012. }
  1013. //合同类 - 新增编号
  1014. if v.contractnumber != "" && info.contractnumber != "" && v.contractnumber != info.contractnumber {
  1015. return true
  1016. }
  1017. if v.projectcode != "" && info.projectcode != "" && v.projectcode != info.projectcode {
  1018. return true
  1019. }
  1020. return false
  1021. }
  1022. //同站点再次判断
  1023. func againHrefRepeat(v *Info, info *Info) bool {
  1024. //if v.buyer == info.buyer {
  1025. //
  1026. //}
  1027. if isBidopentimeInterval(info.bidopentime,v.bidopentime) {
  1028. return true
  1029. }
  1030. if v.budget != info.budget && v.budget != 0 && info.budget != 0 {
  1031. return true
  1032. }
  1033. if isBidWinningAmount(v.bidamount,info.bidamount) && v.bidamount != 0 && info.bidamount != 0{
  1034. return true
  1035. }
  1036. if deleteExtraSpace(v.winner) != deleteExtraSpace(info.winner) && v.winner != "" && info.winner != "" {
  1037. return true
  1038. }
  1039. if v.contractnumber != "" && info.contractnumber != "" && v.contractnumber != info.contractnumber {
  1040. return true
  1041. }
  1042. if v.projectcode != "" && info.projectcode != "" && v.projectcode != info.projectcode {
  1043. return true
  1044. }
  1045. //if info.subtype == "招标" || info.subtype == "邀标" || info.subtype == "询价" ||
  1046. // info.subtype == "竞谈" || info.subtype == "单一" || info.subtype == "竞价" ||
  1047. // info.subtype == "变更" || info.subtype == "其他" {
  1048. // //招标结果
  1049. // if v.budget != info.budget && v.budget != 0 && info.budget != 0 {
  1050. // return true
  1051. // }
  1052. //} else if info.subtype == "中标" || info.subtype == "成交" || info.subtype == "废标" || info.subtype == "流标" {
  1053. // //中标结果
  1054. // if (isBidWinningAmount(v.bidamount,info.bidamount) && v.bidamount != 0 && info.bidamount != 0) ||
  1055. // (deleteExtraSpace(v.winner) != deleteExtraSpace(info.winner) && v.winner != "" && info.winner != "") {
  1056. // return true
  1057. // }
  1058. //} else if info.subtype == "合同" || info.subtype == "验收" || info.subtype == "违规" {
  1059. // //合同
  1060. // if v.budget != info.budget && v.budget != 0 && info.budget != 0 {
  1061. // return true
  1062. // }
  1063. // if (isBidWinningAmount(v.bidamount,info.bidamount) && v.bidamount != 0 && info.bidamount != 0) ||
  1064. // (deleteExtraSpace(v.winner) != deleteExtraSpace(info.winner) && v.winner != "" && info.winner != "") {
  1065. // return true
  1066. // }
  1067. //
  1068. //} else {
  1069. // if v.budget != info.budget && v.budget != 0 && info.budget != 0 {
  1070. // return true
  1071. // }
  1072. //}
  1073. return false
  1074. }
  1075. //关键词再次判断
  1076. func againRepeat(v *Info, info *Info) bool {
  1077. //相同采购单位下
  1078. //if info.buyer != "" && v.buyer == info.buyer {
  1079. //if v.buyer == info.buyer {
  1080. //
  1081. //}
  1082. //if info.subtype == "招标" || info.subtype == "邀标" || info.subtype == "询价" ||
  1083. // info.subtype == "竞谈" || info.subtype == "单一" || info.subtype == "竞价" ||
  1084. // info.subtype == "其他" || info.subtype == "变更" {
  1085. // //预算金额满足条件
  1086. // if v.budget != info.budget && v.budget != 0 && info.budget != 0 {
  1087. // return true
  1088. // }
  1089. //} else if info.subtype == "中标" || info.subtype == "成交" || info.subtype == "废标" ||
  1090. // info.subtype == "流标" || info.subtype == "合同" || info.subtype == "验收" ||
  1091. // info.subtype == "违规" {
  1092. // //中标金额单位满足条件
  1093. // if (isBidWinningAmount(v.bidamount,info.bidamount) && v.bidamount != 0 && info.bidamount != 0) ||
  1094. // (deleteExtraSpace(v.winner) != deleteExtraSpace(info.winner) && v.winner != "" && info.winner != "") {
  1095. // return true
  1096. // }
  1097. //} else {
  1098. // //预算金额满足条件
  1099. // if v.budget != info.budget && v.budget != 0 && info.budget != 0 {
  1100. // return true
  1101. // }
  1102. //}
  1103. if isBidopentimeInterval(info.bidopentime,v.bidopentime) {
  1104. return true
  1105. }
  1106. if v.budget != info.budget && v.budget != 0 && info.budget != 0 {
  1107. return true
  1108. }
  1109. if isBidWinningAmount(v.bidamount,info.bidamount) && v.bidamount != 0 && info.bidamount != 0{
  1110. return true
  1111. }
  1112. if deleteExtraSpace(v.winner) != deleteExtraSpace(info.winner) && v.winner != "" && info.winner != "" {
  1113. return true
  1114. }
  1115. if v.contractnumber != "" && info.contractnumber != "" && v.contractnumber != info.contractnumber {
  1116. return true
  1117. }
  1118. if v.projectcode != "" && info.projectcode != "" && v.projectcode != info.projectcode {
  1119. return true
  1120. }
  1121. return false
  1122. }
  1123. //删除中标单位字符串中多余的空格(含tab)
  1124. func deleteExtraSpace(s string) string {
  1125. //删除字符串中的多余空格,有多个空格时,仅保留一个空格
  1126. s1 := strings.Replace(s, " ", " ", -1) //替换tab为空格
  1127. regstr := "\\s{2,}" //两个及两个以上空格的正则表达式
  1128. reg, _ := regexp.Compile(regstr) //编译正则表达式
  1129. s2 := make([]byte, len(s1)) //定义字符数组切片
  1130. copy(s2, s1) //将字符串复制到切片
  1131. spc_index := reg.FindStringIndex(string(s2)) //在字符串中搜索
  1132. for len(spc_index) > 0 { //找到适配项
  1133. s2 = append(s2[:spc_index[0]+1], s2[spc_index[1]:]...) //删除多余空格
  1134. spc_index = reg.FindStringIndex(string(s2)) //继续在字符串中搜索
  1135. }
  1136. return string(s2)
  1137. }
  1138. //中标金额倍率:10000
  1139. func isBidWinningAmount(f1 float64 ,f2 float64) bool {
  1140. if f1==f2||f1*10000==f2||f2*10000==f1 {
  1141. return false
  1142. }
  1143. return true
  1144. }
  1145. //开标时间区间为一天
  1146. func isBidopentimeInterval(i1 int64 ,i2 int64) bool {
  1147. if i1==0||i2==0 {
  1148. return false
  1149. }
  1150. //不在同一天-或者同一天间隔超过六小时,属于不相等返回true
  1151. timeOne,timeTwo:=i1,i2
  1152. day1 := qutil.FormatDateByInt64(&timeOne, qutil.Date_yyyyMMdd)
  1153. day2 := qutil.FormatDateByInt64(&timeTwo, qutil.Date_yyyyMMdd)
  1154. if day1==day2 {
  1155. //是否间隔超过六小时
  1156. if math.Abs(float64(i1-i2)) >21600.0 {
  1157. return true
  1158. }else {
  1159. return false
  1160. }
  1161. }else {
  1162. return true
  1163. }
  1164. }
  1165. //开标时间区间为一天
  1166. func isTheSameDay(i1 int64 ,i2 int64) bool {
  1167. if i1==0||i2==0 {
  1168. return false
  1169. }
  1170. timeOne,timeTwo:=i1,i2
  1171. day1 := qutil.FormatDateByInt64(&timeOne, qutil.Date_yyyyMMdd)
  1172. day2 := qutil.FormatDateByInt64(&timeTwo, qutil.Date_yyyyMMdd)
  1173. if day1==day2 {
  1174. return true
  1175. }
  1176. return false
  1177. }
  1178. //前置0 五要素均相等认为重复
  1179. func leadingElementSame(v *Info, info *Info) bool {
  1180. isok:= 0
  1181. if info.projectname != "" && v.projectname == info.projectname {
  1182. isok++
  1183. }
  1184. if info.buyer != "" && v.buyer == info.buyer {
  1185. isok++
  1186. }
  1187. if info.subtype == "合同" || info.subtype == "验收" || info.subtype == "违规" {
  1188. if info.contractnumber != "" && v.contractnumber == info.contractnumber {
  1189. isok++
  1190. }
  1191. }else {
  1192. if info.projectcode != "" && v.projectcode == info.projectcode {
  1193. isok++
  1194. }
  1195. }
  1196. if info.title != "" && v.title == info.title {
  1197. isok++
  1198. }
  1199. if v.agency == info.agency {
  1200. isok++
  1201. }
  1202. if isok==5 {
  1203. return true
  1204. }
  1205. return false
  1206. }