standard.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  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. s = strings.Replace(s, " ", "", -1)
  281. a := strings.Split(s, "国")
  282. if len(a) == 1 {
  283. a = strings.Split(s, "第")
  284. if len(a) == 1 {
  285. if v, ok := std.emissionStandard[s]; ok {
  286. return v
  287. }
  288. return calcEmissionStandard(s)
  289. }
  290. }
  291. condition := a[1]
  292. switch {
  293. case strings.Index(a[1], "阶段") > -1:
  294. if arr := strings.Split(a[1], "阶段"); len(arr) > 1 {
  295. condition = arr[0]
  296. }
  297. case strings.Index(a[1], ")") > -1:
  298. if arr := strings.Split(a[1], ")"); len(arr) > 1 {
  299. condition = arr[0]
  300. }
  301. case strings.Index(a[1], ")") > -1:
  302. if arr := strings.Split(a[1], ")"); len(arr) > 1 {
  303. condition = arr[0]
  304. }
  305. case strings.Index(a[1], ",") > -1:
  306. if arr := strings.Split(a[1], ","); len(arr) > 1 {
  307. condition = arr[0]
  308. }
  309. case strings.Index(a[1], ",") > -1:
  310. if arr := strings.Split(a[1], ","); len(arr) > 1 {
  311. condition = arr[0]
  312. }
  313. }
  314. if v, ok := std.emissionStandard[condition]; ok {
  315. return "国" + v
  316. }
  317. return s
  318. }
  319. // pl = 1000
  320. // plL = 1.0L or 1.0T
  321. func Displacement(pl, plL string) int {
  322. multiple := 1
  323. if pl == "" {
  324. pl = plL
  325. multiple = 1000
  326. }
  327. tmp := strings.Replace(pl, "L", "", -1)
  328. tmp = strings.Replace(tmp, "T", "", -1)
  329. t, _ := strconv.ParseFloat(tmp, 64)
  330. t *= float64(multiple)
  331. return int(t)
  332. }
  333. func IsHan(data string) bool {
  334. for _, r := range data {
  335. if unicode.Is(unicode.Scripts["Han"], r) {
  336. return true
  337. }
  338. }
  339. return false
  340. }
  341. func VehicleType(vehicleType string) (string, string) {
  342. reload()
  343. if vehicleType == "轿车" {
  344. return std.vehicleType["小型轿车"], vehicleType
  345. }
  346. vehicleType = strings.ToUpper(vehicleType)
  347. if IsHan(vehicleType) {
  348. if value, ok := std.vehicleType[vehicleType]; ok {
  349. return value, vehicleType
  350. }
  351. return "", vehicleType
  352. }
  353. if value, ok := std.vehicleTypeCode[vehicleType]; ok {
  354. return value, vehicleType
  355. }
  356. return "", vehicleType
  357. }
  358. func PlateType(plateType string) (string, string) {
  359. reload()
  360. if IsHan(plateType) {
  361. if value, ok := std.plateType[plateType]; ok {
  362. return value, plateType
  363. }
  364. return "", plateType
  365. }
  366. if value, ok := std.plateTypeCode[plateType]; ok {
  367. return value, plateType
  368. }
  369. return "", plateType
  370. }
  371. // 日期格式化
  372. func FormatDate(date string) string {
  373. date = strings.TrimSpace(date)
  374. if date == "" {
  375. return date
  376. }
  377. if strings.HasPrefix(date, "1970-01-01") {
  378. return ""
  379. }
  380. if strings.Contains(date, "-") {
  381. // 获取年月日时间格式
  382. if len(date) == MonthLen {
  383. return date + "-01 00:00:00"
  384. }
  385. newDate := strings.Split(date, " ")[0]
  386. if len(newDate) < DataLen {
  387. date = strings.Replace(date, "-", "/", -1)
  388. }
  389. }
  390. if strings.Contains(date, "/") {
  391. newDate := strings.Split(date, " ")[0]
  392. time1, _ := time.Parse(DayLayout2, newDate)
  393. date = time1.Format(DayLayout)
  394. } else {
  395. if len(date) == DaySecLen {
  396. return date
  397. }
  398. }
  399. if len(date) >= DataLen {
  400. date = date[:DataLen] + " 00:00:00"
  401. }
  402. return date
  403. }