GoogleMap Javascript でGreatCircleライン

Leafletで国際線飛行機の航跡ラインを描画したところ、長距離のラインが直線のままなので(プラグインをラップして使うと球面線になるようですが、まだ調べ切れてないので)、利用頻度少なく、課金もさほどないと思い、GoogleMapを使ってみました。

オプションの設定で、グレートサークルが適用されます。

[ ポリラインオプション設定例 ]


// 線の設定 //
gmapS.data.setStyle({
        strokeColor: "#FFFF00", // 黄色
        strokeWeight: 2,
        geodesic: true         // 球面線
      });      

[ 描画画面例 ]
GoogleMap

Leaflet

GoogleChartの連続描画でメモリーリークと解消方法

GoogleChartをJavaScriptで利用していて、変化状況をリアルタイムで表示する折れ線グラフを作ってみたところ、メモリリークが激しいので、調べて直してみました。

1) チャートオブジェクトはグローバル変数にする
2) 描画する前にクリアする

[ コード例 ]


let gchart;

/**
 * 汎用折れ線チャートクラス
 * @type type
 */
class ChartOSInfo {

  /**
   * コンストラクタ
   */
  constructor(chartData, divid, tp, columnnm, columntitle) {
  -- 省略 -- 
  }

  -- 省略 --
  
   /**
   * 折れ線グラフ描画
   * @returns {undefined}
   */
  drawLineChart() {

    -- 省略 --

    // チャートの初期化 //
    if (gchart) {
      gchart.clearChart();
    }
    
    // チャートの描画 //
    gchart = new google.visualization.LineChart(document.getElementById(this.divid));
    gchart.draw(datatable, options);

    
  }

}

ここで教えていただきました。
https://base64.work/so/javascript/1461742

[ 利用例 ]

 

MySQL8 JSON TABLE で配列を扱う

MySQL8からJSONの配列をレコードとして扱えるので、使ってみました。

[ Table例 ]
空港の滑走路のマスタで、複数の滑走路をJSONにしてます。

CREATE TABLE `m_runway` (
	`CD_IATA` CHAR(3) NOT NULL DEFAULT '' COMMENT 'IATA空港コード' COLLATE 'utf8_general_ci',
	`CD_ICAO` CHAR(4) NOT NULL DEFAULT '' COMMENT 'ICAO空港コード' COLLATE 'utf8_general_ci',
	`LAT` DOUBLE(22,10) NOT NULL DEFAULT '500.0000000000' COMMENT '緯度',
	`LON` DOUBLE(22,10) NOT NULL DEFAULT '500.0000000000' COMMENT '経度',
	`RUNWAYS` JSON NULL DEFAULT NULL COMMENT 'JSON明細',
	`TM_ADD` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '追加時刻',
	INDEX `m_runway_CDIATA` (`CD_IATA`) USING BTREE,
	INDEX `m_runway_CDICAO` (`CD_ICAO`) USING BTREE,
	INDEX `m_runway_LAT` (`LAT`) USING BTREE,
	INDEX `m_runway_LON` (`LON`) USING BTREE
)
COMMENT='滑走路マスタ'
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;

[ JSON列のJSON ]


[
    {
        "name": "06",
        "width": {
            "km": 0.046,
            "nm": 0.025,
            "feet": 150,
            "mile": 0.028,
            "meter": 45.72
        },
        "length": {
            "km": 2.316,
            "nm": 1.25,
            "feet": 7598,
            "mile": 1.439,
            "meter": 2315.87
        },
        "surface": "Asphalt",
        "trueHdg": 51.2,
        "isClosed": false,
        "location": {
            "lat": 40.6469841,
            "lon": -75.45063
        },
        "hasLighting": true,
        "displacedThreshold": {
            "km": 0,
            "nm": 0,
            "feet": 0,
            "mile": 0,
            "meter": 0
        }
    },
    {
        "name": "13",
        "width": {
            "km": 0.046,
            "nm": 0.025,
            "feet": 150,
            "mile": 0.028,
            "meter": 45.72
        },
        "length": {
            "km": 1.766,
            "nm": 0.954,
            "feet": 5794,
            "mile": 1.097,
            "meter": 1766.01
        },
        "surface": "Asphalt",
        "trueHdg": 123.1,
        "isClosed": false,
        "location": {
            "lat": 40.6551933,
            "lon": -75.44975
        },
        "hasLighting": true,
        "displacedThreshold": {
            "km": 0,
            "nm": 0,
            "feet": 0,
            "mile": 0,
            "meter": 0
        }
    },
    {
        "name": "24",
        "width": {
            "km": 0.046,
            "nm": 0.025,
            "feet": 150,
            "mile": 0.028,
            "meter": 45.72
        },
        "length": {
            "km": 2.316,
            "nm": 1.25,
            "feet": 7598,
            "mile": 1.439,
            "meter": 2315.87
        },
        "surface": "Asphalt",
        "trueHdg": 231.2,
        "isClosed": false,
        "location": {
            "lat": 40.6600342,
            "lon": -75.42926
        },
        "hasLighting": true,
        "displacedThreshold": {
            "km": 0.152,
            "nm": 0.082,
            "feet": 499,
            "mile": 0.095,
            "meter": 152.1
        }
    },
    {
        "name": "31",
        "width": {
            "km": 0.046,
            "nm": 0.025,
            "feet": 150,
            "mile": 0.028,
            "meter": 45.72
        },
        "length": {
            "km": 1.766,
            "nm": 0.954,
            "feet": 5794,
            "mile": 1.097,
            "meter": 1766.01
        },
        "surface": "Asphalt",
        "trueHdg": 303.1,
        "isClosed": false,
        "location": {
            "lat": 40.6465263,
            "lon": -75.4322357
        },
        "hasLighting": true,
        "displacedThreshold": {
            "km": 0,
            "nm": 0,
            "feet": 0,
            "mile": 0,
            "meter": 0
        }
    }
]

[ Select SQL例 ]

NESTED PATH を指定


    SELECT
      r.CD_IATA,
      r.CD_ICAO,
      -500 AS LAT,
      -500 AS LON,
      detail.NM_RUNWAY,
      detail.HDG,
      ROUND(detail.FEET, 0) AS FEET, 
      ROUND(detail.METER, 0) AS METER
    FROM 
      m_runway r, 

      JSON_TABLE(RUNWAYS, '$[*]' 
      COLUMNS (
        `NM_RUNWAY` VARCHAR(100) PATH '$.name',
        HDG INT PATH '$.trueHdg',
        
        NESTED PATH '$.length' 
        COLUMNS (
          FEET FLOAT PATH '$.feet',
          METER FLOAT PATH '$.meter'
        )               
        )
      ) AS detail
    WHERE
      CD_ICAO = 'RJTT'

[ 結果 ]

+---------+---------+------+------+-----------+------+-------+-------+
| CD_IATA | CD_ICAO | LAT  | LON  | NM_RUNWAY | HDG  | FEET  | METER |
+---------+---------+------+------+-----------+------+-------+-------+
| HND     | RJTT    | -500 | -500 | 04        |   35 |  8215 |  2504 |
| HND     | RJTT    | -500 | -500 | 05        |   42 |  8215 |  2504 |
| HND     | RJTT    | -500 | -500 | 16L       |  150 | 11053 |  3369 |
| HND     | RJTT    | -500 | -500 | 16R       |  150 |  9862 |  3006 |
| HND     | RJTT    | -500 | -500 | 22        |  215 |  8215 |  2504 |
| HND     | RJTT    | -500 | -500 | 23        |  222 |  8215 |  2504 |
| HND     | RJTT    | -500 | -500 | 34L       |  330 |  9862 |  3006 |
| HND     | RJTT    | -500 | -500 | 34R       |  330 | 11053 |  3369 |
+---------+---------+------+------+-----------+------+-------+-------+

MySQL8 タイムゾーンの設定

 

 

 

MySQL8を新規にインストールした状態で、タイムゾーンがUTCのままなので設定しました。
公式ドキュメントによると、タイムゾーンテーブルのロードが必要のようで、下記コマンドでロードして反映。

mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql

my.cnf に下の設定を入れます。

#default-time-zone = 'Asia/Tokyo'
default-time-zone='+9:00'

タイムゾーン名、オフセットどちらでも反映できるようです。

ここで教えていただきました。

https://qiita.com/kakudaisuke/items/f4b76fbfd7f89992d971

 

 

MySQL8 デフォルト my.cnf からbinlogを無効化

新規にインストールしたMySQL8のサーバーで、データサイズが大きく、10GBを超えていて更新が多いデータベースを運用していましたところ、

1) MySQLのメモリ消費が急増
2) サーバーのロードアベレージが常に高い

状態になったので、調べていたところ、MySQL8からデフォルトでbinlogが有効化された状態であることがわかりました。

my.cnfの設定に binlogの無効化を追加したところ大人しくなりました。

disable-log-bin   <== これを追加

今回扱ってるデータについては、障害があった時の完全な復旧が要求されてないので、この対応で対処出来てますが、そうでない場合は、メモリの増設、高速CPU環境への変更などをお勧めします。

date.nager.at (祝日)

祝日カレンダーを作ることになり、海外の祝日が取得できるフリーのAPIを探してましたところ、見つけました。

Home URL : https://date.nager.at/

Usage URL : https://date.nager.at/Api

APIKeyなし、リミットなし無償です。

 

 

 

 

 

 

 

 

 

< 出力例 >

[????@??????? ~]# http https://date.nager.at/api/v2/publicholidays/2020/JP
HTTP/1.1 200 OK
Content-Encoding: gzip
Content-Type: application/json; charset=utf-8
Date: Tue, 26 May 2020 01:59:57 GMT
Server: Microsoft-IIS/10.0
Strict-Transport-Security: max-age=2592000
Transfer-Encoding: chunked
Vary: Accept-Encoding

[
    {
        "counties": null, 
        "countryCode": "JP", 
        "date": "2020-01-01", 
        "fixed": false, 
        "global": true, 
        "launchYear": null, 
        "localName": "元日", 
        "name": "New Year's Day", 
        "type": "Public"
    }, 
    {
        "counties": null, 
        "countryCode": "JP", 
        "date": "2020-01-13", 
        "fixed": false, 
        "global": true, 
        "launchYear": null, 
        "localName": "成人の日", 
        "name": "Coming of Age Day", 
        "type": "Public"
    }, 
    {
        "counties": null, 
        "countryCode": "JP", 
        "date": "2020-02-11", 
        "fixed": false, 
        "global": true, 
        "launchYear": null, 
        "localName": "建国記念の日", 
        "name": "Foundation Day", 
        "type": "Public"
    }, 
    {
        "counties": null, 
        "countryCode": "JP", 
        "date": "2020-04-29", 
        "fixed": false, 
        "global": true, 
        "launchYear": null, 
        "localName": "昭和の日", 
        "name": "Shōwa Day", 
        "type": "Public"
    }, 
    {
        "counties": null, 
        "countryCode": "JP", 
        "date": "2020-05-04", 
        "fixed": false, 
        "global": true, 
        "launchYear": null, 
        "localName": "憲法記念日", 
        "name": "Constitution Memorial Day", 
        "type": "Public"
    }, 
    {
        "counties": null, 
        "countryCode": "JP", 
        "date": "2020-05-04", 
        "fixed": false, 
        "global": true, 
        "launchYear": null, 
        "localName": "みどりの日", 
        "name": "Greenery Day", 
        "type": "Public"
    }, 
    {
        "counties": null, 
        "countryCode": "JP", 
        "date": "2020-05-05", 
        "fixed": false, 
        "global": true, 
        "launchYear": null, 
        "localName": "こどもの日", 
        "name": "Children's Day", 
        "type": "Public"
    }, 
    {
        "counties": null, 
        "countryCode": "JP", 
        "date": "2020-07-20", 
        "fixed": false, 
        "global": true, 
        "launchYear": null, 
        "localName": "海の日", 
        "name": "Marine Day", 
        "type": "Public"
    }, 
    {
        "counties": null, 
        "countryCode": "JP", 
        "date": "2020-08-11", 
        "fixed": false, 
        "global": true, 
        "launchYear": null, 
        "localName": "山の日", 
        "name": "Mountain Day", 
        "type": "Public"
    }, 
    {
        "counties": null, 
        "countryCode": "JP", 
        "date": "2020-09-21", 
        "fixed": false, 
        "global": true, 
        "launchYear": null, 
        "localName": "(敬老の日", 
        "name": "Respect for the Aged Day", 
        "type": "Public"
    }, 
    {
        "counties": null, 
        "countryCode": "JP", 
        "date": "2020-10-12", 
        "fixed": false, 
        "global": true, 
        "launchYear": null, 
        "localName": "体育の日", 
        "name": "Health and Sports Day", 
        "type": "Public"
    }, 
    {
        "counties": null, 
        "countryCode": "JP", 
        "date": "2020-11-03", 
        "fixed": false, 
        "global": true, 
        "launchYear": null, 
        "localName": "文化の日", 
        "name": "Culture Day", 
        "type": "Public"
    }, 
    {
        "counties": null, 
        "countryCode": "JP", 
        "date": "2020-11-23", 
        "fixed": false, 
        "global": true, 
        "launchYear": null, 
        "localName": "勤労感謝の日", 
        "name": "Labour Thanksgiving Day", 
        "type": "Public"
    }, 
    {
        "counties": null, 
        "countryCode": "JP", 
        "date": "2020-12-23", 
        "fixed": false, 
        "global": true, 
        "launchYear": null, 
        "localName": "天皇誕生日", 
        "name": "The Emperor's Birthday", 
        "type": "Public"
    }
]

Javascript ES2015 で連想配列を検索

連想配列の検索がESですっきり短くできないかと、探してたところ見つけましたので、備忘録しておきます。

ここで教えて頂く : https://qiita.com/Nossa/items/4a425e57ec4b7eedb7cb

< コード例 >


   /**
   * 連想配列存在確認
   * @param {type} ary 連想配列
   * @param {type} cd HS4キーの検索対象値
   * @returns {Boolean} 存在 or Not
   */
  let isExistItmInArray = (ary, cd) => {
    
    // ES2015ですっきりさせる //
    const res = ary.some(e => e.HS4 === cd);
    return res;
    
    
    // 昔のやり方 //
    //let res = false;
    //$.each(ary, function (i, itm) {
    /*for (let i = 0; i < ary.length; i++) {
      //console.log(ary[i] + "%" + cd);
      //if (cd.indexOf(ary[i]["HS4"]) === 0) {
      if (ary[i]["HS4"] === cd) {
        res = true;
        break;
      }
    }
    return res;*/
  }

jQuery Chosen でセレクトボックス

セレクトボックスの項目が増えて、選びにくくなって来たので使ってみました。

ここで教えて頂きました : https://qiita.com/mtanabe/items/59dc6c8fea7d9e10093f

本家 : https://harvesthq.github.io/chosen/

プロパティ、イベント、何もいじらなくても、不満な部分解消出来てますが、何か不足発覚したら、ドキュメント見させて頂き、変更しようと思ってます。

< 利用例 >

日本地図

市区町村や郵便番号を選んで、選んだ地区を中心とした地図を表示します。

Bootstrap4を使ってるのでレスポンシブです。

データはRESAS (内閣府地域経済分析システム)のAPIなどを使ってます。

< URL >

https://psn.saoline.co/jpinfo/

< 機能 >

  1.  地区選択を市区町村と郵便番号別地区で切替え
  2.  地図は、Leflet, Gppgle, Bing, Openlayerが選べる
  3.  Leafletは多数のレイヤーを切替え出来る
  4. GeoJSONのマーカーを選んで表示出来る
  5. 調べた場所の現在の天気と天気予報がわかる

< 画面例 >

Leaflet: グーグル衛星レイヤー

 

 

 

Leaflet : オープンストリートマップ

 

郵便番号検索タイプ : BingMap

 

 

 

 

GoogleMap : 航空写真ラベルなし : 東京近辺自衛隊駐屯地マーカー