standard.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  1. package utils
  2. import (
  3. "fmt"
  4. "gd_adm_data/consts"
  5. "gd_adm_data/model"
  6. "regexp"
  7. "strconv"
  8. "strings"
  9. "sync"
  10. "time"
  11. "unicode"
  12. "git.getensh.com/common/gopkgsv2/database"
  13. )
  14. type standard struct {
  15. mu sync.Mutex
  16. ts int64
  17. fuelType map[string]string
  18. fuelTypeCode map[string]string
  19. emissionStandard map[string]string
  20. plateType map[string]string
  21. plateTypeCode map[string]string
  22. vehicleType map[string]string
  23. vehicleTypeCode map[string]string
  24. useProperty map[string]string
  25. usePropertyCode map[string]string
  26. vehicleBodyColor map[string]string
  27. vehicleBodyColorCode map[string]string
  28. }
  29. // 时间格式常量定义
  30. const (
  31. DataLen = len("2006-01-02")
  32. MonthLen = len("2006-01")
  33. DaySecLen = len("2006-01-02 15:04:05")
  34. DayLayout = "2006-01-02"
  35. DaySecLayout = "2006-01-02 15:04:05"
  36. DayLayout2 = "2006/1/2"
  37. DaySecond = 24 * 60 * 60
  38. SecondTime = 60
  39. )
  40. var std standard
  41. func reload() {
  42. if std.ts == 0 || time.Now().Unix()-std.ts > 10*60 {
  43. std = standard{
  44. mu: sync.Mutex{},
  45. fuelType: map[string]string{},
  46. fuelTypeCode: map[string]string{},
  47. emissionStandard: map[string]string{},
  48. plateType: map[string]string{},
  49. plateTypeCode: map[string]string{},
  50. vehicleType: map[string]string{},
  51. vehicleTypeCode: map[string]string{},
  52. useProperty: map[string]string{},
  53. usePropertyCode: map[string]string{},
  54. vehicleBodyColorCode: map[string]string{},
  55. vehicleBodyColor: map[string]string{},
  56. }
  57. } else {
  58. return
  59. }
  60. std.mu.Lock()
  61. defer std.mu.Unlock()
  62. std.ts = time.Now().Unix()
  63. list, err := model.NewAds22Model().List(database.DB())
  64. if err != nil {
  65. return
  66. }
  67. for _, v := range list {
  68. switch v.Type {
  69. case consts.FuelType:
  70. if _, ok := std.fuelTypeCode[v.Source]; !ok {
  71. std.fuelTypeCode[v.Source] = v.Standard
  72. }
  73. std.fuelType[v.Standard] = v.Source
  74. case consts.EmissionStandard:
  75. std.emissionStandard[v.Source] = v.Standard
  76. case consts.PlateType:
  77. if _, ok := std.plateTypeCode[v.Source]; !ok {
  78. std.plateTypeCode[v.Source] = v.Standard
  79. }
  80. std.plateType[v.Standard] = v.Source
  81. case consts.VehicleType:
  82. if _, ok := std.vehicleTypeCode[v.Source]; !ok {
  83. std.vehicleTypeCode[v.Source] = v.Standard
  84. }
  85. std.vehicleType[v.Standard] = v.Source
  86. case consts.UseProperty:
  87. if _, ok := std.usePropertyCode[v.Source]; !ok {
  88. std.usePropertyCode[v.Source] = v.Standard
  89. }
  90. std.useProperty[v.Standard] = v.Source
  91. case consts.VehicleBodyColor:
  92. if _, ok := std.vehicleBodyColorCode[v.Source]; !ok {
  93. std.vehicleBodyColorCode[v.Source] = v.Standard
  94. }
  95. std.vehicleBodyColor[v.Standard] = v.Source
  96. }
  97. }
  98. }
  99. func ParseFuel(fuel string) (string, string) {
  100. reload()
  101. fuel = strings.ToUpper(fuel)
  102. fuel = strings.Replace(fuel, "CNG", "天然气", -1)
  103. fuel = strings.Replace(fuel, "NG", "天然气", -1)
  104. return ParseCodeDetail(fuel, std.fuelTypeCode, std.fuelType, fuelType)
  105. }
  106. func fuelType(s string) (string, string) {
  107. if value, ok := std.fuelType[s]; ok {
  108. return value, s
  109. }
  110. return "", s
  111. }
  112. func getColorCodeDetail(color string) (string, string) {
  113. if value, ok := std.vehicleBodyColor[color]; ok {
  114. return value, color
  115. }
  116. /*for k, _ := range std.vehicleBodyColor {
  117. if strings.Contains(color, k) {
  118. return std.vehicleBodyColor[k], color
  119. }
  120. }*/
  121. for _, v := range color {
  122. if value, ok := std.vehicleBodyColor[string(v)]; ok {
  123. return value, color
  124. }
  125. }
  126. if strings.Contains(color, "银") || strings.Contains(color, "灰") {
  127. return std.vehicleBodyColor["灰"], "灰"
  128. }
  129. if strings.Contains(color, "橙") || strings.Contains(color, "金") {
  130. return std.vehicleBodyColor["黄"], "黄"
  131. }
  132. if strings.Contains(color, "青") {
  133. return std.vehicleBodyColor["绿"], "绿"
  134. }
  135. if strings.Contains(color, "兰") || strings.Contains(color, "深篮") || strings.Contains(color, "篮") {
  136. return std.vehicleBodyColor["蓝"], "蓝"
  137. }
  138. if strings.Contains(color, "咖啡") {
  139. return std.vehicleBodyColor["棕"], "棕"
  140. }
  141. return "", color
  142. }
  143. func ParseColor(color string) (string, string) {
  144. reload()
  145. color = strings.ToUpper(color)
  146. return ParseCodeDetail(color, std.vehicleBodyColorCode, std.vehicleBodyColor, getColorCodeDetail)
  147. }
  148. func ParseProperty(property string) (string, string) {
  149. reload()
  150. property = strings.ToUpper(property)
  151. return ParseCodeDetail(property, std.usePropertyCode, std.useProperty, propertyCodeDetail)
  152. }
  153. func TrimNumberic(data string) string {
  154. pat := "[0-9]"
  155. re, _ := regexp.Compile(pat)
  156. str := re.ReplaceAllString(data, "")
  157. return str
  158. }
  159. func ClearData(data string) string {
  160. data = strings.Replace(data, " ", "", -1)
  161. data = strings.Replace(data, "/", "", -1)
  162. data = strings.Replace(data, "+", "", -1)
  163. data = strings.Replace(data, ",", "", -1)
  164. data = strings.Replace(data, ".", "", -1)
  165. data = strings.Replace(data, ",", "", -1)
  166. data = strings.Replace(data, "、", "", -1)
  167. return data
  168. }
  169. func GetArray(data string) []string {
  170. data = strings.Replace(data, " ", ";", -1)
  171. data = strings.Replace(data, "/", ";", -1)
  172. data = strings.Replace(data, "+", ";", -1)
  173. data = strings.Replace(data, ",", ";", -1)
  174. data = strings.Replace(data, ".", ";", -1)
  175. data = strings.Replace(data, ",", ";", -1)
  176. data = strings.Replace(data, ",", ";", -1)
  177. data = strings.Replace(data, "、", ";", -1)
  178. data = strings.Replace(data, "-", ";", -1)
  179. data = strings.Replace(data, "(", ";", -1)
  180. data = strings.Replace(data, "(", ";", -1)
  181. data = strings.Replace(data, ")", ";", -1)
  182. data = strings.Replace(data, ")", ";", -1)
  183. return strings.Split(data, ";")
  184. }
  185. func ParseCodeDetail(data string, codeMap map[string]string, detailMap map[string]string, f func(string) (string, string)) (string, string) {
  186. data = TrimNumberic(data)
  187. if IsHan(data) {
  188. array := GetArray(data)
  189. ret := ""
  190. for _, v := range array {
  191. code := ""
  192. if f != nil {
  193. code, _ = f(v)
  194. } else {
  195. code, _ = detailMap[v]
  196. }
  197. if strings.Contains(ret, code) {
  198. continue
  199. }
  200. ret = ret + code
  201. }
  202. return ret, data
  203. }
  204. if value, ok := codeMap[data]; ok {
  205. return value, data
  206. }
  207. ret := ""
  208. retCode := ""
  209. data = ClearData(data)
  210. for _, v := range data {
  211. code := fmt.Sprintf("%c", v)
  212. if ret == "" {
  213. if detail, ok := codeMap[code]; ok {
  214. ret = detail
  215. retCode = code
  216. }
  217. } else if detail, ok := codeMap[code]; ok {
  218. ret = fmt.Sprintf("%s+%s", ret, detail)
  219. retCode = retCode + code
  220. }
  221. }
  222. return ret, retCode
  223. }
  224. func propertyCodeDetail(data string) (string, string) {
  225. if value, ok := std.useProperty[data]; ok {
  226. return value, data
  227. }
  228. if strings.Contains(data, "非营业") {
  229. return std.useProperty["非营运"], "非营运"
  230. }
  231. if strings.Contains(data, "营业公路客运") {
  232. return std.useProperty["公路客运"], "公路客运"
  233. }
  234. if strings.Contains(data, "营业城市公交") {
  235. return std.useProperty["营业城市公交"], "营业城市公交"
  236. }
  237. if strings.Contains(data, "营业出租租赁") {
  238. return std.useProperty["出租客运"], "出租客运"
  239. }
  240. if strings.Contains(data, "营业挂车") {
  241. return std.useProperty["货运"], "货运"
  242. }
  243. if strings.Contains(data, "营业货车") {
  244. return std.useProperty["货运"], "货运"
  245. }
  246. if strings.Contains(data, "运输型") {
  247. return std.useProperty["货运"], "货运"
  248. }
  249. if strings.Contains(data, "化工") {
  250. return std.useProperty["危化品运输"], "危化品运输"
  251. }
  252. return "", data
  253. }
  254. func calcEmissionStandard(s string) string {
  255. a := strings.Split(s, ".")
  256. if len(a) == 1 {
  257. return s
  258. }
  259. if len(a[1]) > 0 {
  260. hearder := a[1][0:1]
  261. switch hearder {
  262. case "1":
  263. return "国一"
  264. case "2":
  265. return "国二"
  266. case "3":
  267. return "国三"
  268. case "4":
  269. return "国四"
  270. case "5":
  271. return "国五"
  272. case "6":
  273. return "国六"
  274. }
  275. }
  276. return s
  277. }
  278. func EmissionStandard(s string) string {
  279. reload()
  280. switch s {
  281. case "":
  282. return ""
  283. case "见其它":
  284. return ""
  285. case "美国加洲排放认证证书":
  286. return ""
  287. case "N/A":
  288. return ""
  289. case "-":
  290. return ""
  291. case "--":
  292. return ""
  293. case "0":
  294. return ""
  295. case "未知":
  296. return ""
  297. case "不适用":
  298. return ""
  299. case "/":
  300. return ""
  301. case "无":
  302. return ""
  303. case "#N/A":
  304. return ""
  305. case "﹣":
  306. return ""
  307. case "—":
  308. return ""
  309. case "梅赛德斯-奔驰(中国)汽车销售有限公司":
  310. return ""
  311. case "汽油":
  312. return ""
  313. case "WAUGFEF50KA084988":
  314. return ""
  315. case "WAUGFEF50KA086174":
  316. return ""
  317. case "CNCA-02C-024:2008":
  318. return ""
  319. case "DWS135B1315111100":
  320. return ""
  321. case "EV":
  322. return "EV"
  323. case "98/69/EC":
  324. return "欧四"
  325. case "1":
  326. return ""
  327. case "EUROⅡ":
  328. return "欧二"
  329. case "欧洲1":
  330. return "欧一"
  331. case "欧5":
  332. return "欧五"
  333. case "欧IV":
  334. return "欧四"
  335. case "欧V":
  336. return "欧五"
  337. case "欧六":
  338. return "欧六"
  339. case " 欧IV":
  340. return "欧四"
  341. case "欧洲III号":
  342. return "欧三"
  343. }
  344. if v, ok := std.emissionStandard[s]; ok {
  345. return "国" + v
  346. }
  347. s = strings.Replace(s, " ", "", -1)
  348. a := strings.Split(s, "国")
  349. if len(a) == 1 {
  350. a = strings.Split(s, "第")
  351. if len(a) == 1 {
  352. if v, ok := std.emissionStandard[s]; ok {
  353. return v
  354. }
  355. return calcEmissionStandard(s)
  356. }
  357. }
  358. condition := a[1]
  359. switch {
  360. case strings.Index(a[1], "阶段") > -1:
  361. if arr := strings.Split(a[1], "阶段"); len(arr) > 1 {
  362. condition = arr[0]
  363. }
  364. case strings.Index(a[1], ")") > -1:
  365. if arr := strings.Split(a[1], ")"); len(arr) > 1 {
  366. condition = arr[0]
  367. }
  368. case strings.Index(a[1], ")") > -1:
  369. if arr := strings.Split(a[1], ")"); len(arr) > 1 {
  370. condition = arr[0]
  371. }
  372. case strings.Index(a[1], ",") > -1:
  373. if arr := strings.Split(a[1], ","); len(arr) > 1 {
  374. condition = arr[0]
  375. }
  376. case strings.Index(a[1], ",") > -1:
  377. if arr := strings.Split(a[1], ","); len(arr) > 1 {
  378. condition = arr[0]
  379. }
  380. }
  381. if strings.Contains(s, "ⅠⅠⅠ") || strings.Contains(s, "III") || strings.Contains(s, "Ⅲ") || strings.Contains(s, "国3") {
  382. return "国三"
  383. } else if strings.Contains(s, "ⅠⅤ") || strings.Contains(s, "Ⅳ") || strings.Contains(s, "IV") ||
  384. strings.Contains(s, "ⅠV") || strings.Contains(s, "国4") {
  385. return "国四"
  386. } else if strings.Contains(s, "ⅤⅠ") || strings.Contains(s, "VI") || strings.Contains(s, "VⅠ") ||
  387. strings.Contains(s, "Ⅵ") || strings.Contains(s, "国6") {
  388. return "国六"
  389. } else if strings.Contains(s, "ⅠⅠ") || strings.Contains(s, "II") || strings.Contains(s, "国2") || strings.Contains(s, "Ⅱ") {
  390. return "国二" // 欧标2 欧洲2 欧洲1 欧2
  391. } else if strings.Contains(s, "Ⅰ") || strings.Contains(s, "I") || strings.Contains(s, "国1") {
  392. return "国一"
  393. } else if strings.Contains(s, "Ⅴ") || strings.Contains(s, "V") || strings.Contains(s, "V") || strings.Contains(s, "国5") {
  394. return "国五"
  395. } else if strings.Contains(s, "GB18352.6-2016") {
  396. return "国六"
  397. } 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") {
  398. return "国二"
  399. } else if strings.Contains(s, "GB14762-2008") || strings.Contains(s, "GB14622-2016") || strings.Contains(s, "GB17691-2005") {
  400. return "国四"
  401. } else if strings.Contains(s, "GB18352.5-20013") || strings.Contains(s, "GB18352.5-2013") ||
  402. strings.Contains(s, "GB18352.52013") || strings.Contains(s, "GB18352.5-2014") || strings.Contains(s, "GB18352.5-2015") {
  403. return "国五"
  404. } else if strings.Contains(s, "GB18352.6-2016") {
  405. return "国六"
  406. } else if strings.Contains(s, "18352.3-2005") || strings.Contains(s, "GB3847-2005") {
  407. return "国三"
  408. }
  409. if v, ok := std.emissionStandard[condition]; ok {
  410. return "国" + v
  411. }
  412. return s
  413. }
  414. // pl = 1000
  415. // plL = 1.0L or 1.0T
  416. func Displacement(pl, plL string) int {
  417. multiple := 1
  418. if pl == "" {
  419. pl = plL
  420. multiple = 1000
  421. }
  422. tmp := strings.Replace(pl, "L", "", -1)
  423. tmp = strings.Replace(tmp, "T", "", -1)
  424. t, _ := strconv.ParseFloat(tmp, 64)
  425. t *= float64(multiple)
  426. return int(t)
  427. }
  428. func IsHan(data string) bool {
  429. for _, r := range data {
  430. if unicode.Is(unicode.Scripts["Han"], r) {
  431. return true
  432. }
  433. }
  434. return false
  435. }
  436. func VehicleType(vehicleType string) (string, string) {
  437. reload()
  438. if vehicleType == "轿车" {
  439. return std.vehicleType["小型轿车"], vehicleType
  440. }
  441. vehicleType = strings.ToUpper(vehicleType)
  442. if IsHan(vehicleType) {
  443. if value, ok := std.vehicleType[vehicleType]; ok {
  444. return value, vehicleType
  445. }
  446. return "", vehicleType
  447. }
  448. if value, ok := std.vehicleTypeCode[vehicleType]; ok {
  449. return value, vehicleType
  450. }
  451. return "", vehicleType
  452. }
  453. func PlateType(plateType string) (string, string) {
  454. reload()
  455. if IsHan(plateType) {
  456. if value, ok := std.plateType[plateType]; ok {
  457. return value, plateType
  458. }
  459. return "", plateType
  460. }
  461. if value, ok := std.plateTypeCode[plateType]; ok {
  462. return value, plateType
  463. }
  464. return "", plateType
  465. }
  466. // 日期格式化
  467. func FormatDate(date string) string {
  468. date = strings.TrimSpace(date)
  469. if date == "" {
  470. return date
  471. }
  472. if strings.HasPrefix(date, "1970-01-01") {
  473. return ""
  474. }
  475. if strings.Contains(date, "-") {
  476. // 获取年月日时间格式
  477. if len(date) == MonthLen {
  478. return date + "-01 00:00:00"
  479. }
  480. newDate := strings.Split(date, " ")[0]
  481. if len(newDate) < DataLen {
  482. date = strings.Replace(date, "-", "/", -1)
  483. }
  484. }
  485. if strings.Contains(date, "/") {
  486. newDate := strings.Split(date, " ")[0]
  487. time1, _ := time.Parse(DayLayout2, newDate)
  488. date = time1.Format(DayLayout)
  489. } else {
  490. if len(date) == DaySecLen {
  491. return date
  492. }
  493. }
  494. if len(date) >= DataLen {
  495. date = date[:DataLen] + " 00:00:00"
  496. }
  497. return date
  498. }