package utils import ( "adm-data/consts" "adm-data/model" "fmt" "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() 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 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 }