From f2b6d43cb12ed42d9ab44ea50784066c86eb4ad1 Mon Sep 17 00:00:00 2001 From: Chengxun Lee <24319042+bclswl0827@users.noreply.github.com> Date: Tue, 19 Mar 2024 16:40:00 +0800 Subject: [PATCH] Support earthquake event source API of Korea Meteorological Administration --- CHANGELOG.md | 4 + VERSION | 2 +- app/v1/trace/kma.go | 168 ++++++++++++++++++ app/v1/trace/module.go | 1 + frontend/dist/asset-manifest.json | 4 +- frontend/dist/index.html | 2 +- .../js/{main.22f3dcb0.js => main.6c81bc75.js} | 4 +- ...CENSE.txt => main.6c81bc75.js.LICENSE.txt} | 0 frontend/src/.env | 4 +- 9 files changed, 181 insertions(+), 8 deletions(-) create mode 100644 app/v1/trace/kma.go rename frontend/dist/static/js/{main.22f3dcb0.js => main.6c81bc75.js} (99%) rename frontend/dist/static/js/{main.22f3dcb0.js.LICENSE.txt => main.6c81bc75.js.LICENSE.txt} (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c09d65e..57673793 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ Starting from v2.2.5, all notable changes to this project will be documented in this file. +## v2.11.7 + +- Support earthquake event source API of Korea Meteorological Administration + ## v2.11.6 - Ensure that there is only one Websocket connection after reconnecting diff --git a/VERSION b/VERSION index 27b8213d..cee6f277 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v2.11.6 +v2.11.7 diff --git a/app/v1/trace/kma.go b/app/v1/trace/kma.go new file mode 100644 index 00000000..2b362238 --- /dev/null +++ b/app/v1/trace/kma.go @@ -0,0 +1,168 @@ +package trace + +import ( + "bytes" + "strconv" + "strings" + "time" + + "github.com/PuerkitoBio/goquery" + "github.com/anyshake/observer/utils/duration" + "github.com/anyshake/observer/utils/request" +) + +type KMA struct { + DataSourceCache +} + +func (k *KMA) Property() string { + return "기상청(국내지진조회)" +} + +func (k *KMA) Fetch() ([]byte, error) { + if duration.Difference(time.Now(), k.Time) <= EXPIRATION { + return k.Cache, nil + } + + res, err := request.GET( + "https://www.weather.go.kr/w/eqk-vol/search/korea.do", + 10*time.Second, time.Second, 3, false, nil, + ) + if err != nil { + return nil, err + } + + k.Time = time.Now() + k.Cache = make([]byte, len(res)) + copy(k.Cache, res) + + return res, nil +} + +func (k *KMA) Parse(data []byte) (map[string]any, error) { + result := make(map[string]any) + result["data"] = make([]any, 0) + + reader := bytes.NewBuffer(data) + doc, err := goquery.NewDocumentFromReader(reader) + if err != nil { + return nil, err + } + + doc.Find("#excel_body").Each(func(i int, s *goquery.Selection) { + s.Find("tbody").Each(func(i int, s *goquery.Selection) { + s.Find("tr").Each(func(i int, s *goquery.Selection) { + item := make(map[string]any) + s.Find("td").Each(func(i int, s *goquery.Selection) { + value := strings.TrimSpace(s.Text()) + switch i { + case 1: + item["timestamp"] = k.getTimestamp(value) + case 2: + item["magnitude"] = k.getMagnitude(value) + case 3: + item["depth"] = k.getDepth(value) + case 5: + item["latitude"] = k.getLatitude(value) + case 6: + item["longitude"] = k.getLongitude(value) + case 7: + item["event"] = value + item["region"] = value + } + }) + result["data"] = append(result["data"].([]any), item) + }) + }) + }) + + return result, nil +} + +func (k *KMA) Format(latitude, longitude float64, data map[string]any) ([]Event, error) { + var list []Event + for _, v := range data["data"].([]any) { + l := Event{ + Verfied: true, + Latitude: v.(map[string]any)["latitude"].(float64), + Longitude: v.(map[string]any)["longitude"].(float64), + Depth: v.(map[string]any)["depth"].(float64), + Event: v.(map[string]any)["event"].(string), + Region: v.(map[string]any)["region"].(string), + Timestamp: v.(map[string]any)["timestamp"].(int64), + Magnitude: v.(map[string]any)["magnitude"].(float64), + } + l.Distance = getDistance(latitude, l.Latitude, longitude, l.Longitude) + l.Estimation = getEstimation(l.Depth, l.Distance) + + list = append(list, l) + } + + return list, nil +} + +func (k *KMA) List(latitude, longitude float64) ([]Event, error) { + res, err := k.Fetch() + if err != nil { + return nil, err + } + + data, err := k.Parse(res) + if err != nil { + return nil, err + } + + list, err := k.Format(latitude, longitude, data) + if err != nil { + return nil, err + } + + return list, nil +} + +func (k *KMA) getTimestamp(data string) int64 { + t, _ := time.Parse("2006/01/02 15:04:05", data) + return t.Add(-9 * time.Hour).UnixMilli() +} + +func (k *KMA) getMagnitude(data string) float64 { + m, _ := strconv.ParseFloat(data, 64) + return m +} + +func (k *KMA) getDepth(data string) float64 { + m, _ := strconv.ParseFloat(data, 64) + return m +} + +func (k *KMA) getLatitude(data string) float64 { + numStr := strings.ReplaceAll(data, "N", "") + numStr = strings.ReplaceAll(numStr, "S", "") + numStr = strings.TrimSpace(numStr) + + if strings.Contains(data, "N") { + longitude, _ := strconv.ParseFloat(numStr, 64) + return longitude + } else if strings.Contains(data, "S") { + longitude, _ := strconv.ParseFloat(numStr, 64) + return -longitude + } + + return 0 +} + +func (k *KMA) getLongitude(data string) float64 { + numStr := strings.ReplaceAll(data, "E", "") + numStr = strings.ReplaceAll(numStr, "W", "") + numStr = strings.TrimSpace(numStr) + + if strings.Contains(data, "E") { + longitude, _ := strconv.ParseFloat(numStr, 64) + return longitude + } else if strings.Contains(data, "W") { + longitude, _ := strconv.ParseFloat(numStr, 64) + return -longitude + } + + return 0 +} diff --git a/app/v1/trace/module.go b/app/v1/trace/module.go index 510346aa..db4f3070 100644 --- a/app/v1/trace/module.go +++ b/app/v1/trace/module.go @@ -22,6 +22,7 @@ func (t *Trace) RegisterModule(rg *gin.RouterGroup, options *app.ServerOptions) "CWA": &CWA{}, "HKO": &HKO{}, "JMA": &JMA{}, + "KMA": &KMA{}, "CEIC": &CEIC{}, "USGS": &USGS{}, "SCEA_E": &SCEA_E{}, diff --git a/frontend/dist/asset-manifest.json b/frontend/dist/asset-manifest.json index af8a4bf6..a294ed90 100644 --- a/frontend/dist/asset-manifest.json +++ b/frontend/dist/asset-manifest.json @@ -1,7 +1,7 @@ { "files": { "main.css": "./static/css/main.7a040865.css", - "main.js": "./static/js/main.22f3dcb0.js", + "main.js": "./static/js/main.6c81bc75.js", "static/css/594.d6bfd15f.chunk.css": "./static/css/594.d6bfd15f.chunk.css", "static/js/594.ef2a52fb.chunk.js": "./static/js/594.ef2a52fb.chunk.js", "static/js/846.88ce4ddb.chunk.js": "./static/js/846.88ce4ddb.chunk.js", @@ -49,6 +49,6 @@ }, "entrypoints": [ "static/css/main.7a040865.css", - "static/js/main.22f3dcb0.js" + "static/js/main.6c81bc75.js" ] } \ No newline at end of file diff --git a/frontend/dist/index.html b/frontend/dist/index.html index e73e7aec..48610911 100644 --- a/frontend/dist/index.html +++ b/frontend/dist/index.html @@ -1 +1 @@ -