OmniAICreator/Qiita-1.07M huggingface dataset:
ZooKeeperの起動状態を調べるコマンド

『ZooKeeperを起動後、正しく起動したかを確認したい！！』
といった場合に使うコマンドを調べたのでメモしておきます。

なにはともあれドキュメントを確認します。
https://zookeeper.apache.org/doc/current/zookeeperAdmin.html

なんと `telnet` です。

```console
$ telnet localhost 2181
```

v3.4.0 以降は `mntr` が使える模様。便利。

```
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
mntr
zk_version      3.4.x-xxxxxx, built on xx/xx/xxxx xx:xx GMT
zk_avg_latency  xxxxxx
zk_max_latency  xxxxxx
zk_min_latency  xxxxxx
zk_packets_received  xxxxxx
zk_packets_sent xxxxxx
zk_num_alive_connections  xxxxxx
zk_outstanding_requests  xxxxxx
zk_server_state follower
zk_znode_count  xxxxxx
zk_watch_count  xxxxxx
zk_ephemerals_count     xxxxxx
zk_approximate_data_size        xxxxxx
zk_open_file_descriptor_count   xxxxxx
zk_max_file_descriptor_count    xxxxxx
Connection closed by foreign host.
```

こんな感じで出ます。

`zk_server_state` には leader とか follower が出てノードの状態が手軽に調べられます。

便利ですね。
しかしtelnetて。
Safari で Indexed DB の IDBCursor.onsuccess 引数のメモリに関する問題

# 概要

Safari において、Indexed DB 利用時に IDBCursor の onsuccess コールバック引数のプロパティ target.result を参照した場合、それが null でない場合に特殊なメモリリークが発生した。
上記条件下でブラウザページをリロードした場合、javascript オブジェクトがゾンビ化してメモリ領域に残り続ける。
オブジェクトはリロードの回数に応じて増え続けるため、メモリ圧迫によるブラウザページクラッシュを引き起こす可能性がある。
Chrome ではこの現象は確認できなかった。

尚、当該現象は既に Apple Bug Reporter を通じて報告済みである。

# 現象を確認した環境

- maxOS 10.12.6 / Safari 11.1.1
- iOS 10.3 / Safari
- iOS 11.4 / Safari

# 検証

検証用のサンプルコード。

https://github.com/dolow/safari-idb-memory-leak-sample

```js
// 正常に indexed db が接続できているとする
var transaction = openRequest.result.transaction([storeName], 'readwrite');
var store = transaction.objectStore(storeName);

// 何かレコードを保存していないと、後述のプロパティが null となる
store.put(key, 1);

store.openCursor().onsuccess = function(e) {

    // 1. e.target.result が null の場合
    // var result = e.target.result;

    // 2. e.target.result が null ではない場合
    // var result = e.target.result;
    
    // 3. e.target の参照のみ行う
    // var target = e.target;
    
    // 4. e.target の参照のみだが関数内で展開
    // console.log(e.target);

};
```

## 結果

|case|result|
|----|----|
| 1. e.target.result が null の場合 | リロードによるリークは発生しない |
| 2. e.target.result が null ではない場合 | リロードでリークする |
| 3. e.target の参照のみ行う | リロードによるリークは発生しない |
| 4. e.target の参照のみだが関数内で展開 | リロードでリークする |

## 考察

通常の Webページ/サービスであれば対して問題になりにくいが、大きなバイナリなどを扱うページの場合はクラッシュのリスクが高い。
メモリ解放手段としてページのリロードが行われることもあるが、この不具合が発生する条件下では逆効果である。

# 対応方法 (暫定)

カーソルの用途はいくつかあるが、全てのレコードをイテレートする可能性のある処理を行うものと仮定した場合、`getAllKeys` 及び `getAll` が代替となる。
`getAll` 等は indexeddb2 の仕様であり、比較的新しいバージョンのブラウザでのみサポートされている。

W3C
https://www.w3.org/TR/IndexedDB-2/
caniuse
https://caniuse.com/#feat=indexeddb2

## 対応例 1

```js
var allKeys;
var allValues;

objectStore.getAllKeys().onsuccess = (event) => {
    allKeys = event.target.result;
};
objectStore.getAll().onsuccess = (event) => {
    allValues = event.target.result;
};

...

for (var i = 0; i < allKeys.length; i++) {
    const key = allKeys[i];
    const val = allValues[i];
    doSomething(key, value);
}
```

### この対応の問題点

- 全てのキーと値がメモリ上に載る
- `getAllKeys` と `getAll` の結果 (`event.target.result`) の並び順が保証されている前提である

## 対応例 2

```js
var allKeys;
objectStore.getAllKeys().onsuccess = (event) => {
    allKeys = event.target.result;
};

...

for (var i = 0; i < allKeys.length; i++) {
    const key = allKeys[i];
    objectStore.get(key).onsuccess = (event) => {
        const value = request.result;
        doSomething(key, value);
    };
}
```

### この対応の問題点

- 全てのキーがメモリ上に載る
- キー毎にDBを読むのでパフォーマンス面での懸念が多い


# おまけ

始めて見た時はひいた。
window はいいけど、その下の ArrayBuffer, AudioBuffer がヤバい。

<img width="1280" alt="omake.png" src="https://qiita-image-store.s3.amazonaws.com/0/42873/fc38a58c-7b88-2d4f-2807-88eb03cf2ff3.png">
Matter.jsを触ってみました。

今日は、JavaScriptの2次元グラフィックスの物理演算ライブラリ、Matter.jsを初めて触りました。ブラウザ上で動作します。
覚書として。(2018/7/5)

#Matter.js
公式サイト
http://brm.io/matter-js/

ダウンロード（リリースビルド）
https://github.com/liabru/matter-js/releases

#動作させた環境
##jsdo.it
コードをシェアする必要があったため、オンライン開発環境のjsdo.itを使って動かしました。
##その他
###ボタンの表示
HTMLのinputタグでボタンを表示させたものと、enchant.jsを使って表示させたものの2パタンをテストしました。
どちらも「クリックしたらボールが落ちる」という動作に関しては問題なく行えました。

#参考記事
物理演算エンジン、Matter.jsを使ってみた。
https://qiita.com/yhikishima/items/ed77a4d869bc3bda9bc2

#サンプルコード
今回は、Matter.js + enchant.jsのバージョンを載せます。

##HTMLプログラム
Matter.jsとenchant.jsをライブラリとして追加しました。enchant.jsはjsdo.itでライブラリとして登録されているのでメニューから選択するだけです。Matter.jsは別プロジェクトとしてライブラリを一旦アップしておき、それを追加しました。

```html
<div id='enchant-stage'></p>

```


```javascript

enchant();

window.onload = function() {

    // Matter.jsの変数
    var Engine = Matter.Engine;
    var World = Matter.World;
    var Bodies = Matter.Bodies;
    
    // Matter.js エンジン作成
    var engine = Engine.create(document.body);
    
    // 二つの箱と地面を作成しWorldに追加
    var boxA = Bodies.rectangle(200, 200, 20, 20);
    var boxB = Bodies.rectangle(100, 100, 40, 40);
    var ground = Bodies.rectangle(160, 300, 320, 20, { isStatic: true });
    World.add(engine.world, [boxA, boxB, ground]);
    
    // Matter.js エンジン起動
    Engine.run(engine);

    // ボタンをenchant.jsで作る
    var game = new Game(320, 40);    
    game.onload = function() {    
        // ボタン生成とgame画面への追加
        var button = new Label("ここをクリック！");
        button.x = 10;
        button.y = 5;
        game.rootScene.addChild(button);

        // ボタンがクリックされたとき
        button.addEventListener('touchend', function()
        {
            // 四角を追加
            var box = Bodies.rectangle(200, 0, 20, 20);
            World.add(engine.world, [box]);
        });    
    };
    // enchant.js起動
    game.start();
  
};

```
KVMで使うブリッジをOpenvSwitchにしてみた

KVMで使用するスイッチをLinux標準のブリッジからOpenvSwitchに変更して、外部と接続してみました。
その手順を備忘録として記します。
また、KVMの環境で１つ以上のVMが存在していることを前提とし、VM作成の説明は省きます。VMの作成方法がわからない方はこちら→[CentOS7でKVMを使って仮想マシンをつくってみた](https://qiita.com/wslife/items/502b17a2eb2bedc89447)を参考にしてみてください。

#完成イメージ
![ovs-kvm.jpg](https://qiita-image-store.s3.amazonaws.com/0/173064/19a89a43-9852-98e8-f8a9-927869d09305.jpeg)

#環境
- Host CentOS 7.5
- openvswitch 2.0.0

#手順
##パッケージのインストールと起動
まずは、OpenvSwtichのインストールとデーモンの起動をさせましょう。
最新版のものを触りたのであれば、ソースからインストールするんのがいいでしょう。方法はネット上に転がっていると思うので、ここでは説明しません。

```
# yum install -y openvswitch python-openvswitch
# systemctl start openvswitch
# systemctl enable openvswitch
```

##ブリッジの作成
ブリッジの作成は`ovs-vsctl add-br`コマンドでもできますが、ここではスクリプトに直接書き込みます。
xxの部分は自身の環境に合わせてください。

```
# vi /etc/sysconfig/network-scripts/ifcfg-ovsbr0　　// 以下のように書き込みます

DEVICE=ovsbr0
NAME=ovsbr0
ONBOOT=yes
BOOTPROTO=none
DEVICETYPE=ovs
TYPE=OVSBridge
IPADDR=192.168.0.1
NETMASK=255.255.255.0
GATEWAY=xx.xx.xx.xx
DNS1=xx.xx.xx.xx

# systemctl restart network  // 設定を反映させる
```

##ブリッジとホストのインターフェースを結びつける

```
# ovs-vsctl add-port ovsbr0 eno1
```

ブリッジとホストのインターフェースがちゃんと結びついていれば、以下のような出力が得られます。

```
# ovs-vsctl show
2dc06fcd-3735-4498-a963-3642d7e662d4
    Bridge "ovsbr0"
        Port "ovsbr0"
            Interface "ovsbr0"
                type: internal
        Port "eno1"
            Interface "eno1"
    ovs_version: "2.0.0"
```

##VMのネットワーク設定を編集
既存のVMのネットワーク設定を変更して、`ovsbr0`に接続して、外部と通信できるようにしましょう。
編集する部分は、先頭に「***+***」がついている部分です。
ちなみに、`vi`や`nano`で直接ファイルを編集しても変更は反映されません。

```
# virsh edit vm
+ <interface type='bridge'>
     <mac address='52:54:00:6c:4a:50'/>
+    <source bridge='ovsbr0'/>
+    <virtualport type='openvswitch'>
     <model type='virtio'/>
     <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> 
 </interface>
```

一旦保存終了してから、また開くと以下のようにパラメータが追加されています。

```
 <interface type='bridge'>
     <mac address='52:54:00:6c:4a:50'/>
     <source bridge='ovsbr0'/>
     <virtualport type='openvswitch'>
+       <parameters interfaceid='97233b2f-b55a-4a48-b6f0-cb254854ed39'/>
+     </virtualport>
     <model type='virtio'/>
     <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> 
 </interface>
```

##確認
以上で設定が終わったので、vmが`ovsbr0`と接続されているか、確認してみましょう。

```
# virsh start vm　　// vmの起動
# ovs-vsctl show
2dc06fcd-3735-4498-a963-3642d7e662d4
    Bridge "ovsbr0"
        Port "ovsbr0"
            Interface "ovsbr0"
                type: internal
        Port "eno1"
            Interface "eno1"
        Port "vnet0"             // ←が追加されているので成功！
            Interface "vnet0"
    ovs_version: "2.0.0"
```

#参考
- [KVM環境で、OpenvSwitchでゲストVMを外部ネットワークと接続するメモ
](https://qiita.com/kure/items/8645c28cba67aae49519)
Office365 Homeを購入・インストールする方法

<p><a href="https://www.e-soft.net/products/detail/4">Office365 Home</a>は、Microsoftが家庭向けに提供しているサブスクリプション型サービス。</p>
<p>今回、Office365 Homeを日本で購入して、インストールする方法についてご紹介します。</p>

![normal.jpg](https://qiita-image-store.s3.amazonaws.com/0/217125/0443c54b-e96c-10c9-ee25-ce95f978c384.jpeg)

<h2>Office365 Homeの購入</h2>

<p>Office 365 Home は、マイクロソフトが、中国向けに提供しているサブスクリプション版の家庭向けサービスですが、日本でも購入して、インストールできます。</p>
<p>Office 365 Home で使える機能は主に以下の通り：</p>
<p>1アカウントにつき5台までのWindowsまたはMacでインストール可能<br>
Office 2016バージョンのWord、Excel、PowerPoint、OneNote、Outlook、Publisher、Accessが利用できる<br>
オンラインストレージ「SkyDrive」の容量20GB<br>
毎月60分通話できるSkype通話プランが付帯</p>
<p>Office365 Homeは日本のMicrosoft公式サイトで発売されていないが、Amazonとネットショップから安く購入できます。</p>
<p>Microsoft公式サイトでは年額99.99ドルで発売されていますが、約11,000円になります。ネットショップからは年単位で9,800円の激安価格で契約できます。</p>
<h2>Office365 Homeをインストールする方法</h2>
<p>Office 365 Homeをパソコンにインストールする場合は、マイクロソフトアカウントページ へサインイン、VPNに接続してから、プロダクト キー入力し、言語を日本語に変化する必要があります。</p>
<p>手順1：<a href="https://officesetup.getmicrosoftkey.com/">https://officesetup.getmicrosoftkey.com/</a>にアクセスして、「サインイン」をクリックします。Microsoft アカウントをお持ちでないユーザーは、「新しいアカウントの作成」をクリックします。</p>
![office365home01.jpg](https://qiita-image-store.s3.amazonaws.com/0/217125/466c62e6-28bc-0bad-0a0b-630aa476f8fd.jpeg)

<p>手順2：パスワードを入力して「サインイン」をクリックします。</p>
![office365home02.jpg](https://qiita-image-store.s3.amazonaws.com/0/217125/1d745074-292f-a280-ed02-495ad6204c2e.jpeg)
<P>手順3：VPNで接続先を中国に設定する.香港(Hong Kong)VPNでもOK.</p>
<p>手順4：25文字のプロダクトキーを入力、言語の設定のページになりますが、そこでは日本語はありませんのでとりあえず中国語にしておく。「次へ」をクリックします。</p>

![office365home03.jpg](https://qiita-image-store.s3.amazonaws.com/0/217125/6af0e981-ba9f-d863-abfd-f9453bd47490.jpeg)
<p>手順5：また「次へ」をクリックします。</p>
![office365home04.jpg](https://qiita-image-store.s3.amazonaws.com/0/217125/be60d259-d436-f640-c66e-04b03d406c81.jpeg)
<p>手順6：［インストール］をクリックします。</p>
![office365home05.jpg](https://qiita-image-store.s3.amazonaws.com/0/217125/15add852-93c9-5f25-a23e-5b46788d577e.jpeg)
<p>手順7：［言語とインストールオプション］から日本語を選択して［インストール］をクリックします。</p>
![office365home06.jpg](https://qiita-image-store.s3.amazonaws.com/0/217125/ce90af55-4306-186d-f50d-4f39fcba728c.jpeg)
<p>手順8：インストーラ実行<br>
続いて画面に表示される指示に従います。 </p>
![xoffice365home07.jpg.pagespeed.ic.LOdt2ZFoEb.jpg](https://qiita-image-store.s3.amazonaws.com/0/217125/5a2172fe-ff7a-0f23-ca6c-d1336b4ec868.jpeg)
<p>途中の手順を省略しました。 </p>
<p>手順9：最後に、ダウンロードが完了すると、次の画面が表示されます。「閉じる」をクリックします。　</p>
![office365home08.jpg](https://qiita-image-store.s3.amazonaws.com/0/217125/3d8d992b-2ff3-a23c-4a80-805a9a6553c9.jpeg)
ネットワーククライアント上でのRepnotifyとBeginPlayのタイミング

鈴木です。
マルチプレイクライアント上でのBeginPlayやPostInitComponentの呼び出しタイミングはシングルプレイ時と差があり
マルチプレイを考慮していないといろいろな問題が出たり出なかったりします。

#シングルプレイ時の処理順序
- アクターのSpawnリクエスト
- SpawnActor
- (DeferConstruction)
    - ユーザー初期化コード
- PostActorConstruction
- PreInitComponent
- PostInitComponent
- BeginPlay



#マルチプレイ時の処理順序
マルチプレイ時はパケット受信後にそのオーダーに合わせて初期化が行われます。
DeferConstructionは処理できません
**注目すべきはプロパティのストア位置とRepNotifyがBeginPlayの前に呼ばれることと、SpawnParamterなどのプロパティ適用がPostInitComponentなどの後に行われうことです。**

- パケット受信
- SpawnActor
- PostActorConstruction
- PreInitComponent
- PostInitComponent
- ReceiveBunch
    - **プロパティをアクターにストア**
    - RepNotifyを処理  
- PostNetInit
    - BeginPlay

このような流れになっています。シングルプレイやAuthorityを持っているプロセス上では初期化処理はストレートに行われますが、
クライアントではBeginPlayの前にさまざまなユーザーコードが実行される余地があるため問題が発生しやすいです。
この流れを考慮してあるとスムーズにマルチプレイゲームが構築できるかもしれません。

#BeginPlay前のRepNotifyについて

RepNotifyがBeginPlayなどに依存する場合、正しく処理できない可能性があります。
コールバック関数が呼び出される前にユーザーコードを挟む余地があれば初期化等をおこなって正しく処理出来そうです。
RepNotifies処理部近辺を探してみるといいのがありました

```c++

void FObjectReplicator::PostReceivedBunch()
{
...
	if (!bIsServer && bHasReplicatedProperties)
	{
		PostNetReceive();  <----------------------------
		bHasReplicatedProperties = false;
	}
...
	// Call RepNotifies
	CallRepNotifies(true);
```

これだよこれ。
`virtual void UObject::PostNetReceive()`

こいつで初期化コードを処理すればいい感じ。


**ただしAutorityやシングルプレイ時には呼び出され無いので注意が必要です**

このあたりはBlueprintだと対処しにくいかもしれません。


糸冬
複数AWSアカウントのCodeCommitからgit cloneする際のsubmodule対応

[前回の記事](https://qiita.com/SpeakEasy/items/e92a494a3f6a5f81a74c)の続き。
前回は「複数AWSアカウントのCodeCommitからgit cloneする際のssh設定」について記載したが、今回はcloneするリポジトリがsubmoduleを含んでいた場合の対応について。

## 何もせずsubmodule updateした場合
1. 前回の記事に記載した通り、複数AWSアカウントのssh設定を行う
2. 設定した接続先aws1からリポジトリをcloneする
3. cloneしてきたディレクトリに移動し、submoduleをチェックアウトする

``` :git_submodule
cd  test_app            # 移動
git submodule init      # ローカルの設定ファイルを初期化
git submodule update    # プロジェクトからのデータを取得し、親プロジェクトで指定されている適切なコミットをチェックアウト
```

この時、こんな感じのエラーが吐き出されます。

```
Cloning into '/Users/speak-easy/Documents/workspace/test/test_lib'...
speak-easy@git-codecommit.ap-northeast-1.amazonaws.com: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
fatal: clone of 'ssh://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/test_lib' into submodule path '/Users/speak-easy/Documents/workspace/test/test_lib' failed
Failed to clone 'test_lib'. Retry scheduled

Cloning into '/Users/speak-easy/Documents/workspace/test/test_lib'...
speak-easy@git-codecommit.ap-northeast-1.amazonaws.com: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
fatal: clone of 'ssh://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/test_lib' into submodule path '/Users/speak-easy/Documents/workspace/test/test_lib' failed
Failed to clone 'test_lib' a second time, aborting
```

エラーは***『ssh://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/test_lib』がsubmoduleとして登録されてるけど公開鍵間違ってるぞ***って意味ですね。
なんでそんなエラーが出るかというと、~/.ssh/configに接続名が`git-codecommit.ap-northeast-1.amazonaws.com`の設定がないからです。

## submoduleの接続先設定
なのでsubmoduleのURLの一部も、cloneする時と同じように設定した接続名aws1に置き換えればOK。
submoduleのURLの書き換え手順は下記の通り。

1. git cloneしたディレクトリに移動し、.git/configを開く
2. .git/configの中にsubmoduleのpathが書かれた行があるので、pathの一部を~/.ssh/configに設定した接続名に置き換える

```:.git/config
[submodule "test_lib"]
        active = true
      # url = ssh://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/test_lib
                        ↓
        url = ssh://aws1/v1/repos/test_lib
```

置き換えた後、改めて`git submodule update`すると無事submoduleがcloneされてきました。

## 参考サイト
下記サイトを参考にさせていただきました。

[http://nobollel-tech.hatenablog.com/entry/2016/12/31/190000](http://nobollel-tech.hatenablog.com/entry/2016/12/31/190000)
centos7~のNIC ネットワークデバイス名の変更

#CentOS7から標準でデバイス名の割当がeth0から変わってる
es@abcのように割り当てられるようになった

@はデバイスの種類を表し　o:オンボード　p:pci
abcはnicの固有値なのでmacによって決められる

##運用面で使い勝手が悪いので今までのeth0に変更する

現状のデバイス名を確認する
`ifconfig -a`

**esp123**がデバイス名だった場合

1 カーネル起動時の変更
grubの編集

`vim /etc/default/grub`
net.ifnames=0 biosdevname=0を追記する。
`GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet net.ifnames=0 biosdevname=0"
`

編集後、内容を反映するためにコマンドを実行する。
`grub2-mkconfig -o /boot/grub2/grub.cfg`

以下のような文が表示され、最後にdoneと表示されればよい。

`Generating grub configuration file ...
Found linux image: /boot/vmlinuz-3.10.0-693.el7.x86_64
Found initrd image: /boot/initramfs-3.10.0-693.el7.x86_64.img
Found linux image: /boot/vmlinuz-0-rescue-9346d04a2bfa47d89e7523247656d127
Found initrd image: /boot/initramfs-0-rescue-9346d04a2bfa47d89e7523247656d127.img
done`

2 NICの設定ファイルの変更
NICの設定ファイル名の名前を変更する。
`mv /etc/sysconfig/network-scripts/ifcfg-`**enp123**` /etc/sysconfig/network-scripts/ifcfg-eth0`

ファイルを開き、ens33の部分を2箇所eth0に変更する。
`vim /etc/sysconfig/network-scripts/ifcfg-eth0`

3 設定反映
再起動するとNICのデバイス名が変更される。
`shutdown -r now`
Azure Sphere の開発用ボード買いました

正確に言うと購入予約？

購入先などの情報はここに書きました
https://qiita.com/motoriderse/items/78bbf6bc9edd78c431bb

念のためにエビデンス
![Untitled1.png](https://qiita-image-store.s3.amazonaws.com/0/262079/a8bc069d-df53-d699-0dd5-c042125a3e77.png)
![Untitled2.png](https://qiita-image-store.s3.amazonaws.com/0/262079/f5ba1809-b557-eada-7223-0c838b241cee.png)

住所入力がわからない人の為にメモ
![Untitled3.png](https://qiita-image-store.s3.amazonaws.com/0/262079/36fa6928-58ea-421b-830d-34a078d62b8a.png)

ちなみにpaypal使えます。
5ドルと表示されていますが、これはデポジット（手付金）で
予約の預かり金みたいなもんです。
実際には$84.9ドルらしく
出荷可能になったころに購入意思を確認する連絡があるそうです。
その際にキャンセルした場合はデポジットは返却すると書いてました。
小規模な業務システムを Azure SQL で遠隔地共有する理由

#小規模な業務システムを遠隔地で共有する方法について
業務システムを共有する場合には、ネットワーク環境によってかかえている問題点が違います。

ここでは、ローカルネットワーク(LAN)共有ではなく、離れた場所（遠隔地）間で業務システムを共有する方法につて説明します。

##運用環境について
遠隔地間で業務システムを共有するには、遠隔地間のネットワーク(WAN)環境が必要です。
インターネットで共有する Drop Box や One Drive などでは、フォルダを共有しているだけで、業務システムのデータベースを共有することはできません。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/93227/ea04c9ed-fe60-b5fb-f2b8-c3330ed217c8.png)


私たちは、インターネット環境があれば、遠隔地でも業務システムのデータベースを共有できる仕組みを作成いたしました。

##運用コストについて
遠隔地間で業務システムを共有するには、専用 VPN 回線という方法と、リモートデスクトップという方法が多く使われています。

専用 VPN 回線を利用すると、遠隔地間のネットワーク(WAN)をローカルネットワーク(LAN)と同じ方法で利用できますが、利用コストが高額になります。

また、リモートデスクトップで業務システムを共有するには、サーバー運用の専門知識が必要になります。社内にサーバー管理技術者をかかえるか、サーバー運用を外部委託することになります。そのため、サーバーの管理費用が高額になります。

私たちは、このような問題を Azure SQL データベースを利用して解決しました。
ローカルに Windows Server を設置する必要は、ありません。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/93227/442bcddc-41a7-30b8-6943-9640c4b5f0bf.png)


##活用するアプリケーションについて
業務システムには、活用すると有益なデータが、多く登録されています。
そのため、業務システムのデータを活用するための要望が絶えません。

そのような要望にお応えするために、私たちは、Access と Excel を使って業務システムを作成しました。
Access と Excel を使うことにより、ユーザーは、Excelの関数やAccessのクエリーを使って自由にデータを活用することができます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/93227/c059686d-f90d-0237-54b0-32d66eccbd33.png)


##スマホとの連携について
近年では、外出していても WiFi環境が自由に使えるようになり、社員の方が「外出先から、データを閲覧したい」という要望も多くいただきます。

このようなご要望にお応えするには、Office 365 の PowerApps を勧めています。

PowerApps では、プログラムコードを書かなくても、簡単に Azure SQL データベースを表示したり、することができます。

<img src="https://qiita-image-store.s3.amazonaws.com/0/93227/75c8ffd2-47c8-271f-a4bd-65190629e271.png" width=60%>


##ホームページとの連携について
注文商品の配達状況や納品した製品の検査成績表の発行など、ユーザーがいつでも手軽に操作できるようにするには、業務システムとホームページを連携する必要があります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/93227/442bcddc-41a7-30b8-6943-9640c4b5f0bf.png)

私たちは、ホームページと業務システムの連携が可能な、Azure SQL データベースを採用ししています。

#AccessとExcelを連携してクラウドシステムを作成する
データベースをAzure SQL にセットして、AccessやExcelのプログラムから データベースを遠隔地間で共有するシステムを公開しています。

[<img src="https://qiita-image-store.s3.amazonaws.com/0/93227/1e640f8b-edfd-2b4e-aafe-ce96a835dd7b.png" width=70%>](http://access-cloud.hatenablog.com/entry/database)
http://access-cloud.hatenablog.com/entry/database
flowtypeでconstantsからEnumっぽいUnion型を生成する

下記のようなconstantsがあったとする。

```javascript
const COLORS = {
  WHITE: 'white',
  BLUE: 'blue',
  BLACK: 'black',
  RED: 'red',
  GREEN: 'green',
};
```

このconstantsから

```javascript
type ColorTypes = 'white' | 'blue' | 'black' | 'red' | 'green';
```

こんなUnion型が生成したかった。調べてみるとちょっと汚いが方法はあった。

```javascript
/* @flow */

const COLORS = Object.freeze({
  WHITE: 'white',
  BLUE: 'blue',
  BLACK: 'black',
  RED: 'red',
  GREEN: 'green',
});
type ColorsType = $Values<typeof COLORS>;

const Bad: ColorsType = 'yellow'; // error
const Good: ColorsType = 'white'; // ok
```

これでいける。良い感じ。

ちなみにconstantsとtypeが別ファイルだと機能しなくなる。

```javascript
export const COLORS = Object.freeze({
  WHITE: 'white',
  BLUE: 'blue',
  BLACK: 'black',
  RED: 'red',
  GREEN: 'green',
});
```

```javascript
import { COLORS } from './constants';

type ColorsType = $Values<typeof COLORS>;

const Bad: ColorsType = 'yellow'; // ok
const Good: ColorsType = 'white'; // ok
```

おそらく`Object.freeze`でimmutableであることを同一ファイル内じゃないと認識できないっぽい。
(2018年度版)vagrantでrailsの環境構築してみた(windows,mysql)

# Ruby on Railsをvagrantで動かすまで
メモ書きです。
不具合が起こった場合は責任取れません。笑
## ホストOS側
- windows10
- vagrant 2.1.2
- VirtualBox バージョン 5.2.12



## 作る環境
- vagrant box(bento/centos-7.3)
- ruby 2.5.1
- rails 5.2.0

## 大まかな流れ
1. virutalboxをインストール
2. vagrantをインストール
3. vagrant boxをダウンロード
4. vagrantfileを編集
5. vagrant up
6. rubyもろもろインストール
git reset 解説

git reset コマンドは、初心者が一番訳が分からないところでしょうか。
このコマンドで色んなことが出来るので、どういう場合にどう使えばいいのか混乱してしまいます。

でも実は、非常にシンプルな動作をしているのです。

# git の仕組み

git resetを理解する為に、まずgitの仕組みを抑えておきます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/120192/a9a384bb-f825-f435-2909-888e09f57853.png)

developブランチをチェックアウトした状態で、Bのコミット直後を表しています。

| 項目 | 説明 |
|---|---|
|develop|checkout中のブランチ|
|A, B|コミットデータ|
|INDEX|git add で登録される領域。この内容がコミットとして登録されます。|
|ワーキングツリー|編集対象のローカルのファイルやディレクトリ|

developからワーキングツリーまで縦に並んでいるのは、これらが一致しているということを表しています。

**参考：ブランチの真実**
ブランチは日本語で「枝」になりますが、gitのブランチはコミットを１つしか持ちません。

ブランチは、どのコミットから始まったかという情報を持っておらず、
あくまでも１コミットに付けられた「別名」に過ぎないのです。


## ワーキングツリーを編集
developブランチをcheckoutして、ファイルを編集した状態です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/120192/6ac937dc-2db9-235e-c241-4bf7e1c3c69b.png)

ワーキングツリーのみ先に進んでいます。

## git add で登録
ワーキングツリーの内容を git add で全て登録した状態です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/120192/227c58ed-5a2c-e4e9-b1cf-9cde6b038a02.png)

INDEXも進みました。

## git commit
INDEXに登録されている内容をコミットした状態です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/120192/aade00b7-ef70-4386-fa41-7bc289d8cd48.png)

INDEXは、コミットした後も同じ内容で保持されます。

# git reset の動き
git reset コマンドは、checkout中のブランチを指定コミットに紐づけ直すという動作をします。

## 直前のコミットを取り消したい場合

Cをコミットした状態から以下コマンドを実行します。
```$ git reset HEAD^```

HEADは、checkout中のブランチに紐づいており、つまりはコミットの「別名」にもなります。
 ^ は、その１つ前のコミットを表すので、HEAD^はBコミットを表します。

コマンド実行後
![image.png](https://qiita-image-store.s3.amazonaws.com/0/120192/8da65ff7-ed0f-85b1-6dfd-2def4fae19fb.png)

HEADとHEADが紐づくブランチ(develop)がBコミットに移動します。
INDEXにもBコミットの内容が反映されます。
ワーキングツリーは変化しません。

これによって、Cのコミット直前に戻ることになります。

## ブランチのコミットを全て取り消したい場合
例えば、masterブランチからdevelopブランチを作成してコミット作業を進めていたけど、それらを全て取り消したい、という場合。

```$ git reset --hard master```
とします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/120192/e0ade3ab-9a43-3008-62c6-f6e4bf2fb872.png)

master = Aコミットの場合です。

これも同様に、developブランチがmasterブランチと同じコミットに紐づけられる動作です。
INDEXもAコミットの内容が反映されます。

そして、--hard オプションにより、ワーキングツリーにも反映されます。

## git add を取り消す場合

git add で登録したこの状態から、
![image.png](https://qiita-image-store.s3.amazonaws.com/0/120192/a84b9ee6-2960-1110-b69a-28849b1d40f0.png)

```$ git reset```
とすると。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/120192/8ad95514-417e-cff0-0247-f6a945988b0f.png)

となります。

これは、
```$ git reset```

こう書いたのと同じです。
```$ git reset HEAD```

Bコミットに紐づいている状態から、同じBコミットに紐づけ直すだけなのですが、
その際にINDEXがBコミットの内容で再生成されることで、結果として、git addで登録していた内容がキャンセルされる、
ということになります。
【雑ネタ】英語キーボードから日本語キーボードに切り替える方法

# コンソール上の入力文字列が英語キーボードで入力された場合
そんな困ったときは以下のコマンド入力すると暫定的に解決されます。
お急ぎの時にどうぞ！ #自分自身のためにもw

コマンドはLinuxディストリビューション全般に対して有効ですが、
対象はあくまでコンソール接続からのCUIだけですのでご注意を…

```bash:コマンド内容
loadkeys jp106

```
ShibbolethとかOpenAMとかの記事も更新したいなぁ…
ドロップされたファイルをフォルダで包むDroplet（AppleScript）

概要
===

- フォルダに包まれたファイル
- 包まれてない素のファイル

が混在したフォルダを整理しようかなと思ったけど
いちいち 新規フォルダ作成→リネーム→ファイル投げ込む　とやるのが面倒になり
懐かしのdropletを作成してみた次第。

AppleScript、まとまった情報が残ってないので残しときます。

作り方
====

`/Applications/Utilities/Script\ Editor.app`を起動して、
適当に書いて、
アプリケーションとして保存、
とするとドロップレットのできあがり。

やること
===
1. ドロップされたファイル（複数）について
2. 拡張子を取り除いた名前で新規フォルダを作成し
3. そこにファイルを移動

当然ながら、同名のファイル／フォルダは存在できないので、必要があれば一時的なファイル名で作って逃げる

ソース
===

```applescript

on open objects
	tell application "Finder"
		repeat with obj in objects
			
			-- get name of folder to filename without extension, or same as filename
			set AppleScript's text item delimiters to "."
			set nameElements to every text item of (name of obj as string)
			set lastElementIndex to count nameElements
			if lastElementIndex > 1 then
				set folderName to (items 1 thru (lastElementIndex - 1) of nameElements) as string
			else
				set folderName to (name of obj as string)
			end if
			
			-- check same name exists
			set folderPath to ((folder of obj as string) & folderName)
			if not (exists folderPath) then
				
				-- create folder
				set newFol to make new folder at (folder of obj) with properties {name:folderName}
				
				-- move to it
				move obj to newFol
				
			else
				
				-- generate tmp foldername
				set tmpName to ""
				repeat 21 times
					set tmpName to tmpName & some item of "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
				end repeat
				
				
				-- create folder
				set newFol to make new folder at (folder of obj) with properties {name:tmpName}
				
				-- move to it
				move obj to newFol
				
				-- rename folder
				set (name of newFol) to folderName
			end if
			
			
		end repeat
	end tell
end open

on run
	display alert "Dropped would be embedded with folder"
end run
```
構文

#switch文（条件分岐）
```js
switch(num){
  case 1:
   alert('xxx');
   break;
  case 2:
   alert('yyy');
   break;
}
```
#if文

```js
if(num == 3){
  alert(num);
}
```
```js
if(num == 3){
  alert(num);
}else{
  alert(num+"は3ではない");
}
```
（「else」で「それ以外では」と分岐する）

```js
if(num == 3){
  alert(num);
}elseif(num == 5){
  alert(num+"は５です");
}
```
（「elseif」は特定の条件付きで分岐する）

#while文（繰り返し）

```js
var i = 0;
while(i < 1000){
 alert(i);
 i++;
}
```
（iに0を代入。iが1000未満なら、iの中身を表示して、インクリメントで１を足す。...を繰り返す。）

#for文（繰り返し）
```js
for(var i = 1;i < 1000;i++){
 alert(i);
}
```
（while文よりコンパクト）

#まとめ
条件を分けて処理を変えたい場合はif文、繰り返し処理をやりたい場合はfor文で。

>[ウェブカツ！！](https://webukatu.com/?afid=p5lxu1kvh03rayd2ctjsw4e9bgzq8nom)
RamdaJS の Boolean の反転

```js
const data = {active: false};
const isInactive = R.compose(
  R.not,
  R.propEq('active', true)
);
// not(propEq('active, true, data))

console.log(isInactive(data)); // true

const do = R.compose(...);
const doWhenInactive = R.when(isInactive, do);

doWhenInactive(data);
```
Python3で特定の条件のファイルを再帰的に取得してzipにする

# はじめに

jupyter notebookでデータを作成した後、PCに転送する場合、複数ファイルをzipにして送りたいことがよくあります。

pythonでzipファイルを作成したかったのですが、shutil.make_archiveを使うと.ファイルなどのゴミが入ってしまいます。
なので、必要なファイルのみフィルタできないかなと思い作成しました。

# ソース

```python
import fnmatch
import zipfile
import os

def make_filter_func(pattern_list, match):
    if type(pattern_list) == str:
        pattern_list = [pattern_list]
    if type(pattern_list) != list:
        return None
    
    def _filter_func(f):
        for p in pattern_list:
            if fnmatch.fnmatch(f, p):
                return match
        return not match

    return _filter_func

def get_file_tree(path, archive_list, ignore_list):
    filter_func = lambda x:True
    dfilter_func = filter_func
    
    if archive_list is not None:
        filter_func = make_filter_func(archive_list, True)
    elif ignore_list is not None:
        filter_func = make_filter_func(ignore_list, False)
        dfilter_func = filter_func

    for root, dirs, files in os.walk(path):
        yield from (os.path.join(root, f) for f in files if filter_func(f))
        filtered_dirs = [d for d in dirs if dfilter_func(d)]
        dirs.clear()
        dirs.extend(filtered_dirs)

def make_archive(path, archive_list=None, ignore_list='.*'):
    path_len = len(path)
    with zipfile.ZipFile(path + '.zip', 'w', compression=zipfile.ZIP_DEFLATED) as zip_f:
        for f in get_file_tree(path, archive_list, ignore_list):
            zip_f.write(f, arcname=f[path_len + 1:])
```

# 使い方

指定したディレクトリをzip化します。
デフォルトで.ファイルは無視します。

make_archive(path, archive_list, ignore_list)

path zip化したいディレクトリ名。同じディレクトリにhoge.zipを作成します。
archive_list 格納したいパターン。複数の場合はリスト指定
ignore_list 格納したくないパターン。複数の場合はリスト指定

archive_listとignore_list同時に指定した場合は、ignore_listは無視します。

ignore_listはディレクトリ名もマッチします。

よかったら使ってくださいね。
Word2Vecのお試しのための最小構成

Ubuntu 16.04で試しました。

[Kyubyong/wordvectors: Pre-trained word vectors of 30+ languages](https://github.com/Kyubyong/wordvectors)から[Japanese (w)](https://drive.google.com/open?id=0B0ZXk88koS2KMzRjbnE4ZHJmcWM)を選んでダウンロードする。

```bash:
pip3 install gensim
```

pip3が無いよって怒られるひとは

```bash:
sudo apt-get install python3-pip
```

以下のスクリプトを実行して動作確認。

```bash:
python3 sample.py
```

```python:sample.py
from gensim.models import word2vec

model = word2vec.Word2Vec.load("./ja/ja.bin") # これはダウンロードしたやつ
print(model.corpus_count)

results = model.wv.most_similar(positive=['東京'], negative=["金"])
for result in results:
    print(result)
```
You must pass the 'pipelineProposal' option to @babel/preset-stage-0 が出た時の対処法

なんとなくBabelのversionを`v7.0.0-beta.52`に上げた時にエラー出たのでメモがてらあげてみた。

詳しくはこちらのコミット↓

https://github.com/babel/babel/commit/eac4c5bc17133c2857f2c94c1a6a8643e3b547a7#diff-379134545f266d8c7cf202310391736e

```json
  "presets": [
    [
      "@babel/preset-stage-0",
      {
        "pipelineProposal": "minimal"
      }
    ],
  ]
```

これでエラーが消えます。ちなみに僕が調べたところ`minimal`以外は指定してもダメそう。
Pythonでのsigmoid関数の高速な実装

# 概要
機械学習アルゴリズムで頻繁に利用されるsigmoid関数だが、Pythonで実現しようとすると複数の方法が存在します。そこで、いくつかの実装の中でどれが一番速いのかを調べてみました。

# 方法
思いついた以下の方法について、sigmoidかけた値を算出して比較します。ただし、4と5に関しては使えるシーンが限定されている方法です。

1. [`scipy.special.expit`](https://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.special.expit.html)を呼ぶ (シンプルで良く使われている印象)
2. 定義 $\frac{1}{1 + exp(-x)}$ 通り計算
3. tanhを使って $0.5 \cdot \tanh(0.5 \cdot x) + 0.5$ で計算
4. 与えられる値のrangeが決まっている場合、事前に計算しておき配列で保存
5. 0付近の値が与えられない場合、$\frac{x}{1 + |x|}$ で算出

# 実装
```python
import numpy as np
from scipy.special import expit # 1.

# 2.
normal_expit = lambda x: 1 / (1 + np.exp(-x))
# 3.
tanh_expit = lambda x: 0.5 * np.tanh(0.5 * x) + 0.5

# 4.
min_range, max_range = (-5, 5)
exponent = 6
pre_computed = expit(np.arange(min_range, max_range, 10 ** - exponent))

def computed_expit(x, min_range, pre_computed):
    return pre_computed[np.floor((x - min_range) * (10 ** exponent)).astype(int)]

abs_expit = lambda x: x / (1 + np.abs(x)) # 5.
```

# 結果
![image.png](https://qiita-image-store.s3.amazonaws.com/0/234668/ab5c5579-a642-b58c-e628-cda77efbce49.png)

`scipy.special.expit`が他の方法と比較して2.5倍以上遅いことが分かりました。制約なしの中では定義通りに計算するのが速く、rangeの範囲の問題はある可能性はありますが、4は性能改善が誤差程度で、当然ですが5は高速ですが0付近で異なる値を返すという欠点がありました。

# あとがたり
`exp(-x)`を計算する部分がボトルネックなので、ここを解消するためにフーリエ変換を用いて多項式に分解する方法とかもあるんですが、結局精度がいまいちでず、汎用的な近似にはなりませんでした…残念 :cry:
自分のリポジトリにnpmの外部モジュールを取り込む

foo、bar、bazというnpmモジュールがあるとする
それらをpachage.jsonのある位置にexternal-libというディレクトリを作成しその中にコピーしリポジトリ管理する
package.jsonのdependenciesに外部モジュールを記述する

```:package.json
  "dependencies": {
    "foo": "./external-lib/foo",
    "bar": "./external-lib/bar",
    "baz": "./external-lib/baz"
  }
```

npm iでnode_modulesの下にインストールされる。

* バージョンを固定したい
* 改変したモジュールを使っている
* ciを早くしたい
* npmのトラブルに巻き込まれたくない
* そもそもネットに繋がっていないなど

いろいろな事情に対応できると思う
【codility】Lesson 4: Counting Elements MissingInteger

#subject
配列の中で、出現していない一番小さな値（0以上の値）を返す問題
例）
` A = [1, 3, 6, 4, 1, 2] `の場合 `5`を返す。
` A = [1, 2, 3] `の場合 `4`を返す。
` A = [-1, -2] `の場合 `1`を返す。

#submit
一発クリア！
![image.png](https://qiita-image-store.s3.amazonaws.com/0/237869/fa75c7da-ca0d-9f25-a139-fd30ba747b4b.png)

#program
**Point:Setを使って重複を排除しながらソート**
受け取る配列は、「①ソートされていない」「②重複がある」「③ゼロ以下の数値が紛れている」という特性を持っている。vectorの配列をset配列に入れる処理の中で、①ソートしながら、②重複を防ぎながら、③ゼロ以下の数値を省いた配列をつくり、簡単な処理になるようにした。

```c++:MissingInteger.cpp
#include<iostream>
#include<vector>
#include <set> 
using namespace std;

int solution(vector<int> &inputArray) {
	set<int> checkArray;

	if (!inputArray.empty()) {
		//sort the inputArray
		for (auto i : inputArray) {
			if(i > 0)
				checkArray.insert(i);
		}
		// if inputArray's elements value less than Zero
		if (checkArray.empty()) {
			return 1;
		}
		else{
			int count = 1;
			for (auto i : checkArray) {
				if (!(i == count))
					return count;
				count++;
			}
		}
		return (checkArray.size()+1);
	}
	return 1;
}
```
pdfpcのmacへのインストールはbrewで出来た

[超便利！PDF用プレゼンツール pdfpc](https://qiita.com/fukino/items/9d4217eb13f07e37a0bc)で紹介したpdfプレゼンテーションツールpdfpcですが、ubuntu向けでmacに入れるにはなんとかしてapt-getを使えるようにするかソースをコンパイルするしか...orz
と思っていたらbrewにありました。(公式に書いてないよね...？)

今までの苦労はなんだったのか。
というわけでbrewでインストールできます

```bash
brew install pdfpc
```
http://brewformulas.org/Pdfpc


諸事情により使えないapt-getもinstallできたのでそれについては今度書きます。
説明に入れて良いドメイン名

# ドメイン名の例示ルール
外部に出す資料に本当のURLが入っている場合、存在しないドメイン名に書き換えますが、そのドメイン名は何でも良いわけではなく、決まったルールがあります。

もし、ルール違反の適当なドメイン名を書くと、そのWebサイトに目的外のアクセスが増える問題が発生したり、そのドメインを取得してWebサイトを作る人が現れる可能性があります。
例で使えるドメイン名は取得できないルールになっているので、ルール通りに記述した方が安心です。
# ルール(RFC)
ルールでは、例示用ドメイン名 "example.", "example.com.", "example.net.","example.org."
が決まっていて、
www.example.net
のように説明資料中の例に使えるFQDNを作ることができます。

2018年7月時点では、RFC6761(2013年発行)が最新のルールです。
> RFC6761  Special-Use Domain Names
> https://tools.ietf.org/html/rfc6761
> Updates: 1918, 2606  *

よく見かけるRFC2606は以前の版になっています。
ざっと比較したところ例示用ドメイン名"example."が増えていました。

http://www.example.com/ をアクセスすると、ここは Example Domain で、許可なしで文書の例として使って良いと書いてあります。

IPアドレスにも同様なルールがあります。
> RFC6890  Special-Purpose IP Address Registries
> https://tools.ietf.org/html/rfc6890
> Obsoletes: 4773, 5156, 5735, 5736   

# 結論
ドメイン名の例を書く場合は、適当なドメイン名ではなくルール通りに書きましょう。
Sceneウィンドウに解説テキストを出し、今開いているシーンが何なのかを分かりやすくする

# はじめに
Unityの勉強会でUnityを動かして解説する時に

今開いているシーンがどういうものなのかが

**「分かりにくい」**

という問題があると思います。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/44288/42e16969-40ac-bd41-a2b3-333057b352d2.png)


# Unity上に解説を出せば良いのでは？
Unityの画面に何も解説が表示されてないのが問題ではないか？　

→ なら、**Unityに解説を表示させてみよう**

→ 作ってみました。
<br>

# 作ったもの
Sceneビューに解説テキストが表示されます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/44288/608efe4b-20f9-eb88-74f0-49fdc7fc1720.png)

https://gist.github.com/rngtm/759aa367cf16cbd3952d9c633b589b2a


今開いているシーンがどんなものなのかが**分かりやすくなった**、ような気がします。


# 使い方
## 1. EditorSceneViewText.csを導入
まずは <a href = "https://gist.github.com/rngtm/759aa367cf16cbd3952d9c633b589b2a">EditorSceneViewText.cs</a>をUnityプロジェクト内のEditorフォルダ以下に配置

![image.png](https://qiita-image-store.s3.amazonaws.com/0/44288/39a78e42-a8e5-0293-5297-47dd13fce63f.png)

<br>
# 2. テキストファイルの作成
シーンファイル(.unityファイル)と同じ場所にabout.txtを作成
![image.png](https://qiita-image-store.s3.amazonaws.com/0/44288/686ecb68-b493-3da1-a647-5bb381435ded.png)
<br>
![image.png](https://qiita-image-store.s3.amazonaws.com/0/44288/3174fa97-8194-3772-27b6-a4b48d4ac0df.png)
<br>

# 3. シーンを開く
シーンを開くとabout.txtの中身がSceneビュー上に出てきます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/44288/101b1bca-59de-d1f3-b2dd-004763a86580.png)


![image.png](https://qiita-image-store.s3.amazonaws.com/0/44288/5739e7b1-c5d6-3bfe-a47e-1f9925286d5e.png)


以上で終わりです。


# おまけ: テキストをカラフルにしてみる
マークアップタグを使ってカラフルにするのも面白そうです.

![image.png](https://qiita-image-store.s3.amazonaws.com/0/44288/c85aff5c-36b9-c098-5b2f-480be8d630fb.png)

```about.txt
<color=yellow>これはTestシーンです。</color>
何もしません。
<b><color=#55c500>Qiita</color></b>の記事に使う用途で作成しました。
```



# 参考URL
Sceneビューにちょっと便利なGUIを表示させよう
https://qiita.com/r-ngtm/items/32bfa65b55635756bf3a
VirtualBoxからHyper-Vへ移行した際に、ゲストOSが起動しなくなった時の話

# 環境
ホストOS： windows 10 pro 64bit　1803
ゲストOS： CentOS Linux release 7.5.1804 (Core)
移行前VM管理ツール： VirtualBox
移行後VM管理ツール： Hyper-V

# 背景
Virtualbox上で、CentOSを運用していたのですが、
あまりにもVirtualBoxが重かったので、Windows 10 pro 1803より標準で搭載された
Hyper-Vを使って管理を行うことにしました。

# 移行方法
1. VirtualBoxに標準で同梱されているvboxmanageコマンドを使って、
ディスクイメージを変換  
```
Vboxmanage clonehd --format VDI [vmdkファイル名] [vdiファイル名] 
```
2. Hyper-V 管理マネージャより、マシンを作成。
念のため、移行前のマシンスペックと揃えておいた。  
仮想ハードディスクの接続のところで、「既存のハードディスクを～」を選択し、
1で作成したイメージを指定する。

# 現象
起動後、しばらくすると、以下のような画面でOSが起動しない。。。
![panic.png](https://qiita-image-store.s3.amazonaws.com/0/170075/177a7d94-7d1a-7b3d-02db-abe917f14ef4.png)

しかもHyper-Vのターミナルのため、プロンプトをさかのぼれず、全容が全く分からない。。。

# 原因の切り分けと対処
1. OSのインストールディスクを使ったレスキューモードで起動が可能か  
⇒Noの場合、指定したディスクが壊れている可能性があるので、ディスクイメージの変換からやり直す。
2. kernelのrescueで起動が可能か。下記画面の赤枠部分
![grub.png](https://qiita-image-store.s3.amazonaws.com/0/170075/b9a9d08e-98ce-1283-e262-c81a6542d707.png)

⇒今回、私の場合、これでも起動は可能だった。

3.ほかのバージョンのkernelでも起動するか。
特に下から2番目のバージョンの kernelでも起動ができるかどうかを確認する。
⇒私の場合、下から2番目のバージョンでも起動はできたが、他になると起動できなくなっていた。

4．再度手順2で起動し、ディスク上のデータに欠損がないことを確認。
5．以下のページに従って、initramfsを再作成
[https://wiki.centos.org/TipsAndTricks/CreateNewInitrd](https://wiki.centos.org/TipsAndTricks/CreateNewInitrd)
6．起動時には、起動可能でかつ最新のkernelを使って起動する。

(※kernelやinitramfsを触ったり、レスキューモードを使用したりするため、操作には充分気を付けるようにしてください。)

なぜ起きたのかが不明なので、なにか情報を持っている人はコメントを残していただけるとありがたいです。。。
default_socket_timeoutを一時的に変更したい

忘れないようにメモ。


APIでレスポンスが返却されず処理が落ちてしまう事象があった。

PHP.iniの全体での変更ではなく、
API通信の処理だけdefault_socket_timeoutを変更したい。


```php

ini_set('default_socket_timeout',20); //20秒
```


これでできるっぽいけどテストしたい。

MacにPHPインストールしてると以下のコマンドでPHPのビルトインウェブサーバーが起動する。
`$ php -S localhost:3000`

コマンド実行時のカレントディレクトリがルートディレクトリになるので、
直下に適当なPHPファイルを置く。


```php

<?php
echo date('h:i:s') . "\n";

// 10 秒間遅延させる
sleep(10);

// 再開!
echo date('h:i:s') . "\n";
?>
```


ここに開発中のコンテナからアクセスして実際にdefault_socket_timeoutが変更となるか確認する。


開発中のコンテナに以下のテスト用コードを置く。
起動中のコンテナから見てMacのローカルは`docker.for.mac.localhost`でアクセスできる。

```php
$url = 'http://docker.for.mac.localhost:3000/info.php';

// POST送信するデータ
$data = array(
    'data' => 'postdata',
);

// URL エンコード
$data = http_build_query($data, "", "&");

// 送信時のオプション
$options = array('http' => array(
    'method' => 'POST',
    'content' => $data,
));

// ストリームコンテキストを作成
$options = stream_context_create($options);

// file_get_contents
$contents = file_get_contents($url, false, $options);
```

タイムアウト値の方が少ないと`$content`がFalseになるし、逆だと$contentsに値が返る。
pythonでimport元のclass内変数に引数を渡す

# はじめに

2018/7/9修正
私の理解不足でした。修正しました。

もともとはログ出力モジュールを作って、複数のスクリプトでそれを読み出し。
ログファイル名は読みだした側のスクリプト名にしたり、ログディレクトリをスクリプト毎に分けたりしたかった。

```
/jikkou.py
/lib/module.py
```

test.pyが親スクリプト的なもので、module.pyの中身を読み込んで流用する。
この時にtest.pyで、module.pyの\_\_init\_\_とstdout関数に引数を渡したい。

## それぞれの中身
### jikkou.py

```
#!/usr/bin/python3 -B
# -*- coding: utf-8 -*-

from lib import module

# def main()
def main():
        module.output('hoge').stdout('foo')

# exec main()
if __name__ == '__main__':
        main()
```

### module.py

```
#!/usr/bin/python3
# -*- coding: utf-8 -*-

class output:
    def __init__(self, out1):
        print(out1)

    def stdout(self, out):
        print(out)
```

## 実行結果

```
./jikkou.py
hoge
foo
```

module.output('hoge').stdout('foo')
init側とclass内関数側に引数を渡して実行する。
VS Codeでhtmlタグの開始タグ～閉じタグまでを選択する方法 

最近atomからVScodeに乗り換えたがatomでは開始タグ～閉じタグまでを選択するショートカットをよく使ってた。（デフォのショートカットなのか設定したものなのかは忘れた）
結構重宝していたのでVScodeでも同じようなショートカットはないか調べていたらどうやらEmmet（効率的にHTMLやCSSのマークアップ手助けしてくれる、すごいツール）の機能らしい

## 設定方法
環境設定　→　キーボードショートカット
キーバーインドの検索で `editor.emmet.action.balanceOut` を検索
ショートカットをあてる
VBAでもTupleが使いたい

# はじめに
VBAではFunctionで複数の値を返したい時にC#みたいにTupleが使えない

例えばこんな感じのFunctionがあるとする
(こんなのFunctionにする必要ないのでは？というツッコミはなしで)

```vb
Function TryToInt(value As Variant) As Integer
    If IsNumeric(value) Then
        TryToInt = CInt(value)
    Else
        TryToInt = 0
    End If
End Function
```

これは引数で受け取ったvalueがIntegerに変換できれば変換した値を、できなければ0を返している
しかし、これだと変換に失敗したかを0で判定するというルールを使う側に強いることになる
また、valueに0を渡した時には変換に失敗した扱いになるという致命的な問題がある

```vb
Sub Hoge()
    Dim fuga As String: fuga = "23"
    Dim piyo As Integer
    
    piyo = TryToInt(fuga )
    
    If piyo <> 0 Then
        Debug.Print piyo
    Else
        Debug.Print "あばばばば"
    End If
End Sub
```

それならと、戻り値をVariantにして失敗時にNullを返すとする

```vb
Function TryToInt(value As Variant) As Variant
    If IsNumeric(value) Then
        TryToInt = CInt(value)
    Else
        TryToInt = Null
    End If
End Function
```

```vb
Sub Hoge()
    Dim fuga As String: fuga = "23"
    Dim piyo As Variant
    
    piyo = TryToInt(fuga )
    
    If Not IsNull(piyo) Then
        Debug.Print CInt(piyo)
    Else
        Debug.Print "あばばばば"
    End If
End Sub
```

こうすると0を渡した時の問題は解決するが、変換に成功したかの判定にはNullチェックを強要される
また、Variantで帰ってくるので厳密に型を要する場合は結局キャストする必要がある

調べてみたら、この他にも戻り値を配列にしたり、参照渡しでなんとかしたり...などなどいろいろなやり方があったけど、しっくりくるものは見つからなかった

# Typeを使おう
ということでどうにかしてC#のTupleみたいな感じのことをしようと考えた時、Typeを使う方法を思いついた
Typeとは、ユーザー定義型といい、いわゆる構造体のこと
このTypeに変換した値と成功したかどうかを入れて返せばTupleっぽいことができそう
**注)プロシージャより上に定義する必要があり、PublicなTypeは標準モジュールにのみ定義可能**

```vb
Type IntBoolTuple
    Value As Integer
    IsSucceeded As Boolean
End Type
```

こうやってTypeを定義して

```vb
Function TryToInt(Value As Variant) As IntBoolTuple
    Dim res As IntBoolTuple
    If IsNumeric(Value) Then
        res.Value = CInt(Value)
        res.IsSucceeded = True
    Else
        res.IsSucceeded = False
    End If
    TryToInt = res
End Function
```

```vb
Sub Hoge()
    Dim fuga As String: fuga = "23"
    Dim piyo As IntBoolTuple

    piyo = TryToInt(fuga )
    
    If piyo.IsSucceeded Then
        Debug.Print CInt(piyo.Value)
    Else
        Debug.Print "あばばばば"
    End If
End Sub
```

こうやって使う
こうすれば前述した問題を解決でき、可読性が上がり、インテリセンスまで効くようになる

## 問題点
ただ、これも少し問題点がある

違う複数の値を返したい時に新たにいちいちTypeを定義する必要がある
今回の例のように、IntegerとBooleanではなくStringとBooleanを返したい時などはまたTypeを定義する必要があってめんどくさい
また、型を決めてしまっていると汎用性がなくなる
これは型をVariantにすればある程度は解消できる

```vb
Type Tuple
    Value As Variant
    IsSucceeded As Boolean
End Type
```

ただし、厳密に型を扱う時にはキャストする必要があるし、返したい値の数が変わった時(Valueに加えてValue2も返したい時とか)は新たにTypeを定義する必要がある

# おわりに
複数の値を返すのが少しマシになったかと思う
必ずしもこのやり方がいいとは限らないので、ケースバイケースで使い分けてね
ほかにいいやり方があれば教えて下さい(人∀・)

まぁどんなに工夫してもなにかしらの不満は残るだろうから、そもそもVBAを使わないのが一番の解決策だと思う( ˘ω˘)
memcahedセッションロック取得失敗対策


負荷試験最中接続が重い時がたまにあった。
phpログを確認してみると以下のようなログがでてる
セッションに何か失敗している様子

```
/var/log/php/php.log:[06-Jul-2018 09:59:20 Asia/Tokyo] PHP Warning:  session_start(): Unable to clear session lock record in /var/source/releases/20180705_2052_39/src/app/hoge.php on line 29
/var/log/php/php.log:[06-Jul-2018 09:59:20 Asia/Tokyo] PHP   3. session_start() /var/source/releases/20180705_2052_39/src/app/hoge.php:29
/var/log/php/php.log:[06-Jul-2018 09:59:20 Asia/Tokyo] PHP Warning:  session_start(): Failed to read session data: memcached (path: 10.33.47.62:11211) in /var/source/releases/20180705_2052_39/src/app/hoge.php on line 29
/var/log/php/php.log:[06-Jul-2018 09:59:20 Asia/Tokyo] PHP   3. session_start() /var/source/releases/20180705_2052_39/src/app/hoge.php:29
```

調べてみるとロック取得に失敗している可能性が高い
ロック取得再試行回数や取得インターバルなどを調整
php.iniに以下を追記。
設定値の詳細は公式マニュアルを参照。

```
[memcached]
session.lazy_write = Off;
memcached.sess_lock_wait_min = 200;
memcached.sess_lock_wait_max = 1000;
memcached.sess_lock_retries = 20;
```

php設定を再読込
```
$ sudo systemctl restart php-fpm
```

有効な値を確認

```
$ php -i | grep -e memcached.sess_lock -e session.lazy_write
memcached.sess_lock_expire => 0 => 0
memcached.sess_lock_max_wait => not set => not set
memcached.sess_lock_retries => 30 => 30
memcached.sess_lock_wait => not set => not set
memcached.sess_lock_wait_max => 1000 => 1000
memcached.sess_lock_wait_min => 250 => 250
memcached.sess_locking => 1 => 1
session.lazy_write => Off => Off
```

あとは再現するかどうか待ってみる。
Ajax で Youtube の自動補完(オートコンプリート)

# はじめに
検索フォームのオートコンプリートを自作するのはなかなかしんどいです。今回は動画系の検索フォームに役立つ(かもしれない)オートコンプリート方法を紹介します。とはいっても、Google にリクエストを送って json でデータを受け取り、後は jQuery UI の Autocomplete を使うだけです。

- 参考
    - https://gist.github.com/chandsie/4441018

# 準備
```html
<!-- Autocomplete for search field -->
<link href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" type="text/css" rel="stylesheet"/>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
```
jQuery UI の Autocomplete を使うので上記の２つを記述。また、別途普通の jQuery 記述用のファイルも取り込んでおいてください。


# コード

```html
<input id="keyword" type="text" name="search_value" value="" placeholder="Search...">
```

検索フォームの input に id="keyword" を設定しておきます。

```javascript
<script type="text/javascript">
    var suggestCallBack;
    $(function () {
        $('#keyword').autocomplete({
            source: function (request, response) {
                $.getJSON("http://suggestqueries.google.com/complete/search?callback=?",
                    {
                      "hl":"ja", // Language
                      "ds":"yt", // Restrict lookup to youtube
                      "jsonp":"suggestCallBack", // jsonp callback function name
                      "q":request.term, // query term
                      "client":"youtube" // force youtube style response, i.e. jsonp
                    }
                );
                suggestCallBack = function (data) {
                    var suggestions = [];
                    $.each(data[1], function(key, val) {
                        suggestions.push({"value":val[0]});
                    });
                    suggestions.length = 5; // prune suggestions list to only 5 items
                    response(suggestions);
                };
            },
            autoFocus: true,
            delay: 300,
            minLength: 2,
        });
    });
</script>
```

パラメータだけ解説します。

- suggestions.length：取得した補完候補の中から実際に表示する数(最大10)
- autoFocus：表示された補完候補の一番上にフォーカスをあてるかどうか
- delay：何ミリ秒後に補完候補を取得し、表示するか
- minLength：この値以上の文字が入力されないと補完候補が取得されない
    - 現在は２なので、１文字入力しても何の変化も起きない
    
# おわりに
Google API 系って全然日本人使ってないんですね、ってぐらい日本語の情報が少ないですね。あと注意点として、この手の実装は Google の仕様変更によりすぐ使えなくなったりするので、最新のドキュメントを参照するのが本当に重要だと思います！
javascriptの書き方

# 3つの書き方
1. `<scrip>`タグの間に書く
2. HTMLタグ内に書く
3. 外部ファイルに書く

# 3つの書ける場所
1.`<head>`タグ内
2.`<body>`タグ内
3.タグ自体の中
*3はおすすめできない。

# 3つの気をつける点
1.記述位置：jsによる指示の対象となる要素が、その指示より前にないとダメ。
2.全角：クォーテーション、ダブルクォーテーションで囲んでないとエラー。全角スペース特に注意。
3.読み込むパス：jsファイル作ってhtmlで読み込むとき、そのhtml起点でcssなどのパスを指定する。


>[ウェブカツ！！](https://webukatu.com/?afid=p5lxu1kvh03rayd2ctjsw4e9bgzq8nom)
PHPでSame-site cookie

## 2020年1月13日追記

SameSite cookieは2018年12月にリリースされたPHP7.3.0の`setcookie()`関数でサポートされました。

7.3.0未満のPHPやPSR-7レスポンスに対して`Set-Cookie`ヘッダをを設定したい場合のために[bag2/cookie](https://github.com/bag2php/cookie)ライブラリを開発しました。詳しくは[PSR-7と生PHPに対応したSet-Cookieライブラリを作った - 超PHPerになろう](https://www.phper.ninja/entry/2020/01/13/173426)をお読みください。

--------

近年のCookieでは[SameSite]と呼ばれる新しい属性が提案されました。この記事では、この属性の効能や副作用については言及しません。 ~~めんどくさいからね…~~ [Can I use]によれば現時点で50%を切る程度の普及率ではありますが、非対応ブラウザ向けに利用しても属性が無視されるだけなので、利用開始しても、おそらく支障ありません。

## PHPでの問題

PHPではCookieは[`setcookie()`](http://php.net/manual/ja/function.setcookie.php)で発行します。問題は、この関数のインターフェイスです。

```php
bool setcookie ( string $name [, string $value = "" [, int $expire = 0 [, string $path = "" [, string $domain = "" [, bool $secure = FALSE [, bool $httponly = FALSE ]]]]]] )
```

属性ごとに引数で渡すようになってるので、`SameSite`が入る余地がないのです。

## PHP 7.3での改善

PHPの機能追加提案[PHP: rfc:same-site-cookie](https://wiki.php.net/rfc/same-site-cookie)では、今年中にリリースされるPHP 7.3で追加される**予定**です。この提案が興味深いのは、引数の数を増やすのではなく、オプション引数のための連想配列をひとつだけ受け取るだけになったことです。

```php
bool setcookie ( string $name [, string $value = "" [, int $expire = 0 [, array $options ]]] )
```

つまり、このようにCookieを設定できるようになります。

```php
setcookie('hoge', 'fuga', 3600, [
    'path' => '/',
    'secure' => true,
    'httponly' => true,
    "samesite" => 'Strict',
]);
```

問題は、PHP 7.3のフィーチャーフリーズ予定日が近付いたのに[PRがまだマージされてない](https://github.com/php/php-src/pull/2613)ことです。 (つまり、現在リリースされてる[PHP 7.3.0 alpha 3](http://php.net/archive/2018.php#id2018-07-05-1)にも反映されてません :upside_down:)

## 従来のPHPでのワークアラウンド

では、PHP7.3の世界に辿りつけないわれわれは、まだSameSiteの恩恵に与ることはできないのか？

上記のPRでおもしろい例が紹介されてました。

> <a href="https://github.com/php/php-src/pull/2613#issuecomment-401266510"><img width="776" alt="With PHP < 7.3 some people use a hack to add the samesite option (path="xxx; samesite=..."), but this doesn't work anymore in 7.3 ad the values are filtered. So we really need this to be implemented." src="https://qiita-image-store.s3.amazonaws.com/0/4121/3a00dcd3-c088-0300-a841-985486122104.png"></a>
>
> With PHP < 7.3 some people use a hack to add the samesite option (**`path="xxx; samesite=..."`**), but this doesn't work anymore in 7.3 ad the values are filtered. So we really need this to be implemented.

変な声が出ましたね… ~~SameSiteが入る余地あったけど、これって一種のインジェクションなのでは？？~~ まあこのダーティーハックはいままでのバージョンで動いてるから、正式対応する7.3でも動作保障しないといけないよね、みたいな提案です。

さておき、これを悪用するとPHP7.3未満でも`SameSite`属性が設定できます。

```php
setcookie('hoge', 'fuga', 3600, '/; SameSite=Strict', '', true, true);
```

セッションで利用する場合は[`session_set_cookie_params()`](http://jp2.php.net/manual/ja/function.session-set-cookie-params.php)とか、`php.ini`とか、[`ini_set()`](http://jp2.php.net/manual/ja/function.ini-set.php)とか、PHP7以降では[`session_start()`](http://jp2.php.net/manual/ja/function.session-start.php)でも設定できます。

## まとめ

これは一本とられた。しかしながら、この~~仕様~~挙動を悪用すれば`SameSite`の設定が可能です。

[SameSite]: https://www.owasp.org/index.php/SameSite
[Can I use]: https://caniuse.com/#feat=same-site-cookie-attribute
AlexaにTwilioを使用してコミュニケーション機能を組み込む

Twilio(トゥイリオ)は電話、SMS、FAX、LINE、チャットなどのコミュニケーション用APIを提供するサービスです。

AlexaにTwilioを組み込むサンプルコードを用意しました。

## Twilio Function編
Twilio Functionを利用することでAWSアカウントもAWS Lambdaも不要でAlexaスキルを作ることができます。

- [Lambda不要！SMSを送信するAlexaスキルを作る](https://qiita.com/twilioforkwc/items/f927ec3ec91e8b61d385)
- [Lambda不要！電話を発信するAlexaスキルを作る](https://qiita.com/twilioforkwc/items/6646d21474ec89bcb545)
- [Lambda不要！FAXを送信するAlexaスキルを作る](https://qiita.com/twilioforkwc/items/9db24a79f356c8162111)
- Lambda不要！LINEを送信するAlexaスキルを作る(Coming soon)
- [Lambda不要！SMSを送信するAlexaスキルを作る（ASK SDK v2 for Node.js対応）](https://qiita.com/twilioforkwc/items/9ef80a34605e99697ab1)

## AWS Lambda編
AWS Lambdaをご利用したい場合はこちらをどうぞ。

- [SMSを送信するAlexaスキルを作る](https://qiita.com/twilioforkwc/items/e6d89b04967404b89ee2)
- [SMSを送信するAlexaスキルを作る（ASK SDK v2 for Node.js対応）]
(https://qiita.com/twilioforkwc/items/b82583de93a26a5f4f02)