package utils import ( "fmt" "gd_adm_data/consts" "gd_adm_data/model" "regexp" "strconv" "strings" "sync" "time" "unicode" "git.getensh.com/common/gopkgsv2/database" ) type standard struct { mu sync.Mutex ts int64 fuelType map[string]string fuelTypeCode map[string]string emissionStandard map[string]string plateType map[string]string plateTypeCode map[string]string vehicleType map[string]string vehicleTypeCode map[string]string useProperty map[string]string usePropertyCode map[string]string vehicleBodyColor map[string]string vehicleBodyColorCode map[string]string } // 时间格式常量定义 const ( DataLen = len("2006-01-02") MonthLen = len("2006-01") DaySecLen = len("2006-01-02 15:04:05") DayLayout = "2006-01-02" DaySecLayout = "2006-01-02 15:04:05" DayLayout2 = "2006/1/2" DaySecond = 24 * 60 * 60 SecondTime = 60 ) var std standard func reload() { if std.ts == 0 || time.Now().Unix()-std.ts > 10*60 { std = standard{ mu: sync.Mutex{}, fuelType: map[string]string{}, fuelTypeCode: map[string]string{}, emissionStandard: map[string]string{}, plateType: map[string]string{}, plateTypeCode: map[string]string{}, vehicleType: map[string]string{}, vehicleTypeCode: map[string]string{}, useProperty: map[string]string{}, usePropertyCode: map[string]string{}, vehicleBodyColorCode: map[string]string{}, vehicleBodyColor: map[string]string{}, } } else { return } std.mu.Lock() defer std.mu.Unlock() std.ts = time.Now().Unix() list, err := model.NewAds22Model().List(database.DB()) if err != nil { return } for _, v := range list { switch v.Type { case consts.FuelType: if _, ok := std.fuelTypeCode[v.Source]; !ok { std.fuelTypeCode[v.Source] = v.Standard } std.fuelType[v.Standard] = v.Source case consts.EmissionStandard: std.emissionStandard[v.Source] = v.Standard case consts.PlateType: if _, ok := std.plateTypeCode[v.Source]; !ok { std.plateTypeCode[v.Source] = v.Standard } std.plateType[v.Standard] = v.Source case consts.VehicleType: if _, ok := std.vehicleTypeCode[v.Source]; !ok { std.vehicleTypeCode[v.Source] = v.Standard } std.vehicleType[v.Standard] = v.Source case consts.UseProperty: if _, ok := std.usePropertyCode[v.Source]; !ok { std.usePropertyCode[v.Source] = v.Standard } std.useProperty[v.Standard] = v.Source case consts.VehicleBodyColor: if _, ok := std.vehicleBodyColorCode[v.Source]; !ok { std.vehicleBodyColorCode[v.Source] = v.Standard } std.vehicleBodyColor[v.Standard] = v.Source } } } func ParseFuel(fuel string) (string, string) { reload() fuel = strings.ToUpper(fuel) fuel = strings.Replace(fuel, "CNG", "天然气", -1) fuel = strings.Replace(fuel, "NG", "天然气", -1) return ParseCodeDetail(fuel, std.fuelTypeCode, std.fuelType, fuelType) } func fuelType(s string) (string, string) { if value, ok := std.fuelType[s]; ok { return value, s } return "", s } func getColorCodeDetail(color string) (string, string) { if value, ok := std.vehicleBodyColor[color]; ok { return value, color } /*for k, _ := range std.vehicleBodyColor { if strings.Contains(color, k) { return std.vehicleBodyColor[k], color } }*/ for _, v := range color { if value, ok := std.vehicleBodyColor[string(v)]; ok { return value, color } } if strings.Contains(color, "银") || strings.Contains(color, "灰") { return std.vehicleBodyColor["灰"], "灰" } if strings.Contains(color, "橙") || strings.Contains(color, "金") { return std.vehicleBodyColor["黄"], "黄" } if strings.Contains(color, "青") { return std.vehicleBodyColor["绿"], "绿" } if strings.Contains(color, "兰") || strings.Contains(color, "深篮") || strings.Contains(color, "篮") { return std.vehicleBodyColor["蓝"], "蓝" } if strings.Contains(color, "咖啡") { return std.vehicleBodyColor["棕"], "棕" } return "", color } func ParseColor(color string) (string, string) { reload() color = strings.ToUpper(color) return ParseCodeDetail(color, std.vehicleBodyColorCode, std.vehicleBodyColor, getColorCodeDetail) } func ParseProperty(property string) (string, string) { reload() property = strings.ToUpper(property) return ParseCodeDetail(property, std.usePropertyCode, std.useProperty, propertyCodeDetail) } func TrimNumberic(data string) string { pat := "[0-9]" re, _ := regexp.Compile(pat) str := re.ReplaceAllString(data, "") return str } func ClearData(data string) string { data = strings.Replace(data, " ", "", -1) data = strings.Replace(data, "/", "", -1) data = strings.Replace(data, "+", "", -1) data = strings.Replace(data, ",", "", -1) data = strings.Replace(data, ".", "", -1) data = strings.Replace(data, ",", "", -1) data = strings.Replace(data, "、", "", -1) return data } func GetArray(data string) []string { data = strings.Replace(data, " ", ";", -1) data = strings.Replace(data, "/", ";", -1) data = strings.Replace(data, "+", ";", -1) data = strings.Replace(data, ",", ";", -1) data = strings.Replace(data, ".", ";", -1) data = strings.Replace(data, ",", ";", -1) data = strings.Replace(data, ",", ";", -1) data = strings.Replace(data, "、", ";", -1) data = strings.Replace(data, "-", ";", -1) data = strings.Replace(data, "(", ";", -1) data = strings.Replace(data, "(", ";", -1) data = strings.Replace(data, ")", ";", -1) data = strings.Replace(data, ")", ";", -1) return strings.Split(data, ";") } func ParseCodeDetail(data string, codeMap map[string]string, detailMap map[string]string, f func(string) (string, string)) (string, string) { data = TrimNumberic(data) if IsHan(data) { array := GetArray(data) ret := "" for _, v := range array { code := "" if f != nil { code, _ = f(v) } else { code, _ = detailMap[v] } if strings.Contains(ret, code) { continue } ret = ret + code } return ret, data } if value, ok := codeMap[data]; ok { return value, data } ret := "" retCode := "" data = ClearData(data) for _, v := range data { code := fmt.Sprintf("%c", v) if ret == "" { if detail, ok := codeMap[code]; ok { ret = detail retCode = code } } else if detail, ok := codeMap[code]; ok { ret = fmt.Sprintf("%s+%s", ret, detail) retCode = retCode + code } } return ret, retCode } func propertyCodeDetail(data string) (string, string) { if value, ok := std.useProperty[data]; ok { return value, data } if strings.Contains(data, "非营业") { return std.useProperty["非营运"], "非营运" } if strings.Contains(data, "营业公路客运") { return std.useProperty["公路客运"], "公路客运" } if strings.Contains(data, "营业城市公交") { return std.useProperty["营业城市公交"], "营业城市公交" } if strings.Contains(data, "营业出租租赁") { return std.useProperty["出租客运"], "出租客运" } if strings.Contains(data, "营业挂车") { return std.useProperty["货运"], "货运" } if strings.Contains(data, "营业货车") { return std.useProperty["货运"], "货运" } if strings.Contains(data, "运输型") { return std.useProperty["货运"], "货运" } if strings.Contains(data, "化工") { return std.useProperty["危化品运输"], "危化品运输" } return "", data } func calcEmissionStandard(s string) string { a := strings.Split(s, ".") if len(a) == 1 { return s } if len(a[1]) > 0 { hearder := a[1][0:1] switch hearder { case "1": return "国一" case "2": return "国二" case "3": return "国三" case "4": return "国四" case "5": return "国五" case "6": return "国六" } } return s } func EmissionStandard(s string) string { reload() switch s { case "": return "" case "见其它": return "" case "美国加洲排放认证证书": return "" case "N/A": return "" case "-": return "" case "--": return "" case "0": return "" case "未知": return "" case "不适用": return "" case "/": return "" case "无": return "" case "#N/A": return "" case "﹣": return "" case "—": return "" case "梅赛德斯-奔驰(中国)汽车销售有限公司": return "" case "汽油": return "" case "WAUGFEF50KA084988": return "" case "WAUGFEF50KA086174": return "" case "CNCA-02C-024:2008": return "" case "DWS135B1315111100": return "" case "EV": return "EV" case "98/69/EC": return "欧四" case "1": return "" case "EUROⅡ": return "欧二" case "欧洲1": return "欧一" case "欧5": return "欧五" case "欧IV": return "欧四" case "欧V": return "欧五" case "欧六": return "欧六" case " 欧IV": return "欧四" case "欧洲III号": return "欧三" } if v, ok := std.emissionStandard[s]; ok { return "国" + v } s = strings.Replace(s, " ", "", -1) a := strings.Split(s, "国") if len(a) == 1 { a = strings.Split(s, "第") if len(a) == 1 { if v, ok := std.emissionStandard[s]; ok { return v } return calcEmissionStandard(s) } } condition := a[1] switch { case strings.Index(a[1], "阶段") > -1: if arr := strings.Split(a[1], "阶段"); len(arr) > 1 { condition = arr[0] } case strings.Index(a[1], ")") > -1: if arr := strings.Split(a[1], ")"); len(arr) > 1 { condition = arr[0] } case strings.Index(a[1], ")") > -1: if arr := strings.Split(a[1], ")"); len(arr) > 1 { condition = arr[0] } case strings.Index(a[1], ",") > -1: if arr := strings.Split(a[1], ","); len(arr) > 1 { condition = arr[0] } case strings.Index(a[1], ",") > -1: if arr := strings.Split(a[1], ","); len(arr) > 1 { condition = arr[0] } } if strings.Contains(s, "ⅠⅠⅠ") || strings.Contains(s, "III") || strings.Contains(s, "Ⅲ") || strings.Contains(s, "国3") { return "国三" } else if strings.Contains(s, "ⅠⅤ") || strings.Contains(s, "Ⅳ") || strings.Contains(s, "IV") || strings.Contains(s, "ⅠV") || strings.Contains(s, "国4") { return "国四" } else if strings.Contains(s, "ⅤⅠ") || strings.Contains(s, "VI") || strings.Contains(s, "VⅠ") || strings.Contains(s, "Ⅵ") || strings.Contains(s, "国6") { return "国六" } else if strings.Contains(s, "ⅠⅠ") || strings.Contains(s, "II") || strings.Contains(s, "国2") || strings.Contains(s, "Ⅱ") { return "国二" // 欧标2 欧洲2 欧洲1 欧2 } else if strings.Contains(s, "Ⅰ") || strings.Contains(s, "I") || strings.Contains(s, "国1") { return "国一" } else if strings.Contains(s, "Ⅴ") || strings.Contains(s, "V") || strings.Contains(s, "V") || strings.Contains(s, "国5") { return "国五" } else if strings.Contains(s, "GB18352.6-2016") { return "国六" } else if strings.Contains(s, "8352.2-2001") || strings.Contains(s, "18352.2-2001") || strings.Contains(s, "GB-18352.2-2001") || strings.Contains(s, "GB18352.2-2001") { return "国二" } else if strings.Contains(s, "GB14762-2008") || strings.Contains(s, "GB14622-2016") || strings.Contains(s, "GB17691-2005") { return "国四" } else if strings.Contains(s, "GB18352.5-20013") || strings.Contains(s, "GB18352.5-2013") || strings.Contains(s, "GB18352.52013") || strings.Contains(s, "GB18352.5-2014") || strings.Contains(s, "GB18352.5-2015") { return "国五" } else if strings.Contains(s, "GB18352.6-2016") { return "国六" } else if strings.Contains(s, "18352.3-2005") || strings.Contains(s, "GB3847-2005") { return "国三" } if v, ok := std.emissionStandard[condition]; ok { return "国" + v } return s } // pl = 1000 // plL = 1.0L or 1.0T func Displacement(pl, plL string) int { multiple := 1 if pl == "" { pl = plL multiple = 1000 } tmp := strings.Replace(pl, "L", "", -1) tmp = strings.Replace(tmp, "T", "", -1) t, _ := strconv.ParseFloat(tmp, 64) t *= float64(multiple) return int(t) } func IsHan(data string) bool { for _, r := range data { if unicode.Is(unicode.Scripts["Han"], r) { return true } } return false } func VehicleType(vehicleType string) (string, string) { reload() if vehicleType == "轿车" { return std.vehicleType["小型轿车"], vehicleType } vehicleType = strings.ToUpper(vehicleType) if IsHan(vehicleType) { if value, ok := std.vehicleType[vehicleType]; ok { return value, vehicleType } return "", vehicleType } if value, ok := std.vehicleTypeCode[vehicleType]; ok { return value, vehicleType } return "", vehicleType } func PlateType(plateType string) (string, string) { reload() if IsHan(plateType) { if value, ok := std.plateType[plateType]; ok { return value, plateType } return "", plateType } if value, ok := std.plateTypeCode[plateType]; ok { return value, plateType } return "", plateType } // 日期格式化 func FormatDate(date string) string { date = strings.TrimSpace(date) if date == "" { return date } if strings.HasPrefix(date, "1970-01-01") { return "" } if strings.Contains(date, "-") { // 获取年月日时间格式 if len(date) == MonthLen { return date + "-01 00:00:00" } newDate := strings.Split(date, " ")[0] if len(newDate) < DataLen { date = strings.Replace(date, "-", "/", -1) } } if strings.Contains(date, "/") { newDate := strings.Split(date, " ")[0] time1, _ := time.Parse(DayLayout2, newDate) date = time1.Format(DayLayout) } else { if len(date) == DaySecLen { return date } } if len(date) >= DataLen { date = date[:DataLen] + " 00:00:00" } return date }