package service import ( "github.com/gogf/gf/v2/container/gvar" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gctx" "github.com/gogf/gf/v2/util/gconv" "log" "regexp" "strings" ) var ( clearPatterns = g.Config().MustGet(gctx.New(), "clearPatterns").Strings() bidCommonwealth_blacklistPatterns = g.Config().MustGet(gctx.New(), "bidCommonwealth.blacklistPatterns").Strings() bidCommonwealth_whitelistPatterns = g.Config().MustGet(gctx.New(), "bidCommonwealth.whitelistPatterns").Strings() bidCommonwealth_modelPatterns = g.Config().MustGet(gctx.New(), "bidCommonwealth.modelPatterns").Strings() bidCommonwealth_firstWinnerOrder = g.Config().MustGet(gctx.New(), "bidCommonwealth.firstWinnerOrder").String() bidCommonwealth_firstWinnerOrderClearReg = regexp.MustCompile(g.Config().MustGet(gctx.New(), "bidCommonwealth.firstWinnerOrderClear").String()) quoteModeRules = g.Config().MustGet(gctx.New(), "quoteMode.rules").Maps() quoteModeTableKReg = g.Config().MustGet(gctx.New(), "quoteMode.tableK").String() showOnlyOnce = [][]string{} moreWinnerReg = regexp.MustCompile("[,,、]") ) func init() { for _, v := range g.Config().MustGet(gctx.New(), "bidCommonwealth.showOnlyOnce").Array() { showOnlyOnce = append(showOnlyOnce, gconv.Strings(v)) } } type Rule struct{} func (r *Rule) Execute(b *BidInfo) (bool, string, bool, int, bool) { var bidCommonwealth int var quoteMode string var quoteMode_bigModel, bidCommonwealth_bigModel bool var bigModel map[string]bool if b.Type == 0 { bidCommonwealth = r.bidCommonwealth(b) quoteMode, bigModel = r.quoteMode(b) if bidCommonwealth == -2 && len(bigModel) > 0 { _, quoteMode, quoteMode_bigModel, bidCommonwealth, bidCommonwealth_bigModel = (&Model{}).Do(b, 2) } else if bidCommonwealth == -2 { _, _, _, bidCommonwealth, bidCommonwealth_bigModel = (&Model{}).Do(b, 3) } else if len(bigModel) > 0 { _, quoteMode, quoteMode_bigModel, _, _ = (&Model{}).Do(b, 1) if !bigModel[quoteMode] { quoteMode = "" } } } else if b.Type == 1 { quoteMode, bigModel = r.quoteMode(b) if len(bigModel) > 0 { _, quoteMode, quoteMode_bigModel, _, _ = (&Model{}).Do(b, 1) if !bigModel[quoteMode] { quoteMode = "" } } } else if b.Type == 2 { bidCommonwealth = r.bidCommonwealth(b) if bidCommonwealth == -2 { _, _, _, bidCommonwealth, bidCommonwealth_bigModel = (&Model{}).Do(b, 3) } } if b.Type == 0 || b.Type == 1 { if quoteMode == "" && (b.Bidamount == 0 || b.Bidamount > g.Config().MustGet(gctx.New(), "quoteMode.minBidamount").Float64()) { quoteMode = QuoteMode_Whole } } log.Println(b.Id, "规则", "报价模式", quoteMode, "中标联合体", bidCommonwealth) return true, quoteMode, quoteMode_bigModel, bidCommonwealth, bidCommonwealth_bigModel } // 识别报价模式 func (r *Rule) quoteMode(b *BidInfo) (string, map[string]bool) { for _, v := range quoteModeRules { vv := gvar.New(v).MapStrVar() modeName := vv["mode"].String() for _, row := range b.TableKv { for k, v := range row { if tableV := vv["tableV"].String(); tableV != "" { matchedK, _ := regexp.MatchString(quoteModeTableKReg, k) if !matchedK { if tableK := vv["tableK"].String(); tableK != "" { matchedK, _ = regexp.MatchString(tableK, k) } } matchedV, _ := regexp.MatchString(tableV, v) if matchedK && matchedV { log.Println(b.Id, "tableKv", k, v) return modeName, nil } } } } } bigModel := map[string]bool{} for _, v := range quoteModeRules { vv := gvar.New(v).MapStrVar() modeName := vv["mode"].String() var lineUnderstandPatterns []string if lineUnderstand := vv["lineUnderstand"].MapStrVar(); lineUnderstand != nil { lineUnderstandPatterns = lineUnderstand["patterns"].Strings() } lines := strings.Split(b.Detail, "\n") for lineNum, lineVal := range lines { if r.matchAnyPattern(b.Id, lineVal, vv["patterns"].Strings()) { return modeName, nil } for _, vvv := range lineUnderstandPatterns { countLine := len(strings.Split(vvv, "+")) if countLine > 1 { countLine += vv["space"].Int() } newText := []string{} for i := lineNum; i < lineNum+countLine && i < len(lines); i++ { newText = append(newText, lines[i]) } if r.matchAnyPattern(b.Id, strings.Join(newText, "\n"), []string{vvv}) { return modeName, nil } } } // if modelPatterns := vv["modelPatterns"].String(); modelPatterns != "" && r.matchAnyPattern(b.Id, b.Detail, []string{modelPatterns}) { bigModel[modeName] = true } } return "", bigModel } // 识别中标联合体 func (r *Rule) bidCommonwealth(b *BidInfo) int { // Step 1: 排除黑名单 if r.matchAnyPattern(b.Id, b.Detail, bidCommonwealth_blacklistPatterns) { return -1 } for _, v := range b.KvText { if r.matchAnyPattern(b.Id, v, bidCommonwealth_whitelistPatterns) { return 1 } } if b.FirstWinner != "" && regexp.MustCompile(bidCommonwealth_firstWinnerOrder).MatchString(b.FirstWinner) { log.Println(b.Id, "第一中标候选人", b.FirstWinner, bidCommonwealth_firstWinnerOrder) return 1 } else if r.matchOnlyOnce(b.Id, b.Detail) { return 1 } else if r.matchAnyPattern(b.Id, b.Detail, bidCommonwealth_whitelistPatterns) { return 1 } else if b.Multipackage < 2 && len(moreWinnerReg.Split(b.Winner, -1)) > 1 { log.Println(b.Id, "单包多个中标单位") return 1 } index := strings.Index(b.Detail, "中标") if index != -1 { start := max(0, index-50) end := min(len(b.Detail), index+50) contextAroundWin := b.Detail[start:end] if strings.Contains(contextAroundWin, "联合体") { log.Println(b.Id, "”中标“附件有”联合体“") return 1 } } if r.matchAnyPattern(b.Id, b.Detail, bidCommonwealth_modelPatterns) { return -2 } return -1 } // 匹配任意模式 func (r *Rule) matchAnyPattern(_id string, text string, patterns []string) bool { for _, pattern := range patterns { if strings.HasPrefix(pattern, "全部包含:") { vs := strings.Split(strings.TrimPrefix(pattern, "全部包含:"), "+") index := 0 for _, v := range vs { if strings.Contains(text, v) { index++ } } if index == len(vs) { log.Println(_id, "matchAnyPattern", pattern) return true } continue } if matched, _ := regexp.MatchString(pattern, text); matched { log.Println(_id, "matchAnyPattern", pattern) return true } } return false } // 全部匹配 func (r *Rule) matchAllPattern(text string, patterns []string) bool { count := 0 for _, pattern := range patterns { if matched, _ := regexp.MatchString(pattern, text); matched { count++ } } if count > 0 && count == len(patterns) { return true } return false } func (r *Rule) matchOnlyOnce(_id, text string) bool { for _, v := range showOnlyOnce { count := 0 for _, vv := range v { if len(regexp.MustCompile(vv).FindAllString(text, -1)) != 1 { break } count++ } if count > 0 && count == len(v) { log.Println(_id, v) return true } } return false }