rule.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. package service
  2. import (
  3. "github.com/gogf/gf/v2/container/gvar"
  4. "github.com/gogf/gf/v2/frame/g"
  5. "github.com/gogf/gf/v2/os/gctx"
  6. "github.com/gogf/gf/v2/util/gconv"
  7. "log"
  8. "regexp"
  9. "strings"
  10. )
  11. var (
  12. clearPatterns = g.Config().MustGet(gctx.New(), "clearPatterns").Strings()
  13. bidCommonwealth_blacklistPatterns = g.Config().MustGet(gctx.New(), "bidCommonwealth.blacklistPatterns").Strings()
  14. bidCommonwealth_whitelistPatterns = g.Config().MustGet(gctx.New(), "bidCommonwealth.whitelistPatterns").Strings()
  15. bidCommonwealth_modelPatterns = g.Config().MustGet(gctx.New(), "bidCommonwealth.modelPatterns").Strings()
  16. bidCommonwealth_firstWinnerOrder = g.Config().MustGet(gctx.New(), "bidCommonwealth.firstWinnerOrder").String()
  17. bidCommonwealth_firstWinnerOrderClearReg = regexp.MustCompile(g.Config().MustGet(gctx.New(), "bidCommonwealth.firstWinnerOrderClear").String())
  18. quoteModeRules = g.Config().MustGet(gctx.New(), "quoteMode.rules").Maps()
  19. quoteModeTableKReg = g.Config().MustGet(gctx.New(), "quoteMode.tableK").String()
  20. showOnlyOnce = [][]string{}
  21. moreWinnerReg = regexp.MustCompile("[,,、]")
  22. )
  23. func init() {
  24. for _, v := range g.Config().MustGet(gctx.New(), "bidCommonwealth.showOnlyOnce").Array() {
  25. showOnlyOnce = append(showOnlyOnce, gconv.Strings(v))
  26. }
  27. }
  28. type Rule struct{}
  29. func (r *Rule) Execute(b *BidInfo) (bool, string, bool, int, bool) {
  30. var bidCommonwealth int
  31. var quoteMode string
  32. var quoteMode_bigModel, bidCommonwealth_bigModel bool
  33. var bigModel map[string]bool
  34. if b.Type == 0 {
  35. bidCommonwealth = r.bidCommonwealth(b)
  36. quoteMode, bigModel = r.quoteMode(b)
  37. if bidCommonwealth == -2 && len(bigModel) > 0 {
  38. _, quoteMode, quoteMode_bigModel, bidCommonwealth, bidCommonwealth_bigModel = (&Model{}).Do(b, 2)
  39. } else if bidCommonwealth == -2 {
  40. _, _, _, bidCommonwealth, bidCommonwealth_bigModel = (&Model{}).Do(b, 3)
  41. } else if len(bigModel) > 0 {
  42. _, quoteMode, quoteMode_bigModel, _, _ = (&Model{}).Do(b, 1)
  43. if !bigModel[quoteMode] {
  44. quoteMode = ""
  45. }
  46. }
  47. } else if b.Type == 1 {
  48. quoteMode, bigModel = r.quoteMode(b)
  49. if len(bigModel) > 0 {
  50. _, quoteMode, quoteMode_bigModel, _, _ = (&Model{}).Do(b, 1)
  51. if !bigModel[quoteMode] {
  52. quoteMode = ""
  53. }
  54. }
  55. } else if b.Type == 2 {
  56. bidCommonwealth = r.bidCommonwealth(b)
  57. if bidCommonwealth == -2 {
  58. _, _, _, bidCommonwealth, bidCommonwealth_bigModel = (&Model{}).Do(b, 3)
  59. }
  60. }
  61. if b.Type == 0 || b.Type == 1 {
  62. if quoteMode == "" && (b.Bidamount == 0 || b.Bidamount > g.Config().MustGet(gctx.New(), "quoteMode.minBidamount").Float64()) {
  63. quoteMode = QuoteMode_Whole
  64. }
  65. }
  66. log.Println(b.Id, "规则", "报价模式", quoteMode, "中标联合体", bidCommonwealth)
  67. return true, quoteMode, quoteMode_bigModel, bidCommonwealth, bidCommonwealth_bigModel
  68. }
  69. // 识别报价模式
  70. func (r *Rule) quoteMode(b *BidInfo) (string, map[string]bool) {
  71. for _, v := range quoteModeRules {
  72. vv := gvar.New(v).MapStrVar()
  73. modeName := vv["mode"].String()
  74. for _, row := range b.TableKv {
  75. for k, v := range row {
  76. if tableV := vv["tableV"].String(); tableV != "" {
  77. matchedK, _ := regexp.MatchString(quoteModeTableKReg, k)
  78. if !matchedK {
  79. if tableK := vv["tableK"].String(); tableK != "" {
  80. matchedK, _ = regexp.MatchString(tableK, k)
  81. }
  82. }
  83. matchedV, _ := regexp.MatchString(tableV, v)
  84. if matchedK && matchedV {
  85. log.Println(b.Id, "tableKv", k, v)
  86. return modeName, nil
  87. }
  88. }
  89. }
  90. }
  91. }
  92. bigModel := map[string]bool{}
  93. for _, v := range quoteModeRules {
  94. vv := gvar.New(v).MapStrVar()
  95. modeName := vv["mode"].String()
  96. var lineUnderstandPatterns []string
  97. if lineUnderstand := vv["lineUnderstand"].MapStrVar(); lineUnderstand != nil {
  98. lineUnderstandPatterns = lineUnderstand["patterns"].Strings()
  99. }
  100. lines := strings.Split(b.Detail, "\n")
  101. for lineNum, lineVal := range lines {
  102. if r.matchAnyPattern(b.Id, lineVal, vv["patterns"].Strings()) {
  103. return modeName, nil
  104. }
  105. for _, vvv := range lineUnderstandPatterns {
  106. countLine := len(strings.Split(vvv, "+"))
  107. if countLine > 1 {
  108. countLine += vv["space"].Int()
  109. }
  110. newText := []string{}
  111. for i := lineNum; i < lineNum+countLine && i < len(lines); i++ {
  112. newText = append(newText, lines[i])
  113. }
  114. if r.matchAnyPattern(b.Id, strings.Join(newText, "\n"), []string{vvv}) {
  115. return modeName, nil
  116. }
  117. }
  118. }
  119. //
  120. if modelPatterns := vv["modelPatterns"].String(); modelPatterns != "" && r.matchAnyPattern(b.Id, b.Detail, []string{modelPatterns}) {
  121. bigModel[modeName] = true
  122. }
  123. }
  124. return "", bigModel
  125. }
  126. // 识别中标联合体
  127. func (r *Rule) bidCommonwealth(b *BidInfo) int {
  128. // Step 1: 排除黑名单
  129. if r.matchAnyPattern(b.Id, b.Detail, bidCommonwealth_blacklistPatterns) {
  130. return -1
  131. }
  132. for _, v := range b.KvText {
  133. if r.matchAnyPattern(b.Id, v, bidCommonwealth_whitelistPatterns) {
  134. return 1
  135. }
  136. }
  137. if b.FirstWinner != "" && regexp.MustCompile(bidCommonwealth_firstWinnerOrder).MatchString(b.FirstWinner) {
  138. log.Println(b.Id, "第一中标候选人", b.FirstWinner, bidCommonwealth_firstWinnerOrder)
  139. return 1
  140. } else if r.matchOnlyOnce(b.Id, b.Detail) {
  141. return 1
  142. } else if r.matchAnyPattern(b.Id, b.Detail, bidCommonwealth_whitelistPatterns) {
  143. return 1
  144. } else if b.Multipackage < 2 && len(moreWinnerReg.Split(b.Winner, -1)) > 1 {
  145. log.Println(b.Id, "单包多个中标单位")
  146. return 1
  147. }
  148. index := strings.Index(b.Detail, "中标")
  149. if index != -1 {
  150. start := max(0, index-50)
  151. end := min(len(b.Detail), index+50)
  152. contextAroundWin := b.Detail[start:end]
  153. if strings.Contains(contextAroundWin, "联合体") {
  154. log.Println(b.Id, "”中标“附件有”联合体“")
  155. return 1
  156. }
  157. }
  158. if r.matchAnyPattern(b.Id, b.Detail, bidCommonwealth_modelPatterns) {
  159. return -2
  160. }
  161. return -1
  162. }
  163. // 匹配任意模式
  164. func (r *Rule) matchAnyPattern(_id string, text string, patterns []string) bool {
  165. for _, pattern := range patterns {
  166. if strings.HasPrefix(pattern, "全部包含:") {
  167. vs := strings.Split(strings.TrimPrefix(pattern, "全部包含:"), "+")
  168. index := 0
  169. for _, v := range vs {
  170. if strings.Contains(text, v) {
  171. index++
  172. }
  173. }
  174. if index == len(vs) {
  175. log.Println(_id, "matchAnyPattern", pattern)
  176. return true
  177. }
  178. continue
  179. }
  180. if matched, _ := regexp.MatchString(pattern, text); matched {
  181. log.Println(_id, "matchAnyPattern", pattern)
  182. return true
  183. }
  184. }
  185. return false
  186. }
  187. // 全部匹配
  188. func (r *Rule) matchAllPattern(text string, patterns []string) bool {
  189. count := 0
  190. for _, pattern := range patterns {
  191. if matched, _ := regexp.MatchString(pattern, text); matched {
  192. count++
  193. }
  194. }
  195. if count > 0 && count == len(patterns) {
  196. return true
  197. }
  198. return false
  199. }
  200. func (r *Rule) matchOnlyOnce(_id, text string) bool {
  201. for _, v := range showOnlyOnce {
  202. count := 0
  203. for _, vv := range v {
  204. if len(regexp.MustCompile(vv).FindAllString(text, -1)) != 1 {
  205. break
  206. }
  207. count++
  208. }
  209. if count > 0 && count == len(v) {
  210. log.Println(_id, v)
  211. return true
  212. }
  213. }
  214. return false
  215. }