git ファイルの追加

プロジェクトディレクトリ以下にファイルを追加した時は以下の操作でリモートのレポジトリに反映する

ファイルをインデックスに追加

git add .

特定のファイルのみを追加

git add ファイル名

インデックスに追加されたファイルをローカルレポジトリにcommit

git commit -m "コメント"

リモートレポジトリに反映

git push origin master
Enter passphrase for key '/c/Users/tarumi/.ssh/id_rsa':SSLキーのパスワードを入力

git for windowsをインストールしてgitlabのプロジェクトを操作

Git for windowsのサイトよりインストーラーをダウンロードし、インストール。
インストーラーは「Git-2.16.2-64-bit.exe」
Windows10の場合はWindowsの設定より「アプリのインストール」を「ストアのアプリのみ許可する」以外を選択しておく

インストーラーを実行して以下に従ってインストール

インストール先のディレクトリはC:\Gitに変更

インストールするコンポーネントはデフォルト

デフォルトのエディタ
※後ほど秀丸に変更の予定

bashではwindowsのDOSを使用

SSLの設定

改行の処理の設定

その他のオプション

インストール終了

Gitの初期設定

DOSコマンドを開きメールアドレス、ユーザー名等を設定
※core.quotepathをoffにするとgit statusで変更ファイル一覧を表示するときに、日本語のファイル名が文字化けしないでちゃんと表示される
ユーザー名、メールアドレスはGitlabに設定した値を入力

C:\Users\tarumi>git config --global user.email 'メールアドレス'
C:\Users\tarumi>git config --global user.name 'ユーザー名'
C:\Users\tarumi>git config --global core.quotepath off

SSHのキーを作成
カレントをc:\git\usr\binに移動
以下のコマンドを実行
パスフレーズには任意の値を入力

C:\Git\usr\bin>ssh-keygen -t rsa -C 'メールアドレス'
Generating public/private rsa key pair.
Enter file in which to save the key (/c/Users/tarumi/.ssh/id_rsa):
Created directory '/c/Users/tarumi/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:

[/code]

GitLabのサイトを開きメニューより設定を選択

サイドばーよりSSHきーを選択してSSHキーを入力するページを表示

先ほど作成したid_rsa.pubの内容を張り付ける

以上で設定は終了

最初にプロジェクトのクローンを作成

GitLabで対象のプロジェクトを開き画面上のURLをコピー

PC上にローカルディレクトリを作成してカレントに移動し以下のコマンドを実行

git clone git@gitlab.comから始まるURL(上記でコピーした値)

以上でローカルにcloneが作成される

gitlabを始める

gitlabには自分でサイト構築から始める方法とgithubと同様にサービスを使用する方法の2種類がある。
今回は後者を使ってみる

以下のサイトを開いて
https://gitlab.com/users/sign_in
申し込みを行う。

申し込みを行うとメールが送信されるのでリンクをクリックしてログイン

最初に「New Group」ボタンを押してグループを作成する

グループ名、スコープ等を入力して「Create Group」ボタンを押す。

privateなグループであっても名称はユニークな名称の必要があるようだ。

既に使われている名称を入力すると「Path has already been taken」と表示される。

次にグループ内にプロジェクトを作成

グループの一覧を表示してプロジェクトを作成するグループを選択

「New project」を選択

プロジェクト名、説明、スコープを入力して「Create Project」を選択

以上でプロジェクトが作成される

作成されたプロジェクトのTOPにはプロジェクトのcloneの方法等が記載

MySqlDataReaderがハングアップ

.NET Connector6.0.4.0のMySqlDataReaderを10分以上使用しているとハングアップしてしまいエラーも発生せずにCPUをどんどん消費してしまう。

MySqlCommand my_cmd = my_con.CreateCommand();
my_cmd.CommandText = sql;
MySqlDataReader my_dr = my_cmd.ExecuteReader();
while (my_dr.Read())
{
	ここで処理を行う
}

上記のwhileが10分以上かかるとReadメソッドでハングアップする。
net_read_timeout、net_read_timeoutそれぞれに3600を設定して回避

カテゴリー: MySQL

LeafletでL.Layerから派生した独自レイヤを作る

Leafletでとりあえず500mメッシュを表示させたいと思いL.Layerからの派生を調査。
※jsonやwmsは何も使わずに!

Leafletでは個々のMarkerもL.Layerから派生されている。

L.Layerからの派生したクラスを作成するにはGithubのleafletjs-plugin-templatesを改造するのが最短コース。
LeafletLayerTemplate.jsをダウンロードして眺めればどのように作成すればよいのか、分かり易い。

以下はダウンロードしたLeafletLayerTemplateのコメントを削除したソース。

LeafletLayerTemplateはMarkerと同様の動作を意識して各関数内に実装がされている。

関数initialize
L.LeafletLayerTemplateのインスタンス作成時に呼ばれる関数
L.LeafletLayerTemplateのインスタンスの作成は

var layer = new L.LeafletLayerTemplate();

または

var layer = L.LeafletLayerTemplate();

で作成される。

引数に座標を指定すると関数initializeに座標が渡る。
この引数についてはoptions以外も指定が可能。
例えばlatとlngをそれぞれ渡してもよい。
例)

initialize: function(lat, lng) {
}

関数onAdd
レイヤをmapに追加すると呼ばれる関数。
以下ではdivを作成しmap.getPanes().overlayPaneに追加。
map.on(‘viewreset’, this._updatePosition, this);
は地図の移動時にthis._updatePositionをリスナーとして登録。
※現在はviewresetは機能しないためmoveやmoveendなどを使用する必要がある。
その後、強制的に_updatePositionを呼び出して位置を設定
※_updatePositionはユーザー関数

関数_updatePosition
mapの位置にあわせてdivの位置を移動。

関数onRemove
リスナーを削除し、divを削除

L.LeafletLayerTemplate = L.Layer.extend({

  initialize: function(options) {
    this._latLng = options.latLng;
  },

  onAdd: function(map) {
    this._map = map;
    var layerElementTag = 'div';
    var layerElementClasses = '.leaflet-layer-template leaflet-zoom-hide';
    this._layerElement = L.DomUtil.create(layerElementTag, layerElementClasses);
    map.getPanes().overlayPane.appendChild(this._layerElement);
    map.on('viewreset', this._updatePosition, this);
    this._updatePosition();
  },

  _updatePosition: function() {
    var position = this._map.latLngToLayerPoint(this._latLng);
    L.DomUtil.setPosition(this._layerElement, position);
  },

  onRemove: function(map) {
    map.getPanes().overlayPane.removeChild(this._layerElement);
    map.off('viewreset', this._updatePosition, this);
  }

});
L.leafletLayerTemplate = function(options) {
  return new L.LeafletLayerTemplate(options);
};

もちろん独自レイヤだからといって必ずしもdivを作成してdomを操作する必要もない。
L.Polygonなどを使用してレイヤの描画を行うのも正しい。

以下は500mメッシュを描画する独自レイヤ

leafletで地図上にラベルを表示

WMS、GeoJsonを使わずに地図上にラベルを表示する方法

leafletでラベルを表示するにはプラグイン Leaflet.labelを使う方法とL.divIconを使う2つの方法があるようだ。
※Leaflet.labelが今でも使えるかは不明。
今回はL.divIconを使う方法を採用。
参考Text labels in leaflet

var icon = L.divIcon({
						className: 'meshno',
						html: "123456789"
					});
var marker = L.marker(new L.LatLng(lat, lng), {icon:icon})
marker.addTo(this._map);

EventEmitterをちょっと改造

EventEmitterはDOMを使用せずにイベント機能をクラスに与えることが可能なとても便利なクラス。
但し最大の不満はListener登録時にListener内でのthisを指定できない点。
※バージョンは5.2.4

例)リスナーの登録

var eventEmitter = new EventEmitter();
・・・
eventEmitter.addListener('click', this.on_clicked.bind(this));

上記のようにListener登録してしまうとremoveListenerが正しく機能せずにListenerが残ってしまう。
例)リスナーの削除

eventEmitter.removeListener('click', this.on_clicked.bind(this));

これらの問題を対応するためにEventEmitterを以下に従って修正

addListenerの修正

変更前

proto.addListener = function addListener(evt, listener) {
    if (!isValidListener(listener)) {
        throw new TypeError('listener must be a function');
    }

    var listeners = this.getListenersAsObject(evt);
    var listenerIsWrapped = typeof listener === 'object';
    var key;

    for (key in listeners) {
        if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) {
            listeners[key].push(listenerIsWrapped ? listener : {
                listener: listener,
                once: false
            });
        }
    }

    return this;
};

変更後

proto.addListener = function addListener(evt, listener) {
    if (!isValidListener(listener)) {
        throw new TypeError('listener must be a function');
    }
    // tarumi custom
    var bind_instance = null;
    if(arguments.length > 2){
        bind_instance = arguments[2];
    }
    // tarumi custom

    var listeners = this.getListenersAsObject(evt);
    var listenerIsWrapped = typeof listener === 'object';
    var key;

    for (key in listeners) {
        if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) {
            listeners[key].push(listenerIsWrapped ? listener : {
                listener: listener,
                // tarumi custom
                instance: bind_instance,
                // tarumi custom
                once: false
            });
        }
    }

    return this;
};

関数:emitEventの修正

変更前

proto.emitEvent = function emitEvent(evt, args) {
    var listenersMap = this.getListenersAsObject(evt);
    var listeners;
    var listener;
    var i;
    var key;
    var response;

    for (key in listenersMap) {
        if (listenersMap.hasOwnProperty(key)) {
            listeners = listenersMap[key].slice(0);

            for (i = 0; i < listeners.length; i++) {
                // If the listener returns true then it shall be removed from the event
                // The function is executed either with a basic call or an apply if there is an args array
                listener = listeners[i];

                if (listener.once === true) {
                    this.removeListener(evt, listener.listener);
                }
                response = listener.listener.apply(this, args || []);

                if (response === this._getOnceReturnValue()) {
                    this.removeListener(evt, listener.listener);
                }
            }
        }
    }

    return this;
};

変更後

proto.emitEvent = function emitEvent(evt, args) {
    var listenersMap = this.getListenersAsObject(evt);
    var listeners;
    var listener;
    var i;
    var key;
    var response;

    for (key in listenersMap) {
        if (listenersMap.hasOwnProperty(key)) {
            listeners = listenersMap[key].slice(0);

            for (i = 0; i < listeners.length; i++) {
                // If the listener returns true then it shall be removed from the event
                // The function is executed either with a basic call or an apply if there is an args array
                listener = listeners[i];

                if (listener.once === true) {
                    this.removeListener(evt, listener.listener);
                }

if(listener.instance===null || listener.instance === 'null' || listener.instance === 'undefined' || listener.instance === undefined){
response = listener.listener.apply(this, args || []);
}
else{
response = listener.listener.apply(listener.instance, args || []);
}


                if (response === this._getOnceReturnValue()) {
                    this.removeListener(evt, listener.listener);
                }
            }
        }
    }

    return this;
};

リスナーの登録の変更

eventEmitter.addListener('click', this.on_clicked,this);

リスナーの削除の変更

eventEmitter.removeListener('click', this.on_clicked);

MySQLのストアド、トリガーなどをダンプ

ストアドとトリガーをダンプ

mysqldump -u ユーザー名 -p -h ホスト名 データベース名 --skip-dump-date --no-create-info --no-data --routines > ダンプファイル名

ストアドのみダンプ

mysqldump -u ユーザー名 -p -h ホスト名 データベース名 --skip-dump-date --no-create-info --no-data --routines --skip-triggers > ダンプファイル名

トリガーのみダンプ

mysqldump -u ユーザー名 -p --triggers --no-create-info --no-data -h ホスト名 データベース名 > ダンプファイル名
カテゴリー: MySQL