Skip to content

Commit

Permalink
Support earthquake event source API of Korea Meteorological Administr…
Browse files Browse the repository at this point in the history
…ation
  • Loading branch information
bclswl0827 committed Mar 19, 2024
1 parent 65d4f68 commit f2b6d43
Show file tree
Hide file tree
Showing 9 changed files with 181 additions and 8 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v2.11.6
v2.11.7
168 changes: 168 additions & 0 deletions app/v1/trace/kma.go
Original file line number Diff line number Diff line change
@@ -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
}
1 change: 1 addition & 0 deletions app/v1/trace/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{},
Expand Down
4 changes: 2 additions & 2 deletions frontend/dist/asset-manifest.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down Expand Up @@ -49,6 +49,6 @@
},
"entrypoints": [
"static/css/main.7a040865.css",
"static/js/main.22f3dcb0.js"
"static/js/main.6c81bc75.js"
]
}
2 changes: 1 addition & 1 deletion frontend/dist/index.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!doctype html><html><head><meta charset="utf-8"/><link rel="icon" href="./favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no"/><link rel="apple-touch-icon" href="./logo192.png"/><link rel="manifest" href="./manifest.json"/><style>.public-loading{width:100%;height:100%;display:flex;position:fixed;align-items:center;flex-direction:column;justify-content:center}.public-loading span{color:#1f2937;margin-top:20px;font-weight:600;font-size:1.25rem}.public-loading svg{animation:rotate 1s linear infinite}@keyframes rotate{100%{transform:rotate(360deg)}}</style><script defer="defer" src="./static/js/main.22f3dcb0.js"></script><link href="./static/css/main.7a040865.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div class="public-loading"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="#6b21a8" width="70px"><path d="M304 48a48 48 0 1 0 -96 0 48 48 0 1 0 96 0zm0 416a48 48 0 1 0 -96 0 48 48 0 1 0 96 0zM48 304a48 48 0 1 0 0-96 48 48 0 1 0 0 96zm464-48a48 48 0 1 0 -96 0 48 48 0 1 0 96 0zM142.9 437A48 48 0 1 0 75 369.1 48 48 0 1 0 142.9 437zm0-294.2A48 48 0 1 0 75 75a48 48 0 1 0 67.9 67.9zM369.1 437A48 48 0 1 0 437 369.1 48 48 0 1 0 369.1 437z"/></svg> <span>Loading...</span></div><div id="root"></div></body></html>
<!doctype html><html><head><meta charset="utf-8"/><link rel="icon" href="./favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no"/><link rel="apple-touch-icon" href="./logo192.png"/><link rel="manifest" href="./manifest.json"/><style>.public-loading{width:100%;height:100%;display:flex;position:fixed;align-items:center;flex-direction:column;justify-content:center}.public-loading span{color:#1f2937;margin-top:20px;font-weight:600;font-size:1.25rem}.public-loading svg{animation:rotate 1s linear infinite}@keyframes rotate{100%{transform:rotate(360deg)}}</style><script defer="defer" src="./static/js/main.6c81bc75.js"></script><link href="./static/css/main.7a040865.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div class="public-loading"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="#6b21a8" width="70px"><path d="M304 48a48 48 0 1 0 -96 0 48 48 0 1 0 96 0zm0 416a48 48 0 1 0 -96 0 48 48 0 1 0 96 0zM48 304a48 48 0 1 0 0-96 48 48 0 1 0 0 96zm464-48a48 48 0 1 0 -96 0 48 48 0 1 0 96 0zM142.9 437A48 48 0 1 0 75 369.1 48 48 0 1 0 142.9 437zm0-294.2A48 48 0 1 0 75 75a48 48 0 1 0 67.9 67.9zM369.1 437A48 48 0 1 0 437 369.1 48 48 0 1 0 369.1 437z"/></svg> <span>Loading...</span></div><div id="root"></div></body></html>

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions frontend/src/.env
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
REACT_APP_VERSION=v2.11.6
REACT_APP_RELEASE=810bc581-20240319144037
REACT_APP_VERSION=v2.11.7
REACT_APP_RELEASE=65d4f684-20240319163755

0 comments on commit f2b6d43

Please sign in to comment.