Wprowadzenie do serwisu www - METEO (wersja 0.95 [2020.07.16])

Wstęp

W ramach laboratorium zostaną przedstawione proste skrypty umożliwiające odczyt danych z centralnej bazy danych w której gromadzone są dane pomiarowe z lokalnych stacji meterologicznych. Dane udostępniane są w formacie CSV (ang. Comma Separated Values - wartości rozdzielone przecinkiem) lub w formacie JSON (ang. JavaScript Object Notation). W ramach zajęć przedstawione zostaną obydwa formaty danych i metody pobierania ich z serwisu. W kolejnych ćwiczeniach zostaną zaprezentowane odpowiednie skrypty opracowane w języku HTML i JavaScript przetwarzające dane do odpowiednich wykresów i tabel.

Plan laboratorium

Ćwiczenie 1. Dane w formacie CSV i JSON

Dane w formacie CSV

Dane w formacie CSV (ang. Comma Separated Values - wartości rozdzielone przecinkiem) [1] wykorzystywane są do przechowywania danych w plikach tekstowych lub przenoszenia danych pomiędzy aplikacjami z wykorzystaniem typu MIME [2] - text/csv. Specyfiakacja struktury danych została zamieszczona w dokumencie RFC 4180 [3]. W ramach tego formatu moźemy wyróżnić rekordy, w których wartości są oddzielone od siebie seperatorem (przecinek, średnik lub znak tabulacji). Kolejne rekordy oddzielone są znakami końca linii CRLF.

Dla serwisu METEO opracowano polecenia zwracające pary wartości ( czas pomiaru, wielkość mierzona) np. czas i temperatura. Przykładowy rekord dla czasu i temperatury przedstawiono poniżej.

   2014-06-24 10:00:01, 14.6
  

Przykładowy plik w formacie CSV data_csv.txt

Dane w formacie JSON

JSON jest formatem wymiany danych pomiędzy systemami komputerowymi opracowanymi w różnych językach programistycznych [4,5]. Odpowiednie biblioteki przetwarzające dane dostępne są w większości z nich. Jest formatem tekstowym, będącym podzbiorem języka JavaScript. Struktura tego formatu danych została opisana w dokumencie RFC 4627 [6]. Obecną implementację w języku ECMA Script można znaleźć w dokumencie ECMA-404 [7]. Podczas przesyłania danych w formacie JSON wykorzystujemy typ MIME - application/json. Standardowym system kodowania jest format UTF-8 [8,9]

Struktura jednego rekordu danych generowanego przez serwis METEO dla wszystkich typów danych pomiarowych zawartych w bazie przedstawiona została poniżej.

   {"time":"2014-06-01 00:00:05", "station":"s0",
    "data":{"pa":"988.40","ha":"81.00","ws":"1.30","t0":"10.00","p0":"1013.00","ta":"13.20","ra":"1.77","wd":"225.00"}}
  

Kolejne klucze przedstawiają następujące wielkości meteorologiczne:

Przykładowy plik w formacie JSON : data_json.txt

Linki do dodatkowych materiałów (dostęp na dzień 16.07.2020):

  1. Wikipedia: CSV (format pliku)
  2. Wikipedia: Multipurpose Internet Mail Extensions
  3. RFC 4180, Common Format and MIME Type for Comma-Separated Values (CSV) Files
  4. JSON.ORG, JSON: wprowadzenie.
  5. Wikipedia: JSON
  6. RFC 4627, The application/json Media Type for JavaScript Object Notation (JSON)
  7. Standard ECMA-404, The JSON Data Interchange Format,(October 2013)
  8. UTF-8 and Unicode
  9. Wikipedia: UTF-8

Ćwiczenie 2. Odczyt danych z serwisu METEO w formacie CSV i JSON

Dane w formacie CSV

Odczyt danych z serwisu WWW w formacie CSV następuje poprzez polecenie:

http://mech.fis.agh.edu.pl/meteo/rest/csv/{par}/{station}/{start-data}/{end-data}

gdzie:

{par}
identyfikator mierzonej wielkości meteorologicznej: pres0 - ciśnienie na poziomie morza, temp - temperatura, temp0 - temperatura punktu rosy, humi - wilgotność, rain1 - opad w ciągu ostatniej godziny, rain - opad dobowy, windd - kierunek wiatru, winds - prędkość wiatru i windg - chwilowa prędkość wiatru.
{station}
identyfikator stacji
{start-date}
początkowa data pomiarów
{end-date}
końcowa data pomiarów

Przykładowe polecenie pobierające dane ze stacji "s000" dotyczące temperatury z okresu od 2020-07-10 do 2020-07-15.

http://mech.fis.agh.edu.pl/meteo/rest/csv/temp/s000/2020-07-10/2020-07-15

Dane w formacie JSON

Odczyt danych z serwisu WWW w formacie JSON następuje poprzez polecenie:

http://mech.fis.agh.edu.pl/meteo/rest/json/{par}/{station}/{start-data}/{end-data}

gdzie:

{par}
identyfikator mierzonej wielkości meteorologicznej: all - wszystkie parametry, pres0 - ciśnienie na poziomie morza, temp - temperatura, temp0 - temperatura punktu rosy, humi - wilgotność, rain1 - opad w ciągu ostatniej godziny, rain - opad dobowy, windd - kierunek wiatru, winds - prędkość wiatru i windg - chwilowa prędkość wiatru.
{station}
identyfikator stacji
{start-date}
początkowa data pomiarów
{end-date}
końcowa data pomiarów

Przykładowe polecenie pobierające dane z okresu od 2020-07-10 do 2020-07-15.

http://mech.fis.agh.edu.pl/meteo/rest/json/all/s000/2020-07-10/2020-07-15

Ćwiczenie 3. Odczyt danych z serwisu METEO i prezentacja w tabeli HTML

Dane w formacie CSV

Do prezentacji danych w postaci tabeli wykorzystamy odpowiedni skrypt opracowany w języku HTML5 [1]. Krótkie wprowadzenie do języka HTML5 można znaleźć na stronach serwisów: W3Schools [2] lub "Kurs HTML" [3]. W ramach skryptu wykorzystany został element <input> typu "button", w którym obsługując zdarzenie "onclick()" w JavaScript wywołujemy funkcję sendRequest() pobierającą dane z serwera z wykorzystaniem technologii AJAX. Element <div> z identyfikatorem "result" jest węzłem dokumentu HTML w którym umieścimy dane pobrane z serwera.

Plik lab_ex01.html ( [listing skryptu] link do skryptu )


#1: <!DOCTYPE html>
#2: <html>
#3:    <head>
#4:       <meta charset="utf-8">
#5:       <title>Ajax: Odczyt danych z serwera</title>
#6:       <link type="text/css" href="lab.css" rel="stylesheet" />
#7:       <script src="lab_ex01.js" type="text/javascript"></script>
#8:    </head>
#9:    <body>
#10:      <div style="text-align:center" >
#11:        <table border="1" bgcolor="gray">
#12:          <tr><th><big>Ajax: Odczyt danych z serwera</big></th></tr>
#13:        </table>
#14:        <br />
#15:        <form action="#">
#16:           <input type="button" value="Pobierz dane z serwera" onclick="sendRequest()"/>
#17:        </form>
#18:      </div>
#19:      <div id="result"></div>
#20:     </body>
#21: </html>
  

Przedstawiony poniżej skrypt składa się z trzech funkcji, które obsługują technologię AJAX. Technologia AJAX (ang. Asynchronous JavaScript and XML, asynchroniczny JavaScript i XML) umożliwiają opracowanie aplikacji internetowych, w których interakcja przeglądarki z serwerem WWW odbywa się bez przeładowania całego dokumentu wyświetlanego w przeglądarce [4, 5, 6, 7]. W standardowym modelu serwisu WWW, każda interakcja z serwerem WWW wymaga przeładowania całego dokumentu HTML wyświetlanego w przeglądarce. W ramach technologii AJAX wykorzystujęmy następujące standardy: język HTML, język JavaScript, język XML [8] oraz standard DOM [9]. Do komunikacji pomiędzy przeglądarką a serwerem WWW wykorzystywany jest obiekt XMLHttpRequest (XHR) obsługiwany przez język JavaScript.

Utworzenie instancji obiektu XHR jest realizowane w pierwszej funkcji getRequestObject() w poniższym skrypcie. Standardowo w języku JavaScript obiekt ten tworzymy poleceniem "new XMLHttpRequest()" (linia kodu 7). Jednakże w starszych przeglądarkach IE (wersja 5 i 6) obiekt ten zostanie utworzony poprzez polecenie "new ActiveXObject('Microsoft.XMLHTTP')" (linia kodu 5).

W kolejnej funkcji "sendRequest()" przygotowujemy obiekt XHR do wysłania na serwer WWW. Własność "onreadystatechange" obsługuje funkcję, która zostanie wykonana po poprawnym odebraniu informacji z serwisu WWW poprzez przeglądarkę W naszym przykładzie jest to nazwa trzeciej funkcji "handleResponse" umieszczonej w naszym skrypcie. Kolejne dwie linie kodu w funkcji są odpowiedzialne za wysłanie żądania na serwer. Metoda open() ustala adres serwera i metodę protokołu HTTP wybraną do komunikacji z serwerem, w naszym przypadku jest to metoda GET. Metoda send() wysyła żądanie na serwer.

Ostatnia funkcja "handleResponse()" odpowiedzialna jest za obsługę zwrotnej informacji z serwera. Po sprawdzeniu czy kod odpowiedzi jest 4 (obsługa żądania zakończona), w własności "responseTEXT" obiektu XHR znajdujemy zwróconą przez serwer informację. Teraz należy ją odpowiednio przetworzyć i wyświetlić na stronie. W odpowiedzi z serwera otrzymujemy dane w formacie CSV. Na początek wykorzystując metodę "split()" umieszczamy kolejne rekordy dokumentu CSV w kolejnych rekordach tablicy txtLines[] (linia kodu 28). Następnie tworzymy tabelkę HTML w zmiennej znakowej txt. W pętli for (linie kodu 33-36) przetwarzamy tablice txtLines umieszczając poszczególne wartości danych w kolejnych komórkach tablicy (linie 34 i 35). Na koniec pozostaje umieszczenie tablicy na stronie. Realizowane jest poprzez metodę innerHTML [10] w standardzie DOM, która modyfikuje określony węzeł naszego dokumentu HTML. Wybór węzła dokunujemy wykorzystując metodę "getElementById()" [11] obiektu "document".

Plik lab_ex01.js ( [listing skryptu] link do skryptu )


#1: var xhr;
#2: function getRequestObject()      {
#3:        // Utworzenie obiektu XMLHttpRequest
#4:        if ( window.ActiveXObject)  {
#5:             return ( new ActiveXObject("Microsoft.XMLHTTP")) ;
#6:         } else if (window.XMLHttpRequest)  {
#7:            return (new XMLHttpRequest())  ;
#8:         } else {
#9:            return (null) ;
#10:         }
#11:   }
#12: function sendRequest()      {
#13:        // Inicjalizacja obiektu xhr typu XMLHttpRequest
#14:        xhr = getRequestObject() ;
#15:        // Przydzielenie obserwatora do zdarzenia readystatechange
#16:        // Utworzenie wlasnej implementacji obslugujacej zdarzenie
#17:        xhr.onreadystatechange = handleResponse ;
#18:        // Ustalenie adresu i protokolu HTTP
#19:        xhr.open("GET", "http://mech.fis.agh.edu.pl/meteo/rest/csv/temp/s000/2020-07-10/2020-07-15", true);
#20:        // Wyslanie zadania na serwer
#21:        xhr.send(null);
#22:   }
#23: function handleResponse()      {
#24:        if (xhr.readyState == 4)    {
#25:           //alert(xhr.responseText);
#26:           var txtData = xhr.responseText ;
#27:           var txtLines = [];
#28:           txtLines = txtData.split(/\r\n|\n/);
#29:           txtLines.pop();
#30:           var Lines = [];
#31:           var txt = "<p>Licza przetworzonych wierszy: " + txtLines.length.toString() + "</p>";
#32:           txt += "<table class='data'><tr><th>Czas</th><th>Temperatura (C)</th></tr>" ;
#33:           for (var i=0, max=txtLines.length; i<max; i++) {
#34:              Lines = txtLines[i].split(',');
#35:              txt += "<tr><td>" + Lines[0] + "</td><td>" + Lines[1] + "</td></tr>" ;
#36:           }          
#37:           txt += "</table>" ;
#38:           document.getElementById('result').innerHTML = txt;
#39:        }
#40: }
  

Do sformatowania tesktu dokumentu HTML wykorzystane zostały polecenia języka arkuszy styli CSS (ang. Cascading Style Sheets) [12].

Plik CSS formatujący stronę - lab.css ( [listing skryptu] link do pliku )


#1: table.data { border-collapse:collapse; width:60%;  font-size:12px;  }
#2: table.data, table.data td, table.data th { border:1px solid blue; }
#3: table.data th { background-color: aqua; }
#4: table.data td { text-align:right ; padding-right:10px; }
#5: table.data tr:nth-child(old) { background-color: #f0f8ff; }
#6: table.data tr:nth-child(even) { background-color: #e8e8e8 }  

Poniżej prezentacja uruchomionego przykładu (link do uruchomienia w nowym oknie lab_ex01.html).

Dane w formacie JSON

Do prezentacji danych w postaci tabeli wykorzystamy odpowiednie skrypty opracowane w języku HTML5, JavaScript i CSS. Funkcjonalność skryptów w języku HTML i CSS jest analogicza do przedstawionych powyżej skryptów "lab_ex01.html" i "lab.css".

Plik lab_ex02.html ( [listing skryptu] link do skryptu )

#1: <!DOCTYPE html>
#2: <html>
#3:    <head>
#4:       <meta charset="utf-8">
#5:       <title>Ajax: Odczyt danych z serwera</title>
#6:       <link type="text/css" href="lab.css" rel="stylesheet" />
#7:       <script src="lab_ex02.js" type="text/javascript"></script>
#8:    </head>
#9:    <body>
#10:      <div style="text-align:center" >
#11:        <table border="1" bgcolor="gray">
#12:          <tr><th><big>Ajax: Odczyt danych z serwera</big></th></tr>
#13:        </table>
#14:        <br />
#15:        <form action="#">
#16:           <input type="button" value="Pobierz dane z serwera" onclick="sendRequest()"/>
#17:        </form>
#18:      </div>
#19:      <div id="result"></div>
#20:     </body>
#21: </html>
  

Podobnie jak dla formatu CSV został przygotowany odpowiedni skrypt w JavaScript pobierający dane z wykorzystaniem technologii AJAX. Dwie pierwsze funkcje "getRequestObject()" i "sendRequest()" są identyczne do odpowiednich funkcji w skrypcie "lab_ex01.js". W trzeciej funcji "handleResponse()" różnica jest w przetworzeniu zwróconego wyniku. Po przeczytaniu danych z własnoności "responseText" obiektu XHR wykorzystujemy funkcję "evel()" [13] w JavaScript do utworzenia tablicy obiektów (linia kodu 20). Pojedynczy obiekt w tablicy zawiera dane przedstawione w ćwiczeniu 1 dla formatu danych JSON. Dostęp do określonego parametru pomiaru następuje przez wskazanie na numer obiektu w tablicy i wskazanie określonego parametru. Przykładowo wpis "jsonObj[2].time" pobiera czas pomiaru dla trzeciego punktu pomiarowego w danych zwróconych przez serwer, a wpis "jsonObj[2].data.temp" pobiera wartość temperatury dla tego punktu.

Plik lab_ex02.js ( [listing skryptu] link do skryptu )

#1: var request;
#2: function getRequestObject()      {
#3:        if ( window.ActiveXObject)  {
#4:             return ( new ActiveXObject("Microsoft.XMLHTTP")) ;
#5:         } else if (window.XMLHttpRequest)  {
#6:            return (new XMLHttpRequest())  ;
#7:         } else {
#8:            return (null) ;
#9:         }
#10:   }
#11: function sendRequest()      {
#12:        request = getRequestObject() ;
#13:        request.onreadystatechange = handleResponse ;
#14:        request.open("GET", "http://mech.fis.agh.edu.pl/meteo/rest/json/all/s000/2020-07-10/2020-07-15", true);
#15:        request.send(null);
#16:   }
#17: function handleResponse()      {
#18:        if (request.readyState == 4)    {
#19:           //alert(request.responseText);
#20:           var jsonObj=eval(  "("  +  request.responseText    +  ")"    );
#21:           //alert(jsonObj[0].data.p0);
#22:           var txt = "<p>Licza przetworzonych wierszy: " + jsonObj.length.toString() + "</p>";
#23:           txt += "<table class='data'><tr><th>Czas</th><th>Ciśnienie (hPa)</th></tr>"
#24:           for (var i=0, max=jsonObj.length; i<max; i++) {
#25:              txt += "<tr><td>" + jsonObj[i].time + "</td><td>" + jsonObj[i].data.p0 + "</td></tr>" ;
#26:           }          
#27:           txt += "</table>" ;
#28:           document.getElementById('result').innerHTML = txt;
#29:        }
#30: }
  

Poniżej prezentacja uruchomionego przykładu (link do uruchomienia w nowym oknie lab_ex02.html).


Linki do dodatkowych materiałów (dostęp na dzień 16.07.2020):

  1. HTML5, A vocabulary and associated APIs for HTML and XHTML
  2. Kurs HTML
  3. HTML5 Introduction
  4. Wikipedia: AJAX
  5. W3Schools: AJAX
  6. Technologies Used in AJAX
  7. Wprowadzenie do technologii AJAX
  8. Wikipedia: AJAX
  9. Wikipedia: Obiektowy model dokumentu
  10. W3Schools: innerHTML
  11. W3Schools: getElementById()
  12. Wikipedia: Kaskadowe arkusze styli
  13. W3Schools: JavaScript eval() Function

Ćwiczenie 4. Tworzymy wykres określonej wielkości meteorologicznej

W ramach tego ćwiczenia zostanie przedstawiony skrypt umożliwiający tworzenie wykresów mierzonych wielkości fizycznych. Do realizacji projektu wykorzystamy bibliotekę graficzną opracowaną w języku JavaScript dygraphs. Biblioteka dostępna jest pod adres URL http://dygraphs.com/. Biblioteka wymaga danych w formacie CSV. Dane pobierane są w skrypcie opracowanym w języku JavaScript. Skrypt lab_ex03.js jest modyfikacją skryptu lab_ex01.js, w którym zamiast tworzyć tabelkę wywołujemy funkcję graph() rysującą wykres. Parametry wykorzystane do tworzenia wykresu - podpis wykresu "title", podpis osi y "ylabel", rysowanie punktów "drawPoints:true" i brak linii łączącej poszczególne punkty pomiarowe "strokeWidth:0". W ramach ćwiczenia został przedstawiony wykres dla ciśnienia atmosferycznego, zmieniając polecenie pobierające dane z serwera (skrypt lab_ex03.ja) zgodnie z informacją w ćwiczeniu drugim można otrzymać wykresy dla każdej mierzonej wielkości meteorologicznej (dodatkowo należy również zmienić opis rysunku i osi y w funkcji graph()).

Plik lab_ex03.html ( [listing skryptu] link do skryptu )

#1: <!DOCTYPE html>
#2: <html>
#3:    <head>
#4:       <meta charset="utf-8">
#5:       <script type="text/javascript" src="dygraphs.js" ></script>
#6:       <script type="text/javascript" src="lab_ex03.js" ></script>
#7:       <script type="text/javascript" >
#8:          function graph(csv_data) {
#9:             var g3 = new Dygraph(
#10:             document.getElementById("graphdiv3"),
#11:             csv_data,
#12:             {
#13:                title: 'Temperatura',
#14:                ylabel: 'Temperatura (C)',
#15:                strokeWidth: 0,
#16:                drawPoints: true
#17:                //drawGapEdgePoints: true
#18:             } );
#19:          }
#20:       </script>
#21:    </head>
#22:    <body onload="sendRequest()">
#23:       <div id="myDiv"></div>
#24:       <div id="graphdiv3" style="width:500px; height:300px;"></div>
#25:    </body>
#26: </html>   

Plik lab_ex03.js ( [listing skryptu] link do skryptu )

#1: var request;
#2: function getRequestObject()      {
#3:        if ( window.ActiveXObject)  {
#4:             return ( new ActiveXObject("Microsoft.XMLHTTP")) ;
#5:         } else if (window.XMLHttpRequest)  {
#6:            return (new XMLHttpRequest())  ;
#7:         } else {
#8:            return (null) ;
#9:         }
#10:   }
#11: function sendRequest()      {
#12:        request = getRequestObject() ;
#13:        request.onreadystatechange = handleResponse ;
#14:        request.open("GET", "http://mech.fis.agh.edu.pl/meteo/rest/csv/temp/s000/2020-07-10/2020-07-15/", true);
#15:        request.send(null);
#16:   }
#17: function handleResponse()      {
#18:       myDiv = document.getElementById("myDiv");
#19:       if (request.readyState == 1) {
#20:            myDiv.innerHTML += "Status zadania:" ;
#21:       } 
#22:       else if (request.readyState == 2) {
#23:            myDiv.innerHTML += "." ;
#24:       }
#25:       else if (request.readyState == 3) {
#26:            myDiv.innerHTML += "." ;
#27:       }
#28:       else if (request.readyState == 4)    {
#29:           //alert(request.responseText);
#30:           var data = request.responseText;
#31:           graph(data);
#32:        }
#33: }
  

Poniżej prezentacja uruchomionego przykładu (link do uruchomienia w nowym oknie lab_ex03.html).

Ćwiczenie 5. Wyznaczamy dobową wartość średnią, minimalna i maksymalną

W ramach tego ćwiczenia zostaną wyznaczone wartości śrenie, minimalne i maksymalne dla pomiarów dobowych. W ramach ćwiczenia wykorzystamy trzy skrypty: lab_ex04.html, lab_ex04.js i lab.css. Skrypt lab_ex04.js jest analogiczny do skryptu lab_ex02.js. Wykorzystując technologię AJAX czytamy z serwisu WWW dane w formacie JSON. W ramach skryptu lab_ex04.html został zawarty kod HTML i skrypt w języku JavaScript przeliczający dane pomiarowe w funkcji values(). Schemat blokowy funkcji values() przedstawiono na rysunku poniżej. Na schemacie blokowym nie umieszczono wszystkich zmiennych reprezentujących poszczególne wielkości pomiarowe.

Funkcja values() jest wywoływana w funkcji handleResponse() w skrypcie lab_ex04.js po poprawnym pobraniu danych w formacie JSON przez technologię AJAX. Początkowo w liniach kodu od 13 do 46 initializujemy zmienne wykorzystywane w programie poprzez przypisanie wartości 0 lub wartości pierwszego analizowanego pomiaru (np. data w linii kodu 14 czy wartości minimalne i maksymalne w liniach kodu 26 - 43). Zmienna n reprezentuje liczbę pomiarów w ciagu doby, natomiast zmienna id kolejną analizowaną dobę, W ramach pętli, która zaczyna się w linii 47 a kńczy w linii 115, analizowane są kolejne wartości pomiarowe. Pętla kończy się po przeanalizowaniu wszystkich danych. Po odczytaniu daty pomiaru w kolejnym pomiarze sprawdzamy czy należy on do analizowanej doby czy nie. Jeżeli należy to dodajemy kolejne wartości pomiarów do tablicy avgValue (linie 55-62) oraz sprawdzamy wartości minimalne (63-70) i maksymalne (71-78). Jeżeli jest to inna data to wyliczamy wartości średnie (linie 81-88) dzieląc zsumowane wartości pomiarów przez ich liczbę w czasie analizowanej doby, zwiększamy wartość zmiennej id o jeden i tworzymy odpowiednie elementy w tablicach avgValue, minValue i maxValue dla następnej doby. Zmienną n zerujemy.

Plik lab_ex04.html ( [listing skryptu] link do skryptu )

#1: <!DOCTYPE html>
#2: <html>
#3: <head>
#4:   <meta charset="utf-8">
#5:   <link type="text/css" href="lab.css" rel="stylesheet" />
#6:   <script type="text/javascript" src="lab_ex04.js" ></script>
#7:   <script type="text/javascript">
#8:     function datesEqual(d1,d2,m1,m2,y1,y2) {
#9:          ret = d1 === d2 && m1 === m2 && y1 === y2;
#10:          return ret;
#11:      }
#12:     function values(jsonObj) {
#13:           var avgValue = [];
#14:           var s = jsonObj[0].time;
#15:           var bits = s.split(/\D/);
#16:           date1 = new Date(bits[0], --bits[1], bits[2], bits[3], bits[4]);
#17:           y1 = date1.getFullYear();
#18:           m1 = date1.getMonth();
#19:           d1 = date1.getDate();
#20:           
#21:           var dateValue = [];
#22:           var minValue = [];
#23:           var maxValue = [];
#24:           
#25:           dateValue[0] = new Date(y1, m1, d1);
#26:           minValue[0] = [];
#27:           minValue[0][0] = parseFloat(jsonObj[0].data.p0);
#28:           /*
#29:           minValue[0][1] = parseFloat(jsonObj[0].data.ha);
#30:           minValue[0][2] = parseFloat(jsonObj[0].data.ws);
#31:           minValue[0][3] = parseFloat(jsonObj[0].data.t0);
#32:           minValue[0][4] = parseFloat(jsonObj[0].data.);
#33:           minValue[0][5] = parseFloat(jsonObj[0].data.ta);
#34:           minValue[0][6] = parseFloat(jsonObj[0].data.ra);
#35:           minValue[0][7] = parseFloat(jsonObj[0].data.wd);
#36:           */
#37:           maxValue[0] = [];
#38:           maxValue[0][0] = parseFloat(jsonObj[0].data.p0);
#39:           /*
#40:           maxValue[0][1] = parseFloat(jsonObj[0].data.ha);
#41:           maxValue[0][2] = parseFloat(jsonObj[0].data.ws);
#42:           maxValue[0][3] = parseFloat(jsonObj[0].data.t0);
#43:           maxValue[0][4] = parseFloat(jsonObj[0].data.p0);
#44:           maxValue[0][5] = parseFloat(jsonObj[0].data.ta);
#45:           maxValue[0][6] = parseFloat(jsonObj[0].data.ra);
#46:           maxValue[0][7] = parseFloat(jsonObj[0].data.wd);
#47:           */    
#48:           avgValue[0] = [0,0,0,0,0,0,0,0];      
#49:           var n =0;
#50:           var id = 0;
#51:           for (var i=0, max=jsonObj.length; i<max; i++) {
#52:              s = jsonObj[i].time;
#53:              bits = s.split(/\D/);
#54:              date2 = new Date(bits[0], --bits[1], bits[2], bits[3], bits[4]);
#55:              d2 = date2.getDate();
#56:              m2 = date2.getMonth();
#57:              y2 = date2.getFullYear();
#58:              if ( datesEqual(d1,d2,m1,m2,y1,y2) ) {
#59:                avgValue[id][0] += parseFloat(jsonObj[i].data.p0);
#60:                /*
#61:                avgValue[id][1] += parseFloat(jsonObj[i].data.ha);
#62:                avgValue[id][2] += parseFloat(jsonObj[i].data.ws);
#63:                avgValue[id][3] += parseFloat(jsonObj[i].data.t0);
#64:                avgValue[id][4] += parseFloat(jsonObj[i].data.p0);
#65:                avgValue[id][5] += parseFloat(jsonObj[i].data.ta);
#66:                avgValue[id][6] += parseFloat(jsonObj[i].data.ra);
#67:                avgValue[id][7] += parseFloat(jsonObj[i].data.wd);
#68:                */
#69:                if ( minValue[id][0] > parseFloat(jsonObj[i].data.p0) ) minValue[id][0] = parseFloat(jsonObj[i].data.p0);
#70:                /*
#71:                if ( minValue[id][1] > parseFloat(jsonObj[i].data.ha) ) minValue[id][1] = parseFloat(jsonObj[i].data.ha);
#72:                if ( minValue[id][2] > parseFloat(jsonObj[i].data.ws) ) minValue[id][2] = parseFloat(jsonObj[i].data.ws);
#73:                if ( minValue[id][3] > parseFloat(jsonObj[i].data.t0) ) minValue[id][3] = parseFloat(jsonObj[i].data.t0);
#74:                if ( minValue[id][4] > parseFloat(jsonObj[i].data.p0) ) minValue[id][4] = parseFloat(jsonObj[i].data.p0);
#75:                if ( minValue[id][5] > parseFloat(jsonObj[i].data.ta) ) minValue[id][5] = parseFloat(jsonObj[i].data.ta);
#76:                if ( minValue[id][6] > parseFloat(jsonObj[i].data.ra) ) minValue[id][6] = parseFloat(jsonObj[i].data.ra);
#77:                if ( minValue[id][7] > parseFloat(jsonObj[i].data.wd) ) minValue[id][7] = parseFloat(jsonObj[i].data.wd);
#78:                */
#79:                if ( maxValue[id][0] < parseFloat(jsonObj[i].data.p0) ) maxValue[id][0] = parseFloat(jsonObj[i].data.p0);
#80:                /*
#81:                if ( maxValue[id][1] < parseFloat(jsonObj[i].data.ha) ) maxValue[id][1] = parseFloat(jsonObj[i].data.ha);
#82:                if ( maxValue[id][2] < parseFloat(jsonObj[i].data.ws) ) maxValue[id][2] = parseFloat(jsonObj[i].data.ws);
#83:                if ( maxValue[id][3] < parseFloat(jsonObj[i].data.t0) ) maxValue[id][3] = parseFloat(jsonObj[i].data.t0);
#84:                if ( maxValue[id][4] < parseFloat(jsonObj[i].data.p0) ) maxValue[id][4] = parseFloat(jsonObj[i].data.p0);
#85:                if ( maxValue[id][5] < parseFloat(jsonObj[i].data.ta) ) maxValue[id][5] = parseFloat(jsonObj[i].data.ta);
#86:                if ( maxValue[id][6] < parseFloat(jsonObj[i].data.ra) ) maxValue[id][6] = parseFloat(jsonObj[i].data.ra);
#87:                if ( maxValue[id][7] < parseFloat(jsonObj[i].data.wd) ) maxValue[id][7] = parseFloat(jsonObj[i].data.wd);
#88:                */
#89:                n++;
#90:               } else {
#91:                avgValue[id][0] /= n;
#92:                /*
#93:                avgValue[id][1] /= n;
#94:                avgValue[id][2] /= n;
#95:                avgValue[id][3] /= n;
#96:                avgValue[id][4] /= n;
#97:                avgValue[id][5] /= n;
#98:                avgValue[id][6] /= n;
#99:                avgValue[id][7] /= n;
#100:                */
#101:                id++;
#102:                y1=y2;
#103:                m1=m2;
#104:                d1=d2;
#105:                dateValue[id] = new Date(y1, m1, d1);
#106:                avgValue[id] = [0,0,0,0,0,0,0,0];
#107:                minValue[id] = [];
#108:                minValue[id][0] = parseFloat(jsonObj[i].data.p0);
#109:                /*
#110:                minValue[id][1] = parseFloat(jsonObj[i].data.ha);
#111:                minValue[id][2] = parseFloat(jsonObj[i].data.ws);
#112:                minValue[id][3] = parseFloat(jsonObj[i].data.t0);
#113:                minValue[id][4] = parseFloat(jsonObj[i].data.p0);
#114:                minValue[id][5] = parseFloat(jsonObj[i].data.ta);
#115:                minValue[id][6] = parseFloat(jsonObj[i].data.ra);
#116:                minValue[id][7] = parseFloat(jsonObj[i].data.wd);
#117:                */
#118:                maxValue[id] = [];         
#119:                maxValue[id][0] = parseFloat(jsonObj[i].data.p0);
#120:                /*
#121:                maxValue[id][1] = parseFloat(jsonObj[i].data.ha);
#122:                maxValue[id][2] = parseFloat(jsonObj[i].data.ws);
#123:                maxValue[id][3] = parseFloat(jsonObj[i].data.t0);
#124:                maxValue[id][4] = parseFloat(jsonObj[i].data.p0);
#125:                maxValue[id][5] = parseFloat(jsonObj[i].data.ta);
#126:                maxValue[id][6] = parseFloat(jsonObj[i].data.ra);
#127:                maxValue[id][7] = parseFloat(jsonObj[i].data.wd); 
#128:                */
#129:                n=0;
#130:               } 
#131:            }
#132:            avgValue[id][0] /= n;
#133:            /*
#134:            avgValue[id][1] /= n;
#135:            avgValue[id][2] /= n;
#136:            avgValue[id][3] /= n;
#137:            avgValue[id][4] /= n;
#138:            avgValue[id][5] /= n;
#139:            avgValue[id][6] /= n;
#140:            avgValue[id][7] /= n;
#141:            */
#142:            var txt = "<table class='data'><tr><th>Czas pomiaru</th><th>Ciśnienie min</th><th>Ciśnienie max</th><th>Ciśnienie avg</th></tr>"
#143:            for (var i=0; i<id; i++) {
#144:              txt += "<tr><td class='val'>" + dateValue[i].toDateString() + "</td>";
#145:              txt += "<td class='val'>" + minValue[i][0] + "</td>";
#146:              txt += "<td class='val'>" + maxValue[i][0] + "</td>";
#147:              txt += "<td class='val'>" + avgValue[i][0].toFixed(2) + "</td></tr>" ;
#148:            }          
#149:            txt += "</table>" ;
#150:            document.getElementById('result').innerHTML = txt;
#151:      }     
#152: </script>  
#153: </head>    
#154: <body onload=sendRequest()>
#155:    <div id="result" ></div>
#156: </body>
  

Plik lab_ex04.js ( [listing skryptu] link do skryptu )

#1: var request;
#2: function getRequestObject()      {
#3:        if ( window.ActiveXObject)  {
#4:             return ( new ActiveXObject("Microsoft.XMLHTTP")) ;
#5:         } else if (window.XMLHttpRequest)  {
#6:            return (new XMLHttpRequest())  ;
#7:         } else {
#8:            return (null) ;
#9:         }
#10:   }
#11: function sendRequest()      {
#12:        request = getRequestObject() ;
#13:        request.onreadystatechange = handleResponse ;
#14:        request.open("GET", "http://mech.fis.agh.edu.pl/meteo/rest/json/all/s000/2020-06-01/2020-06-15", true);
#15:        request.send(null);
#16:   }
#17: function handleResponse()      {
#18:        if (request.readyState == 4)    {
#19:           //alert(request.responseText);
#20:           var jsonObj=eval(  "("  +  request.responseText    +  ")"    );
#21:           //alert(jsonObj[0].time);
#22:           values(jsonObj);
#23:        }
#24: }
  

Poniżej prezentacja uruchomionego przykładu (link do uruchomienia w nowym oknie lab_ex04.html).

Ćwiczenie 6. Skrypt z możliwością wyboru wielkości prezentowanej na wykresie

W kolejnym ćwiczeniu wykorzystamy rozwiązania przedstawione w poprzednich ćwiczeniach. Przedstawiona poniżej strona WWW umożliwia wybór okresu dla którego będziemy analizować dane pomiarowe. Po wyborze dat, dane zostają pobrane z serwisu z wykorzystaniem technilogii AJAX w formacie JSON dla wszystkich danych pomiarowych z wybranego okresu. Stronę obsługują trzy skrypty: lab_ex05.html, lab_ex05a.js i lab_ex05b.js.

W ramach skryptu lab_ex05.html wybieramy poczatkową i końcową datę dla analizowanych danych pomiarowych (elementy <input>) a następnie wybieramy typ danych, które będą prezentowane w ramach elementu <select>. W skrypcie zawarte są również dwie funkcje opracowane w JavaScript - "checkData()" sprawdzająca poprawność wprowadzonych dat i "graph() rysująca wykres".

Skrypt lab_ex05a.js jest modyfikacją skryptu lab_ex02.js i odpowiada za transfer danych z serwera w formacie JSON.

Skrypt lab_ex05b.js zawiera funkcję values() przedstawioną w ćwiczeniu 4. Funkcja została zmodyfikowana, dane dla kolejnych wartości dobowych umiwszczane są w tablicy obiektów (np. avgValue[]{} ) a nie jak w ćwiczeniu 4 w dwuwymiarowej tablicy (np. avgValue[][]). Takie rozwiązanie ułatwia wybór danych do prezenacji na wykresie i w tablicy.

Plik lab_ex05.html ( [listing skryptu] link do skryptu )

#1: <!DOCTYPE html>
#2: <html>
#3:    <head>
#4:       <meta charset="utf-8">
#5:       <script type="text/javascript" src="dygraphs.js" ></script>
#6:       <script type="text/javascript" src="lab_ex05a.js" ></script>
#7:       <script type="text/javascript" src="lab_ex05b.js" ></script>
#8:       <link type="text/css" href="lab.css" rel="stylesheet" />
#9:       <link rel="stylesheet" type="text/css" href="http://cdn.gday.net.au/A.form_formatting.css.pagespeed.cf.MNok_y6LAw.css">
#10:       <script type="text/javascript" >
#11:          var jsonObj = {};
#12:          var parTitllv= {};
#13:          var minValue = [];
#14:          var maxValue = [];
#15:          var avgValue = [];
#16:          var dateValue = [];
#17:          parTitle = { "pa":"Ciśnienie" , "p0":"Ciśnienie zredukowane", "ha":"Wilgotność", 
#18:                       "ta":"Temperatura", "t0":"Punkt rosy", "ra":"Opad",
#19:                       "wd":"Kierunek wiatru", "ws":"Szybkość wiatru" };
#20:          function checkData() {
#21:          // regular expression to match required date format 
#22:             re = /^20[12][0-9]\-[01][0-9]\-[0-3][0-9]$/; 
#23:             var d1 = document.getElementById("startdate"); 
#24:             //alert(" 1. Invalid date format: " + d1.value); 
#25:             if(d1.value == '' || (d1.value != '' && !d1.value.match(re)) ) { 
#26:                alert("Nieporawny data początkowa: " + d1.value); 
#27:                //form.startdate.focus(); 
#28:                return false; 
#29:             }
#30:             var d2 = document.getElementById("enddate"); 
#31:             if( !d2.value.match(re) ) { 
#32:                alert("Niepoprawna data końcowa: " + d2.value); 
#33:                //form.startdate.focus(); 
#34:                return false; 
#35:             }
#36:             sendRequest(d1,d2);
#37:          }
#38:          function graph() {
#39:             values();
#40:             var par = document.getElementById('par');
#41:             if ( par.selectedIndex > 0 ) {
#42:                var val = par.options[par.selectedIndex].value;
#43:                var csv_data = "";
#44:                for (var i=0; i<jsonObj.length; i++) {
#45:                  csv_data += jsonObj[i].time + "," + jsonObj[i].data[val] + "\n" ;
#46:                }
#47:                var g3 = new Dygraph(
#48:                   document.getElementById("graphdiv3"),
#49:                   csv_data,
#50:                   {
#51:                      title: parTitle[val],
#52:                      ylabel: parTitle[val],
#53:                      strokeWidth: 0,
#54:                      drawPoints: true
#55:                      //drawGapEdgePoints: true
#56:                   } );
#57:                var txt = "<table class='data'><tr><th>Data pomiaru</th><th>Wart. min</th><th>Wart. max</th><th>Wart. avg</th></tr>"
#58:                for (var i=0; i<dateValue.length; i++) {
#59:                    txt += "<tr><td class='val'>" + dateValue[i].toDateString() + "</td>";
#60:                    txt += "<td class='val'>" + minValue[i][val] + "</td>";
#61:                    txt += "<td class='val'>" + maxValue[i][val] + "</td>";
#62:                    txt += "<td class='val'>" + avgValue[i][val].toFixed(2) + "</td></tr>" ;
#63:                }          
#64:                txt += "</table>" ;
#65:                document.getElementById('valdiv').innerHTML = txt;
#66:             }     
#67:          }
#68:       </script >
#69:    </head>
#70:    <body >
#71:       <div id="inp">
#72:       <fieldset><legend>Wybór okresu pomiarowego</legend>
#73:       <label>Data początkowa</label><span><input id="startdate" type="text" size="12" placeholder="yyyy-mm-dd" name="startdate" value="2020-06-01"> <small>(yyyy-mm-dd)</small></span>
#74:       <label>Data końcowa</label><span><input id="enddate" type="text" size="12" placeholder="yyyy-mm-dd" name="enddate" value="2020-06-14"> <small>(yyyy-mm-dd)</small></span>
#75:       <span><input type="submit" onclick="checkData()"></input></span>
#76:       </fieldset>
#77:       </div>
#78:       <div id="myDiv"></div>
#79:       <div id="sel" style="display:none">      
#80:       <select id="par" name="par" onchange=graph() >
#81:            <option value="0">Proszę wybrać wielkość mierzona</option>
#82:            <!--option value="pa">Ciśnienie</option-->
#83:            <option value="p0">Ciśnienie na poziomie morza</option>
#84:            <option value="ha">Wilgotność</option>
#85:            <option value="ws">Prędkość wiatru</option>
#86:            <option value="wd">Kierunek wiatru</option>
#87:            <option value="ta">Temperatura</option>
#88:            <option value="t0">Punkt rosy</option>
#89:            <option value="ra">Opad deszczu</option>
#90:       </select>
#91:       </div>
#92:       </div>
#93:       <div id="graphdiv3" style="width:500px; height:300px;"></div>
#94:       <div id="valdiv" style="width:800px; height:300px""><div>
#95:    </body>
#96: </html>  

Plik lab_ex05a.js ( [listing skryptu] link do skryptu )

#1: var request;
#2: function getRequestObject()      {
#3:        if ( window.ActiveXObject)  {
#4:             return ( new ActiveXObject("Microsoft.XMLHTTP")) ;
#5:         } else if (window.XMLHttpRequest)  {
#6:            return (new XMLHttpRequest())  ;
#7:         } else {
#8:            return (null) ;
#9:         }
#10:   }
#11: function sendRequest(d1,d2)      {
#12:        request = getRequestObject() ;
#13:        request.onreadystatechange = handleResponse ;
#14:        //alert ("/"+d1.value+"/"+d2.value);
#15:        request.open("GET", "http://mech.fis.agh.edu.pl/meteo/rest/json/all/s000/"+d1.value+"/"+d2.value, true);
#16:        request.send(null);
#17:   }
#18: function handleResponse() {
#19:       myDiv = document.getElementById("myDiv");
#20:       if (request.readyState == 1) {
#21:            myDiv.innerHTML += "Pobieranie danych:" ;
#22:       } 
#23:       else if (request.readyState == 2) {
#24:            myDiv.innerHTML += "." ;
#25:       }
#26:       else if (request.readyState == 3) {
#27:            myDiv.innerHTML += "." ;
#28:       }
#29:        if (request.readyState == 4)    {
#30:           //alert(request.responseText);
#31:           jsonObj=eval(  "("  +  request.responseText    +  ")"    );
#32:           //alert(jsonObj[0].data.pa);
#33:           document.getElementById('sel').style.display = "block";
#34:        }
#35: }
  

Plik lab_ex05b.js ( [listing skryptu] link do skryptu )

#1:     function datesEqual(d1,d2,m1,m2,y1,y2) {
#2:          ret = d1 === d2 && m1 === m2 && y1 === y2;
#3:          return ret;
#4:      }
#5:     function values() {
#6:           //var avgValue = [];
#7:           var s = jsonObj[0].time;
#8:           var bits = s.split(/\D/);
#9:           date1 = new Date(bits[0], --bits[1], bits[2], bits[3], bits[4]);
#10:           y1 = date1.getFullYear();
#11:           m1 = date1.getMonth();
#12:           d1 = date1.getDate();
#13:           
#14:           //var dateValue = [];
#15:           //var minValue = [];
#16:           //var maxValue = [];
#17:           
#18:           dateValue[0] = new Date(y1, m1, d1);
#19:           minValue[0] = {};
#20:           minValue[0].pa = parseFloat(jsonObj[0].data.pa);
#21:           minValue[0].ha = parseFloat(jsonObj[0].data.ha);
#22:           minValue[0].ws = parseFloat(jsonObj[0].data.ws);
#23:           minValue[0].t0 = parseFloat(jsonObj[0].data.t0);
#24:           minValue[0].p0 = parseFloat(jsonObj[0].data.p0);
#25:           minValue[0].ta = parseFloat(jsonObj[0].data.ta);
#26:           minValue[0].ra = parseFloat(jsonObj[0].data.ra);
#27:           minValue[0].wd = parseFloat(jsonObj[0].data.wd);
#28:           maxValue[0] = {};
#29:           maxValue[0].pa = parseFloat(jsonObj[0].data.pa);
#30:           maxValue[0].ha = parseFloat(jsonObj[0].data.ha);
#31:           maxValue[0].ws = parseFloat(jsonObj[0].data.ws);
#32:           maxValue[0].t0 = parseFloat(jsonObj[0].data.t0);
#33:           maxValue[0].p0 = parseFloat(jsonObj[0].data.p0);
#34:           maxValue[0].ta = parseFloat(jsonObj[0].data.ta);
#35:           maxValue[0].ra = parseFloat(jsonObj[0].data.ra);
#36:           maxValue[0].wd = parseFloat(jsonObj[0].data.wd);    
#37:           avgValue[0] = {pa:0,ha:0,ws:0,t0:0,p0:0,ta:0,ra:0,wd:0};      
#38:           var n =0;
#39:           var id = 0;
#40:           for (var i=0, max=jsonObj.length; i<max; i++) {
#41:              s = jsonObj[i].time;
#42:              bits = s.split(/\D/);
#43:              date2 = new Date(bits[0], --bits[1], bits[2], bits[3], bits[4]);
#44:              d2 = date2.getDate();
#45:              m2 = date2.getMonth();
#46:              y2 = date2.getFullYear();
#47:              if ( datesEqual(d1,d2,m1,m2,y1,y2) ) {
#48:                avgValue[id].pa += parseFloat(jsonObj[i].data.pa);
#49:                avgValue[id].ha += parseFloat(jsonObj[i].data.ha);
#50:                avgValue[id].ws += parseFloat(jsonObj[i].data.ws);
#51:                avgValue[id].t0 += parseFloat(jsonObj[i].data.t0);
#52:                avgValue[id].p0 += parseFloat(jsonObj[i].data.p0);
#53:                avgValue[id].ta += parseFloat(jsonObj[i].data.ta);
#54:                avgValue[id].ra += parseFloat(jsonObj[i].data.ra);
#55:                avgValue[id].wd += parseFloat(jsonObj[i].data.wd);
#56:                if ( minValue[id].pa > parseFloat(jsonObj[i].data.pa) ) minValue[id].pa =parseFloat(jsonObj[i].data.pa);
#57:                if ( minValue[id].ha > parseFloat(jsonObj[i].data.ha) ) minValue[id].ha =parseFloat(jsonObj[i].data.ha);
#58:                if ( minValue[id].ws > parseFloat(jsonObj[i].data.ws) ) minValue[id].ws =parseFloat(jsonObj[i].data.ws);
#59:                if ( minValue[id].t0 > parseFloat(jsonObj[i].data.t0) ) minValue[id].t0 =parseFloat(jsonObj[i].data.t0);
#60:                if ( minValue[id].p0 > parseFloat(jsonObj[i].data.p0) ) minValue[id].p0 =parseFloat(jsonObj[i].data.p0);
#61:                if ( minValue[id].ta > parseFloat(jsonObj[i].data.ta) ) minValue[id].ta =parseFloat(jsonObj[i].data.ta);
#62:                if ( minValue[id].ra > parseFloat(jsonObj[i].data.ra) ) minValue[id].ra =parseFloat(jsonObj[i].data.ra);
#63:                if ( minValue[id].wd > parseFloat(jsonObj[i].data.wd) ) minValue[id].wd =parseFloat(jsonObj[i].data.wd);
#64:                if ( maxValue[id].pa < parseFloat(jsonObj[i].data.pa) ) maxValue[id].pa =parseFloat(jsonObj[i].data.pa);
#65:                if ( maxValue[id].ha < parseFloat(jsonObj[i].data.ha) ) maxValue[id].ha =parseFloat(jsonObj[i].data.ha);
#66:                if ( maxValue[id].ws < parseFloat(jsonObj[i].data.ws) ) maxValue[id].ws =parseFloat(jsonObj[i].data.ws);
#67:                if ( maxValue[id].t0 < parseFloat(jsonObj[i].data.t0) ) maxValue[id].t0 =parseFloat(jsonObj[i].data.t0);
#68:                if ( maxValue[id].p0 < parseFloat(jsonObj[i].data.p0) ) maxValue[id].p0 =parseFloat(jsonObj[i].data.p0);
#69:                if ( maxValue[id].ta < parseFloat(jsonObj[i].data.ta) ) maxValue[id].ta =parseFloat(jsonObj[i].data.ta);
#70:                if ( maxValue[id].ra < parseFloat(jsonObj[i].data.ra) ) maxValue[id].ra =parseFloat(jsonObj[i].data.ra);
#71:                if ( maxValue[id].wd < parseFloat(jsonObj[i].data.wd) ) maxValue[id].wd =parseFloat(jsonObj[i].data.wd);
#72:                n++;
#73:              } else {
#74:                //alert ( "-----"+n+"------" ) ;
#75:                avgValue[id].pa /= n;
#76:                avgValue[id].ha /= n;
#77:                avgValue[id].ws /= n;
#78:                avgValue[id].t0 /= n;
#79:                avgValue[id].p0 /= n;
#80:                avgValue[id].ta /= n;
#81:                avgValue[id].ra /= n;
#82:                avgValue[id].wd /= n;
#83:                id++;
#84:                y1=y2;
#85:                m1=m2;
#86:                d1=d2;
#87:                dateValue[id] = new Date(y1, m1, d1);
#88:                avgValue[id] = {pa:0,ha:0,ws:0,t0:0,p0:0,ta:0,ra:0,wd:0};
#89:                minValue[id] = {};
#90:                minValue[id].pa = parseFloat(jsonObj[i].data.pa);
#91:                minValue[id].ha = parseFloat(jsonObj[i].data.ha);
#92:                minValue[id].ws = parseFloat(jsonObj[i].data.ws);
#93:                minValue[id].t0 = parseFloat(jsonObj[i].data.t0);
#94:                minValue[id].p0 = parseFloat(jsonObj[i].data.p0);
#95:                minValue[id].ta = parseFloat(jsonObj[i].data.ta);
#96:                minValue[id].ra = parseFloat(jsonObj[i].data.ra);
#97:                minValue[id].wd = parseFloat(jsonObj[i].data.wd);
#98:                maxValue[id] = {};         
#99:                maxValue[id].pa = parseFloat(jsonObj[i].data.pa);
#100:                maxValue[id].ha = parseFloat(jsonObj[i].data.ha);
#101:                maxValue[id].ws = parseFloat(jsonObj[i].data.ws);
#102:                maxValue[id].t0 = parseFloat(jsonObj[i].data.t0);
#103:                maxValue[id].p0 = parseFloat(jsonObj[i].data.p0);
#104:                maxValue[id].ta = parseFloat(jsonObj[i].data.ta);
#105:                maxValue[id].ra = parseFloat(jsonObj[i].data.ra);
#106:                maxValue[id].wd = parseFloat(jsonObj[i].data.wd); 
#107:                n=0;
#108:              } 
#109:            }
#110:            avgValue[id].pa /= n;
#111:            avgValue[id].ha /= n;
#112:            avgValue[id].ws /= n;
#113:            avgValue[id].t0 /= n;
#114:            avgValue[id].p0 /= n;
#115:            avgValue[id].ta /= n;
#116:            avgValue[id].ra /= n;
#117:            avgValue[id].wd /= n;
#118:      }  
  

Poniżej prezentacja uruchomionego przykładu (link do uruchomienia w nowym oknie lab_ex05.html).

Ćwiczenie 7. Dane statystyczne - liczba pomiarów w miesiącu w każdym dniu

W przedstawionym ćwiczeniu wykorzystamy polecenie REST zwracające liczbę pomiarów w ramach wybranego miesiąca w kolejnych jego dniach. W przyszłości zostanie udostępniona metoda zwracająca informację czy w danym miesiącu były zbierane dane. Stronę obsługują dwa skrypty: lab_ex06.html, lab_ex06.js.

Odczyt danych z serwisu WWW w formacie JSON następuje poprzez polecenie:

http://mech.fis.agh.edu.pl/meteo/rest/json/stat/{station}/{rrrr-mm}

gdzie:

{station}
identyfikator stacji
{rrrr-mm}
wybrany miesiąc pomiarów

Przykładowe polecenie pobierające dane z miesiąca - czerwiec 2020.

http://mech.fis.agh.edu.pl/meteo/rest/json/stat/s000/2020-06

Do prezentacji danych w postaci tabeli wykorzystamy odpowiednie skrypty opracowane w języku HTML5, JavaScript i CSS. Funkcjonalność skryptów w języku HTML i CSS jest analogicza do przedstawionych powyżej skryptów "lab_ex02.html" i "lab.css".

Plik lab_ex06.html ( [listing skryptu] link do skryptu )

  #1: <!DOCTYPE html>
#2: <html>
#3:    <head>
#4:       <meta charset="utf-8">
#5:       <title>Ajax: Odczyt danych z serwera</title>
#6:       <link type="text/css" href="lab.css" rel="stylesheet" />
#7:       <script src="lab_ex06.js" type="text/javascript"></script>
#8:    </head>
#9:    <body>
#10:      <div style="text-align:center" >
#11:        <table border="1" bgcolor="gray">
#12:          <tr><th><big>Ajax: Odczyt danych z serwera</big></th></tr>
#13:        </table>
#14:        <br />
#15:        <form action="#">
#16:           <input type="button" value="Pobierz dane z serwera" onclick="sendRequest()"/>
#17:        </form>
#18:      </div>
#19:      <div id="result"></div>
#20:     </body>
#21: </html>
  

Podobnie jak w ćwiczeniu drugim został przygotowany odpowiedni skrypt w JavaScript pobierający dane z wykorzystaniem technologii AJAX. Dwie pierwsze funkcje "getRequestObject()" i "sendRequest()" są identyczne do odpowiednich funkcji w skrypcie "lab_ex02.js". W trzeciej funcji "handleResponse()" różnica jest w przetworzeniu zwróconego wyniku. Po przeczytaniu danych z własnoności "responseText" obiektu XHR wykorzystujemy funkcję "evel()" w JavaScript do utworzenia tablicy obiektów (linia kodu 20). Dostęp do określonej wartości parametru następuje przez wskazanie na numer obiektu w tablicy i wskazanie określonego parametru. Przykładowo wpis "jsonObj[2].data.day" pobiera numer dnia w miesiącu dla którego zostały zebrane wszystkie wyniki pomiarowe dostępne w bazie. Wpis "jsonObj[2].count" pobiera liczbę zarejestrowanych pomiarów.

Plik lab_ex06.js ( [listing skryptu] link do skryptu )

  #1: var request;
#2: function getRequestObject()      {
#3:        if ( window.ActiveXObject)  {
#4:             return ( new ActiveXObject("Microsoft.XMLHTTP")) ;
#5:         } else if (window.XMLHttpRequest)  {
#6:            return (new XMLHttpRequest())  ;
#7:         } else {
#8:            return (null) ;
#9:         }
#10:   }
#11: function sendRequest()      {
#12:        request = getRequestObject() ;
#13:        request.onreadystatechange = handleResponse ;
#14:        request.open("GET", "http://mech.fis.agh.edu.pl/meteo/rest/json/stat/s000/2020-06", true);
#15:        request.send(null);
#16:   }
#17: function handleResponse()      {
#18:        if (request.readyState == 4)    {
#19:           //alert(request.responseText);
#20:           var jsonObj=eval(  "("  +  request.responseText    +  ")"    );
#21:           //alert(jsonObj[0].data.pa);
#22:           var txt = "<p>Licza przetworzonych wierszy: " + jsonObj.length.toString() + "</p>";
#23:           txt += "<table class='data'><tr><th>Dzień pomiaru</th><th>Liczba pomiarów</th></tr>"
#24:           for (var i=0, max=jsonObj.length; i<max; i++) {
#25:              txt_day = jsonObj[i].data.day + "/" + jsonObj[i].data.month + "/" + jsonObj[i].data.year ;
#26:              txt += "<tr><td>" + txt_day + "</td><td>" + jsonObj[i].count + "</td></tr>" ;
#27:           }          
#28:           txt += "</table>" ;
#29:           document.getElementById('result').innerHTML = txt;
#30:        }
#31: }
  

Poniżej prezentacja uruchomionego przykładu (link do uruchomienia w nowym oknie lab_ex06.html).

Ćwiczenie 8. Informacje o szkołach uczestniczących w projekcie

W przedstawionym ćwiczeniu wykorzystamy polecenie REST zwracające informacje o szkołach w projekcie. Ćwiczenie obsługują dwa skrypty: lab_ex07.html, lab_ex07.js.

Odczyt danych z serwisu WWW w formacie JSON następuje poprzez polecenie:

http://mech.fis.agh.edu.pl/meteo/rest/json/info/

Do prezentacji danych w postaci tabeli wykorzystamy odpowiednie skrypty opracowane w języku HTML5, JavaScript i CSS. Funkcjonalność skryptów w języku HTML i CSS jest analogicza do przedstawionych powyżej skryptów "lab_ex02.html" i "lab.css".

Plik lab_ex07.html ( [listing skryptu] link do skryptu )

  #1: <!DOCTYPE html>
#2: <html>
#3:    <head>
#4:       <meta charset="utf-8">
#5:       <title>Ajax: Odczyt danych z serwera</title>
#6:       <link type="text/css" href="lab.css" rel="stylesheet" />
#7:       <script src="lab_ex07.js" type="text/javascript"></script>
#8:    </head>
#9:    <body>
#10:      <div style="text-align:center" >
#11:        <table border="1" bgcolor="gray">
#12:          <tr><th><big>Ajax: Odczyt danych z serwera</big></th></tr>
#13:        </table>
#14:        <br />
#15:        <form action="#">
#16:           <input type="button" value="Pobierz dane z serwera" onclick="sendRequest()"/>
#17:        </form>
#18:      </div>
#19:      <div id="result"></div>
#20:     </body>
#21: </html>
  

Podobnie jak w ćwiczeniu drugim został przygotowany odpowiedni skrypt w JavaScript pobierający dane z wykorzystaniem technologii AJAX. Dwie pierwsze funkcje "getRequestObject()" i "sendRequest()" są identyczne do odpowiednich funkcji w skrypcie "lab_ex02.js". W trzeciej funcji "handleResponse()" różnica jest w przetworzeniu zwróconego wyniku. Po przeczytaniu danych z własnoności "responseText" obiektu XHR wykorzystujemy funkcję "evel()" w JavaScript do utworzenia tablicy obiektów (linia kodu 20). Dostęp do określonej wartości parametru następuje przez wskazanie na numer obiektu w tablicy i wskazanie określonego parametru. Przykładowo wpis "jsonObj[2].station" pobiera identyfikator szkoły.

Plik lab_ex07.js ( [listing skryptu] link do skryptu )

  #1: var request;
#2: function getRequestObject()      {
#3:        if ( window.ActiveXObject)  {
#4:             return ( new ActiveXObject("Microsoft.XMLHTTP")) ;
#5:         } else if (window.XMLHttpRequest)  {
#6:            return (new XMLHttpRequest())  ;
#7:         } else {
#8:            return (null) ;
#9:         }
#10:   }
#11: function sendRequest()      {
#12:        request = getRequestObject() ;
#13:        request.onreadystatechange = handleResponse ;
#14:        request.open("GET", "http://mech.fis.agh.edu.pl/meteo/rest/json/info/", true);
#15:        request.send(null);
#16:   }
#17: function handleResponse()      {
#18:        if (request.readyState == 4)    {
#19:           //alert(request.responseText);
#20:           var jsonObj=eval(  "("  +  request.responseText    +  ")"    );
#21:           //alert(jsonObj[0].data.pa);
#22:           // var txt = "<p>Licza przetworzonych wierszy: " + jsonObj.length.toString() + "</p>";
#23:           txt  = "<table class='data'><tr><th>Identyfikator</th><th>Nazwa</th><th>Długość</th><th>Szerokość</th><th>Wysokość</th></tr>";
#24:           txt += "<tr><th>szkoły</th><th>szkoły</th><th>geograficzna</th><th>geograficzna</th><th></th></tr>";
#25:           for (var i=0, max=jsonObj.length; i<max; i++) {
#26:              txt += "<tr><td>" + jsonObj[i].station + "</td><td>" + jsonObj[i].name + "</td><td>" + jsonObj[i].long  ;
#27:              txt += "</td><td>" + jsonObj[i].lati + "</td><td>" + jsonObj[i].alti + "</td></tr>" ; 
#28:           }          
#29:           txt += "</table>" ;
#30:           document.getElementById('result').innerHTML = txt;
#31:        }
#32: }
  

Poniżej prezentacja uruchomionego przykładu (link do uruchomienia w nowym oknie lab_ex07.html).