OmniAICreator/Qiita-1.07M huggingface dataset:
Cent OS 7 の docker を overlay 対応させる方法

# cent で ftype=1 のdiskを `/var/lib/docker` にマウントする方法

fedora系はdocker のoverlay対応がいまいち。原因はdisk formatがいまいち。このせいでどうでもいいハマりがなくならない。

> [**Use the OverlayFS storage driver | Docker Documentation**](https://docs.docker.com/storage/storagedriver/overlayfs-driver/)  
>> **xfs (RHEL 7.2 and higher)**, but only with **d_type=true** enabled. Use `xfs_info` to verify that the **ftype** option is set to **1**. To format an xfs filesystem correctly, use the flag **-n ftype=1**.


いろいろ調べると、cent installerは `ftype=1` のフォーマットができないので `/var/lib/docker` にだけ違うパーティションを作るのがいいらしい。

docker 的には `d_type = true` で redhat的には `ftype=1` らしい。同じものを示すらしい。

1. ESXi(virtual boxとか) で全パーティション合計容量のハードディスクを１つマウントしたVMを用意
1. cent installerでパーティション自分で作るを選ぶ
1. 自動生成を選んで  `/`, /boot, /swap を作ってもらう
1. `/` の容量を減らす
1. パーティションを追加して `/var/lib/docker` を作る（残り容量が勝手に当たる）
    2. このやり方だと / も /var/lib/docker もlvmになるので後から追加可能になる
1. os install
1. 起動したら `/var/lib/docker` をフォーマットし直す

```py
   df -hT
   umount /var/lib/docker
   mkfs.xfs -f -n ftype=1 /dev/centos/var_lib_docker 
   mount -a
   df -hT
   xfs_info /var/lib/docker/ | grep ftype=1
```

> 参考  
https://docs.docker.com/storage/storagedriver/overlayfs-driver/  
https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/7.2_release_notes/technology-preview-file_systems  
http://man7.org/linux/man-pages/man8/mkfs.xfs.8.html  
https://superuser.com/questions/1321926/recreating-an-xfs-file-system-with-ftype-1
【Android】LiveDataが使いやすくなる拡張関数【Kotlin】


ViewのデータにLiveDataを用いている場合に、Viewのデータを更新するタイミングなどを細かく指定したい場合などがあります。

> 「Fragmentの生成時にデータがあればそのまま表示するが、データがない場合はローディングを表示し、データをフェッチしてからデータを表示する。ただし、画面回転やバックグラウンドから戻ってきたときなどには、Fragmentのビューを再生成せず、前回と同じ状態を保ちたい。」みたいな

そんな要件をみたすためにLiveDataからのデータの受け取りを工夫し、それらを拡張関数として作成したのでここで紹介します。

## データがNullのときは受け取らない

```kotlin
fun <T> LiveData<T>.observeNotNull(owner: LifecycleOwner, observe: (value: T) -> Unit) = apply {
    observe(owner, Observer { value ->
        value ?: return@Observer
        observe(value)
    })
}
```

使用前は以下のようにNullのときは早期returnさせたりしていました。

```kotlin
livedata.observe(this, Observer {
    it ?: return@Observer
    action(it)
})
```

これが以下のようにシンプルにかけます。

```kotlin
livedata.observeNotNull(this) { action(it) }
```

## データがNullのときも受け取る

```kotlin
fun <T> LiveData<T>.observeNullable(owner: LifecycleOwner, observe: (value: T?) -> Unit) = apply {
    observe(owner, Observer { value ->
        observe(value)
    })
}
```

こちらは今までと使い方は変わりませんが、Nullも流れてくるんだなっていうのがわかりやすいです。

```kotlin
livedata.observeNullable(this) { nullableAction(value) }
```

## データを一度だけ受け取る

```kotlin
fun <T> LiveData<T>.observeAtOnce(owner: LifecycleOwner, observe: (value: T) -> Unit) = apply {
    observe(owner, object : Observer<T> {
        override fun onChanged(value: T?) {
            removeObserver(this)
            observeNotNull(owner, observe)
        }
    })
}
```

observeしてから初めてデータが流れてきた場合のみ受け取れるようになります。observeしたいタイミングではまだLiveDataにデータがないが、そのうちデータが流れてくるので、そのときに一度だけ処理したい場合などに有効です。

```kotlin
livedata.observeAtOnce(this) { action(it) }
```

もしデータがすでにあり、一度だけデータを受け取りたい場合は、`action(livedata.value)` のように直接使うと良いと思います。

## データがないときに一度だけ別のアクションをする

```kotlin
fun <T> LiveData<T>.doIfEmpty(doing: () -> Unit) = apply {
    value ?: doing()
}
```

LiveDataにデータがない場合に何かを実行する。他の拡張関数と組み合わせて使うことが多い。

```kotlin
livedata
    .doIfEmpty { initialize() }
    .observeNotNull(this) { action(it) }
```

## データがあるときに一度だけ別のアクションをする

```kotlin
fun <T> LiveData<T>.doIfNotEmpty(doing: (value: T) -> Unit) = apply {
    value?.let { doing(it) }
}
```

LiveDataにデータがある場合に何かを実行する。こちらも他の拡張関数と組み合わせて使うことが多い。`observeAtOnce` との違いは、受け取りを待たずに即時実行されることです。

```kotlin
livedata
    .doIfEmpty { initialize() }
    .doIfNotEmpty { action(it) }
```

こちらは他の `observe` 系と組み合わせるとobserve時に、2回受け取り処理をすることになるので気をつけたい。処理タイミングを細かく指定したい場合には良いかも。

```kotlin
livedata
    .doIfNotEmpty { action(it) }
    .observeNotNull(this) { anotherAction(it) }
```

## 補足

LiveDataからのデータの受け取りタイミングをできるだけ正確に管理したい場合は、ActivityやFragmentでの受け取りタイミングがどこで発生するのかと、そのときにLiveDataを持っているViewModelがどのライフサイクルで動いているものかなど意識する必要があります。

LiveDataをFlowableから生成している場合は、FlowableがBehaviorなのかPublishなのかも関係してきそうです。
vagrantで気軽にKubernetes The Hard Way

# 概要

[Kubernetes The Hard Way](https://github.com/kelseyhightower/kubernetes-the-hard-way)というのは、Kubernetesクラスタ作成チュートリアルで、他の構築手段と比べて**The Hard Way（難易度の高いやり方）**という特徴があります。
kubeadmやminikubeを使ったワンコマンドの構築ではなく、より原始的に、1ステップずつコマンドを実行し、丁寧に（？）クラスタを作成する手法です。

これを体験することで、普段は便利コマンドに隠されてしまっているKubernetesの構築手順をを理解することができ、実際のクラスタ運用でも役に立つ知識を身につけることができます。

ということで早速試してみたいのですが、オリジナルの[Kubernetes The Hard Way](https://github.com/kelseyhightower/kubernetes-the-hard-way)はGCP（Google Cloud Platform）上での手順となっており、課金が発生しますし、また本来のKubernetes構築とは関係ないGCPのファイアーウォールの設定なども実施する必要があります。もっと気軽にThe Hard Wayしたい！！と思って調べていると、素晴らしいものがありました。

https://github.com/kenfdev/kubernetes-the-hard-way-vagrant

これはvagrant（とvirtualbox）を使ってローカル環境でKubernetes The Hard Wayができるというものです。

# Kubernetes the hard way with vagrant
オリジナルは https://github.com/kinvolk/kubernetes-the-hard-way-vagrant のようですが、https://github.com/kenfdev/kubernetes-the-hard-way-vagrant の方がオススメです。

kenfdev版の特徴

- オリジナルと同じcontainerdを使っている (kinvolkはcri-oを使っている）
- オリジナルで最近追加されたgVisorを使っている
- オリジナルと同じpod-cidr(kinvolkはオリジナルとは違うcidr)
- オリジナルのドキュメントと紐づいた簡単に実行できるスクリプト群

特に最後の点が非常に便利で、kenfdev版の[scripts/k8s-the-hard-way以下](https://github.com/kenfdev/kubernetes-the-hard-way-vagrant/tree/master/scripts/k8s-the-hard-way)にあるスクリプトがオリジナルのドキュメントと対応したファイル名となっており、オリジナルのドキュメントをみつつ、コマンドだけはvagrant版を使うという使い方ができます。

# vagrant版のクラスタ構成

全部で7台のVMが構築されます。実行するマシンにはそれなりのスペックが要求されます。

- LB
    - kube-apiserverを束ねるロードバランサ役のVMです。
- controller*3
    - kubernetesのmasterのVMです。etcdもここで動きます
- worker*3
    - kubernetesのworkerのVMです。

# 進め方

基本的にオリジナルのドキュメントをみつつ、コマンドはkenfdev版を使う、というやり方で進めました。gcloudコマンドは全て実行せずに飛ばしました。
ルーティングの設定などはvagrantであらかじめ実行する方式となっており https://github.com/kenfdev/kubernetes-the-hard-way-vagrant/tree/master/scripts/bootstrap ここからその内容を確認できます。

# はまったところ

ほとんどそのまま実行するだけなのでハマるところはないのですが

## vagrant-scpを連続すると何かおかしい
> Received disconnect from 127.0.0.1 port 2202:2: Too many authentication failures

こんなエラーが出ました。[IdentitiesOnly=yes by jonasfj · Pull Request #21 · invernizzi/vagrant-scp · GitHub](https://github.com/invernizzi/vagrant-scp/pull/21)が似たような問題だったので参考にしつつ

```~/.ssh/config
Host *
  IdentitiesOnly=yes
```

とすれば出なくなりました。

# 感想

腰が重かったKubernetes The Hard Wayでしたが、vagrant版を使うことで、気軽に試すことができました。
DockerでRemix (Browser-Only Solidity IDE) コンテナを作ろうとしてできなかった

https://qiita.com/KumanoT/items/acdb5233f28af9cad4dd

こちらを参考に。

以下Dockerfile

```Dockerfile
FROM ubuntu:16.04

# install utilities
RUN \
  apt-get update && \
  apt-get install -y git curl wget screen && \
  apt-get install -y build-essential libssl-dev python && \
  apt-get install -y language-pack-ja

RUN \
  apt-get install -y apt-file && \
  apt-file update && \
  apt-get install -y software-properties-common

RUN \ 
  apt-add-repository -y ppa:ethereum/ethereum && \
  apt-get update && \
  apt-get install -y solc

# set locale & timezone
RUN locale-gen ja_JP.UTF-8
ENV LANG ja_JP.UTF-8
ENV LC_ALL ja_JP.UTF-8
ENV TZ Asia/Tokyo

# install remix
RUN \
  curl -sL https://deb.nodesource.com/setup_7.x | bash && \
  apt-get install -y nodejs

RUN git clone https://github.com/ethereum/remix-ide.git
WORKDIR /remix-ide
RUN npm install
RUN npm run setupremix 

EXPOSE 8080

CMD ["npm", "start"]


```

ビルド

```
docker build -t remix:latest .
```

実行

```
docker run -p 8080:8080 remix
```

ブラウザで確認
http://localhost:8080/ 

すると、remixのヘッダーのみで中身がない状態

##環境
Mac OSX10.11.6
Docker Version:      18.03.1-ce
カレンダーライブラリ flatpickr.js で、月を横に複数個並べるオプション

## flatpickr.js
Documentation: https://flatpickr.js.org/

![image.png](https://qiita-image-store.s3.amazonaws.com/0/82699/2d48114f-0ce6-04e3-7937-9369a36436ec.png)


## flatpickr.js を使いつつ、一度に複数月を表示する
ライブラリの使い方は割愛しますが、以下オプションで設定できます。
※ すでにリリースされていますが、ドキュメントに記載がありませんでした。

```
{
  showMonths: 3
}
```

### DEMO
https://codepen.io/mtmtkzm/pen/OEQvLB

```javascript
document.querySelector(".flatpickr").flatpickr({
  inline: true,
  showMonths: 3,
});
```

## ちなみに
jQuery UI の Datepicker でいう `numberOfMonths` です。
パイプライン指数平滑フィルタ (パイプラインIIR)

指数平滑フィルタ:

$$
y_n = \alpha x_n + (1 - \alpha)y_{n-1}
$$

アナログで言えば1次のRCローパスフィルタに対応するフィルタだが、この式をそのままハードウェア化した場合、毎クロック演算することはできない。というのも単純な話、$y_n$ に $y_{n-1}$の項をフィードバックしようにも、積和演算で数クロック遅れてしまうので間に合わないのである。例えばXilinxのDSP48E1スライスの場合は、積和演算(P=A*B+C)のA入力からP出力まで3クロックかかってしまう。


ではどうするかというと、

```math
\begin{eqnarray*}
y_n &=& \alpha x_n + (1 - \alpha)y_{n-1} \\
 &=& \alpha x_n + \alpha(1 - \alpha) x_{n-1} + (1 - \alpha)^2 y_{n-2} \\
 &=& \alpha x_n + \alpha(1 - \alpha) x_{n-1} + \alpha(1 - \alpha)^2 x_{n-2} + (1 - \alpha)^3 y_{n-3}  \\
&=& ...
\end{eqnarray*}
```

と、$y_{n-k}$を $y_{n-k-1}$に展開していって、積和演算のレイテンシでも間に合うようにフィードバック項を遅らせる。[^1]

DSP48E1スライスで言えば、レイテンシが3クロックなので、 $y_{n-3}$が出るまで展開する。

なお回路は複雑になる[^2]ので、どうしても指数平滑が必要な場合[^3]でもなければ別のローパスフィルタを使ったほうがいい。



---


[^1]: もちろんこの手法は指数平滑フィルタだけでなく、通常のIIRフィルタにも応用可能である。
[^2]: Vivado HLSで実装できないか頑張ったが、私の高位合成力が足らないのか無理だった。
[^3]: 今まで使っていたアナログフィルタの代替として使いたい場合など。
【GAS】Googleカレンダーの今日の日程を定期的にメールする

#概要
Googleカレンダーにある今日の日程をメールしてくれます．

こんな感じです．

> 今日の予定
08時00分 - 08時30分 : 散歩
15時00分 - 18時00分 : プログラミング
18時00分 - 18時30分 : 夕飯
20時00分 - 21時00分 : お風呂
21時00分 - 03時00分 : バイト

#内容

```javascript
function myFunction() {
  const calendar = CalendarApp.getCalendarById('カレンダーID');
  const events = calendar.getEventsForDay(new Date());
  
  //時間の整形
  function makeTime(Date) {
    function addZero(num) {
      return (num <= 9 ? '0' : '') + num;
    }
    return addZero(Date.getHours()) + '時' + addZero(Date.getMinutes()) + '分';
  }

  var body = events.reduce(function(tmp, event) {
    return tmp + makeTime(event.getStartTime()) + ' - ' + makeTime(event.getEndTime()) + ' : ' + event.getTitle() + '\n';
  }, '');
  
  //メール送信
  MailApp.sendEmail({
    to: '送りたい相手のメールアドレス',
    subject: '今日の予定',
    body: body
  });

}
```

後はこれにGASのトリガーをセットすると定期的に今日の日程を送ってくれます．
また，特定の時間帯の予定だけメールしたり，特定の言葉が入っている物のみメールしたりもできると思います．
これとは別ですが，カレンダーの予定から自動でメールしてくれるような応用もできると思います．

#参考資料
[Calendar Service  |  Apps Script  |  Google Developers](https://developers.google.com/apps-script/reference/calendar/)
有償の IT カンファレンスに参加する意味を考える (@kenakamu ver.) 

先日 @kenazuma さんが [有償の IT カンファレンスに参加する意味を考える](https://qiita.com/kenazuma/items/0cb8295d15a5b6898ebd) という記事を公開されました。とても興味深い内容だったので、私も自分の考えフォローアップ記事として書いておきます。

# そもそもセッション受講が目的なのか？

この問いかけには Yes と No があります。

**Yes**
興味の優先順位が 3 番くらいで、ビデオも見ない可能性があるものは、会場にいるというメリットを活かして参加するため、セッション受講が目的となります。カンファレンスの 50% 程はこれに当てます。

**No**
上記の理由以外では No です。残りの 50% は登壇者やイベントの運営側、展示会場や他の参加者の方とのネットワーキングに使います。

# セッションには、聴講だけでなく参加した方が良い

カンファレンスはもともと**参加**するものなので、当然 Yes です。以下私の**参加**の仕方です。

**質問する**
セッション前、中、後問わず状況に応じて質問します。セッション中の質問は「他の参加者の時間を奪うのは良くない」という声も聴きますが、質問することで得られる回答はみんなで共有できるため、そのような回答を得やすい質問を選びます。

**ネットワーキング**
Ask the Speaker ではより個別の案件に関わる質問や、スピーカーとの連絡先交換をします。また質問に来ている人達とも一緒に話して連絡先交換をします。自分がやっている活動などを共有して認知してもらうこともこの場でやります。

尚、**名刺交換はネットワーキングではありません**。その後も本当に繋がっていける工夫を各々する必要があります。Facebook/LinkedIn などもそういう意味では同じかもしれないですが、一言メッセージをすぐ送ったり、ブログをお互いにフォローするなどできることは色々あります。


# レコーディングされないセッション、あるいはエキスポ展示などは狙い目

展示会場は、隙あらば必ず行き、出展者と話をしつつここでもネットワーキングをします。

**トレンド**
1st パーティーベンダーが出している製品と、それを利用する 3rd パーティーベンダーの製品は似て非なるものであり、より現実社会を反映していると思います。ここでなんとなくトレンドを見て取ることができるので面白いです。

**ネットワーキング**
極力雑談や展示しているものの話だけではなく、自分の考えや課題など具体的な話をしながらコンテキストを共有し、その後の繋がりになるよう心がけています。

**ネタ探し**
ハンズオンや展示の仕方など、盗めるものは盗みます。

# ITカンファレンスに**参加**する事で大きくモチベーションが上がることを甘く見ない

技術者に限らず、普段の業務以外の ＋１ を以下にやるかが大事なため、カンファレンスには積極的に顔出し、**参加**するようにしています。そのことでモチベーションも上がるし、そのためにもモチベーションがあがるので一石二鳥です。またその様子は後日チームと共有します。

またこれに限らずセッション参加後に色々試せる環境があることもモチベーション向上となります。性能のいい PC とクラウド系のサブスクリプション、トレーニングコースの受講など色々ほしい。。。

# あとでレコーディングを視聴できるとしても集中して学習できる時間をまとまってとるのは難しい

おっしゃる通り。無理ですね。これが 50% はセッションに参加する理由です。また参加しなかったセッションで見たいものは、事前にスケジュールを組んで見れるように時間を取ります。

# Rock Star であれ

私はこれを当事者意識と理解してます。傍観者や聴衆ではなく、**参加者**であることで自然とそうなりますが、目的を明確にしておくと行動指針となります。

# 究極の参加は登壇

隙あらば登壇する。を基本姿勢にいつも狙っています。登壇者になれなくとも勉強になるし、参加者としての目線も変わるので面白いです。以下いくつかの登壇方法です。

**コミュニティイベント**
まず参加者として参加して、主催者を探し当て、情熱でアピール。

**オフィシャルイベント**
1st パーティーではカバーしきれない部分を上記のコミュニティを活用して提案。情熱でアピール。

**主催**
一番簡単なのは自分でイベントを開催すること。自動的に登壇者になれます。


# 最後に

さて、コミュニティに興味があり、英語で登壇したいが自信がない場合、是非以下のコミュニティで登壇してください。最大限のフォローをいたします。

[Tokyo .NET Developer meetup](https://www.meetup.com/ja-JP/Tokyo-NET-Developers-Meetup/?_locale=ja-JP)
[en-JP](https://www.meetup.com/ja-JP/meetup-group-en-jp/)
Tomcat8でデバッグしていたらレスポンスが変なので調べた

ajaxでサーバーにアクセスするWebアプリケーションをデバッグしていたら、なぜかレスポンスが変。
レスポンスボディもHTTPヘッダも想定したものが返ってこない。
原因を調べたのでまとめ。

##実行環境
 - Tomcat8.0
 - SpringMVC
 - EclipseでTomcatを動かしてデバッグ
 - とりあえず動作確認的にajaxでWebアプリにアクセスして固定値のレスポンスを取ってくるだけの処理にしていた

##

```java:Test.java
@RestController
public class TestController {

    @RequestMapping(value = "/test.do", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String test(HttpServletRequest request) throws Exception {
        return "{ \"success\" : true }";
    }
}
```

```js:ajax.js
var req = new XMLHttpRequest();
req.open("POST", "test.do");
req.send();
```

##状況
 - TestControllerのtestメソッド内でブレークできたのでURL間違いなどはない
 - HTTPステータスは200が返ってきている
 - FilterやInterceptorも調べたがレスポンスを変えるような処理はない。むしろresponseオブジェクトの中には想定した内容が格納されていた
 - ブラウザによる差異はない。どのブラウザでも変なレスポンスが返ってきている
 - たまに正常なレスポンスが返ってくることもある

##原因
ステップ実行で深く深く潜っていくとtomcat-coyote.jar内の```NioChannel.class```にて例外をスローしていた。

```java:NioChannel.class
/**
 * This method should be used to check the interrupt status before
 * attempting a write.
 *
 * If a thread has been interrupted and the interrupt has not been cleared
 * then an attempt to write to the socket will fail. When this happens the
 * socket is removed from the poller without the socket being selected. This
 * results in a connection limit leak for NIO as the endpoint expects the
 * socket to be selected even in error conditions.
 */
protected void checkInterruptStatus() throws IOException {
    if (Thread.interrupted()) {
         throw new IOException(sm.getString("channel.nio.interrupted"));
    }
}
```
この例外が上層でキャッチされ、エラー用のレスポンスに書き換えられていた。
*Thread.interrupted()*はスレッドに割り込みが発生しているときに```true```を返すメソッド。
特に割り込みが発生するような処理はないので、この状況で発生し得る割り込みと言えば・・・
**デバッガによるブレーク**。
試してみると確かにブレークしたときにだけ変なレスポンスになっていた。

##あとがき
この例外のスタックトレースが毎回コンソールに出ていたんですが、200が返ってきてたので無視してました。
ちょっとでもエラーっぽかったら無視したらダメですね。
でもひどい罠だと思う。
スマホで低速回線のテストを行う

#概要
アプリで「タイムアウトしました、ネットワーク環境を確認してください」というメッセージを作ったものの
確認する方法がなくて、調べました。

#使うもの
Mac(LANケーブルに接続されていること)
Apple Developer Account
Network Link Conditioner

#やり方
1.Network Link Conditionerをダウンロード
https://developer.apple.com/download/more/?name=for%20Xcode
(Hardware IO Tools for Xcodeの最新版をダウンロード)
2.ダウンロードしたdmgから、インストール
dmgの中にNetwork Link Conditioner.prefPaneを選択し、インストール
3.設定する
テストしたい接続状態のProfileを選択し、ONにする。
4.Macのwifi共有を行う
5.スマホでwifi接続

#参考URL
https://dev.classmethod.jp/smartphone/iphone/network-link-conditioner/
npmで、package.jsonにあるパッケージの、tarボールのURLの一覧が欲しい

接続ドメインが制限された環境下で、「接続予定のドメインを教えてくれ」と言われた。
ので、ドメインの一覧が欲しい。

```bash
cat package.json | \
jq -r '(.dependencies + .devDependencies) | keys | .[]' | \
xargs -I{} npm view {} dist.tarball
```

## 解説
- catコマンドで、依存関係をpackage.jsonから読み出す
- jqコマンドで依存関係部分のみを取得する
    - `.フィールド名`フィルタで、当該部分のみ選択する
    - `keys`フィルタで、ハッシュのキーのみ配列で取得する。(パッケージ名が取れる。)
    - `.[]`で、配列を分解して出力する
    - `-r`で、引用符を出力しないようにする
- xargsコマンドで、それぞれの要素を1個ずつ処理する
    - `-I{}`でplaceholderを明示できる
- npm view コマンドで、tarボールのURLを取得する
    - npm view helpには、`npm view [パッケージ名] フィールド名.サブフィールド名...`という使い方が書いてある
    - 例えば、`npm view jquery`を試してみると、付表のような感じになる。
    - `dist`, `keywords`, `maintainers` `dist-tag`がフィールド名の様子。
    - tarのURLは`dist.tarball`で取れる。


```
jquery@3.3.1 | MIT | deps: none | versions: 48
JavaScript library for DOM operations
https://jquery.com

keywords: jquery, javascript, browser, library

dist
.tarball https://registry.npmjs.org/jquery/-/jquery-3.3.1.tgz
.shasum: 958ce29e81c9790f31be7792df5d4d95fc57fbca
.integrity: sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg==

maintainers:
- dmethvin <dave.methvin@gmail.com>
- mgol <m.goleb@gmail.com>
- scott.gonzalez <scott.gonzalez@gmail.com>
- timmywil <4timmywil@gmail.com>


dist-tags:
beta: 3.3.1    latest: 3.3.1

published 5 months ago by timmywil <4timmywil@gmail.com>
```
firestoreを利用していてiosをarhiveできない対応


firestoreに依存している状態でarchiveしようとするとエラーになります。
原因は[これ](https://github.com/firebase/firebase-ios-sdk/issues/1412)です。
firestoreが依存しているgRPC-RxLibraryに問題があり、これは[修正されている](https://github.com/grpc/grpc/pull/15531/files)ようです。

が、まだ2018/6/20時点では古いバージョンを参照しています。

なので対応版が出るまでは以下のように対応しましょう。

# 方法1

Poffileで、install時の処理で、Allow Non-modular includes in Framework ModulesをYESにします。

```Podfile
post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      config.build_settings['CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES'] = 'YES'
    end
  end
end
```

# 方法2

もしくは、CI環境で以下のようなshellを呼び出す方法もあります。

```gRPC-RxLibrary_bugfix.sh
#!/bin/bash -l
set -eux
: usage
: sh -x gRPC-RxLibrary_bugfix.sh ~/Sources/sample-project

: $1 
workspace=$1
cat $workspace/ios/Pods/Target\ Support\ Files/gRPC-RxLibrary/gRPC-RxLibrary-umbrella.h | sed -e  's:\#import "transformations/GRXMappingWriter.h"::g' > $workspace/ios/Pods/Target\ Support\ Files/gRPC-RxLibrary/gRPC-RxLibrary-umbrella.h-temp

rm -rf $workspace/ios/Pods/Target\ Support\ Files/gRPC-RxLibrary/gRPC-RxLibrary-umbrella.h
mv $workspace/ios/Pods/Target\ Support\ Files/gRPC-RxLibrary/gRPC-RxLibrary-umbrella.h-temp $workspace/ios/Pods/Target\ Support\ Files/gRPC-RxLibrary/gRPC-RxLibrary-umbrella.h
```

fastlaneを使っている場合は、buildするときのlaneで以下のようにすればいいでしょう。

```Fastfile
    cocoapods(use_bundle_exec: true)

    sh "./shell/gRPC-RxLibrary_bugfix.sh #{workspace}"

```
WSLでX Windows他

# 設定メモ
6/29に環境作ったので編集

下記を参考にした
https://ygkb.jp/7291
https://qiita.com/Aruneko/items/c79810b0b015bebf30bb
https://www.pcgamer.com/linux-in-windows-10/

# DBのアップデートとパッケージのアップデート
これやらないと、後でapt-getでこける。
sudo apt-get update
sudo apt-get upgrade

# 日本語化
読む分には英語でも良いけど、表示はして欲しい。
sudo apt install language-pack-ja
sudo update-locale LANG=ja_JP.UTF-8
sudo dpkg-reconfigure tzdata
sudo apt -y install manpages-ja manpages-ja-dev

何故か文字化けしている時は、コンソールを疑ってみるのも有り。
プロパティ
から
フォント
を選んで、日本語のフォントを選択。

# いくつか追加してみる
sudo apt install vim-nox
sudo apt install git
sudo apt install build-essential
sudo apt install zsh
sudo apt-get install libssl-dev
sudo apt-get install libreadline-dev
sudo apt-get install zlib1g-dev
sudo apt-get install x11-apps
sudo apt-get install x11-utils
sudo apt-get install x11-xserver-utils
sudo apt-get install libsqlite3-dev
sudo apt-get install nodejs
sudo apt-get install fonts-ipafont
sudo apt-get install libxml2-dev
sudo apt-get install libxslt1-dev

# Xmingを入れてみる
Xサーバを下記からダウンロードしてインストール
https://sourceforge.net/projects/xming/

Windows上のUbuntuから、GUIなUbuntuアプリを実行させたい。
echo “export DISPLAY=:0.0” >> ~/.bashrc

お試しに入れてみる。
sudo apt-get install gedit

実験
gedit

# デスクトップを入れる。
sudo apt install xfce4
sudo apt install gnome-themes-standard
sudo apt install conky

設定しておく。

# いつでも使える準備

nano ~/.xinitrc

中身はこちら
> \#!/usr/bin/env bash
> export LANG="en_US.UTF-8”
> export LC_ALL="en_US.UTF-8”
> exec startxfce4

実行権限付けてリンク
chmod +x ~/.xinitrc
ln -s ~/.xinitrc ~/.xsession

いくつか追加してみる
sudo apt install emacs24-nox
sudo apt install emacs24
行選択可能なTableを作って矢印キーで操作する


クリック時に行選択ができるテーブルを作って、更に上下キーが押されたときにkeydownイベントを拾って選択を切り替えられるようにしてみた。
参考にしたのは[StackOverFlowのこちらの質問](https://stackoverflow.com/questions/16959133/html-table-tr-onkeydown-not-working)の２番めの回答

#概要
JavaScriptでは、フォーカスが設定できる要素じゃないとキーイベントが使えないらしいので、テーブルがクリックされた時にテキストボックスにフォーカスを設定してテキストボックスのイベントとして処理を行う。

#実装

```html
<div>
   <!-- readonly属性をつけとかないと、テーブルがクリックされたときに文字が入力できてしまう。 -->
   <input type="text" id="tableEventShifter" readonly>

   <table id="myTable">
     <thead>
        <tr><th>name</th><th> price</td></tr>
     </thead>
     <tbody>
       <tr>
         <td>aaaa</td><td>1000</td>
       </tr>
       <tr>
         <td>bbbb</td><td>2000</td>
       </tr>
       <tr>
         <td>cccc</td><td>3000</td>
       </tr>
      </tbody>
   </table>
</div>
```

```css
body{margin:0;padding:0;}

/* テキストボックスを隠す */
div{background:white;}
#tableEventShifter{
  /* テキストボックスを邪魔にならない場所に置くのであれば特に以下の通りにしなくても大丈夫です。 */
  /* ただし、フォーカスが設定されないとだめなので、display:none;はNG*/
  position:absolute;
  z-index: -10;
  height:0;
}

/* 行の選択色 */
.selected {background:yellow;}
```

```javascript

// テーブルクリック時、テキストボックスにフォーカスをセット
$("#myTable").on("click",function(e){
  $("#tableEventShifter").focus();
});

// クリック時、行選択(ヘッダ除く)
$("#myTable tbody tr").on("click",function(e){
  // 選択されている他の行があれば選択解除
  $(this).siblings().removeClass("selected");
  // クリックされた行を選択
  $(this).addClass("selected"); 
});

// Tableタグではkey系のイベントが拾えないので、textboxのイベントとしてバインドする
$("#tableEventShifter").on("keydown", function(e) {
    switch (e.keyCode) {
      case 38: // ↑キー
        // 上の行を選択
        $('#myTable tbody tr:not(:first).selected')
          .removeClass('selected')
          .prev().addClass('selected')
        break;
        
      case 40: // ↓キー
        // 下の行を選択
        $('#myTable tbody tr:not(:last).selected')
          .removeClass('selected')
          .next().addClass('selected')
        break;
    }
  // スクロールさせない
  e.preventDefault();
});

```

#CodePen
<p data-height="609" data-theme-id="0" data-slug-hash="QxaVRx" data-default-tab="html,result" data-user="yanchi4425" data-embed-version="2" data-pen-title="Row selectable table on key events." class="codepen">See the Pen <a href="https://codepen.io/yanchi4425/pen/QxaVRx/">Row selectable table on key events.</a> by Yanchi4425 (<a href="https://codepen.io/yanchi4425">@yanchi4425</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
ぷららサーバー上でHTML内にwordpress呼び出す時にはまった。

# ぷららビジネスサーバーでWordpress4.9.6を動かす。
ぷららサーバー上でHTML内にwordpressで作ったブログの
タイトルのみ表示させるのに３日くらいかかったのでメモ。

まず、HTMLで記述したトップページにPHPでブログのタイトル
を呼び出す記述をして.htmlで保存。

同ファイル最上部に

`<?php require('/絶対パス/wp-blog-header.php'); ?>` 

と記述。

そしてdirectoryRootに.htaccessで

`AddType application/x-httpd-php .php .html`

で、HTMLファイルでもPHPとして読み込ませる事ができるようにしたところ。


**"サーバーの PHP バージョンは 5.1.6 ですが WordPress 4.9.6 は 5.2.4 以上のみでご利用になれます"**

というエラー発生。

多分.htaccess関連で記述ミスってるんだろうなと思ったけど、ぷららはサーバー
としての関連情報ほとんどでてこない。

サーバーのコントロールパネルから、コード検索したらphp53というのが
/user/bin/php53にあるとのことだったので、こちらを指定してしないと
バージョンの低いPHPが呼び出されてしまうんだろうと踏んで、htaccessを

`AddType application/x-httpd-php53 .php .html`

に書き直したら無事表示されました。
AWS ElasticSearch ServiceのデータをPHPで取得する

ESデータがGETでフルオープンの場合の取得方法です。
ESのポリシーにIAM RoleのARN書きたいんじゃぁ〜って方はこちら=>[IAM Roleを使ってAWS ElasticSearch ServiceのデータをLaravelで取得する](https://qiita.com/bboobbaa/items/3dc775eea01a75369b3c)

# AWS側の設定

Amazon Elasticsearch Serviceポリシー例
外部からのGETのみ許可します。

```json:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": "es:ESHttpGet",
      "Resource": "arn:aws:es:ap-northeast-1:000000000000:domain/xxx/*"
    }
  ]
}
```

# ComposerでClientBuilderをインストール

ClientBuilderが必要なのでcomposer.jsonに追記します。

```json:composer.json
"require": {
    "elasticsearch/elasticsearch": "~6.0"
}
```

`$ composer update`

準備が整ったのであともう一歩です。

# PHP側から読み込み

```php:xxx.php
use Elasticsearch\ClientBuilder;

$hosts = [
    'https://xxx.ap-northeast-1.es.amazonaws.com:443'
];

$client = ClientBuilder::create()->setHosts($hosts)->build();

$params = [
    'index' => '*'
];

$response = $client->search($params);
```

`$response`にデータ返ってきていると思います。

パラメーターの詳しい書き方はこちら
https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/_search_operations.html
How to Install golang in Ubuntu 18.04 LTS?

### Step 1. Download golang 
```
# cd /opt/
# sudo wget https://dl.google.com/go/go1.10.3.linux-amd64.tar.gz
# sudo tar zxvf go1.10.3.linux-amd64.tar.gz
```

### Step 2. Set environment
```
# sudo vim /etc/profile.d/golang-env.sh
export GOROOT=/opt/go
export GOPATH=$HOME/IdeaProjects  <-------- You can change it.
export PATH=$GOPATH/bin:$GOROOT/bin:$PATH

:wq!
```

### Step 3. Set environment
```
# sudo su -
# sudo source /etc/profile
# exit
```

### Step 4. Check
```
# go
go version go1.10.3 linux/amd64
```







https://tecadmin.net/install-go-on-ubuntu/
ElectronアプリもTypeScriptで書きたい

webpackでビルドしてから実行でもいいですが、そのまま起動できるとうれしいと思いませんか？ぼくは思いました。

# やりかた

1. `npm i ts-node`
2. TypeScriptで適当にコードを書く
2. 適当なところにindex.jsを作る

以下のような感じで、tsのエントリポイントをロードする

```js:index.js
require("ts-node").register();
require("./src/main"); // src/main/index.ts がエントリポイントとする
```

あとは、

```sh
$ electron .
```

すればアプリが起動します。
以上です。よろしくおねがいいたします。

# ちゅうい

おそらくですが、アプリの起動時にts-nodeによるトランスパイルを行っているので、動作は遅くなると思います。
実際にバイナリとして出力するときは、きちんとjsとして出力してあげたほうがいいんじゃないかなと思います。
jq コマンド | 「配列内のハッシュ」を値で絞り込む or 除外する

# JSONファイルの例

配列の中にハッシュが連なっている例。

```json
[
  {
    "name": "Alice"
  },
  {
    "name": "Bob"
  },
  {
    "name": "Carol"
  }
]
```

# valueで絞り込む場合

```
cat name.json | jq '.[] | select(.name == "Bob")'

{
  "name": "Bob"
}
```

# valueで除外する場合
 
```
$ cat name.json | jq '.[] | select(.name != "Bob")'

{
  "name": "Alice"
}
{
  "name": "Carol"
}
```









<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
IE11において背景画像が表示されない

仕事で出会ったバグを解決するまで少し骨が折れたのでまとめ。

##何が起きたか
bodyタグのonloadでファイルダウンロードを行っている画面において、一部画像が表示されなくなる。

##どんな状況か
- 画面遷移するとbodyタグのonloadが発火し、自動でダウンロードが始まる。という機能の画面
- imageタグで読み込んだ画像は表示される
- background-imageで指定された背景画像が表示されない
- IE7からIE11への移行案件だったが、IE7では起こらず、IE11でのみ起こる
- IE以外のブラウザでも発生しない
- ダウンロードをリクエスト（＝location.hrefの書き換え）する直前にalertなどを表示させると画像も表示される
 - ブレークポイントで止めても画像が表示される
 - location.hrefに代入するURLは直リンなので画面遷移は発生しない

##状況から推察される原因
背景画像の読み込み中にURLが書き換えられたため、読み込みが中断した。

##ポイント
onload内で処理をしているため、画像等の読み込みが完了した後に実行されるものだと思っていたが、
**背景画像については読み込み完了していなくてもonloadが発火する。**
この仕様はIEのみでなくchromeやFirefoxでも同様だが、URLが書き換わることで読み込みを中断してしまうのはIEのみだった。

IE7で起こらないのはIE11になってDOMの解析速度が上がったことでonloadが背景画像の読み込みに追いついてしまったのではないかと思う。

##解決方法
ダウンロードURLをリクエストしている処理を、setTimeout等で別スレッドにすると最後まで読み込まれる。

##所感
上記の原因・対策は実験と推察から得られたものなので確証はない。
でも背景画像が読み込まれなくてもonloadが発火するのは何度も再現できたので確かだと思う。
覚えておいたほうがよさそう。
Vagrantでのローカル開発環境構築を勉強してみた。

#開発環境を作ろう
新米プログラマです。

プログラミングの勉強を始める前にまずは環境構築をしないと何も始まらないということで今回は"VirtualBox"で仮想環境を構築したわけですが…

その際に"Vagrant"というツールを使ってすごく簡単に環境構築できました！

この環境構築でプログラミング挫折する人も多いみたいです。

##Vagrantとは
Vagrantは環境構築を助けてくれるツールで、仮想マシンの設定や仮想マシンの管理を簡単に行うことができます。

Vagrantのコマンドを打つことで仮想マシンの設定などの操作を代行してくれるイメージですね。

##Vagrantでの環境構築のやり方

###1. まずはVirtualBoxとVagrantをインストール。
インストールしたら僕の場合はWindows10なのでPowerShellで操作を行っていきます。

###2.仮想マシンを複数作成することを考えてそれらをまとめるフォルダを作成　→　その配下に仮想マシンを作成するフォルダを作る

$ mkdir MyVagrant

$ cd MyVagrant

$ mkdir MyCentOS

$ cd MyCentOS


これで user/MyVagrant/MyCentOS に移動しました。このフォルダに仮想マシンを作成します！

###3.仮想マシン設定用のVagrantfileを作る
Vagrantfileは仮想マシンの構成を記述するファイルです。中身はいろいろ設定が書いてあるけど、

今回はホストのIPアドレスの部分しか触ってないのでまだ詳しくはわかってないです・・・


$ vagrant init bento/centos-6.7

上のコマンドで初期化され、Vagrantfileが作成される。


bento/centos-6.7はBoxファイルで仮想マシンを起動するテンプレートが記述されているファイル。

Boxファイルは公開されているものもありますし、自分で作成することも可能です。

ユーザ名/Box名という形になっています。

僕のイメージだとBoxファイルにそれぞれの仮想マシンごとの起動のさせ方、Vagrantfileはその仮想マシンの詳細が書いてあるって感じ。

すごい間違っていそうで怖い…

###4．Vagrantfileを編集して仮想マシンのIPアドレスを設定する
このVagrantfileのIPアドレスが書かれた行のコメントアウトを解除します。
これでこのローカルホストのIPが設定されます。

###5．仮想マシンを起動する（少し時間かかります）
$ vagrant up

これで仮想マシンが起動されました。今後は上のコマンドを打つだけで今回作成した仮想マシンと同じ環境が作られます。

すごい簡単にできて本当に驚きました！！！

参考にさせていただいた記事
https://qiita.com/ozawan/items/160728f7c6b10c73b97e

Vagrantのコマンド

vagrant box add <name, url, or path> ：　Box追加

vagrant box remove 　：　Box削除

vagrant box list　：　Box一覧

vagrant init [name [url]] 　：　Vagrantの初期化・Vagrantfileが作成される

vagrant ssh　：　sshログイン

vagrant up　：　仮想マシン起動

vagrant halt ：　仮想マシン停止

vagrant reload 　：　仮想マシン再起動

vagrant destroy　：　仮想マシン削除

vagrant package　：　パッケージ作成 仮想マシンをパッケージングする(Box形式で出力)

vagrant plugin install ：　プラグイン追加

vagrant plugin list ：　プラグイン一覧表示
CentOS7でNIC名を任意に変更する

CentOS7に特定のNIC名でないとインストールができないシステムをインストールする必要があったので、NIC名を変更する方法を調査した。

##そもそもなぜ変更する必要があるのか
CentOS7（RHEL7）からNIC名の命名規則が変わったから。
https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/networking_guide/ch-consistent_network_device_naming

6以前ではeth*といった名前がデフォルトであったため、eth*に依存したシステムになっていた。
システム側を改修してNIC名に依存しない形にするのが最もきれいな解決策だが、
状況が許さなかったのでNIC名側を変更することになった。

##eth*に戻すには
####１．NetworkManagerを無効化する
NetworkManagerがNIC名を勝手に変えたりしてしまうことがあるから。

```sh
systemctl stop NetworkManager
systemctl disable NetworkManager
```
####２．```/usr/lib/udev/rules.d/60-net.rules```というファイルを作成し、下記内容を記述する。

```:/usr/lib/udev/rules.d/60-net.rules
ACTION=="add", SUBSYSTEM=="net", DRIVERS=="?*", ATTR{type}=="1", PROGRAM="/lib/udev/rename_device", RESULT=="?*", NAME="$result"
```

上記記述をするとOS起動時に
１．```/lib/udev/rename_device```を実行
２．```/etc/sysconfig/network-script/ifcfg-***```というファイルを検索
３．そのファイルに記載されている```HWADDR```の値とNICのMACアドレスを比較
４．一致する場合は同ファイル内の```DEVICE```の値をNIC名として設定
という処理をしてくれる。

####３．```/etc/sysconfig/network-scripts/ifcfg-eth0```を作成
名前を変えたいNICについている名前が```enp0s8```とかだったら

```sh
mv /etc/sysconfig/network-scripts/ifcfg-enp0s8 /etc/sysconfig/network-scripts/ifcfg-eth0
```

####４．```HWADDR```と```DEVICE```の値を編集する

```:/etc/sysconfig/network-scripts/ifcfg-eth0
HWADDR=XX:XX:XX:XX:XX:XX
DEVICE=eth0
NAME=eth0 # NAMEがあったらこれも合わせておく
```
####５．再起動

```sh
reboot
```

##デフォルトゲートウェイについて
NIC名を変えるとデフォルトゲートウェイの設定が消えることがある。
下記ファイルにNIC名指定でデフォルトゲートウェイの設定が記述されていると発生する。


```:/etc/sysconfig/network
NETWORKING=Yes
#GATEWAYDEV=enp0s8
GATEWAYDEV=eth0 # GATEWAYDEVの値を変更後の名前にしておく
GATEWAY=192.168.1.1
```

##biosdevnameとnet.ifnames
調査しているとbiosdevnameとnet.ifnamesを無効化してeth*に戻す方法を紹介しているサイトが多かった。
ただその方法だとPCI識別番号順（多分```ip a```で表示される順）にeth0、eth1～と割り振られてしまうので狙ったNICに狙った名前を付けることができない。
今回は2番目のNICにeth0、4番目のNICにeth1のように名前を付けたかったので上記の方法をとった。

また、biosdevnameとnet.ifnamesを無効化してから、udevルールやHWADDRで命名順序を変えようとすると名前の重複が発生してうまくいかないようだ。
https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/networking_guide/sec-troubleshooting_network_device_naming

##参考
https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/networking_guide/sec-understanding_the_device_renaming_procedure
TypeScript2.8 Conditional Types 活用事例


普段 Redux を愛用しているのですが、ボイラープレートの生産性の悪さが好きではなく、ヘルパーを作成しました。  
紹介記事: [Redux はもう辛くない。redux-aggregate](https://qiita.com/Takepepe/items/a79e767b38981c910c3f)

このライブラリですが、以下の様なsrc関数があるとします。

```src.ts
interface State {
  count: number
}
function increment(state: State): State {
  return { ...state, count: state.count + 1 }
}
function setCount(state: State, payload: { value: number }): State {
  return { ...state, count: payload.value }
}
```
ここから、以下の様な dist関数が生成されます。

```dist.ts
function increment(): { type: string } {
  return { type: 'counter/increment' }
}
function setCount<PL>(payload: PL): { type: string, payload: PL } {
  return { type: 'counter/setCount', payload }
}
```
dist関数の `setCount` payload型 に推論をマッピングすることが本稿の主旨です。src関数の第二引数型を抽出、dist関数の第一引数型へ cast します。もし src関数の第二引数が無ければ、dist関数の第一引数は never に。

## Conditional Types

v2.8 から追加された機能です。詳細は先人の資料をご参照ください。

- [TypeScript 2.8 の Conditional Types について](https://qiita.com/Quramy/items/b45711789605ef9f96de)
- [TypeScript 2.8.1 変更点](https://qiita.com/vvakame/items/2e32aeded05997f77dfa)
- [Today's TypeScript Types](https://speakerdeck.com/brn/todays-typescript)

初見ではこの Conditional Types の使い道が思いつかなかったのですが、@Quramy さんの記事で、まさに「第二引数を抽出してマッピングする」という節があり、参考にさせていただきました。変更後の型定義は以下の様になりました。
https://github.com/takefumi-yoshii/redux-aggregate/blob/master/typings/index.d.ts#L3-L10

```index.ts
type A1<T>          = T extends (a1: infer I, ...rest: any[]) => any ? I : never
type A2<T>          = T extends (a1: any, a2: infer I, ...rest: any[]) => any ? I : never
type MT<T>          = (state: A1<T>) => A1<T>
type MTPL<T>        = (state: A1<T>, payload: A2<T>) => A1<T>
type CR<T>          = () => { type: string }
type CRPL<T>        = (payload: A2<T>) => { type: string, payload: A2<T> }
type Mutation<T>    = MT<T> | MTPL<T>
type Creator<T>     = T extends MT<T> ? CR<T> : CRPL<T>
```

新しい TypeScript の機能は普段のコーディングでは中々利用場面が思い浮かびませんが、
こういったライブラリにはインパクトが大きいですね。今後も変化を追っていきたいと思います。
SourceTreeで差分ファイルを作りたい。けどコピペで動かない時の記事。

#差分ファイルの作成は結構面倒なのでSourceTreeで作りたい
いらないファイルを消し、必要なファイルだけを用意したフォルダ構成を作成するのは結構面倒くさい。
前に作った差分ファイルのフォルダ構成を流用して、などとものぐさをするとミスして痛い目をみることもある。（最近やってしまった）

せっかくファイル管理でミスが起きないようにgitで武装したのに、納品ファイルにミスが起きるようでは意味がない。
この辺を自動化できないだろうか。。と思って探したら色々ヒットした。

##そのままコピペでうまく、、いかない
この辺が最新記事だったので参考にしてみたが、うまくいかない。
これらの記事が悪いのではなく私の環境が悪いのである。
ふつうの人はこれでうまくいくのです。
[ICS MEDIA - SourceTreeの使い方 | コミット間の差分ファイルの抽出 (カスタム操作を使う方法)](https://ics.media/entry/4475)
[Crouton - sourcetreeでgitファイル差分をzip化するカスタムアクション](http://cresson.ivory.ne.jp/kuruton/git_001)
[Jiro Laboratory - SourceTree（Git）から差分ファイルを抽出してzipに圧縮](http://jirolabo.hatenablog.com/entry/2018/05/30/222912)

Windowsの場合の記述も書いてくれてるのに、なぜうちだとうまくいかんのか。

##なぜうまくいかなかったか
上記を参考にして実行、赤いエラー。
もしくは、正常に終わったように見えて何もファイルが作られない。

主に以下の原因でした。
###gitにパスが通っていない。
パスを通すかgit.exeの場所をフルパスで記述してやる必要があった。
####forしてる部分
``for /F "usebackq" %%i in (`git diff --name-only %PARAM1% %PARAM2%`) do (``
↓
``for /F "usebackq" %%i in (`"C:\Users\myusername\AppData\Local\Atlassian\SourceTree\git_local\bin\git.exe" diff --name-only %PARAM2% %PARAM1% --diff-filter=ACMR`) do (``

``--diff-filter=ACMR``についてはこちらの記事で[Qiita - gitでブランチ間の差分ファイルを抽出](https://qiita.com/hirosco/items/84849ed8fd91da6aae05#%E5%89%8A%E9%99%A4%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%8C%E3%81%82%E3%81%A3%E3%81%9F%E3%81%A8%E3%81%8D%E3%81%AE%E3%82%A8%E3%83%A9%E3%83%BC%E5%AF%BE%E7%AD%96)

####zip作ってる部分
``git archive --format=zip --prefix=archive/ %PARAM1% %RET_DIR% -o archive.zip``
↓
``"C:\Users\myusername\AppData\Local\Atlassian\SourceTree\git_local\bin\git.exe" archive --format=zip %PARAM1% %RET_DIR% -o sabun.zip``

###エラーのログ出力が文字化けしたりする
メモ帳でバッチを直したせいか。BOMなしUTF8で保存したら大丈夫に。

ググルさんに当てずっぽうで聞きまくる前に
ちゃんとエラーメッセージを読めばよかった。
恥ずかしいくらいのミス微修正で動いたので、当方のバッチファイルの記述は書く意味がない。
でもちゃんと動いてます。転載元記事の方々、ありがとうございました。

# 日本語フォルダを含むと失敗する
2018/12/26追記
どうやらマルチバイト文字含むパスだと失敗するようなので追記。
[[小ネタ][git] 日本語ファイルの文字化けを回避する](https://dev.classmethod.jp/tool/git/git-avoid-illegal-charactor-tips/) の記事をバッチに適用して解決。
せっかくなので使ってるバッチ全体を記載してみる。
日付.zipと日本語パス対応を入れてます。

```:バッチの中身
@echo off
if "%2" EQU "" (
    set PARAM1=HEAD
    set PARAM2=%1
) else (
    set PARAM1=%1
    set PARAM2=%2
)
"C:\Users\xxxxx\AppData\Local\Atlassian\SourceTree\git_local\bin\git.exe" config --global core.quotepath false
chcp 65001
setlocal enabledelayedexpansion
set YYYYMMDD=%DATE:/=%
set RET_DIR=
for /F "usebackq" %%i in (`"C:\Users\xxxxx\AppData\Local\Atlassian\SourceTree\git_local\bin\git.exe" diff --name-only %PARAM2% %PARAM1% --diff-filter=ACMR`) do (
    set RET_DIR=!RET_DIR! "%%i"
)
 
"C:\Users\xxxxxx\AppData\Local\Atlassian\SourceTree\git_local\bin\git.exe" archive --format=zip %PARAM1% %RET_DIR% -o sabun_%YYYYMMDD%.zip
```
Go言語 環境構築 on Windows

# はじめに
- 軽くGo言語を試してみた備忘録です。
- インストールせずに試すには、[チュートリアル：A Tour of Go](https://go-tour-jp.appspot.com/list)が便利です。

## ダウンロード
- [Downloads - The Go Programmnig Language](https://golang.org/dl/)
  - [go1.10.3.windows-386.zip](https://dl.google.com/go/go1.10.3.windows-386.zip)
  - [go1.10.3.windows-amd64.zip](https://dl.google.com/go/go1.10.3.windows-amd64.zip)

## ファイルの展開

```txt:展開先フォルダ
C:\Go
```

## 環境変数のパス設定

```txt:パス追加
C:\Go\bin
```

## 作業用フォルダ作成

```txt:作業用フォルダ
C:\Go>mkdir mygo
```

## Hello Go World!

```go:hello.go
package main

import "fmt"

func main () {
    fmt.Println("Hello Go World!")
}
```

## 実行

```txt:実行コマンド
C:\Go\mygo>go run hello.go
Hello Go World!
```

## ビルド

```txt:ビルドコマンド
C:\Go\mygo>go build hello.go
```
hello.exeファイルが生成される。

```txt:実行コマンド
C:\Go\mygo>hello
Hello Go World!
```

## 雑記
プログラムを記述してて、今まで触れた言語(C，Java，PHP，Pythonなど)と
異なるので違和感を感じた点。

- 変数 型 の順序 (ただし型は省略形もある)
- 変数 := 値 のコロン
- import "xxx" の""
- 先頭文字の大小でスコープがかわる

とりあえず、片足踏み込んだのでPythonと併せてゆっくり習得していきたい。

## 参考リンク
- [Go言語の初心者が見ると幸せになれる場所](https://qiita.com/tenntenn/items/0e33a4959250d1a55045)
- [他言語プログラマがgolangの基本を押さえる為のまとめ](https://qiita.com/gcfuji/items/e2a3d7ce7ab8868e37f7)
- [動的言語だけやってた僕が、38日間Go言語を書いて学んだこと](https://qiita.com/suin/items/22662f43b6a6e8728798)
Vue.jsでForm要素をコンポーネント化する

# やりたいこと
- 新規作成画面と更新画面で`<form>`要素の内容は同じであることが多いので、コンポーネント化して使いまわしたい。

# 実装例

ユーザー作成画面

```UserCreatorPage.vue
<template>
  <div>
    <user-form v-model="userForm" />
  </div>
</template>

<script lang="ts">
import Vue from "vue";
import UserForm from "./UserForm.vue";

export default Vue.extend({
  name: "user-creator-page",
  components: { UserForm },
  data() {
    return {
      userForm: {
        firstName: '',
        lastName: ''
      }
    };
  },
});
</script>
```

ユーザーフォーム

```UserForm.vue
<template>
  <form>
    <div class="form-group">
      <label for="last-name">性</label>
      <input type="text" class="form-control" id="last-name" :value="value.lastName" @input="update('lastName', $event.target.value)" />
    </div>
    <div>
      <label for="first-name">名</label>
      <input type="text" class="form-control" id="first-name" :value="value.firstName" @input="update('firstName', $event.target.value)" />
    </div>
  </form>
</template>

<script lang="ts">
import Vue from "vue";

export default Vue.extend({
  name: "user-form",
  props: ['value'],
  methods: {
    update(key: string, value: string) {
      this.value[key] = value
      this.$emit('input', this.value)
    },
  }
});
</script>
```

# 参考

- [コンポーネントで v-model を使う](https://jp.vuejs.org/v2/guide/components.html#%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88%E3%81%A7-v-model-%E3%82%92%E4%BD%BF%E3%81%86)
コミットログから直近のマージコミットを探す

コミットログから直近のマージコミットを探すコマンド方法。

コミットログを表示するコマンドでは`--merges`オプションを使うと、マージコミットだけに絞り込むことができるので、これを利用する。

# ログを表示する

```shell-session
$ git log -1 --merges
commit 37af3d14b552f3d1a4b91a3d47c13dc1a547bb23 (master)
Merge: 6a4f5f1 00e114e
Author: suin <suin@example.com>
Date:   Wed Jun 20 11:54:19 2018 +0900

    Merge branch 'topic-1'
```

# コミットハッシュを取得する

```console
$ git rev-list -1 --merges HEAD
37af3d14b552f3d1a4b91a3d47c13dc1a547bb23
```
HomebrewでGolangのバージョンを最新にアップグレード

## brew upgradeしたときの最新が古い

```
brew upgrade go
```

しても、現在の1.9.2が最新なんだと。ほう


## Fomulaをアップデート
[https://formulae.brew.sh/formula/go:embed:cite]

上のgoのformulaページ見るとStableが1.10になっている。ちゃんとなってるやん。

ということは自分のローカルのFormulaが古いようなのでpullする。

```zsh
cd /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/Formula
git pull origin master
```

ちなみにこのpullするのをコマンドでするにはどうすればいいんだろうか。

わからなかったけど、今回はこれでいい。

pullできたらもう一度、

```sh
brew upgrade go
```



>
==> Upgrading 1 outdated package, with result:
go 1.9.2 -> 1.10.2
==> Upgrading go
==> Downloading https://homebrew.bintray.com/bottles/go-1.10.2.high_sierra.bottle.tar.gz
######################################################################## 100.0%
==> Pouring go-1.10.2.high_sierra.bottle.tar.gz
[==> Caveats
A valid GOPATH is required to use the `go get` command.
If $GOPATH is not specified, $HOME/go will be used by default:
  https://golang.org/doc/code.html#GOPATH
>
You may wish to add the GOROOT-based install location to your PATH:
  export PATH=$PATH:/usr/local/opt/go/libexec/bin
==> Summary
🍺  /usr/local/Cellar/go/1.10.2: 8,161 files, 336.7MB


確認してみよう。

```
go version
```

>go version go1.10.2 darwin/amd64

ちゃんと上がった。

ちなみに、Mac OS自体のバージョンもちゃんと最新にしておきましょう。じゃないと多分問題起きるよ。
AnsibleのGathering FactsでAuthentication or permission failure.

## <INS>実行コマンド

```
$ ansible-playbook make_my_env.yml -K
```

## <INS>エラー文

```
TASK [Gathering Facts] **********************************************************************************************************************************************************************************************************************
fatal: [localhost]: UNREACHABLE! => {"changed": false, "msg": "Authentication or permission failure. In some cases, you may have been able to authenticate and did not have permissions on the target directory. Consider changing the remote tmp path in ansible.cfg to a path rooted in \"/tmp\". Failed command was: ( umask 77 && mkdir -p \"` echo /home/miyagaw61/.ansible/tmp/ansible-tmp-1529461607.904595-153673846566447 `\" && echo ansible-tmp-1529461607.904595-153673846566447=\"` echo /home/miyagaw61/.ansible/tmp/ansible-tmp-1529461607.904595-153673846566447 `\" ), exited with result 1", "unreachable": true}
        to retry, use: --limit @/mnt/c/Users/miyagaw61/home/src/github.com/miyagaw61/chikuwansible/make_my_env.retry
```

### 注目した場所

```
Failed command was: 
( 
umask 77 && mkdir -p \"` echo /home/miyagaw61/.ansible/tmp/ansible-tmp-1529461607.904595-153673846566447 `\" && echo ansible-tmp-1529461607.904595-153673846566447=\"` echo /home/miyagaw61/.ansible/tmp/ansible-tmp-1529461607.904595-153673846566447 `\"
)
```

## <INS>解決法

コマンド部分を切り抜いてみる


```
umask 77 && mkdir -p \"` echo /home/miyagaw61/.ansible/tmp/ansible-tmp-1529461607.904595-153673846566447 `\" && echo ansible-tmp-1529461607.904595-153673846566447=\"` echo /home/miyagaw61/.ansible/tmp/ansible-tmp-1529461607.904595-153673846566447 `\"
```

エスケープを除く

```
umask 77 && mkdir -p "` echo /home/miyagaw61/.ansible/tmp/ansible-tmp-1529461607.904595-153673846566447 `" && echo ansible-tmp-1529461607.904595-153673846566447="` echo /home/miyagaw61/.ansible/tmp/ansible-tmp-1529461607.904595-153673846566447 `"
```

実行

```
$ umask 77 && mkdir -p "` echo /home/miyagaw61/.ansible/tmp/ansible-tmp-1529461607.904595-153673846566447 `" && echo ansible-tmp-1529461607.904595-153673846566447="` echo /home/miyagaw61/.ansible/tmp/ansible-tmp-1529461607.904595-153673846566447 `"
mkdir: cannot create directory ‘/home/miyagaw61/.ansible/tmp’: Permission denied
```

削除

```
$ sudo rm -rf ~/.ansible/tmp
```

再実行

```
$ umask 77 && mkdir -p "` echo /home/miyagaw61/.ansible/tmp/ansible-tmp-1529461607.904595-153673846566447 `" && echo ansible-tmp-1529461607.904595-153673846566447="` echo /home/miyagaw61/.ansible/tmp/ansible-tmp-1529461607.904595-153673846566447 `"
ansible-tmp-1529461607.904595-153673846566447=/home/miyagaw61/.ansible/tmp/ansible-tmp-1529461607.904595-153673846566447
```
apache + pythonでdockerを管理

# 目的
以下の画像のようにWebでDockerを管理
![image.png](https://qiita-image-store.s3.amazonaws.com/0/188794/decc6600-52d9-a0c6-1ea6-061553953e3b.png)


# 環境
```shell
[uniqpirlo]$ cat /etc/redhat-release
CentOS Linux release 7.2.1511 (Core)
[uniqpirlo]$ apachectl -v
Server version: Apache/2.4.6 (CentOS)
Server built:   Apr 20 2018 18:10:38
[uniqpirlo]$ python3.6 --version
Python 3.6.4
[uniqpirlo]$ docker --version
Docker version 1.12.6, build 3e8e77d/1.12.6
```

# 手順
## apache関連
設定ファイル

```shell:/etc/httpd/conf/httpd.conf
・・・
<Directory "/var/www/cgi-bin">
    AllowOverride None
    #Options None
    Options ExecCGI
    Require all granted
    AddHandler cgi-script .py
</Directory>
・・・
```

上記設定の変更後apacheを再起動

```shell
[uniqpirlo]# systemctl restart httpd
```

apacheユーザをdockerグループに追加

```shell
[uniqpirlo]# usermod -aG docker apache
```

上記設定の変更後dockerを再起動

```shell
[uniqpirlo]# systemctl restart docker
```

## python関連
pythonスクリプトを以下のフォルダに作成（rootユーザまたはapacheユーザ）

```shell
[uniqpirlo]$ pwd
/var/www/cgi-bin
```
Flipと回転による画像水増し

超解像で遊んでいたら、学習データの拡張でflipと回転をする必要があったのでメモ。
超解像のための学習データを拡張する場合には、画像が劣化するinterpolationは利用しない。このため、flipと0, 90, 180, 270度の回転の組み合わせで8通りのデータ拡張を行う。
これらの回転は `cv2.flip` と `cv2.transpose` で実現する。

```py
import numpy as np
import cv2


def main():
    base_w, base_h = 40, 30
    patch_size = max(base_w, base_h)
    base_image = np.ones((base_h, base_w, 3), dtype=np.uint8) * 255
    font = cv2.FONT_HERSHEY_PLAIN
    cv2.putText(base_image, "test", (0, base_h), font, 1, (255, 0, 0))
    output_image = np.zeros((patch_size, patch_size * 8, 3), dtype=np.uint8)
    i = 0

    for image1 in [base_image, cv2.transpose(base_image)]:
        for image2 in [image1, cv2.flip(image1, 0)]:
            for image3 in [image2, cv2.flip(image2, 1)]:
                h, w, _ = image3.shape
                output_image[:h, i * patch_size:i * patch_size + w] = image3
                i += 1

    cv2.imshow("output image", output_image)
    cv2.waitKey(-1)


if __name__ == '__main__':
    main()
```
Input:
![base.png](https://qiita-image-store.s3.amazonaws.com/0/139809/2fc164f0-b07c-c3cc-8e68-af0a255f8cca.png)


Output:
![aug.png](https://qiita-image-store.s3.amazonaws.com/0/139809/ae3da984-2e9e-6304-5130-aaefc6fd0c50.png)

ちゃんとflipと回転角を指定する場合は、ちゃんと組み合わせを考える必要があるが、実は[numpy.rot90](https://docs.scipy.org/doc/numpy/reference/generated/numpy.rot90.html)という関数があり、その実装が参考になる。

flipまで組み合わせると、全部やってくれる実装はないので、自分で実装する必要がある。rot90 + flipの組み合わせだと、微妙に無駄な処理が発生することがある。気にしないといけないケースは殆どないと思われるが…

まとめると下記のような結果になる。

![rot_flip.png](https://qiita-image-store.s3.amazonaws.com/0/139809/957eabb5-985e-a652-6e59-5b46a552f05e.png)
ActiveRecordでの範囲指定検索

ActiveRecordでBETWEEN的な範囲指定検索をしたいケースがあり、挙動を調べたので整理してみました。
( ※Rails 5.2.0, MySqlで確認しています。)

以下のようにRangeで表現することができます。

```ruby
User.where(id: from..to)
```

## 通常の範囲指定
検索条件に`1..10`を指定すると、BETWEEN句に変換してくれます。

```ruby
User.where(id: 1..10)
```

```sql
SELECT  `users`.* FROM `users` WHERE `users`.`id` BETWEEN 1 AND 10 LIMIT 11
```

## from以上
toに`Float::INFINITY`を指定すると、BETWEEN句ではなく空気を読んで`id >= 1`に変換してくれます。すごい！

```ruby
User.where(id: 1..Float::INFINITY)
```

```sql
SELECT  `users`.* FROM `users` WHERE `users`.`id` >= 1 LIMIT 11
```

## to以下
逆にfrom`Float::MIN`を指定すると、idの最小値=0に置き換え(DBの型から判別してる？)、BETWEEN句に変換してくれます。  

```ruby
User.where(id: Float::MIN..10)
```

```sql
SELECT  `users`.* FROM `users` WHERE `users`.`id` BETWEEN 0 AND 10 LIMIT 11
```

## from/toが同値
from/toに同値を指定すると、`BETWEEN 1 AND 1`となりました。
`id = 1`を期待していたのですが、1件なら性能も大差ないでしょうし問題なさそうです。  
```ruby
User.where(id: 1..1)
```
```sql
SELECT  `users`.* FROM `users` WHERE `users`.`id` BETWEEN 1 AND 1 LIMIT 11
```

## おすすめの範囲指定
上記の挙動をふまえ、以下のようなコードに落ち着きました。

```ruby
from = query.id_from.blank? ? Float::MIN : query.id_from
to = query.id_to.blank? ? Float::INFINITY : query.id_to
User.where(id: from..to)
```
ActiveRecordは便利な機能がたくさんあって面白いですね！しっかり勉強していこうと思います。
もっとスマートな書き方あるよ！という方いましたらぜひ教えてください！
vimで勝手にヘルプが開くのをなんとかしたい

私は普段、Windows10+Vagrant+VirtualBox+Putty+Linuxという組み合わせで作業しています。Linux上のエディタはVimです。

ところで最近ノートPCを新調したのですが、テンキー周りのレイアウトが以下のようになっていました。

![ten-key.jpg](https://qiita-image-store.s3.amazonaws.com/0/47305/2c85d3f0-7ae3-69fa-fd84-737a9780b1e8.jpeg)

ブラインドタッチを練習しつつ早30年(!)なのですが、このキーボードだとバックスペースキーが小さくて、ついついその隣りにある[NumLk]を押してしまうことが増えました。Vimの挿入モードで[NumLk]を押すとヘルプが起動します。これを一日に何度もやっていると、そのたびにパワーを削がれてしまいます。

同様に、Vimの挿入モードで[1]を押すと[q]、[2]が[r]、[3]が[s]になるという、ストレスフルな状態になっています。なんとかしたい。

ずっとVimの方を調べていたのですがそれっぽい情報を見つけられずにいたところ、ようやく本日PuTTY側で解決策を見つけました。

[PuTTY numeric keypad mappings](http://vim.wikia.com/wiki/PuTTY_numeric_keypad_mappings)

やり方は書いてあるとおりで、PuTTYの設定画面から[端末]＞[高度な設定]＞[アプリケーションキーパッドモードを無効にする]にチェックを入れるというものでした。ようやくこれで幸せになれそうです。ちなみに「アプリケーションキーパッド」については、以下に解説がありました。

[キーパッドモードについて](https://ttssh2.osdn.jp/manual/ja/usage/tips/appkeypad.html)

Windowsでも今後標準でSSHクライアントがサポートされそうな雰囲気ですが、PuTTYはWinSCPとの相性がよく、当分は離れられそうにありません。
自前の配列データベースからqiime2で使える分類モデルを作成する

自前で持ってる16Sとか18SとかITSのデータベースとqiime2を使ってコミュニティ解析をしたい場合に、データベースからqiime2で使える単純ベイズ分類器のモデルを作成する流れをメモしたものです。

公式のこ↑こ↓（https://docs.qiime2.org/2018.4/tutorials/feature-classifier/ ） を参考にしています。

最終的に単純ベイズ分類器のモデルを作成するので、精度のよい分類器を作成するためにはノイズを取り除いたりすることが必要になると思います。

#### とりあえずデータベースをqiime2のフォーマットにする
配列データと系統情報を記したタブ区切りテキストファイルをqiime2フォーマットにします。

```
qiime tools import \
  --type 'FeatureData[Sequence]' \
  --input-path database-seqs.fasta \
  --output-path database-seqs.qza
```

```
qiime tools import \
  --type 'FeatureData[Taxonomy]' \
  --source-format HeaderlessTSVTaxonomyFormat \
  --input-path taxonomy.txt \
  --output-path ref-taxonomy.qza
```

#### データベース配列のノイズ除去
データベース配列にプライマーが含まれていたり、長さが揃っていない場合は下のコマンドなどで除去します。

```
qiime feature-classifier extract-reads \
  --i-sequences database-seqs.qza \
  --p-f-primer XXXXXXXXXXXXXXXX \
  --p-r-primer XXXXXXXXXXXXXXXX \
  --p-trunc-len 120 \
  --o-reads ref-seqs.qza
```
「XXXXXXXXXXXXXXXX」の部分は任意のprimerシークエンス。


#### 単純ベイズ分類器のモデル作成
単純ベイズ分類器のモデルを作成します。
裏で動いているのはPythonのscikit-learn 0.19.1に入ってるNaive Bayes classifierらしいです。

```
qiime feature-classifier fit-classifier-naive-bayes \
  --i-reference-reads ref-seqs.qza \
  --i-reference-taxonomy ref-taxonomy.qza \
  --o-classifier classifier.qza
```

#### 作成したモデルをテストする
公式に準じるとモデル作成に使った配列でテストしてますが（下記）、本当ならmockコミュニティとか使うべきなんでしょうね。

```
qiime feature-classifier classify-sklearn \
  --i-classifier classifier.qza \
  --i-reads rep-seqs.qza \
  --o-classification taxonomy.qza
```

分類結果を可視化します。

```
qiime metadata tabulate \
  --m-input-file taxonomy.qza \
  --o-visualization taxonomy.qzv
```
```
qiime tools view taxonomy.qzv
```