OmniAICreator/Qiita-1.07M huggingface dataset:
VSCodeでWSLのGitを使う(Ubuntu 18.04)

VSCodeにはバージョン管理の機能が統合されています。

[Using Version Control in VS Code](https://code.visualstudio.com/docs/editor/versioncontrol)

しかし、WSL上のワークスペースをVSCodeで開いた際に、WSLのGitを参照してくれません:sob:

![image.png](https://qiita-image-store.s3.amazonaws.com/0/97227/e0f72d6e-c31e-6914-eb82-abc29620c3e6.png)

GithubでもいくつもIssueがたっていたり、日本語の記事もありましたがどれもうまく動きませんでした。

しかし、以下の対応でついにうまく動きました！！！ :joy:
(Ubuntu 18.04です。)

```bash:git.bat
@echo off
wsl wslpath -aw $(git %*) 2> nul 
if not %errorlevel% == 0 (
    wsl git %*
)
@echo on
```

```json:settings.json
{
    "git.path": "C:\\Tools\\git.bat"
}
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/97227/af8ae33c-8e1a-0a2c-0054-6dae9e07b14d.png)

### 参考

https://gist.github.com/victor-perez/8ba25540394ec68b11f4b2699fb4d4ce
TortoiseSVNのpatchを使いこなす

自分の修正を誰かに渡して組合せの動作確認を依頼する時に、ソースコードそのまま渡して上書きしてね！という具合にしていませんか？
階層が違うファイルを複数送る場合、１つ１つ階層に上書きしてもらう手間がありますし、、リビジョンのベースが違って、上書きしたことで思わぬ先祖返りを起こしてしまうかもしれません。

そんな時に役立つのが***patch***です。
本記事では、patchファイルを自在に扱うための方法を記します。とっても簡単ですよ！

#patchファイルでできること
**1. 複数ファイルの変更を1ファイルで送れる**
 階層情報もpatchに含まれるので、「〇〇のディレクトリの〇〇というファイルです」のような説明が不要になります。
 
**2. 簡単に送り合える**
 変更部分に関する情報のみを送るので、ファイルサイズが非常に軽いです。メールやチャットでのやり取りも容易。

#patchファイルを作る
さて、早速作っていきましょう！
基本的にpatchファイルを作るには、2つの方法があります。

##ディレクトリを指定する(オススメ)
1. 変更されたファイルが入っている親ディレクトリを右クリックしてTortoise SVN → パッチの作成を選択
2. patchにしたいファイルにチェックを入れてOKを押す
3. 保存先のディレクトリを選択
4. 作ったディレクトリパスを教えてあげると親切
 
##ファイルを指定する
1.変更したファイルを右クリックしてTortoise SVN -> パッチの作成を選択
2.patchにしたいファイルにチェックを入れてOKを押す(1つでも出ます・・・）
3.保存先のディレクトリを選択
4.作ったディレクトリパスを教えてあげると親切（理由は後ほど）

.patchというファイルが出来たら成功です。

#patchファイルを適用する
patchを貰ったら適用します。こちらも方法が２つあります。

##パスを指定
1. patchファイルを右クリックしてTortoiseSVN -> パッチを適用 を選ぶ
2. 作成者に教えてもらったディレクトリパスを指定する。
3. 教えてもらっていない場合は、適当に対象の作業ディレクトリのルートディレクトリを選択。
（さすがにどの作業コピーに適用するかは分かっているかと思いますので・・）
4. 「どのパスを使いますか？」というようなメッセージが出たら、「見つかったパス」を指定。
5. マージウィンドウと小窓が出ますので、全部適用する場合、小窓の「全て適用」を押したら終了。
6. ファイル個別に適用したい場合、小窓のファイル名をダブルクリックしてマージします。


##ディレクトリまで持って行く
ちょっと作業が簡単になります。
1. patchファイルを教えてもらったディレクトリに置く。
2. TortoiseSVN -> パッチを適用 を選ぶ
3. マージウィンドウと小窓が出ますので、全部適用する場合、小窓の「全て適用」を押したら終了。
4. ファイル個別に適用したい場合、小窓のファイル名をダブルクリックしてマージします。


競合が発生したら、どちらを適用するか選びますが、この辺りはマージと変わらないので、省略します。
Unity ARKit Plugin のサンプルを起動しようとしたらめちゃくちゃエラーが出たそこのあなたに捧げる

# サンプルのビルドも出来ないのか俺は
という気持ちになったそこのあなた、大丈夫です**私も仲間です。**

ARKitをとりあえず触ってみたかった私は、
UnityでARKitアプリを開発するための環境構築チュートリアル (3/3)
http://www.atmarkit.co.jp/ait/articles/1801/10/news011_3.html
を見ながらとりあえずサンプルをビルドしてみようと思いました。

で、iOSのバージョンとか諸々合わせてから、ビルドしようとすると…

<img width="247" alt="スクリーンショット 2018-06-26 14.49.18.png" src="https://qiita-image-store.s3.amazonaws.com/0/111089/fcf9289b-9b5e-6bea-292e-9a3faf4d076e.png">

200個以上のエラー。
200個までしか表示できねえよ、みたいなのが201個目のエラーだったのでたぶんもっとあったんだと思います。

どうしようもなさすぎるほどのエラーの数で、
しかも調べても違う状況でこのエラーが出てる人で自分の場合どうしていいかわかんなかったり、
StackOverFlow見てもUnityのバージョンじゃね？
みたいな話が出て以上、みたいな感じでよくわからなくて。

で、ここでエンジニアの雑談コミュニティmohikanz
https://qiita.com/organizations/mohikanz
の皆様に聞いてみたら、
なんとUnity入れるところからやってくれまして、結果
**「いや普通にできたよ」**
と。

UnityもXcodeも最新だと言うので、じゃあもうそこ合わせるしかないなと思い、
macOSを最新にしないとXcodeも最新に出来なかったので
OSのアップデートからはじめ、
Xcodeを最新にしました。

そしたら無事普通にビルドできました…

バージョンの変遷を載せておきます。
## 元々のバージョン
Unity 2017.4.1f
Xcode 9.2

## ビルドできたのは
Unity 2017.4.1f
Xcode 9.4.1

でした。
もし仲間がいたらXcodeのバージョンをあげようね！！

ありがとうmohikanz！！！
Raspberry Pi Zero WHでCrystal Signal PI

Raspberry Pi Zero WHでも[Crystal Signal Pi](http://crystal-signal.com/)が使えたので、その報告です。

無線LANで繋がったネットワーク内で警告灯を光らせたくて適当なものを探していたらCrystal Signal Piを見つけたのですが、これは「Raspberry Pi 第一世代 Model B+以降が必要」となっていて、余らせていたRaspberry Pi Zero WHで使えるかわからなかったのですが試したら普通に使えました。

<img src="https://qiita-image-store.s3.amazonaws.com/0/90023/83b30673-94f0-2b53-1549-18ebc21f2da5.jpeg" width="300">

# Crystal Signal Piとは？
詳細はこちらの記事などをご覧ください。
https://qiita.com/usiusi360/items/ab6498cb05d2a91927c4

# 注意点
・Crystal Signal PiのケースにRaspberry Pi Zero WHを固定する際、ネジ2本での固定となります。
・写真を見るとわかりますが、各種端子へのアクセスがしづらいです。
・miniHDMIをHDMIに変換するコネクタがCrystal Signal PIのネジと干渉したので、コネクタを削る必要がありました。
GitLabとRedmine連携

###やりたいこと
gitlabのブランチにpushされたら自動でrdmine上のブランチに反映したい。
###公式ページ
[gitlab](https://about.gitlab.com/)
###導入バージョン
10.8.4-ee
###公式ページ
[Redmine](http://redmine.jp/)
###導入バージョン
3.4.6

###サーバー　
CentOS7

###サーバーの設定###
サーバーでbareリポジトリの作成
[公式ガイド](http://guide.redmine.jp/RedmineRepositories/#git)
サーバーにmkdirでフォルダを作ってね！
作ったフォルダに移動してクローン
git clone --bare http://userId:Password@gitLabUrl/root/xxxxx.git xxxxx.git！
フォルダのpermissionの設定も忘れずに！
忘れると
 GithubHook: Command 'git fetch origin' didn't exit properly. Full output: ["error: cannot open FETCH_HEAD: Permission denied\n", "\n"]
こんなエラーがくる

###Redmineの設定###
下記ページに移動
プロジェクト内→設定→リポジトリ
新しいリポジトリ→バージョン管理システムgitを選択
識別子を記入
リポジトリのパスを入力(上記で作成したフォルダのpath)
ファイルとディレクトリの最新コミットを表示するにチェック

###GitLabの設定###

GitLabの設定
下記ページまで異動しWebhooks を設定
http://GitLabUrl/プロジェクト/settings/integrations

URLのみ入力
http://redmineのURL/github_hook?project_id=レッドマインのプロジェクト名&repository_id=リポジトリ識別子?key=redmineの管理→設定→リポジトリ→APIkEY

以上で連携ができた。
ページ内の画像読み込みが終わるまで待つ処理

スムーズスクロールをさせているときに、外部ページからハッシュタグつきで飛んできた時
ページ内要素の読み込みが終わってからスクロールさせないと、変な位置に止まってしまう。
ほかにも画像ロードが終わるまで待つ処理は結構使うことがあるので、スムーズスクロール処理の内容と一緒にメモしておく。

エラー処理とかは特にいれていません。

```js
  // window
  var $window = $(window);
  // body&html
  var scrollElement = 'body,html';

  // window load event
  $window.on('load', function () {
    // URLにハッシュがついていれば画像ロードをまつ
    var urlHash = location.hash;
    if (urlHash) {
      var $target = $(getTarget(urlHash));
      var promise = preload();
      // 画像ロード終了後にスクロールを実行
      promise.then(function () {
        scrollToAnchor($target);
      });
    }
  });

  // 画像の先読み関数。promiseを返す。
  function preload() {
    var $images = $('img');
    var promises = [];
    var retDefer = $.Deferred();

    $images.each(function (index, item) {
      var defer = $.Deferred();

      if (isLoaded(item)) {
        // ロード済みなので待たない
        defer.resolve();
      } else {
        // ロードしてなければロード
        // ロード処理後のコールバックでresolve
        // ロードできなくても無視する
        $(item).load($(item).attr('src'),function(){
          defer.resolve();
        });
      }
      promises.push(defer.promise());
    });

    $.when.apply(null, promises).done(function () {
      retDefer.resolve();
    });
    return retDefer.promise();
  }

  // load check
  function isLoaded(element) {
    // IE以外
    if (element.complete) {
      return true;
    }
    // IEは画像の幅を取得することでロード済かどうかを判断
    if (typeof element.naturalWidth !== 'undefined' && element.naturalWidth > 0) {
      return true;
    }
    return false;
  }

  // scroll to anchor
  function scrollToAnchor($target) {
    // スクロールするスピード
    var speed = 400;
    // スクロールするポジション
    var position = 0;

    position = $target.offset().top;
    $(scrollElement).animate({'scrollTop': position}, speed, 'swing');
  }

  // get href of clidked link
  function getTarget(href) {
    return href === '#' || href === '' ? 'html' : href;
  }

```

## 参考にしたサイト
* 先読みする画像全ての読み込みが完了したら処理をする（上級）

http://jquery-master.net/blog/preload_promise/
MacでのUSキーボードでの英数/かな変換ショートカット

## control + space で変換させてイライラしてませんか？
私はしてました。
ひらがな入力にしたくて`control + space`と打ったら、英字になって、
「すでにひらがなやったんかい！！」って。

こちら↓がそんなイライラを解放するショートカットになります。

`shift + control + j` → ひらがな
`shift + control + '` → 英字

カタカナ/半角カタカナの変換も。（ほとんど使ってませんが）

`shift + control + k / ; `

これでcontrol + spaceで無駄に打ちまくるイライラから解放される！

~~ちょっと難点として、
iterm2だと、`control + j`とかが無効化されずに二重に動作しちゃうのが今の悩みではあるけど、
これは設定変更で多分なんとかなる。~~
iterm2でショートカット持ってかれないように、設定を変更できます。

参考：[iTerm で Ctrl + Shift + J でかな入力変換する方法](http://tech.portalshit.net/2012/02/28/chage-input-mode-in-iterm-with-ctrl+shift+j/)

## 余談
Macの備え付けキーボードは日本語で、外部キーボードとしてUSのを使ってる状況で気づいたのだけど、
USキーボード触ってる時は上記のショートカットなのだけど、
Macの日本語キーボード触ってたら、英字変換は

`shift + control + :`

になるという発見をしました。

賢いなー。（同じ位置の違うキーにあてがってくれてる）

もしよければ私のキーボード遍歴も合わせてお楽しみください。

[私のキーボードジャーニー](https://qiita.com/misosouplover51/items/3f135360b0f022392ce3)
初めてのプログラム制作

今日は、ifとwhileの使い方を学んだので、これを利用した簡単な戦闘プログラムを作ってみました。

体力500、防御力１～10で変動する敵を攻撃し倒すといった内容です。

```rb
life=500

while life>0 do
  attack=rand(1..50)
  defense=rand(5..10)

    if attack>defense then
      damage=attack-defense
      remain=life-damage
      puts "敵に#{damage}のダメージ。残り#{remain}"
      life=remain

    else
      puts "攻撃が効かない！"
    end

end

puts "敵を倒した！"
```

syntax errorと格闘しながらなんとか仕上げることができました。ブラッシュアップできる点を指摘していただけると幸いです。
C言語　配列

<h1>配列</h1>

配列とは、同じデータ型の複数の値を1つの変数にまとめて使用するためのものです。

配列を使うと同じデータ型の変数を複数宣言する必要がなくなるため、簡潔にコードを記述することができるようになります。

配列を宣言する方法
配列の宣言は次のように、データ型と変数名と要素数を記述します。

```c
// 配列の宣言
int intArray[3];

// 配列を使わない場合の宣言
int num1, num2, num3;
```

配列を使うと複数の値を1つの変数でまとめて扱うことができるため、コードを簡潔に記述できることが確認できます。

配列を初期化する方法
ここでは配列を初期化する方法を解説します。

配列の初期化は宣言と同時に初期化する方法と、値を1つずつ代入する方法があります。

配列の宣言と同時に初期化する場合は、配列の要素数の記述を省略することができます。

配列を初期化する方法を次のプログラムで確認してみましょう。

```c
#include <stdio.h>

int main(void) {

    // 宣言と同時に初期化
    int intArray1[3] = { 1, 2, 3 };
    for (int i = 0; i < 3; ++i) {
        printf("%d ", intArray1[i]);
    }
    printf("\n");

    // 要素数を省略して初期化
    int intArray2[] = { 4, 5, 6 };
    for (int i = 0; i < 3; ++i) {
        printf("%d ", intArray2[i]);
    }
    printf("\n");

    // 1つずつ値を代入して初期化
    int intArray3[3];
    intArray3[0] = 7;
    intArray3[1] = 8;
    intArray3[2] = 9;
    for (int i = 0; i < 3; ++i) {
        printf("%d ", intArray3[i]);
    }

    return 0;
}
```

```text:実行結果
1 2 3 
4 5 6 
7 8 9 
```

このプログラムでは配列を指定した値で初期化して、その値を表示しています。

プログラムの実行結果から、いずれの方法でも初期化ができていることが確認できます。
proxy 環境の npm で 403 forbidden が返ったら 

registry を https から http にしてみるといいよ。

`npm config set registry http://registry.npmjs.org/`

これでも駄目なこともあるらしいけど試してみて。

以下の投稿が詳しいけど、`npm 403 forbidden` でググっても出てこなかったので投稿してみた。

[proxy環境下でのnpm config設定](https://qiita.com/tenten0213/items/7ca15ce8b54acc3b5719 "proxy環境下でのnpm config設定")
【KARTE】Webhookを利用してchatworkに通知を送る

KARTEの[Webhook機能](https://support2.karte.io/campaign/campaign-appfunc/campaign-appfunc-func/981/)を利用すると、ユーザーの行動イベントをトリガーにChatworkに通知やタスク付けを行うことができます。

#設定方法
チャットワークAPIを使えるようにしておき、X-ChatWorkTokenを用意します。

各エンドポイントやその他APIに関する情報はこちら
[チャットワークAPIドキュメント](http://developer.chatwork.com/ja/)

Webhookテンプレート（サポート対象外）のカスタマイズ画面から以下を変数として設定してください。

##通知のみ
| 変数名       |値        |
|:-----------------|:------------------|
| target_url             |              https://api.chatwork.com/v2/rooms/ルームID/messages |
| method           |            POST |
| body             |              body=メッセージ内容 |
| headers.Content-Type               |                application/x-www-form-urlencoded |
| headers.X-ChatWorkToken               |                ****** |

##タスク付け
| 変数名       |値        |
|:-----------------|:------------------|
| target_url             |              https://api.chatwork.com/v2/rooms/ルームID/tasks |
| method           |            POST |
| body             |              body=メッセージ内容&to_ids=[ユーザーID]&limit=[タスク期限日] |
| headers.Content-Type               |                application/x-www-form-urlencoded |
| headers.X-ChatWorkToken               |                ****** |

※タスク期限日はUnix timeで入力してください
Bootstrap4でチェックボックスの色を変える

Bootstrap4.1でチェックボックスの色を変えるのは簡単にできるが、ドキュメントに載っていなかったのでメモ。

```html
<html>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB" crossorigin="anonymous">

<style>
    .custom-checkbox .custom-control-input:checked ~ .custom-control-label::before {
        background-color:red;
    }
</style>
<body>
    <div class="custom-control custom-checkbox">
        <input type="checkbox" class="custom-control-input" id="customCheckBox1">
        <label class="custom-control-label" for="customCheckBox1">Check this custom checkbox</label>
    </div>
</body>

</html>
```

<p data-height="265" data-theme-id="0" data-slug-hash="dKwMVz" data-default-tab="css,result" data-user="pikanji" data-embed-version="2" data-pen-title="Bootstrap Custom Checkbox" class="codepen">See the Pen <a href="https://codepen.io/pikanji/pen/dKwMVz/">Bootstrap Custom Checkbox</a> by pikanji (<a href="https://codepen.io/pikanji">@pikanji</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
LinuxbrewでUbuntu18.04のパッケージ管理

#Linuxbrewとは
MacでおなじみのパッケージマネージャーHomebrewのLinux版。
Ubuntuではapt系が一般的ですが，個人的にこっちの方が使いやすいです。

Linuxbrewの主な特徴として

- root権限が必要ない
- ホームディレクトリ配下にインストールされるので、不要になった時は削除が簡単(環境を汚さない)
- LinuxとMacで同じパッケージパッケージマネージャーが使える。

などがあります。
LinuxでもHomebrewが使いたい人にオススメです。

#環境
Ubuntu 18.04 LTS

#インストールと設定
Linuxbrewの[公式サイト](http://linuxbrew.sh)にもインストール方法は載っています。

###事前準備
事前に必要なパッケージをインストールしておきます。この部分だけ、root権限が必要になります。

```
$ sudo apt-get install build-essential curl file git
```

###インストール
下記のコマンドでLinuxbrewをインストールできます。

```
sh -c "$(curl -fsSL https://raw.githubusercontent.com/Linuxbrew/install/master/install.sh)"
```

###環境変数
次にパスを通します。
使っているshellの設定ファイルに追加してください。bashだと`~/.bashrc`です。

```bash:~/.bashrc
# おそらくこれだけでOK
export PATH='/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin':"$PATH"

# エラーが出る場合はこれも追加
PATH="$HOME/.linuxbrew/bin:$PATH"
export MANPATH="$(brew --prefix)/share/man:$MANPATH"
export INFOPATH="$(brew --prefix)/share/info:$INFOPATH"
```

###確認
正しくインストールできたか確認します。
下記のコマンドでエラーが出なければ成功です。

```
$ brew doctor
Your system is ready to brew.
```

#基本的な使い方
使い方はHomebrewと全く同じです。基本的なコマンドのみ紹介します。

※ フォーミュラ(Formula)
パッケージのこと。brewではフォーミュラと呼びます。

###インストール

```
brew install フォーミュラ名
```

###アンインストール

```
brew uninstall フォーミュラ名
```

###フォーミュラの検索

```
brew search キーワード
```

###インストール済みのパッケージを最新にする

```
$ brew upgrade
```
###Homebrew自体を最新にする

```
$ brew update
```

###brewに問題がないか調べる。
```
brew doctor
```

#最後に
Linuxbrewについて紹介させていただきました。
何か間違いなどありましたらコメントください。
Google Driveのフォルダに提出されているレジュメの状況をSlackに投稿し、次の提出先のフォルダを作成するBOTを作ったみた。

# 作ったもの

設定した日にレジュメの提出状況をSlackに晒し、次週の提出先のフォルダを作ります。
Google Apps Scriptの週トリガーを使用して自動化しています。
自分のフォルダのみを作成して、レジュメを提出していない状況も見られましたのでそれにも対応しています。
個人情報のため、名前とURLの一部は伏せさせていただきます。

![photo.jpg](https://qiita-image-store.s3.amazonaws.com/0/177657/18699b3f-9ca4-5b7b-3973-3de6036b6ab3.jpeg)

# 作った経緯

私が所属しているゼミの課題の1つで毎週、レジュメを提出しています。
提出先は、Google Driveに提出期限が記載された日付のフォルダ（例えば"20180629"みたいな）に
自分の名前のフォルダーを作り、提出しています。

しかし、提出率が悪いという状況が続いていました。

ゼミでは、ツールとしてSlackとGoogle Driveを使用していました。
Slack × Google Driveを合わせてどうにかできないかを考えた時に簡単に実装できそうなGoogle Apps Scriptを知りました。

同じようなことをされている方もいらしゃったのでGoogle Apps Scriptで作ってみました。

# 作り方

こちらの記事を参考にさせていただきました。
[GoogleAppsScriptで特定のDriveフォルダにあるファイル更新情報をSlackで通知する](https://qiita.com/minanami/items/9354424db32aba7e6a86)

SlackのWebhook URLを取得方法をこちらです。
[SlackのWebhook URL取得手順](https://qiita.com/vmmhypervisor/items/18c99624a84df8b31008)

Google DriveのFolder IDの取得方法はこちらです。
[基本中の基本！GASでGoogleドライブのファイル・フォルダをIDで取得する](https://tonari-it.com/gas-google-drive-file-folder-id/)

```js
function sendToSlack(body, channel) {
  
  var url = "SlackのWebhook URL";
  var data = {
    "channel" : channel,
    "username" : "レジュメ警察",
    "text" : body,
    "icon_emoji" : "設定したい絵文字"
  };
  var payload = JSON.stringify(data);
  var options = {
    "method" : "POST",
    "contentType" : "application/json",
    "payload" : payload
  };
  
  var response = UrlFetchApp.fetch(url, options);
  
}

function createFolder(url) {
  
  var folder = DriveApp.getFolderById(url);
  var today = new Date();  
  
  today.setDate(today.getDate() + 7);
  
  var foldername = Utilities.formatDate(today, "Asia/Tokyo", "yyyyMMdd");
  var newfolder = folder.createFolder(foldername);
  
}

function updateFolder() {
  
  var flg;
  var folderURL = '監視したいGoogle DriveのフォルダID';  
  var folderID = DriveApp.getFolderById(folderURL).getFolders().next().getId();
  var folder = DriveApp.getFolderById(folderID);
  var files = folder.getFolders();
  var array = new Array{};
  var compDate = new Date();    
  createFolder(folderURL);
  
  compDate.setDate(compDate.getDate() - 7);
  
  while (files.hasNext()) {
    
    var file = files.next();
    var lastUpdateDate = file.getLastUpdated();
    var fileObject = file.getFiles().hasNext();
    
    if(lastUpdateDate > compDate) {
      if(fileObject == true) {
        array.push("【"+ file.getName() +"】" + "最終更新：" + Utilities.formatDate(lastUpdateDate, "Asia/Tokyo", "yyyy/MM/dd HH:mm"));
        array.push("URL：" + file.getUrl());
      } else {
        array.push("【"+ file.getName() +"】" + "フォルダーの中身がありません。")
        array.shift()
      }
    }
    
    flg = array.slice(array.length - 2, array.length);
    
  }
  
  sendToSlack("ここ1週間で提出されたレジュメについてお知らせします。\n" + array.join("\n"), "#task");
  
}
```

# 最後に

これを作ったせいなのか、ゼミの友人に見せたら**「嫌なものを作ってくれたね」**と言われました。
BOT作りは楽しいので良しとしましょう。
Dockerでのethereum環境構築(geth編)

## まえがき

ethereumの開発環境をdockerで共有したい。

dockerには不慣れなのでひとまずDockerFileやDockerComposeのことは考えずに、コンテナ作成〜起動確認までをやってみる。

## 環境

- macOS High Sierra 10.13.4
- Docker for mac 18.03.1-ce-mac65

Docker for macはインストール済みとします。

## イメージの取得

gethのイメージをpullします。

```
docker pull ethereum/client-go #tagをつけないとlatest版を取得する
```

* tag一覧は[こちら](https://hub.docker.com/r/ethereum/client-go/tags/)

## コンテナの作成

取得したイメージからコンテナを作成します。

今回はethereumテストネットのropstenのノードを立てます。

```
docker run -d --name ethereum-ropsten-node -v $HOME/geth/ropsten:/root \
        -p 8545:8545 -p 30303:30303 \
        ethereum/client-go \
        --networkid "3" \
        --cache=1024 \
        --syncmode "fast" \ // 2018/09/25修正 --fastから左記へ変更
        --rpc \
        --rpcapi "db,eth,net,web3,personal,admin,miner" \
        --rpccorsdomain="*" \
        --rpcaddr "127.0.0.1"
```

### コマンド説明

- `-d`
    - デーモンで起動
- `--name ethereum-ropsten-node`
    - コンテナ名を「ethereum-ropsten-node」とする
- `-v $HOME/geth/ropsten:/root`
    - ボリュームのマウント先を指定
        - `$HOME/geth/ropsten`は、ホストのフォルダ
        - `/root`は、コンテナ内のフォルダ
- `-p 8545:8545`
    - ポートの指定
- `-p 30303:30303`
    - 同じくポートの指定
- `ethereum/client-go`以降は、gethの起動オプション
    - gethの起動オプションの詳細は[こちら](https://github.com/ethereum/go-ethereum/wiki/Command-Line-Options)

## 起動確認

コンテナに入り、shを起動します。

```
docker exec -it ethereum-ropsten-node /bin/sh
```

今回はgethの起動時オプションに、rpcのオプションを付けていたのでRPC接続します。

```
geth attach http://127.0.0.1:8545
```

gethのjavascriptコンソールが立ち上がるので、ChainDataの同期を確認します。

追記: 2018/09/25

同期確認は少し時間を立ってから実行してください。(5分くらい?)

同期開始前の場合、 `false` と表示されます。

追記ここまで

```
> eth.syncing
{
  currentBlock: 17984,
  highestBlock: 5834590,
  knownStates: 35989,
  pulledStates: 33439,
  startingBlock: 0
}
```

無事、ChainDataの同期が始まってました。


## あとがき

今回は単純にgethのノードのみを起動しましたが、機会があればdocker-compose + node + truffleとかの方法も書いてみたいと思います。

以上。
Gitでpush済のcommitをsqushでまとめる方法

## 概要
表題のとおり。やリかたよく忘れるので備忘録も兼ねて。

## 対象者
push済のcommit変えちゃダメとかそういうのいいから今すぐpush済のcommitをsqushでまとめたい人。

## rebaseコマンドを使う
### rebaseコマンド
HEADから遡って、まとめたいcommit数 + 1を指定する。
以下は、HEADから遡って4commitをまとめる例。
(HEADも含めて4commit)

```
$ git rebase -i HEAD~5
```

### まとめる対象commitを選択
すると以下のような画面が開く。
`This is a just commit`以外の`pick`を`s`もしくは`squash`に書き換えて、保存する。

なぜ１行目は書き換えないのかというと、こうすることで、`This is a just commit`に他のcommitが集約されるからだ。そのために、4commitまとめるのに、`HEAD~5`を指定したのだ。

ちなみに全部`s`にすると、`Cannot 'squash' without a previous commit`って怒られる。

```diff
pick 2008349 This is a just commit
-pick 20381e5 This is the first commit
-pick ca67ac9 This is the second commit
-pick 34e8939 This is the third commit
-pick bc0eb17 This is the fourth commit
+s 20381e5 This is the first commit
+s ca67ac9 This is the second commit
+s 34e8939 This is the third commit
+s bc0eb17 This is the fourth commit

# Rebase 36b1d53..bc0eb17 onto 36b1d53
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#  x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out
```

## push
あとは自己責任でpush。

```
$ git push origin +master
```

## 参考
- [rebase -i でコミットをまとめる](https://qiita.com/takke/items/3400b55becfd72769214#git-push--f)
- [How to squash already pushed commits](https://blog.liplex.de/how-to-squash-already-pushed-commits/)
raspi最新カーネルでjuliusを動かす

# 概要
RaspberryPi3で音声認識ソフトウェアjuliusを動かそうとすると以下のようなエラーが出ることがあり

```
Stat: adin_oss: device name = /dev/dsp (application default)
Error: adin_oss: failed to open /dev/dsp
failed to begin input stream
```
このエラーはカーネルバージョンが最新でなければ以下のコマンドで回避できます

```
sudo modprobe snd-pcm-oss
```
juliusのインストールや使い方は以下の記事を参考に。
[ラズパイと音声認識でLチカ](https://qiita.com/mr_04v/items/6a16663ce9a80b2e2b92)

しかし、先日発売されたRaspberryPi3b+ではカーネルのバージョンが最新である必要があり
最新のカーネルでは`snd-pcm-oss`のモジュールが含まれていないため
先ほどのコマンドを入力すると以下のようになってしまいます

```
sudo modprobe snd-pcm-oss
modprobe: FATAL: Module snd-pcm-oss not found in directory /lib/modules/4.14.34-v7+
```
この回避方法を以下で説明していきたいと思います

## 回避方法　　
### カーネルバージョンのダウングレード （RaspberryPi3b+以外）
RaspberryPi3b+は最新バージョンでないと動かないので飛ばしてください。
エラーの原因は

- 最新のカーネルでは`snd-pcm-oss`のモジュールが含まれていない

であるためカーネルをダウングレードすればいいというお話。

以下のコマンドで4.5.59にダウングレードすると先ほどのコマンドが通るようになる

```
sudo rpi-update a6b3e852ca70f2a12850b4542438583cc3b29788
```

### 使用するサウンドドライバを変更する（＊最新カーネル対応）
最新カーネルで動かしたい場合は，juliusのコンパイルの際にサウンドドライバをoss標準でないものに指定する必要があります

```
sudo apt-get install osspd-alsa
sudo aptitude install libasound2-dev
./configure --with-mictype=alsa
make
make install
```

これでできるはずです

ちなみにデバイスをしていするために以下のコマンドでカードを確認して正しく指定する必要があります

```
arecord -l
export ALSADEV=hw:1
```

なにかあればコメントください！
Ubuntu 16.04にDockerとDocker-composeをインストール


Ubuntu 16.04にDockerとDocker-composeをインストール

## First of all 

```
sudo apt-get update
sudo apt-get install git
```

## Prepare project user

```
sudo useradd -m -s /bin/bash admin
sudo su - admin
ssh-keygen -t rsa -b 4096 // This is for deploy key.
```

## Set up docker official repository

Install packages to allow apt to use a repository over HTTPS.

```
sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"
```

## Install Docker CE (Community Edition)

```
sudo apt-get update
sudo apt-get install docker-ce
docker -v
```

## Install Docker-compose

```
sudo curl -L https://github.com/docker/compose/releases/download/1.20.1/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
docker-compose --version
```

## Set docker group to project user

```
sudo gpasswd -a admin docker
sudo systemctl restart docker
```
GithubのPullRequestがcommitだらけで汚ねぇ… commitを整理する方法を伝授します！！

## はじめに
Githubを使う人なら誰でも直面する問題。
そう、数多の`git commit`によって引き起こされる

  **どのファイルの何を編集したかわからなくなる問題**。
　
`git commit -m`で何かしらのコメントを残すだろうけれど、それで全体像が把握できるわけもなく。
場合によっては、コメントが原因でわかりにくくなってしまうかも。
そんな状況になってしまった時のためにコミットを整理する方法を覚えておこう！！

## 環境
端末上の操作を行うため、tmuxがあると便利。
導入してなければ、コミットの番号?を記録できるものを用意

## commit整理手順

1. ログの確認
`glgga`か`git log`を使ってコミットの情報を調べる。
そこで表示された情報をたどりながら、戻りたいcommitを見つけて、その番号を記録する。
`tmux`使っている人は、ペイン分割すればOK。
`glgga`…git logをツリー上にして表示してくれるコマンド
  
1. 不要なコミットを削除する
`git reset --hard HEAD〜○`でHEADから戻りたいcommitの一つ前のcommitまでを数える。
数えたら、その数を○に入れる。
＊git reset --hard…commitごとファイルを削除するコマンド

1. ほしいコミットだけを取り入れる
`git reset --hard`で削除したcommitから`git cherry-pick`で必要なcommitを持ってくる。
だいたいコンフリクトが起こるので、どっちかを選んで、`git commit`

1. Githubへ反映
 ローカルで行った、コミットの削除などをリモートに強制的に反映させる。

##　操作例
```
$ glgga
$ git reset --hard HEAD〜○
$ git cherry-pick (commit ID)
$ git push --force
```
industrial_ci で roslaunch test する 1. はじめに

# はじめに
先日，[ROS勉強会#24](https://rosjp.connpass.com/event/89616/)にて発表してきました．
[発表資料はこちら](https://www.slideshare.net/RyodoTanaka1/roslaunch-test-industrialci)

勉強会では，
[ROSCon-JPを盛り上げ，ゆくゆくは本家ROSConの日本開催を目指そう！](https://knowledge.sakura.ad.jp/3754/)
そのためにも，日本のROSユーザーは無視できないぞ！と世界中の人に知らしめよう！！
というお話がありました．
日本のROSユーザーはみんなちゃんとテスト通してるぞ！
ってことになれば，多少は影響あると思います（笑）
というわけでroslaunch testやりまくりましょう！！！

# ROSにおけるテスト駆動開発
テスト駆動開発って面倒＆大変ですよね．．．
何より，
**ROSパッケージの場合，テストコードが書けない，launchするだけのパッケージ**
とかたくさんあると思います．
てかむしろそっちの方が多いように思います．．．
そこで本投稿では，`roslaunch test`を`industrial_ci`を介して実行できるようにする方法をご紹介したいと思います．

# `roslaunch test`のメリット
ROSの開発プロジェクトにおいて，２台以上のPCを用いている場合，圧倒的に`roslaunch test`をやっておいたほうが良いです．
というのも，研究室あるあるの
「先輩，何故か僕のPCでは動きません．助けてください！（泣）」
「まじか．．．」
なんていうトラブルが圧倒的に減ります．
研究室単位でさえこんな状況なので，他は言わずもがなな気がします．

# 実施までの手順
というわけで，`industrial_ci`を使って`roslaunch test`を`Travis CI`上で行うところまでの手順を記したいと思います．

なお，本投稿に登場する重要ワードについては本記事最下部の「補足」にリンクを貼っているのでそちらをご覧ください．

1. [はじめに](https://qiita.com/RyodoTanaka/items/790d92c00065311e1165)　**← 今ココ**
2. [Travis CI と Github の連携](https://qiita.com/RyodoTanaka/items/5051e3403525822a38ee)
3. `industrial_ci`の導入
4. `CMakeLists.txt`の記述方法
5. ローカルでのチェック
6. 実際のパッケージでの動作例

# 補足
下記に本投稿に出てくる重要ワードに関する参考リンクを載せておきます．

- [テスト駆動開発（CI）とは？](https://postd.cc/test-driven-development/)
- [industrial_ci とは？](https://www.youtube.com/watch?time_continue=297&v=GTHp5kfkr-4)
- [launch test とは？](http://wiki.ros.org/roslaunch/#Catkin)
- [Travis CI とは？](https://knowledge.sakura.ad.jp/3754/)
fishでファイルを連番つきコピーで複製する。にはforループ

# コード

```bash
for i in (seq 10)
    cp target.txt target$i.txt
end
```

# やりたいこと

ディレクトリにある`target.txt`をn個コピーして同一フォルダに設置したい。

# できない

[linux - Copy a range of files in command line (ZSH/BASH) - Server Fault](https://serverfault.com/questions/370403/copy-a-range-of-files-in-command-line-zsh-bash)

のようにワンライナーでしたかったけどできなかった。
bashでこのコードを動かしてもできず、よくよく読むとすでにあるファイルを別ディレクトリへのコピーだった…

bashでもforループに頼りそう

***

`seq`や`xargs`を使ったワンライナーが出来ないか考えたものの、スキル不足で断念。

***

このコードだけでは0パディングできず、自然順ソートしない環境で見にくいのであまりよくない。
PowerShellからAzureのBing Speech APIを呼び出すテスト

#目的
Bing Speech APIを、テスト目的で使ってみたい。
大体curlを使うらしいけど、もっと手軽に(Windows環境で他のソフトをインストールせずに)試してみたい。

#やりかた
Invoke-RestMethodコマンドレットを使う。
Power Shell 4.0で動作確認。

```powershell
Invoke-RestMethod -Uri "https://speech.platform.bing.com/speech/recognition/conversation/cognitiveservices/v1?language=ja-JP&format=detailed" -Method POST -ContentType "audio/wav; codec=audio/pcm; samplerate=8000" -Headers @{"Transfer-Encoding" = "chunked";"Ocp-Apim-Subscription-Key" = "APIキーをここに指定"} -InFile "C:\Users\username\desktop\音声ファイル.wav" -OutFile "C:\Users\username\desktop\認識結果.json"
```

- samplerate
- APIキー
- InFile
- OutFile

の4つを書き換えれば、とりあえず動く・・・はず。

#結果
こんな感じのjsonが取れます。

```json:認識結果.json
{"RecognitionStatus":"Success","Offset":1600000,"Duration":58800000,"NBest":[{"Confidence":0.5427112,"Lexical":"本日は晴天なり","ITN":null,"MaskedITN":null,"Display":"本日は晴天なり"},{"Confidence":0.5427112,"Lexical":"本日は晴天なり","ITN":null,"MaskedITN":null,"Display":"本日は晴天なり"},{"Confidence":0.5427112,"Lexical":"本日は晴天なり","ITN":null,"MaskedITN":null,"Display":"本日は晴天なり"},{"Confidence":0.542555034,"Lexical":"本日は晴天なり","ITN":null,"MaskedITN":null,"Display":"本日は晴天なり"},{"Confidence":0.542555034,"Lexical":"本日は晴天なり","ITN":null,"MaskedITN":null,"Display":"本日は晴天なり"}]}
```


#参考にさせていただいたページ
Bing Speech APIで音声ファイルをテキスト化してChatworkに投稿してみました。
https://dev.classmethod.jp/cloud/bing-speech-api/

Windowsにcurlが無い？いいえ、Invoke-RestMethodがあります。GrailsアプリへのPOSTリクエストを試す
https://qiita.com/_y_u_/items/94dd8ad6fcc8d278f433
AngularにSentryを導入する

* Angular5(@angular/* 5.2.0)
* sentry(https://sentry.io)

## 1. 何ができるか？

* 発生した例外を検知できる
* 例外は管理コンソールで確認できる
* OSやブラウザ等の環境情報が取れる
* スタックトレース
* issue化、statusやassign管理
* Slack通知

## 2. 導入

とりあえずhttps://sentry.io にアクセスしてプロジェクトを作ってAngularを有効にしたりします

```bash

$ npm install raven-js --save
```

## 3. 初期化と検知設定

*app.module.ts*

```typescript
import { NgModule, ErrorHandler } from '@angular/core';
import * as Raven from 'raven-js';

Raven.config('https://xxxxxxxx@sentry.io/xxxxxx').install();
export class RavenErrorHandler implements ErrorHandler {
  handleError(err:any) : void {
    Raven.captureException(err);
  }
};

@NgModule({
  providers: [
    { provide: ErrorHandler, useClass: RavenErrorHandler },
  ],
})
```

## 4. 環境を設定する

初期化までやってしまえば、例外のキャプチャは開始されます
何かしらの例外が発生すると、https://sentry.io に表示されます

ただ、このままだとローカルでの``ng serve``時などの例外も全て検知されてしまいます
environmentsを定義して、developmentやproductionのみ検知する等の対策が必要です

**4-1. environemtnsを定義する**

Angularではsrc/environments/environment.{env}.tsのように設定ファイルを置いておくと、
``ng serve --{env}``で設定を切り替える事ができます

今回は、devとprodの2環境を用意して、prodのみエラー検知ができるようにします

*src/environments/environemtn.prod.ts*

```typescript
export const environment = {
  production: false,
  development: true,
};
```

*src/environments/environemtn.dev.ts*

```typescript
export const environment = {
  production: false,
  development: true,
};
```

**4-2. ng serveやng buildで環境を切り替える**

prod環境で実行、ビルドする場合

```
$ ng serve --prod
$ ng build --prod
```

dev環境で実行、ビルドする場合

```
$ ng serve --dev
$ ng build --dev
```

もちろんステージング等の環境を増やしていく事もできます
オプションをつけない、つまりenvironment.tsをdev環境にしてしまう手もあります

**4-3. 検知設定を変更**

```typescript
export class RavenErrorHandler implements ErrorHandler {
  handleError(err:any) : void {
    if (environment.production) {
      Raven.captureException(err);
    }
  }
};
```

これで本番環境のみ、例外を検知するようになります

## べんり

本番環境で起きた不具合や例外をいち早く検知できるのは非常にありがたいです
特にデータに依存するような例外だと、再現性がなくデバッグに非常にコストがかかります

そういった例外を詳細に確認できたり通知できたりするのでかなり便利です
OSSRHへのアップロードにおけるエラー (The key ID must be in a valid form (eg 00B5050F or 0x00B5050F), given value: ~) の対応策

# はじめに

Gradleで作成したライブラリをOSSRHアップロードしようと思って、下記のサイトなどをいろいろ参考に、Windows版GPGと格闘しつつ、とうとうアップデート用のスクリプトをGradleで作成しました。

参考サイト:

* [GitHub＋Maven Centralで自作ライブラリを公開する](https://qiita.com/yoshikawaa/items/a7a7c1d927f6e7e75320)
* [gpg (GNU Privacy Guard)の使い方](https://qiita.com/moutend/items/5c22d6e57a74845578f6)
* [GradleでMaven Central Repositoryに成果物をリリースする](https://int128.hatenablog.com/entry/20130409/1365434513)
* [Publier une librairie open source sur Maven Central](https://www.dev-mind.fr/blog/2018/publish_maven_central.html)

さて、ついにアップロードだ！
と思いスクリプトを実行させようとすると、次のようなエラーが発生しました。

```gradle:エラー文
FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':signArchives'.
> The key ID must be in a valid form (eg 00B5050F or 0x00B5050F), given value: 0000111122223333444455556666777788889999

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 1s
4 actionable tasks: 1 executed, 3 up-to-date
The key ID must be in a valid form (eg 00B5050F or 0x00B5050F), given value: 0000111122223333444455556666777788889999
```

ちなみに、作っていたgradle.propertiesファイルは次の通りです。

```gradle:gradle.properties
signing.keyId=0000111122223333444455556666777788889999
signing.secretKeyRingFile=C:/HOME/.gnupg/secring.gpg
sonatypeUsername=Morichan
sonatypeFullname=Morichan
```

`signing.keyId`変数には、次のコマンドで取得したIDを入力していました。

```sh:コマンド
$ gpg --list-keys
C:/HOME/AppData/Roaming/gnupg/pubring.kbx
--------------------------------------------------------
pub   rsa2048 2018-06-28 [SC] [有効期限: 2020-06-27]
      0000111122223333444455556666777788889999
uid           [  究極  ] Morichan <mori@@earth.cs.miyazaki-u.ac.jp>
sub   rsa2048 2018-06-28 [E] [有効期限: 2020-06-27]
```



# 正しいgradle.propertiesファイルの書き方

下の通りにすると解決しました。

```gradle:gradle.properties
signing.keyId=88889999
signing.secretKeyRingFile=C:/HOME/.gnupg/secring.gpg
sonatypeUsername=Morichan
sonatypeFullname=Morichan
```

`signing.keyId`変数の桁が小さくなりました。
具体的には、下8桁のみを入力することで解決できました。

参考サイト: https://github.com/gradle/gradle/issues/1918

参考サイトによると、桁数が多すぎてエラーを返すようです。
それを防ぐためには、次のコマンドで入手したIDを入力すれば解決できます。

```sh:コマンド
$ gpg --list-keys --keyid-format SHORT
C:/HOME/AppData/Roaming/gnupg/pubring.kbx
--------------------------------------------------------
pub   rsa2048/88889999 2018-06-28 [SC] [有効期限: 2020-06-27]
      0000111122223333444455556666777788889999
uid         [  究極  ] Morichan <mori@@earth.cs.miyazaki-u.ac.jp>
sub   rsa2048/94D3B77A 2018-06-28 [E] [有効期限: 2020-06-27]
```

様々なサイトでは`gpg --list-keys`コマンドで大丈夫と書いてありましたが、新しいバージョンではIDの桁が大きくなっており、GPG2の最新版とGradleの最新版で衝突してしまうようです。



# おわりに

~~無事アップロードできました。~~

いろいろやらなければならないことが残ってましたが、なんとかアップロードできました。

リリースまでの参考: [Publier une librairie open source sur Maven Central](https://www.dev-mind.fr/blog/2018/publish_maven_central.html)

フランス語が日本語でスラスラ読めるいい時代になりましたね。
Codableを活用してHTTPCookieを永続化する

## コード
ご査収ください。永続化というより`HTTPCookie`を`Data`に変換してます。`Data`になれば`UserDefaults`等に保存できるのでいいですよね。`Data`に変換せずに`Realm`に保存するのもありだと思います。

```swift
struct Cookie: Codable {
    var name: String
    var value: String
    var domain: String
    var path: String
    var expires: Date?
    var secure: Bool

    init(_ cookie: HTTPCookie) {
        name = cookie.name
        value = cookie.value
        domain = cookie.domain
        path = cookie.path
        expires = cookie.expiresDate
        secure = cookie.isSecure
    }

    static func decode(_ data: Data) -> Cookie? {
        return try? JSONDecoder().decode(Cookie.self, from: data)
    }

    var data: Data? {
        return try? JSONEncoder().encode(self)
    }

    var httpCookie: HTTPCookie? {
        return HTTPCookie(properties: [
            HTTPCookiePropertyKey.name: name,
            HTTPCookiePropertyKey.value: value,
            HTTPCookiePropertyKey.domain: domain,
            HTTPCookiePropertyKey.path: path,
            HTTPCookiePropertyKey.expires: expires as Any,
            HTTPCookiePropertyKey.secure: secure
        ])
    }
}

// 使い方
let httpCookie: HTTPCookie
let data: Data? = Cookie(httpCookie) // これをUserDefaultsにでも保存どうぞ
let decoded: HTTPCookie? = Cookie.decode(data!) // 取り出したいときはdecodeしてあげてください
```

## なぜCodable
`NSKeyedArchiver`を使って、archiveして保存したりしてたんですけど、Unarchiveしたときに`HTTPCookie`の`createdAt`が2001/01/01になっちゃって困ったのでやめました。ちなみに、調べてよく出てくる例で使われている`NSkeyedArchiver.archivedData`はiOS13からDeprecatedになるみたいなので気をつけてください。

[NSKeyedArchiver.archivedData](https://developer.apple.com/documentation/foundation/nskeyedarchiver/1413189-archiveddata)

もっといいやり方あったり、これまずくねっていうのあったらコメントください。
Windows Subsystem for Linux(WSL)でDebianとWindowsにX

# 下記を参考にしてWSL有効化とDebian導入
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 -y install task-japanese locales-all 
sudo update-locale LANG=ja_JP.UTF-8
### ここでいったん終了してから、Ubuntuを再起動
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 install less

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上のDebianから、GUIなDebianアプリを実行させたい。
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
ElastiCache nodeのCloudWatchによる死活監視

AWSは、どのサービスも高い高可用性を誇っており、オンプレ環境とは比較にならないほど運用に手間がかからない。
しかしいくら高い可用性を誇るAWSと言えど、時には物理障害やAWSのVMホストなどの障害に遭ってしまうことはある。
特にRAMメモリを使用したサービスであるElastiCacheは、物理障害が比較的発生しやすいサービスである。
しかし、EC2などと違ってCloudWatchで死活監視を行う仕組みやMetricsは、デフォルトでは用意されていない。
多くの場合は自動復旧するが、障害解析などの目的でElastiCacheに障害が発生したことを検知したい場合がある。
そこで、今回はElastiCache(Redis)のService downを検知する方法を紹介する。

# 必要なもの

- AWS CLI(ElastiCacheおよびCloudWatchにアクセスできる権限が付与されていること)
- redis-cli

# Source code

```check-redis.sh
#!/bin/bash
export LANG=C
FAIL_COUNT=0
NODES=(`aws elasticache describe-cache-clusters | grep **CLUSTER NAME** | awk '{print $4}'`)
for NODE in ${NODES[*]}
do
	HOST=$NODE.abcd12.0001.apne1.cache.amazonaws.com
	redis-cli -h $HOST ping 2 >/dev/null 2>&1
	if [ $? -ne 0 ]
	then
		FAIL_COUNT=`expr $FAIL_COUNT + 1`
		logger -p 3 "ElastiCache connection failed. Host: $HOST"
	fi
done
aws cloudwatch put-metric-data --namespace "ElastiCache" --value $FAIL_COUNT --metric-name 'Unhealthy node count' --dimensions "Cluster=**CLUSTER NAME**" --unit "Count"
```

`**CLUSTER NAME**`や`HOST`変数のエンドポイントは、各自の環境に合わせて読み替えること。

# 設定方法

1. 上記のScriptを任意の場所(`/usr/local/bin/`など)に配置する。
2. 配置したScriptをCron実行

```crontab
* * * * *	/usr/local/bin/check-redis >/dev/null 2>&1
```

これで、ElastiCacheのノードがダウンした場合に、CloudWatchによって検知できるようになる。
IE11 で開発者ツールが開かないとき

いつの間にか ［Ｆ１２］を押しても、右クリックで「要素の検査」をしても開発者ツールが開かなくなってた

とりあえずここを参考にして直った
https://www.sevenforums.com/tutorials/152554-internet-explorer-f12-developer-tools-enable-disable.html


レジストリを開いて、以下のキーを ０ に設定
[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Internet Explorer\IEDevTools]
"Disabled"=0


復活した
よかった
pip installに成功したのに、読み込みに失敗するライブラリの解決方法

# これなに？
pip installが成功しているにも関わらず、ライブラリとしてロードされないケースがあったので、その解決方法について。Amazon Linux AMIの問題みたいです。

# 環境
Amazon Lambdaの開発環境です。

- Amazon EC2 Linux (AMI: Amazon Linux AMI 2018.03.0.20180508 x86_64 HVM)
- Python 3.6.5
    - このAMIのプリインストールはPython 2.7なので、yumで追加installしています
- VirtualEnv

# 症状

`pip show`しても、インストールしたライブラリが表示されない。
この状態で当該ライブラリを`import`しようとすると`ModuleNotFoundError: No module named 'xxxx'`となる。


```shell-session:インストール
$ pip --no-cache-dir install pyminizip
Collecting pyminizip
Installing collected packages: pyminizip
Successfully installed pyminizip-0.2.3
```

```shell-session:インストール結果の確認。認識されていない。
$ pip show pyminizip
$ 
```

# 解決策

[ここ](https://github.com/pypa/pip/issues/4464)に詳しく書かれているが、Amazon Linux AMIではpythonのライブラリの読込先（`sys.path`）として、`/lib/`だけが設定されてしまっている。
一方で、ライブラリによっては`/lib64/`にインストールされるものがあり、`/lib64/`を読込先として追加してあげないとダメだね、というオチ。


一時的なテストなら環境変数`$PYTHONPATH`に追加すればOK。永続的にこのライブラリを使うのであれば、`.pth`ファイルを利用する。以下は、`.pth`を追加した場合。

```shell-session:.pthファイルの作成
$ echo /home/ec2-user/yourVirtualEnv/lib64/python3.6/dist-packages > /home/ec2-user/yourVirtualEnv/lib/python3.6/dist-packages/mypath.pth
$ cat mypath.pth
/home/ec2-user/yourVirtualEnv/lib64/python3.6/dist-packages
```

```shell-session:確認
$ pip show pyminizip
Name: pyminizip
Version: 0.2.3
Summary: A minizip wrapper - To create a password encrypted zip file in python.
Home-page: https://github.com/smihica/pyminizip
Author: Shin Aoyama
Author-email: smihica@gmail.com
License: UNKNOWN
Location: /home/ec2-user/encryptfile/lib64/python3.6/dist-packages
Requires:
Required-by:
$ 
```

# 参考にしたページ

- [PythonRecipe：ライブラリローダを制御する](http://lightson.dip.jp/zope/ZWiki/210Python_e3_81_ae_e3_83_a9_e3_82_a4_e3_83_96_e3_83_a9_e3_83_aa_e3_83_ad_e3_83_bc_e3_83_80_e3_82_92_e5_88_b6_e5_be_a1_e3_81_99_e3_82_8b)
    - `.pth`ファイルの利用方法について。
- [GitHub：Packages installed by pip in lib64 are not recognized by pip](https://github.com/pypa/pip/issues/4464)
    - この問題についてのスレ
【マメ知識】Watson Discoveryで類似文書検索を行う

# はじめに
今年になってWatson Discoveryで類似文書検索ができるようになりました。
実際にその動作を確認しましたので、呼出し方のメモを残しておきます。

# 前提
Discoveryのインスタンス、コレクションは作成済み、文書のアップロードまで済んでいるものとします。
この手順については、例えば[Watson Discovery(フルサポート版)に日本語大量文書を投入](https://qiita.com/makaishi2/items/b5af7a9807b58cde7194)を参考にして下さい。

テストは、Watson Studio上のJupyter Notebbookで行っています。こちらのセットアップについても、上の書き込みを参考にして下さい。

# 事前手順
Discoveryのインスタンスを作って、environment_Id, collection_idを取得するまで

```py3
# 個別設定
# 管理コンソールのcredentail情報をコピーします。
credencial = {
  "url": "https://gateway.watsonplatform.net/discovery/api",
  "username": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "password": "xxxxxxxxxxxx"
}

# ライブラリ読み込み
import json
from watson_developer_cloud import DiscoveryV1
# In the constructor, letting the SDK manage the IAM token
discovery = DiscoveryV1(version = '2018-03-05',
                        username = credencial['username'],
                       password = credencial['password'])

# environment_id取得

environments = discovery.list_environments()['environments']
environment_id = environments[1]['environment_id']

print('environment_id: ', environment_id)

# collection_id取得
# (下のロジックはcolelctionが一つしかない前提)
collections = discovery.list_collections(environment_id = environment_id)['collections']
collection_id = collections[0]['collection_id']

print('collection_id: ', collection_id)
```

# 類似検索API呼出し

ここでなんらかの手段で、類似検索の元になる文書のidを取得します。
それがわかった後で、次の形でAPIを呼び出します。


```py3
# 類似検索
# id = "b5eb9c23-824a-4dc9-873e-9d17eaeb5a5d"と類似の文書を検索する

my_query = discovery.query(
    environment_id = environment_id, 
    collection_id = collection_id, 
    similar = 'true',
    similar_document_ids = ['b5eb9c23-824a-4dc9-873e-9d17eaeb5a5d'],
    return_fields = ['id', 'pat_id', 'pat_name', 'summury'])
print(json.dumps(my_query, indent=2, ensure_ascii=False))
```
Dockerを導入する際に気になったところとか。


気になったモヤモヤとか。随時更新。

### MySQLのデータ蓄積について

- Data Volumeを使う。/var/lib/mysql にマウントする
- Volumes Containeを使う

### 編集したソースをDocker内に反映するには？

- ホストPCのソースコードの置いてあるディレクトリをマウントする。ホストPCにあるソースをいじる。
- Docker内で実装してもいいけど、imageの作り直しが発生して手間そう。
ETロボコン mruby用教材の補足ページ(2018年)

ETロボコンmruby教材をリリース後に見つかった不具合情報や、ビルドの仕方の詳しい解説など公開しても差し支えない範囲でこちらに記載していきます。

公開できない情報については、こちらで更新あったことだけお知らせしますので、該当情報をあたってくださいね。


# 事前準備
2018年度版はEV3RT（β7）, mruby, mruby-ev3rtを使用しています。
開発環境の作り方は[こちら](https://qiita.com/yamanekko/items/f4744383146aaee25ac5)を参照してください。


[mruby-ev3rt](https://github.com/yamanekko/mruby-ev3rt)を最新にしてください。
（2018/06/30のcommitで技術教育の教材で使うメソッドを追加しています）

# 参考資料
[mruby-ev3rt API一覧](https://qiita.com/yamanekko/items/b5c8f6fcbd61daa40307)

# はまりポイント

### CygwinでのMRUBY_PATHの指定方法

Makefile.inc の以下について、WindowsでCygwinを使用している場合はWindowsのパスを指定してください。

```
# mrubyのパスを環境変数に設定するか、以下を使用してください
# MRUBY_PATH := /usr/local/mruby (ここにmrubyのパスをいれます)
```
↑のところを例えばこんな感じで

```
MRUBY_PATH := C:/cygwin64/home/yuri/mruby
```
既存のリモートリポジトリURLを新規作成したリポジトリのURLに変更する方法

## はじめに

この記事は、既存のリモートリポジトリからGitCloneする時に、新規作成したリポジトリのURLに変更する方法について書いたものです。

例えば、学習やコードリーディング用に他の人が作成したリポジトリを自分なりに色々といじりたいと思ったことってありません？

そのままクローンしてローカルでいじるだけでもいいんですが、せっかくだったらPushして自分の作業履歴をバージョン管理したいですよね。

この記事が少しでもお役に立てたら嬉しいです。

## 対象となる読者

* Gitコマンドについて基礎的な理解ができている人
* Githubへすでにアカウント登録している人



## 新規リポジトリの作成

まずはGitHubのページから、`New Repository`を選択し、新規リポジトリを作成します。

![new-repository.png](https://qiita-image-store.s3.amazonaws.com/0/195539/403d2bb7-882e-d922-e48d-feaa50885f26.png)


`Repository name`に任意のリポジトリ名を入力します。

![new-repository-002.png](https://qiita-image-store.s3.amazonaws.com/0/195539/01f5364d-66df-6f05-7784-70091fe8ca69.png)


問題がなければCreate Repositoryを押下しましょう。

![new-repository-003.png](https://qiita-image-store.s3.amazonaws.com/0/195539/5d9e6606-685c-1fe1-dcc6-c452a4275559.png)


` push an existing repository from the command line`にあるコマンドを使うので、ブラウザを開いたままにしておきます。

![new-repository-004.png](https://qiita-image-store.s3.amazonaws.com/0/195539/ba3f782e-9f85-cbd3-f60a-52ac4050162b.png)


```
# 新規作成したリモートリポジトリのURL
git remote add origin git@github.com:yuta-ushijima/sample.git
git push -u origin master
```

## ローカルでの作業

ここからはローカルでターミナルを使った作業になります。

まずは、現在のプロジェクトのリモート情報を以下のコマンドで確認しましょう。

```
git remote -v
```

次のような結果が返ってきます。

```
origin	git@github.com:StephenGrider/ReduxSimpleStarter.git (fetch)
origin	git@github.com:StephenGrider/ReduxSimpleStarter.git (push)
```

上記の情報を新規リポジトリのリモート情報に書き換えます。

```
git remote set-url origin git@github.com:yuta-ushijima/sample.git
```

書き換わったかどうか、もう一度`git remote -v`で確認してみましょう。

```
git remote -v
```

次のような結果が返ってので、ちゃんとリモート先が変更されているのが確認できます。

```

origin	git@github.com:yuta-ushijima/sample.git (fetch)
origin	git@github.com:yuta-ushijima/sample.git (push)
```

この状態で`git status`で差分を確認して見ましょう。

```
git status
```

何かしらの差分が出ているはずです。人によってはステージング前かもしれませんし、commit直前かもしれません。

```
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   package-lock.json

no changes added to commit (use "git add" and/or "git commit -a")
```

あとはそのままpushすれば、ブラウザの画面を更新すると、先ほどpushしたcommitが反映されているはずです。
【イベントレポート】サポート切れJavaフレームワークの WEBセキュリティ対策事例セミナー

本記事は、
つい先日第2版が出版された、通称「徳丸本」こと「体系的に学ぶ安全なWebアプリケーションの作り方」の著者 徳丸浩先生を基調講演にお招きし、
弊社スタイルズ、EGセキュアソリューションズ、SCSKが登壇した『[サポート切れJavaフレームワークの WEBセキュリティ対策事例セミナー](https://www.stylez.co.jp/news/20180627_seminar/)』(2018/6/27)のイベントレポートです。

 ![20180627_サポート終了Javaフレームワークセミナー](https://qiita-image-store.s3.amazonaws.com/0/223994/4eca861d-a167-9e14-7404-a68fa363881b.png)
　
業務システムやインターネットを活用している企業にとって、つまりほとんどの企業にとって、避けては通れないソフトウェアのサポート終了問題。
 
 　

本セミナーでは、Webシステムのセキュリティ対策の理想と現実を、
**・多くの企業のセキュリティコンサルティングをしてきたEGセキュアソリューションズ**、
**・顧客のアプリケーション保守を長期的に担っているSCSK**、
**・サポート終了したJavaフレームワークやOSSの移行ツールを開発・提供しているスタイルズ**
の3社から、
事例を交え、セキュリティ上考えなくてはいけない王道パターンと現実的な解決の手段や対策方法を講演しました。
　

　
▼当日の会場の様子
![20180627_サポート終了Javaフレームワークセミナー_会場](https://qiita-image-store.s3.amazonaws.com/0/223994/11ddb8f8-7885-73ec-9f9b-1f487f64da07.jpeg)

　
以下は今回のセミナーの概要。
　

#そもそもサポート切れとは？

- サポート切れ（サポート終了）するとセキュリティの脆弱性が発生しても、
脆弱性に対処するためのパッチが提供されないことを意味する

- ソフトウェアには、購入者に対する「約束」となる
サポートライフサイクルポリシーがある。

#システムのライフサイクルを考える
情報セキュリティの教科書としては、
システムを開発・構築する企画のタイミングで、

- ソフトウェアのサポート終了を見据えて、
どのような対策をとるかを考えておく必要がある。
　

#特に注意しなくてはいけない脆弱性とは？

- Windows XP のサポート終了が報道されたときに結構な騒動となったが、
Windows XPは、基本的にファイアーウォールの中にいるため、悪意の攻撃者が能動的な行動はとりづらい

- インターネットに出ているJavaフレームワークは、
ファイアーウォールの外側にいるため、インターネットを経由して、
悪意の攻撃者が能動的な行動をしやすい。


現実的な脆弱性の解としては、

- 後継ソフトウェアにマイグレーション
- サイトを閉じる

が教科書的に求められているとのことでした。




#Javaフレームワークのサポート切れを使うということは特に難易度が高い

サポート終了したソフトウェアは、
セキュリティパッチも更新されないため、
**使い続けるという選択肢はない。**

しかしながら、現実問題として、
サポート終了ソフトウェア、特にJavaフレームワークのような開発の現場で採用されたフレームワークのサポート終了に対して、

- 費用・効果・他の対応策の検討などから、
迅速に対応ができないことが多々ある。

けれど、**サポート終了のJavaフレームワークを続けるには、
相当な運用コストがかかる。**


なぜなら

- 脆弱性情報に目を光らせなくちゃいけない
- クリティカルな対応が求められてくる
- そのため、運用コストがかかる


#最後に

セミナー主催者としての感想を最後に。。

　
今回のセミナーでは、
予めセミナーお申込者から寄せられた「ご質問」を登壇者の方にディスカッション（インタビュー）形式でご質問をさせていただくコーナーを
スタイルズ主催セミナーとしては初めて試ませていただきました。
　

![20180627_サポート終了Javaフレームワークセミナー_ディスカッション](https://qiita-image-store.s3.amazonaws.com/0/223994/338003fb-beaf-f2fc-eca8-73f3e94ada61.jpeg)

インタビューアーとして、うまいインタビューではなかったところは反省しつつも、
最後には、追加の質問を会場でも多くいただき、
今まで企画してきたビジネスセミナーの中でも、
登壇者とご来場者のコミュニケーションを活発にすることができたセミナーとなりました！
　
ご来場いただいた皆様、優しく見守ってくださり、本当にありがとうございます。
　
　
追加のご質問やスタイルズのセミナー資料については、
[スタイルズコーポレートサイトのお問い合わせフォーム](https://www.stylez.co.jp/)からその旨ご連絡、ご請求をお待ちしております！