지진 경보

33526 단어

안녕하세요!저는 제프 로덴이라고 하는데 오클라호마 주립 대학의 비전통 학생입니다.지난 10년 동안 지질학자였던 저는 소프트웨어 공학의 직업 전환기에 처해 있습니다.개인 프로젝트를 선택할 때 나는 어떤 방식으로 나의 과거 경험을 프로젝트에 융합시키고 싶다는 것을 안다.그래서 지진 경보를 울리기로 했어요!Microsoft Azure 기능, 코스모스 DB, Twilio, 미국지질조사국(USGS)이 실시간 지진 데이터를 제공하는 API를 활용한 웹 애플리케이션이다.그리고 사용자가 결정한 관심 지역의 최근 지진 위치와 진도를 알 수 있는 문자를 보낸다.
지진 경보 흐름도

나는 내가 가장 잘 아는 것부터 시작해서 사람들이 이 서비스를 등록할 수 있도록 간단한 정적 사이트를 만들기로 결정했다.이곳의 주요 목적은 사용자의 전화번호를 수집하여 텍스트를 수신하고 통지할 최소 지진 크기(최소 지진급)와 이 위치 주위의 위도, 경도와 반경(마일 단위)을 수집하는 것이다.사용자가 critera를 입력하고submit을 누르면 폼 데이터는Azure HTTP 트리거 함수로 전송되며, 이 함수는 데이터를 가져와 코스모스 DB에 저장됩니다.나는 지리 인코딩 API를 사용할 계획이다. 이렇게 하면 사용자는lat/long이 아니라 도시 이름과 주를 입력할 수 있지만, 이것은 버전 2를 기다려야 한다.
추가 정보를 얻기 위해 나는 미국 지질탐사국 API가 제공한 데이터로 지난 1시간, 하루, 일주일 동안 전 세계에서 발생한 지진을 표시하기로 결정했다.
등록 페이지

등록 페이지 HTML
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>smsEarthquake Alert</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
   <div class="main">
        <div class="nav">
            <ul>
                <li><a href="#text">Text Alert</a></li>
                <li><a href="#hour">Earthquakes Past Hour</a></li>
                <li><a href="#day">Past Day</a></li>
                <li><a href="#week">Past Week</a></li>
              </ul>
        </div>
       <div class="main-container">
            <header class="main-header">
                <a name="text"></a>
                <h1>
                    <span class="tan">sms</span>Earthquake Alert
                </h1>
                <h2>Enter your phone number and other criteria to recieve notifications</h2>
            </header>
            <div class="form">
                <form method="POST" id="formsub" action="https://smsearthquake.azurewebsites.net/api/HttpTrigger1_subForm?code=BPBzT9AZmQdk4y9TEuPFgUv2VsHZ2910zP9Parws3XaYnhldorfRJA==">    
                    <input type="text" id="phoneNum" class="input-phoneNum" placeholder="phone number" autocomplete="off"></input>
                    <input type="text" id="mag" class="input-mag" placeholder="minimum magnitude" autocomplete="off"></input><br>
                    <input type="text" id="radius" class="input-radius" placeholder="radius (ft)" autocomplete="off"></input>
                    <input type="text" id="lat" class="input-lat" placeholder="latitude" autocomplete="off"></input>
                    <input type="text" id="long" class="input-long" placeholder="longitude" autocomplete="off"></input><br>
                    <button id="submit-button" class="submit-button">submit</button>
                </form>
            </div>
            <div class="table-hour">
                <a name="hour"></a>
                <h1>Earthquakes in the Past Hour</h1>
                <table class="table">
                    <tr class="eq-info">
                        <th>Magnitude</th>
                        <th>Place</th>
                        <th>Time</th>
                        <th>Longitude</th>
                        <th>Latitude</th>
                        <th>Depth (Km)</th>
                    </tr>
                    <tbody id="hourData">
                    </tbody>
                </table>
            </div>
            <div class="table-day">
                <a name="day"></a>
                <h1>Earthquakes in the Past Day</h1>
                <table class="table">
                    <tr class="eq-info">
                        <th>Magnitude</th>
                        <th>Place</th>
                        <th>Time</th>
                        <th>Longitude</th>
                        <th>Latitude</th>
                        <th>Depth (Km)</th>
                    </tr>
                    <tbody id="dayData">
                    </tbody>
                </table>
            </div>
       </div>
    </div>
</body>
</html>
<script src="bc.js" type="text/javascript"></script>
등록 페이지 Javascript
//Collecting Form data and Posting it to my HTTP Trigger
var formsub = document.getElementById('formsub');
var button = document.getElementById('submit-button');
var phoneNum = document.getElementById('phoneNum');
var mag = document.getElementById('mag');
var lat = document.getElementById('lat');
var long = document.getElementById('long');
var radius = document.getElementById('radius');

button.addEventListener('click', function (ev) {

    ev.preventDefault();
    ev.stopPropagation();
    var body = {
        "phoneNum": phoneNum.value,
        "lat": lat.value,
        "long": long.value,
        "radius": radius.value,
        "magnitude": mag.value
    }
    fetch("http://localhost:7071/api/formsSubmit", {
        method: "POST",
        headers: {
            "content-type": "application/json"
        },
        body: JSON.stringify(body)
    })
});

//Populating Tables with recent EQ data
fetch('https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_hour.geojson').then(
    res => {
        res.json().then(
            data => {
                var temp = "";
                data.features.forEach(u => {
                    temp += "<tr>";
                    temp += "<td>" + Math.round(u.properties.mag * 1e2) / 1e2 + "</td>";
                    temp += "<td>" + u.properties.place + "</td>";
                    var utcSeconds = u.properties.time;
                    var d = new Date(utcSeconds);
                    temp += "<td>" + d + "</td>";
                    temp += "<td>" + u.geometry.coordinates[0] + "</td>";
                    temp += "<td>" + u.geometry.coordinates[1] + "</td>";
                    temp += "<td>" + Math.round(u.geometry.coordinates[2] * 1e2) / 1e2 + "</td></tr>";
                })
                document.getElementById("hourData").innerHTML = temp;
                console.log(data);
            }
        )
    }
)
Azure 함수 HTTP 트리거
html 페이지에서 전송된 폼 데이터를 받아서 빈 지진 ID 그룹을 추가한 다음 코스모스 DB에 저장합니다.이 빈 eqID 그룹은 필요합니다. 이렇게 하면 누군가가 이미 통지한 지진을 추적할 수 있습니다. 이렇게 하면 그들은 같은 지진에 대한 중복 텍스트를 받지 않습니다!
module.exports = async function (context, req) {

    const contact = req.body;
    contact.eqID = []
    context.bindings.outputDocument = contact;

}
Azure 함수 HTTP 타이머
지금이 제일 어려운 부분!내 코스모스 DB에서 사용자 연락처를 추출한 다음 USGS API에서 위도/길이/반경 및 진도 기준에 맞는 지진 목록을 가져와야 합니다.
그리고 나는 이 지진 목록을 반복해서 훑어보고 미국 지질조사국이 모든 지진에 분배한 유일한 ID를 검사했다. 사용자가 이미 문자를 받은 eqID 그룹이 아니라.이 ID가 목록에 없으면 Twilio를 통해 전송되는 크기와 대략적인 위치를 보여 주는 메시지가 표시됩니다.
이것은 나에게 처음에는 많은 처리를 필요로 하기 때문에, 나는 처음에 내가 논리를 어떻게 구성해야 하는지를 파악하기 위해 위조 코드를 작성했을 뿐이다.

현재 나의 해결 방안은 이중 플러그인 for 순환을 사용하고 있으며, O (n^2) 도 마찬가지다.나는 이보다 더 효과적인 해결 방안이 있다고 믿지만, 이것이 바로 내가 현재 사용하고 있는 것이다. -)
논리적 구조를 손에 넣은 후에 저는 Azure HTTP 타이머 기능을 통해 이 모든 것을 실행에 옮기기 시작했습니다. 이 기능은 10분마다 한 번씩 실행하여 새로운 지진을 검사합니다!
const fetch = require('node-fetch');

//Beginning of the Timer function
module.exports = async function (context, myTimer, contacts) {
//arrays used for the twilio message body and updating the cosmos DB with quake IDs.
    var messages = [];
    var documentsToSave = [];

 //Pulling a contact from Cosmos and getting their EQ criteria into vars to make a fetch request
    for(var contact of contacts) {
        var startTime = new Date().toISOString().substring(0,10);

//As Americans we are used to using miles, but the USGS API deals in kilometers, so I convert a users desired radius from miles to kilometers before making the fetch call to the USGS.
        var maxradiusKm = contact.radius * 1.60934;
        var fetchUrl = "https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&starttime=" 
                + startTime + "&latitude="
                + contact.lat + "&longitude="
                + contact.long + "&maxradiuskm="
                + maxradiusKm + "&minmagnitude="
                + contact.magnitude;
        var response = await fetch(fetchUrl);

//We now have an array of earthquakes that have happened in the users desired area  
      var EQs = await response.json();

        EQs.features.forEach(quake => {
            const quakeMag = Math.round(quake.properties.mag * 1e2) / 1e2;
            const place = quake.properties.place;

//Checking here to make sure its a new quake, and not one previously notified about
//If its new one, a text is sent out 
            if(contact.eqID.includes[quake.id] == false)
                messages.push({
                    body: quakeMag.toString() +" magnitude "+ place,
                    to: "+1"+contact.phoneNum
                }); 
                context.bindings.messages = messages;
                contact.eqID.push(quake.id);
                documentsToSave.push(contact);
        });
        context.bindings.outputDocument = documentsToSave;
    } 
};
놀랍게도 오클라호마 주에서는 지진이 발생하는 시간이 통상적으로 그리 길지 않다!이제 우리는 인내심을 가지고 앉아서 자연의 어머니가 다리를 내밀기를 기다릴 수밖에 없다.오퍼하지만 오클라호마 주에는 국경이 없어요. 놀라실 거예요...그래, 네 말이 맞다. 그러나 그것은 완전히 다른 박문이다. -) 어쨌든, 지금 우리 앉아서 좀 기다리자.
Twilio로부터 알림 받기
이것은 내 휴대전화의 화면 캡처로 내가 사는 오클라호마시티에서 100마일 범위 내에서 발생한 지진을 알게 한다.

보시다시피 그날 오후 4시 전에 우리는 이미 대량의 소지진이 발생했다.
결론
나는 이 프로젝트에서 많은 것을 배웠다.나는 전문적인 경험이 매우 부족한 상황에서 이 일을 시작했는데 처음에는 매우 당황스러웠다.프로젝트를 시작한 후에 초점을 잃고 멈추는 것은 항상 쉽다.이 방면에서Bit 프로젝트는 매우 훌륭합니다. 저는 임무를 계속 완수할 수 있습니다. 여기 있는 사람들이 저를 도와 모든 문제를 해결할 뿐만 아니라 제가 책임을 지고 정상적인 궤도에 오르도록 합니다!
특히 저의 스승 앤서니 주(Anthony Chu)에게 감사를 드립니다. 그는 저를 많은 빈틈과 낙담할 수 있는 막다른 골목에서 데리고 왔습니다. 저는 이것들을 함께 놓았습니다. 그리고 비트 프로젝트의 서버가 없는 지도자 에밀리, 이브린과 줄리아에게도 감사를 드립니다.
이 프로젝트를 위해 시간과 노력을 기울여 주신 모든 분들께 진심으로 감사드립니다!

좋은 웹페이지 즐겨찾기