OmniAICreator/Qiita-1.07M huggingface dataset:
【コード0行】BitriseでiOSアプリのデプロイ自動化してSlackに通知するまで

副業でiOS開発をしているが、CI環境が整備されていなかったため、ずっと使ってみたかったBitriseを使ってリリースビルドの自動化を試してみた。

Bitriseについてや、初回のワークフロー(Appの登録など)は、色んなブログで紹介されているので、割愛。
下記ステップで段階的に着手してみた。

##### ステップ
1. Bitriseのwebサイトでリリースビルドを実行する:rocket:
2. 手元のmacで実行する:desktop:
3. リリースビルドが終わったらslackに通知する:satellite:
4. slackから実行できるようにする:helicopter:

## 1. Bitriseのwebサイトでリリースビルドを実行する
web上でWorkflowを作成して、ぽちぽちしてたら完成。簡単。。


Workflow全体
![app.bitrise.io_app_af197aaf40607adf(iPad Pro).png](https://qiita-image-store.s3.amazonaws.com/0/30423/236ffd48-93b0-7a8d-7583-398d1f1e47d3.png)



## 2. 開発環境で実行する
curlのコマンドがworkflowごとに用意されている。
`Start/Schedule a build` ボタンをタップして、 `Advance` タブの最下部にcurlのコマンドがあるので、コピペしてよしなに使う
<img width="1430" alt="bitrise_curl.png" src="https://qiita-image-store.s3.amazonaws.com/0/30423/580d60b8-8f08-5676-9597-080bdd179332.png">


## 3. リリースビルドが終わったらslackに通知する
Slackへ通知は下記手順でOK

1. Incoming WebhooksをSlackに追加
2. Slackのstepを作成し、Incoming Webhooksの `Webhook URL` をセット

詳しくは公式ブログ参照:
https://blog.bitrise.io/slack-away

<img width="1424" alt="bitrise_slack.png" src="https://qiita-image-store.s3.amazonaws.com/0/30423/75f5e5bf-d95f-5323-688d-f74186014797.png">

## 4. slackからBitriseのworkflowを実行する
BitriseにSlack用のIncoming Webhooksが用意されているので、そのwebhook URLをコピー

![](https://devcenter.bitrise.io/img/webhooks/webhook-providers.png)

SlackのOutgoing Webhooksで、特定のメッセージに反応して先ほどコピーしたwebhookのURLを叩くようにすればOK。
`[メッセージ] workflow:[workflow名]|branch:[branch名]` のフォーマットでつぶやくとBitriseのワークフローが走る。

フォーマットの詳しい説明は、下記を参照
https://devcenter.bitrise.io/webhooks/adding-a-slack-webhook/


## 完成:tada:
1行もコードを書かずにslackでリリースビルド実行 -> 結果をslack通知が実現できてびっくりした。
Bitrise便利。。
本業ではfastlaneとの連結を視野に入れていたけど、ワンチャンBitriseだけで済むかもしれない

<img width="553" alt="スクリーンショット 2018-08-12 17.18.05.png" src="https://qiita-image-store.s3.amazonaws.com/0/30423/210f732d-f27b-407a-7e76-8fe19d6fa45f.png">



## 詰まったこと
Code Signing Errorでコケる

```
Code Signing Error: No profiles for '{アプリ名}' were found:  Xcode couldn't find any iOS App Development provisioning profiles matching '{アプリ名}'.
```

**解決法**
codesigndocというBitrise製のツールを使って実行。
すると面倒な証明書周りのアップロードタスクを対話形式でやってくれる

https://devcenter.bitrise.io/code-signing/ios-code-signing/collecting-files-with-codesigndoc/
Discordのボイスチャンネルに誰かが入ったら通知するbot

# はじめに  
discordrbの記事が少ない！
rubyでbotが書きたい！

# 今回作るもの
タイトル通り  

# 手順
## discordrbのインストール

```shell
$ gem install discordrb
```

## Discord botのtokenを取得
[ここ](https://discordapp.com/developers/applications/)にアクセスし「Create an application」を押して１つapplicationを作る

CLIENT IDを取得

```
https://discordapp.com/oauth2/authorize?client_id=ここに取得したClientID&scope=bot&permissions=0
```
にアクセスしbotをServerに接続させる

するとさきほどのページのbotページからTOKENを取得することができる．

## botを作る

とりあえずソースコード

```ruby:bot.rb
TOKEN = '自分で取得してね'
CLIENT_ID = ID(数字)

# 通知用のチャンネルID
inform_channel = チャンネルID または '#チャンネルname'

# bot
bot = Discordrb::Commands::CommandBot.new token: TOKEN, client_id: CLIENT_ID, prefix:'/'

# 誰かがvoice channelに出入りしたら発火
bot.voice_state_update do |event|
    # 発火させたユーザー名を取得
    user = event.user.name

    # もしデータが空だと抜けていったチャンネルを取得
    if event.channel == nil then
        # チャンネル名を取得
        channel_name = event.old_channel.name

        # 退出したことをinform_channelに通知
        bot.send_message(inform_channel, "@everyone #{user} が #{channel_name}を出たで～")
    else
        # チャンネル名を取得
        channel_name = event.channel.name

        # 入室したことをinform_channelに通知
        bot.send_message(inform_channel, "@everyone #{user} が #{channel_name}に入ったで～")
    end
end

# botを起動
bot.run
```

### 説明?
`voice_state_update`：ボイスチャンネルで変更があれば発火するイベント
`event.user.name`：発生されたユーザ名を取得
`event.channel`：ボイスチャンネルに入室したとき情報が入る．退出したときはnilが入る
`bot.send_message(channel_id, '送りたい内容')`：channel_id（#channel_nameでも可）にメッセージを送信する

# テスト

```shell
$ ruby bot.rb
```

![03.png](https://qiita-image-store.s3.amazonaws.com/0/171487/7ef00f06-0c0a-6093-34e2-f9f3cd7bdfc7.png)
動いた
WordPress更新 FTP/FTPS 無効化

#環境
OS: Ubuntu18.04 LTS
WEB: Apache2.4
PHP: PHP7.2
DB: MySQL5.7

#対応
##Apache User/Group 確認
```terminal
$ vim /etc/apache2/envvars

// www-data というのを確認
export APACHE_RUN_USER=www-data
export APACHE_RUN_GROUP=www-data
```
##Apache User/Group を、オーナーにする
```terminal
// example DocumentRoot /var/www/wordpress
$ sudo chown -R www-data.www-data /var/www/wordpress
```
#参考
[Wordpressの更新で、FTP経由のアップデートを回避する方法](https://qiita.com/pugiemonn/items/c3f9bca255082a085b6c)
[ubuntuのapacheユーザーとグループ](https://qiita.com/shim0mura/items/191350e892ea9a310127)
Manjaro linux で Logicool マウスのレシーバーとマウスを接続するメモ

# はじめに
LogicoolのUnifyレシーバーは一つのUSB端子で複数のデバイス(マウス、キーボード等)を接続できるスグレモノですが、デバイスにこだわったり随時買い集めたりすると別々に購入することになります。
この時、Windowsなんかを持っていると勝手に接続してくれたりするのですが、Linuxしか使っていないガチプロやオタクはこの接続に少し手順が必要になります。

# フローチャート
1. 起動出来るWindowsを持っているなら素直にそちらで接続しましょう。
2. Ubuntu等のメジャーなOSではSolaarというツールが動くはずです。
   そちらをどうぞ (参考: https://qiita.com/nmatayoshi/items/e57b2b94d8b58746d361)
3. Linuxではよくあることですが、特定のツールが動かなかったりします(特にGUI等)。
   今回は、Solaarが動かないので、pairing tool というCUIのツールを使います。

# 手順
ここで、Arch系のOSはありがたいことにAURが使えます。あるものは使うに越したことはないのでそちらを使いましょう。
そのようなものがパッケージマネージャに無い場合は "linux logicool" 等で検索するとpairing tool を直接落として実行するやり方等のわかりやすいものがいくつかあるのでそちらを参考にして下さい

さて、実際の手順です。

まず、レシーバーをUSBに差し込み、デバイスの電源をオフにします。

```bash
yaourt pairing_tool
# (以下、yaourtの手順に従いダウンロード、インストール) 
ls -l /sys/class/hidraw/hidraw*/device/driver | awk -F/ '/receiver/{print $5}'
# ここで出てきた"hidraw0"等のデバイス名を用いる
sudo pairing_tool /dev/hidraw0
```

これでデバイスの電源をONにすれば認識してくれます
終わりです。

# 参考
https://wiki.archlinux.jp/index.php/Logitech_Unifying_Receiver#pairingtool
WordPress パスワード忘れたけどメールが送信できない対応

#事象
ワードプレスをインストールしたものの、時間が経ってパスワードを忘れてしまった！検索すると、md5でハッシュ化したパスワードをphpMyAdminでwp_usersのパスワードを書き換えるものばかり。

```
メールを送信できませんでした。
ホスティングサービス上で mail() 関数が無効になっている可能性があります。
```

#環境
OS: Ubuntu18.04 LTS
WEB: Apache2.4
PHP: PHP7.2
DB: MySQL5.7

#対応
##sendmail停止
```console
// sendmailが起動中か
$ sudo ps aux | grep sendmail

// sendmailを停止する
$ sudo service sendmail

// 停止したか確認
$ sudo ps aux | grep sendmail

// 停止していない場合
$ sudo pkill sendmail
```
##postfixインストール
```console
// postfix インストール
$ sudo apt install postfix

// postfix 起動
$ systemctl start postfix

// postfix 起動確認
$ ps aux | grep postfix
```
#まとめ
sendmailでやろうと思ったけれど、うまくいかずにpostfixで対応しました。突貫、md5でパスワードを書き換える方法でもいい気はしますが、もやっとするのでpostfixにて対応。
jsのbindは意味がわからない

jsのbindは意味がわからない。


> bind() メソッドは、呼び出された時に新しい関数を生成します。新しい関数が呼び出される時、this キーワードは与えられた値がセットされ、ます。2 個目以降の引数は、新しい関数より前に、ターゲット関数の引数として与えられます。
> [Function\.prototype\.bind\(\) \- JavaScript \| MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Function/bind)

「引数をbind(拘束)した新しい関数を作れる」という事はわかったけど、それ何が嬉しいの？と思っていた。
しかし先日、ある出来事をきっかけに理解することができたのでポエムを書いてみる。


---

> この物語はフィクションです。登場する人物はすべて架空のもので(略

---

私はmodule(もしくはpackage)の開発者。githubを通じて便利な関数を公開している。

先日も`redCharacter`という超絶便利な関数を公開した所だ。

```js
// java script
var redCharacter = function(val) {
  if (val >= 0) {
    return val;
  } else {
    return `<span style="color:red;">${val}</span>`;
  }
}
```

```coffee
# coffee script
redCharacter = (val)->
  if val >= 0
    return val
  else
    return "<span style=\"color:red;\">#{val}</span>
```

見ての通り、引数の数字がマイナスなら赤字を返すという関数だ。  
「赤字はdeficitだろ」というクレームはともかく、他にも要望が入った。

「文字色がredはドギツいので`#CC0000`くらいがいい」「いや`#990000`だ」「閾値はゼロ以外にも設定したい」などなど。  
仕方がないので仕様を変えてみた。

```js
// java script
redCharacter = function(val, color) {
  color = color || 'red';
  if (val >= 0) {
    return val;
  } else {
    return `<span style="color:${color};">${val}</span>`;
  }
}
```

```coffee
# coffee script
redCharacter = (val, color)->
  color = color or 'red'
  if val >= 0
    return val
  else
    return "<span style=\"color:#{color};\">#{val}</span>
```

公開して数日、プルリクエストが来た。

> はじめまして、こんにちは。
> あなたの作ったredCharacterを使わせていただいています。とても便利です。  
> しかし私のプロジェクトでは赤字を`#CC0000`に統一しています。なので`redCharacter(-100, '#CC0000')`といちいち色指定するのは不便です。  
> そこでbindできるように書き換えてみました。良ければPullお願いします。

ソースコードは以下のようになっている。

```js
// javascript
redCharacter = function(val) {
  var color, threshold;
  color = (this != null ? this.color : void 0) != null ? this.color : 'red';
  threshold = (this != null ? this.threshold : void 0) ? this.threshold : 0;
  if (val >= threshold) {
    return val;
  } else {
    return `<span style="color:${color};">${val}</span>`;
  }
}
``` 

```coffee
# coffee script
redCharacter = (val)->
  color = if @?.color? then @color else 'red'
  threshold = if @?.threshold then @threshold else 0
  if val >= threshold
    return val
  else
    return "<span style=\"color:#{color};\">#{val}</span>
```
使い方は以下。  
文字色が`red`で良ければそのまま使える。

```js
redCharacter(-100)
// '<span style="color:red;">-100</span>');
```

文字色を変えたければbindして新しい関数を作る。  
新しい関数は文字色を`#CC0000`に拘束してあるので、引数を都度指定する必要が無い。

```js
var newRedCharacter = redCharacter.bind({color: '#CC0000'})
newRedCharacter(-100)
// '<span style="color:#CC0000;">-100</span>'
newRedCharacter(100)
newRedCharacter(-20)
// 当然ながら何度でも使える
```

ちなみに、呼び出しが1回限りなら以下の方法でも良い。

```js
redCharacter.call({color: 'pink'}, -100)
// '<span style="color:pink;">-100</span>'
```


---

そんなわけでbindとは「引数をbind(拘束)した新しい関数を作れる」関数である。  
繰り返し使うカスタム関数を手軽に生成できるのが便利。


### おまけ
qiitaのmarkdownって色記号をバッククオートで括るとサンプル色見られるんすね。
`#ddd`  `#123` `#f90`
どうやって機械学習するの？

# はじめに
勉強したことをアウトプットする試み。
自分なりの思考でまとめてみる。
書いてる内容に対するご指摘は大歓迎！

機械学習とは何ぞやと自分なりに理解できたが、機械学習をどう使うかのイメージは分かりづらい。
私として素人目に機械学習に期待するのは、「これは何が写ってる？」「明日雨予報だけど売上はどんな感じ？」「ネット上からパンダの写真を集めてきて」「将棋で私に勝って」などなど。
でも、これを実現するためにどういう方法で学習させればいいのだろうか。

# 機械学習の手法
機械学習はどういうふう行われるのか。手法として大きく３つあるらしい。
１．教師あり学習（Supervised Learning）
　　入力値と出力値のセットを用いて学習させる。「入力と出力の関係」を学習するもの。
２．教師なし学習（Unsupervised Learning）
　　入力値のみを用いて学習させる。「データの構造」を学習するもの。
３．強化学習（Reinforcement Learning）
　　試行錯誤を通じて環境に適応するように学習させる。「価値を最大化するような行動」を学習するもの。

言葉の意味はわかるけど、実際どう使うのかイメージがわかない。

# 教師あり学習とは
既に答えが分かっているデータを何らかのアルゴリズムを用いて、入力（問）と出力（答）の関係性を獲得する学習手法。
学習で獲得した関係性を「学習モデル」とし、「学習モデル」に未知のデータを入力すると何かしらの出力を得るようになる。

この段階で、教師あり学習の完了となるわけね。

「学習モデル」というのは、入力と出力の関係性を「何かしらのアルゴリズム（数式やルールなど）」と「学習で得たパラメータ」とで構成されたものと理解している。
「学習で得たパラメータ」とは、なんとなく良い感じに出力にするために計算する時に加える手心（を数値化したもの）って感じ？

これらをざっくり言うと、答えが分かっている事柄、答えが予測できる事柄を学習させる手法ってことなんだと思う。

もう少し具体的に考えてみよう・・・
それじゃあ、写真画像を入力して「猫」か「犬」かを出力（判定）させる「学習モデル」を獲ようとした場合、
やることは、教師データ（入力値と出力値のセット）を使って学習させる。
>教師データ例
[入力値]画像A　[出力値]猫　・・・セットA
[入力値]画像B　[出力値]犬　・・・セットB
[入力値]画像C　[出力値]猫　・・・セットC
　　・
　　・
[入力値]画像n　[出力値]猫　・・・セットn
　
　

>[入力値]![image.png](https://qiita-image-store.s3.amazonaws.com/0/170424/80991576-1d43-0b3f-d598-353a9488891a.png)　[出力値] 猫　／　[入力値]![image.png](https://qiita-image-store.s3.amazonaws.com/0/170424/fb6540e8-b918-5765-bc64-fb74feea4dfd.png)　[出力値] 犬

上記のように「画像Aは猫ですよー」「画像Bは犬ですよー」って学習させるわけですね。
何かしらのアルゴリズムを使って・・・（何らしかのアルゴリズムは後日書として）

学習が完了すると「学習モデル」が出来上がる。
出来上がった「学習モデル」に猫か犬の画像を入力すると「猫」か「犬」を出力するわけだ。

”教師あり学習”いっちょ上がりっ！

# 教師なし学習とは
答えが分からないデータを何らかのアルゴリズムを用いて、データの持つ規則性や傾向を獲得する学習手法。

まあ、答えが分からないデータを学習させるわけだから、機械自身に何かを見つけ出してもらうわけだ。
与えられたデータの中から、よく似ているデータ、珍しいデータを選り分け、グルーピングしていく感じかな。

こちらも具体的に考えてみよう・・・
購買情報を元に顧客を数種類のグループに分けるような問題を解くことができるかな。
入力は購買情報や顧客情報、出力はグループとしてみよう。
>
|顧客番号|年齢|性別|生鮮食品平均購入額|生活用品平均購入額|惣菜弁当平均購入額|平均来店数|
|-------|--------|-------|-------|-------|-------|-------|
|A0100254|48|男|891|1547|0|5|
|A0201758|21|女|754|261|158|20|
|A0575462|60|女|259|501|586|12|
|A0250148|34|男|0|1238|0|2|
|A0365479|28|男|0|0|498|21|
|A0152473|54|女|843|247|163|24|
|　　.|　.|　.|　　.|　　.|　　.|　　.|　　.|

上記のようなデータを学習させると、何かしらの出力が得られて、
・グループAに分類された顧客は、惣菜弁当の購入金額が高い。
・グループBに分類された顧客は、全体的に購入金額が低い。
・グループCに分類された顧客は、生鮮食品の購入金額が高い。
などなどと分析する。
分析結果を「グループCの顧客には生鮮食品のセール情報をDMしてみよう」みたいなマーケティング戦略に使ったりするんだろうね。

”教師なし学習”いっちょ上がりっ！

# 強化学習とは
機械の行動に対して、アメ（報酬）を与えて、より価値が高くなる行動を選択させる学習手法。

何らかのアルゴリズムを使って出した行動に対して報酬を与え、報酬がより多く貰える行動を学習していく感じかな。

例えば、ロボットがボールを掴む動作を学習するとしよう。教師あり学習の場合、「腕や肘の関節が何度で、動作速度がXXのときは、掴め」などといちいち正解を教えてあげる必要がある。
しかし、強化学習の場合、うまくボールを掴めた行動に掛かった時間を報酬として与える。すると強化学習は「次はもっと早くボールを掴めるように、掴み方を少し変更してみよう」と制御アルゴリズムを自ら変更して行動する。これをたくさん繰り返すとボールを掴む動作がうまくなり、失敗しなくなるってことだね。
将棋や囲碁のAIにもこういった学習を行ってるみたいだ。

これは、機械自身が試行錯誤を繰り返し、少しずつ成長していく夢のある学習方法じゃないか！（でも、大変らしいｗ）

”強化学習”いっちょ上がりっ！

# まとめ
機械学習のどんな学習方法を選択するべきかを理解するには、経験がないとなかなか難しい。
やはり、試行錯誤を繰り返して、自分自身が強化学習していくべきだなｗ
日付比較の覚え方とDate.todayについて

#日付の比較について

日付を比較する時大なり小なりがどっちかなかなか覚えられないので覚え方を自分なりに考えて見たのでメモ。

比較の覚え方
未来の方が比重が大きい（未来の方が大切）ので未来が大きければ真

```
未来　＞ 　過去　　　true
```

未来の方が小さければ　偽

```
未来 　＜ 　過去           false
```

これで僕は覚えやすくなりましたwww

#Date.todayについて

~~何気なくDate.todayを使用していたがこれはUTCで出力されるので注意が必要
日本時間にするためにはDate.currentを使用する必要がある。~~

-追記-
znzさんにご指摘頂き修正しました（ありがとうございます！）

railsで使用する際、Date.tomorrowやDate.yesterdayはapplication.rbのタイムゾーンを反映するのにDate.todayは環境変数で指定したタイムゾーンを反映しており、指定がない場合はUTCになります。

application.rbで指定したタイムゾーンを使用する場合はDate.currentとする。

application.rbでのタイムゾーンの指定

```
config.time_zone = 'Asia/Tokyo'
config.active_record.default_timezone = :local
```
CentOS7でメールサーバを立てるために必要な要素まとめ

## はじめに
CentOS7でメールサーバを立てるためには、結構やることが多くまず何が要素として必要なのかわからず詰まってしまいがちだと思うので、メールサーバ構築に必要な要素をまとめてみます。

## 必要な要素（大まかに）
- サーバ用PCの準備（LinuxPCの用意もしくはレンタルサーバ・VPSの契約）
  - さくらのVPS, ConohaVPSなど
- 固定IPの取得（VPSやレンタルサーバを契約するとついてくるはずです）
- ドメイン取得
  - お名前.comなど
- DNS設定
  - Aレコード
  - MXレコード
- ポート開放
  - firewalld, iptables, VPS側の設定
  - 25, 993, 465など
- 送信設定
  - Postfix
  - SMTP認証など
- 受信設定
  - Dovecot
  - バーチャルユーザ作成
- SSL/TSL設定（証明書発行）
  - Let's Encryptなど
- メーラー（もしくはメール送信コマンド）
  - Thunderbirdなど
  - sendmailコマンドなど
- デバッグ手法
  - ログ出力用の設定
  - `$ tail -F /var/log/maillog`

少しずつ更新していきます。
macOSでbash-completionを有効にする(ついでにgit-completionも)

* 要Homebrew

```bash
brew install bash-completion
echo "[ -f /usr/local/etc/bash_completion ] && . /usr/local/etc/bash_completion" >> ~/.bash_profile
ln -s /Library/Developer/CommandLineTools/usr/share/git-core/git-completion.bash /usr/local/etc/bash_completion.d/git-completion.bash

exec $SHELL -l
```

これで各種コマンド入力時にTABキーを押下すると補完が効くようになります。
自分用 Python Tips

# Style
主にPEP8で規定されている内容について、特筆しておきたいものを書く

## 条件分岐
- リストなどが空であることを判定する際には、length()でそのサイズが0であることをチェックするよりも、対象のオブジェクト自身がFalse判定となることを利用する方が好ましい
    - ex)
        - x: if length(a_list) == 0:  
                 （リストが空だった場合の処理）
        - o: if a_list:  
                 （リストが空だった場合の処理）

# リスト内容表記
##
gifアニメに書き出したら、インスタンス内のタイムラインが動かない場合

Animate CCで作ったアニメーションをgifアニメに書き出したところ、
メインのタイムラインしか動いていなくて、ムービークリップのインスタンスが動かないと言われたので調べた。

確かに、ムービークリップのタイムラインは動かないまま再生される。
だいたい、Animate CC上でも、メインタイムラインでプレビューするとインスタンス自体のタイムラインは動いてないように見える。
Google先生に教えを仰いだ結果・・・

## 結論
**インスタンスのビヘイビアーを「グラフィック」に変更せよ**

なぜ「ムービークリップ」のままでは、その中のタイムラインが動いてくれないのかは分からない。
そういう仕様なんだろうけど、どうしてそういう仕様なのか、その思想は知らん。

flashはもう死んだ感がすごくて、検索しても情報が少なかった。
そんな中で、正解に導いてくれたページがこちら。
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q12146130807
まさか知恵袋に解答が書いているケースがあるとは。
機械学習知識ゼロの囲碁キチが3か月で囲碁AIを作った話　～GUI編～

## **前回まで**
[機械学習知識ゼロの囲碁キチが3か月で囲碁AIを作った話 ～概要編～](https://qiita.com/intenseG/items/2fe5f867b0afe439fc6b)

[機械学習知識ゼロの囲碁キチが3か月で囲碁AIを作った話 ～導入編～](https://qiita.com/intenseG/items/34b452cbab04817cdaef)

[機械学習知識ゼロの囲碁キチが3か月で囲碁AIを作った話 ～棋譜学習編～](https://qiita.com/intenseG/items/73cd082443aed2eb7b5d)

[機械学習知識ゼロの囲碁キチが3か月で囲碁AIを作った話 ～番外編～](https://qiita.com/intenseG/items/7c51b7da8ffb07b00111)

## **概要**
今回は、棋譜学習させて出来上がったモデルファイルをGUIで動かす方法について解説していきます。

## **手順**
1. Sabakiをインストール
2. バッチファイルの作成
3. Sabakiに囲碁AIを設定

## **Sabakiのインストール**
**囲碁AIをコマンドプロンプト上で動かせたけど、やっぱりネット碁みたいにグラフィカルな碁盤と碁石で動かしたい！**

そこで登場するのがGUI(グラフィカルユーザインタフェース)です。

囲碁のGUIソフトはいくつかありますが、開発・更新が活発(2018/8/11時点)で、GUIも綺麗な[Sabaki](https://github.com/SabakiHQ/Sabaki)を使っていきたいと思います。

それではまず、[Sabaki](https://github.com/SabakiHQ/Sabaki)のページを開き、releasesタブを開いてください。

開けたらSabakiの最新版をインストールしましょう。

ここで注意点があって、releases画面からインストールする際にOSがWindowsの64bitなら```sabaki-v0.35.1-win-x64-setup.exe```を選択する必要があるということです。

Windowsの32bitなら```sabaki-v0.35.1-win-ia32-setup.exe```を選択します。

後は画面に従っていけばインストールは完了です！

## **バッチファイルの作成**
Sabakiのインストールが出来たら、次はSabaki上で動かすためのバッチファイルを書いていきます。
まず、お好きなテキストエディタで新規ファイルを作り、以下の一行を追記してください。

- CPU版 持ち時間無し 1手3秒
```python pyaq.py --main_time=0 --byoyomi=3 --cpu```

- GPU版 持ち時間無し 1手3秒
```python pyaq.py --main_time=0 --byoyomi=3```

追記できたら、ファイル名を```start.bat```にして **Pyaqフォルダ直下に保存しましょう。**

今後、囲碁AIの設定を変えたいときは```start.bat```を編集すればOKです！

## **Sabakiに囲碁AIを設定**
やっとここまで来ました。Sabakiに囲碁AIの名前とパスを登録してGUIで動かしてみましょう！

まず、SabakiのEngineタブからManage Engines...を開いてください。開いた画面がプログラムの登録画面です。

開いたら左下のAddボタンを押してプログラム登録フォームを追加し、一番上の段に囲碁AIの名前、2段目に先ほど作ったbatファイルのフルパスを入力しましょう。

![igo_AI_qiita1.png](https://qiita-image-store.s3.amazonaws.com/0/228364/49b97cd4-3c73-bcee-37e6-202a1ec8102b.png)

これで囲碁AIをSabakiで使えるようになりました。

EngineタブからAttach...の順に開き、対戦者のところに先ほど登録した囲碁AIの名前を指定してOKボタンを押せば対戦が始まります！

**[2024/02/02追記]**
Sabakiのバージョンアップの影響（？）で対戦者のところに囲碁AIを指定しても自動的に対局が始まらなくなったようです。
**キーボードのF10キーを押して着手を生成することで人間 対 AIで対局することが出来るようになります（エンジンメニューから着手を生成を選択してもOK）**

![igo_AI_qiita2.png](https://qiita-image-store.s3.amazonaws.com/0/228364/9a65b422-0a42-772f-7e44-299ec1175daf.png)

また、EngineタブからToggle GTP Consoleを開くと、対戦中に囲碁AIの思考ログを見ることができるのでオンにしておくことをオススメします。

![igo_AI_qiita3.png](https://qiita-image-store.s3.amazonaws.com/0/228364/3e97fd1e-da92-6942-6ebe-1b0342126a5b.png)

**もし、エラーが出て対戦が始まらない場合は、学習がうまくいってないか、batファイルのパス指定が間違っている可能性が高いです。**

## **あとがき**
囲碁が好きすぎて機械学習という未知の世界に飛び込んでみましたが、非常に面白いですね！

囲碁AIを作り始めてから、これはスマホアプリに導入すると面白いんじゃないか、とか色々な可能性を発見できたことは非常に大きかったんじゃないかなと思っています。

~~なんといっても自分の棋譜だけを学習させたオレオレ囲碁AIとか楽しすぎる！！！~~

## **参考リンク**
- [Sabaki](https://github.com/SabakiHQ/Sabaki)
- [Pyaq](https://github.com/ymgaq/Pyaq)
- [囲碁AI製造機](https://colab.research.google.com/drive/1qTJY_0AfrtwiyGYnmd6PZweWw1zG7n33)
PythonでJSONをゴリ押してみる

Pythonで、さくっとWeb APIにQueryを投げたい。
ただ、少量とは言えど、JSONをべた書きしたくない。

少量のJSONであれば、dictとlistを組み合わせて、ゴリ押しで書けます。

例えば、以下のようなJSONを書きたい場合を考えます。

```text:sample
{
    "hostname" : "web",
    "interfaces" : [
        {
            "ipaddress" : "127.0.0.1",
            "port" : "80"
        }
    ]   
} 
```

Python3で書いてみます。コードは以下の通りです。

```python:sample.py
import json

json_query = {}
json_query["hostname"] = "web"
json_query["interfaces"] = []
json_query["interfaces"].append({})
json_query["interfaces"][0]["ipaddress"] = "127.0.0.1"
json_query["interfaces"][0]["port"] = 80

print(json.dumps(json_query, indent=2))
```

ちなみに、typeを出力した結果は以下の通りです。

```python:sample.py
print(type(json_query))
print(type(json_query["interfaces"]))
print(type(json_query["interfaces"][0]))
```

```text:result
<class 'dict'>
<class 'list'>
<class 'dict'>
```

dictは要素名や[]を指定して代入し、listにはひたすらappendを繰り返します。
この2つを組み合わせて、さくさくっとJSONを書けます。
ローカル開発環境構築（MySQL編）+Workbench接続

社内研修用に手持ちのPC端末上に仮想のローカル開発環境（VM）を構築し、そこにMySQLをインストールして、Workbenchから接続する方法を模索していたので、備忘録＋参照用に記載しておきます。  

### ■環境

* 使用PC：Windows10  

* 構築する仮想マシン：Ubuntu16.04

### ■必要なソフトウェアのインストール


1. Vagrant
https://www.vagrantup.com/downloads.html

2. VirtualBox
http://www.oracle.com/technetwork/server-storage/virtualbox/downloads/index.html?ssSourceSiteId=otnjp

3. Workbench
https://dev.mysql.com/downloads/workbench/

WindowsでMySQL Workbenchをインストールして実行するには、以下のライブラリがインストールされている必要があります。  

* Microsoft .NET Framework 4.5
https://www.microsoft.com/ja-JP/download/details.aspx?id=30653


* Visual C++ Redistributable for Visual Studio 2015（Visual Studio 2015 の Visual C++ 再頒布可能パッケージ）
https://www.microsoft.com/ja-JP/download/details.aspx?id=48145

ライブラリがインストールされていれば、ページ下部に進みOSを選択して```Download```をクリック
![79d974dd-45f6-4eff-97d5-084593aaa87a.png](https://qiita-image-store.s3.amazonaws.com/0/94953/de7b2c36-2d8c-d239-a705-f7bda2386a04.png)


以下の画面が表示されれば、<b>```No thanks, just start my download.```</b>をクリック。ダウンロードされたインストーラの指示に従いインストールを行って下さい。
![af09b9a9-6af4-4d13-b993-b15aa15a68b9.png](https://qiita-image-store.s3.amazonaws.com/0/94953/08c96550-1737-5585-1bfc-54b09b0ef557.png)


### ■ローカル開発環境（VM）の構築
今後仮想環境を複数作成する可能性を考慮して、仮想環境を括る”Vagrant”をCドライブ直下に作成し、その下に今回作成する仮想環境のディレクトリを作成

```
> mkdir C:\Vagrant\mysql_ubuntu1604
```

cdコマンドで移動

```
> cd C:\Vagrant\mysql_ubuntu1604
```

Vagrantfile の作成

```
> vagrant init bento/ubuntu-16.04
```

Vagrantfileの編集　　
作成されたVagrantfileをエディタで開き、35行目、以下の部分のコメントアウトを外す

```
config.vm.network "private_network", ip: "192.168.33.10"
```

VMの起動

```
> vagrant up
```

VMへSSH接続

```
> vagrant ssh
```


### ■Ubuntuの日本語化

```
$ sudo apt-get -y install language-pack-ja-base language-pack-ja ibus-mozc
```


```
$ localectl set-locale LANG=ja_JP.UTF-8 LANGUAGE="ja_JP:ja"
// パスワードを入力
```


```
$ source /etc/default/locale
```


```
$ echo $LANG
ja_JP.UTF-8
```


### ■Ubuntuの諸々アップデート
```
sudo apt-get update && sudo apt-get -y upgrade && sudo apt-get -y dist-upgrade && sudo apt-get -y autoremove && sudo apt-get -y autoclean
```

```
sudo init 6
// 再起動
```

### ■MySQLインストール
```
sudo apt-get install mysql-server
// rootのパスワード設定
```

### ■よく使うコマンド
MySQLバージョン確認

```
$ mysql --version
mysql  Ver 14.14 Distrib 5.7.22, for Linux (x86_64) using  EditLine wrapper
```

MySQLにrootユーザでログイン

```
$ mysql -u root -p
// パスワードを入力
```

MySQLの状態確認

```
$ mysqladmin ping -u root -p
Enter password:
mysqld is alive
```

### ■Workbenchの設定
VagrantでSSH接続中であればexitしておく  
Workbenchを起動したらAdd Connectionsをクリックして以下画像のように設定
![03281efb-3584-4055-9be0-147a7288b6da.png](https://qiita-image-store.s3.amazonaws.com/0/94953/730b0b6f-1722-9091-ff2e-b6389e514314.png)
![8fc914c2-d96f-48a5-8da2-672774c36a64.png](https://qiita-image-store.s3.amazonaws.com/0/94953/ca0dbbd9-dd2e-77b6-6a3e-0e9fc0dedeaa.png)

VM上のMySQLに接続できました。
![2018-08-11.png](https://qiita-image-store.s3.amazonaws.com/0/94953/dfbd923b-6c1e-41d1-d858-893858f7bb13.png)


### ■参考サイト  
[便利な公式ツールMySQL Workbenchの使い方と日本語化方法](http://proengineer.internous.co.jp/content/columnfeature/6605)
※日本語化はかかる手間と得られる恩恵が見合わない気がするのでやりませんでした。
ネストしたリストや辞書をPandasデータフレームに格納

自分でネストしたリストや辞書をPandasデータフレームに格納しようとしてもうまく行かないことが多かった。この度、以下のリンクでJason形式をデータフレームに変換するPandasの機能を読んだ。
以下のやり方でも成功するまでに時間がかかったが、コツは「自分のネストの仕方をリンクのやり方に合わせること」だった。

https://note.nkmk.me/python-pandas-json-normalize/
Windows10インストール用USBをLinux上で作る

# はじめに
Windows10を使っていたが、ある日突然SSDがお亡くなりになった。
リカバリー用のメディアも作っておらず、途方に暮れそうになったところを頑張ったメモ。

# 必要なもの

- USBメディア。今回は32GBのものを使用。8GBあれば足りる？
- USBが使えるLinux。ディストリビュージョンは何でも良いはず。今回は Raspbian on Raspberry Piを使用。
- Windows10インストールイメージを入手するためのインターネット接続環境。

# Windows10インストールイメージの入手
今復旧したWindows端末から検索するとなぜか出てこないが、
Android端末で「Windows10 インストールイメージ」で検索すると下記URLがヒットするので、
ここからイメージのURLを特定して、Linux端末でwget等でダウンロードする。
https://www.microsoft.com/ja-jp/software-download/windows10ISO

# USBメモリをブータブル化
持っていたUSBメモリはブート非対応のものだったので、fdiskでブータブル化する。

~~~
sudo fdisk /dev/sdb
d (すでにある領域をとりあえず消しておく)
n
p (プライマリパーティションを作る)
1 (第1パーティションを作る)
(開始セクタの指定。全領域使用で良ければそのままエンター)
(終了セクタの指定。全領域使用で良ければそのままエンター)
t (パーティションタイプを変更する)
7 (NTFS/exFATとかはこの番号だと思う)
a (ブートフラグ(アクティブフラグ)を立てる)
w (書き込み)
~~~

# USBメモリをフォーマット
~~~
sudo mkfs -t vfat /dev/sdb1
~~~

# ダウンロードしたWindows10インストールイメージのファイルをUSBメモリへ突っ込む
~~~
sudo mkdir /mnt/iso
sudo mount -t iso9660 -o loop (Windows10インストールイメージファイルパス) /mnt/iso
sudo mkdir /mnt/sdb1
sudo mount -t vfat /dev/sdb1 /mnt/sdb1
cd /mnt/sdb1
sudo cp -r /mnt/iso/* .
~~~

# 後処理
~~~
cd
sudo umount /mnt/iso
sudo rm -r /mnt/iso
sudo umount /mnt/sdb1
sudo rm -r /mnt/sdb1
~~~

# 私はこれでインストールできました
あとはSSDを換装した我がPCに接続して、ブートプライオリティを変更して、無事起動&インストールできました。

# 最後に
- 持ってて良かったラズパイ！
- ファイルの中身自体はコピペで済むなんて、良い時代になったものだ。
- バックアップはちゃんとしておきましょう。
JSTQB AL テストマネージャ 第7章 210分

### 参考
ありがとうございます

- [Advanced Level シラバス日本語版 テストマネージャ](http://jstqb.jp/dl/JSTQB-Syllabus.Advanced_TM_Version2012.J03.pdf)

- [スクエアリング　｜　用語集](http://squaring.jp/term/terms.do)

- [テストマネージャ試験対策勉強会](https://www.slideshare.net/mhlyc/ss-63870834)

## 7.2 個人のスキル

テスト担当者のスキル向上

- ソフトウェア・システムの利用
- ドメインまたはビジネスについての知識
- 分析、開発、テクニカルサポートを含む、ソフトウェア開発プロセスの様々なフェーズでの活動
- ソフトウェアテストの活動


スキルアセスメントスプレッドシートを使用して、チームの強みと弱みを識別できる。

- 理想的なテストチームは、スキルと経験度合いが混在している

## 7.4 組織内におけるテストの適合
![image.png](https://qiita-image-store.s3.amazonaws.com/0/10966/8e373382-63a0-5838-9554-f50ef4fe082b.png)

## 7.5 モチベーション
## 7.6 コミュニケーション

- テストプロダクトの文書化
- レビュー済みのドキュメントのフィードバック
- 情報の収集と拡散



*７．４のテストチームの分類と、メリットとデメリットを抑えればよし。*
JSTQB AL テストマネージャ 第６章 135分

### 参考
ありがとうございます

- [Advanced Level シラバス日本語版 テストマネージャ](http://jstqb.jp/dl/JSTQB-Syllabus.Advanced_TM_Version2012.J03.pdf)

- [スクエアリング　｜　用語集](http://squaring.jp/term/terms.do)

- [テストマネージャ試験対策勉強会](https://www.slideshare.net/mhlyc/ss-63870834)



## 6.2 ツール選択

#### 6.2.1 オープンソースツール

```:オープンソースツール
オープンソースなツール
```

- 注意事項
 - 初期購入コストは高くないが、正式なサポートがほとんどない。
 - ただし、非公式であったりするサポートをユーザに提供する熱心なサポータが存在する。
 - 特定の問題を解決したり、単一の問題に対処したりするために作成されており、類似のベンダーツールの機能のすべては実行できないことがある。

#### 6.2.2 カスタムツール

#### 6.2.3 投資効果（ROI）

ROIを固定費と初期コストの両方で検討する

- 初期コスト
 - 目的と目標を満たすためのツール要件の定義
 - 適切なツールとツールベンダーの評価および選択
 - ツールの購入、適用、または開発
 - ツールの初期トレーニングの実行
 - 他のツールとの統合
 - ツールをサポートするために必要なハードウェア／ソフトウェアの購入
- 固定費
 - ツール所有コスト
     - ライセンス料金およびサポート料金
     - ツール自体のメンテナンスコスト
     - ツールにより作成された成果物のメンテナンス
     - 継続的なトレーニングおよびメンタリングのコスト
 - 別の環境へのツールの移植
     - 将来のニーズへのツールの適用
     - 選択したツールを最適に使用できるようにするための品質とプロセスの改善

- ROIを検討する際のリスクの考慮
 - 組織の未成熟性
 - テスト対象のソフトウェアの変更により、ツールによる成果物に複数の版（リビジョン）が必要となるため、ツールによる成果物のメンテナンスが困難となる可能性
 - テストアナリストによるテストタスクへの関与の減少がもたらす、テスト価値の低下
     - たとえば、自動化したスクリプトを実行しているときのみ、欠陥検出の効率が低下してしまうなど


#### 6.2.4 選択プロセス

以下、検討する必要あり
- ビジネスにとっては、、、、
- プロジェクトにとっては、、、、
- ツールの利用者にとっては、、、、


#### ツールのライフサイクル
- 調達
- サポートとメンテナンス
    - ツールの継続したサポートとメンテナンス
- 進化
    - 改造の検討
- 廃棄
    - ツールの使用をやめる

#### ツールのメトリクス

収集するデータの種類
- テストマネジメントツール
    - 実行ステータス（合格、不合格、スキップ、ブロック、待ち行列内）
- 欠陥マネジメントツール
- 静的解析ツール
- 性能テストツール
- カバレッジツール

[JSTQB ALへの道](http://jasst.jp/symposium/jasst15hokkaido/pdf/S3-1-1.pdf)

>投資効果ROIは重要とみた。
ツールの導入の失敗は、ここの考慮ができていないことが多いから。
自動化とかもそうだけど、自動化すればコストは下がる。。。と簡単にいうけれど、
導入コストやメンテナンスコストを考えると、たいていはコストオーバーになりま
す。
Android:SDカード上のHTMLファイルを表示するのに苦労したので

# はじめに
Androidタブレットで多量な画像ファイルと音楽ファイルを持ち歩きたいという要望から、WebViewを使って簡単なアプリを作ろうかとしたところ意外と苦労したので。。

#タブレット端末の環境
Lenovo 501LV (Android 5.0.2, API21)

# 外部SDカードのパス
``` file:///storage/sdcard1 ```

最初落とし穴は
「SDカード上のHTMLファイルを表示する」
でググったたこと、、

次に
Lenovo 501LVでは、`getExternalStorageDirectory()`で
SDカードのパスがひろえなかった。。（機種によっては内部ストレージのパスを返すらしい）

で、最終的には
ログをちゃんとみてたら

```
D/Environment: getStorageVolume,  volume:StorageVolume:
        mStorageId=65537 mPath=/storage/emulated/0 mDescriptionId=17040812 
        mPrimary=true mRemovable=false mEmulated=true mMtpReserveSpace=10 
        mAllowMassStorage=false mMaxFileSize=0 mOwner=UserHandle{0} mUuid=null 
        mUserLabel=null mState=mounted 
D/Environment: getStorageVolume,  volume:StorageVolume:
        mStorageId=131073 mPath=/storage/sdcard1 mDescriptionId=17040810 
        mPrimary=false mRemovable=true mEmulated=false mMtpReserveSpace=0 
        mAllowMassStorage=true mMaxFileSize=4294967295 mOwner=null mUuid=0403-0201 
        mUserLabel=null mState=mounted 
```


`mPath=/storage/sdcard1`

(・・;)
ココでした。。

ｵﾜﾘ
CloudFormation Fn::Cidr の実行例

Fn::Cidr関数の実行例がなくて実行イメージがわからなかったので記載

使い方は[Fn::Cidr - AWS CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-cidr.html)を参照。

# サンプルテンプレート
```yaml
---
AWSTemplateFormatVersion: '2010-09-09'
Description: 'Amazon EKS Sample VPC'

Parameters:
  VpcBlock:
    Type: String
    Default: 192.168.0.0/16
    Description: The CIDR range for the VPC. This should be a valid private (RFC 1918) CIDR range.

Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref VpcBlock
      EnableDnsSupport: true
      EnableDnsHostnames: true

Outputs:
  Subnets:
    Description: Output Fn::Cidr
    Value: !Join [ ":", !Cidr [ !Ref VpcBlock, 10, 8 ] ]
```

# 結果
リストで取得できるのね。
![Screen Shot 2018-08-11 at 15.04.34.png](https://qiita-image-store.s3.amazonaws.com/0/230552/c7325dac-59c6-9f69-1911-7baf2bff209a.png)

# 所感
この関数でハードコードする部分が減りそう。
テンプレートの再利用にも役に立ちそう。
追悼ワインバーグ

2018/8/7にワインバーグが亡くなりました(ということを今日知りました)。ので、追悼として、僕が影響を受けたワインバーグの本を紹介していきたいと思います。

ワインバーグを知らない方はぜひ<a href=https://ja.wikipedia.org/wiki/ジェラルド・ワインバーグ>Wikipedia</a>を参照してみてほしいです。〜の法則みたいなユーモアに富んだ警句みたいなものが沢山めっちゃ見れます。

なお今回の記事は勢いに任せて一気に書いてしまっています。結構間違いがあると思いますのでご了承願います。

ほんでワインバーグという人がどんな人かというと、エドワード・ヨードンとかビル・ゲイツと一緒にIT殿堂入りしている人なんで偉大な人みたいなんですけど、僕にとっては、プログラミングという極めて論理的な作業に対して心理学とか社会学とかいう人文系の知識を持ち込んだら面白いんじゃねえかという主旨の本を書く人です。

ITに関してかなり初期(がいつからか分からんが)から活動している人で影響力が強く、例えば、<b>レビューの指摘を受けてもそれはコードに対するものであなたに対してではない</b>とか、<b>品質というものは相対的なものだ</b>とか、そういうことが本に書いてあれば、それは直接的であれ間接的であれワインバーグの影響を受けていると言っていいと思います。ていうか、僕の知る限りワインバーグの本が出たのって1970〜2010くらいなので、ワインバーグがどのくらいソフトウェア文化に影響を与えたかが今からすると良く分からないというのが正直なところです。でもいい本はいっぱいあります。

ウチの本をひっくり返したところ、<a href=http://amzn.asia/h1g0gVm>プログラミングの心理学</a>がいっちゃん古くて1971年に出版されています。47年前に書かれたこの本では、認知的不協和という心理学的現象が紹介されます。これは、乱暴に要約すると、人間は自分が作品にかけたコストに応じて自分と作品を同一視する傾向があるというものです。つまりプログラマーにとってプログラムは自分と同じだと思う傾向が強いので、プログラマーはプログラムと自分を分離して考えるよう気をつけなければならないし、プログラミングに関わる人はプログラマのエゴを傷つけないよう慎重に言葉やふるまいを選ぶ必要があるということが述べられています。

プログラミングの心理学がプログラミング×心理学であるとすれば、<a href=http://www.kyoritsu-pub.co.jp/series/38/>ソフトウェア文化を創るシリーズ</a>はプログラミング×社会学っていう感じの本で、全4作、5年もかけて出版されたこのシリーズは現代のソフトウェア管理の土台の部分を固めた本の一つと言っていいんじゃないかと思います。内容は、品質とは何か(1)、ソフトウェアをどう測定するか(2)、いかにして適切に組織を管理するか(3)、そして組織変革をどう管理するか(4)と多岐に及びます。
個人的にこのシリーズで最も衝撃的だったのは変革管理という概念です。Aという状態からBという状態に組織が変革する場合、A→Bとはならず、A→カオス期→Bという順序で変革が起こり、そしてそれは管理可能であるということです。変革を管理するって、普通あんまり考えなくないですか？まあ、このシリーズは多岐に渡りすぎてて正直半分も理解できていないのですが、、、でもとても大事なことが書いてあるように思います。

個人的にワインバーグ本で最も好きな書籍は<a href= http://amzn.asia/9tSD4d7>コンサルタントの道具箱</a>で、僕にとっての行動の指針みたいなものです。金の鍵とかジャイロスコープ、酸素マスクなど謎のメタファがめっちゃあってワインバーグ節の真骨頂って感じがします。まあ、現実には、僕はこの本の10%も実践できていないんですけど。。。
この本を含め、ワインバーグの本には<b>適合的</b>という言葉が結構出てきます。この意味がどうもはっきりしないのですが、可能な限り感情を排除して妥当な行動するみたいな意味なんじゃないかと思うんですがどうでしょう。
ワインバーグはいつも、人間は弱くて馬鹿な生き物なんだから失敗して当たり前なんじゃねという立場で本を書いているように僕には感じられて、それはワインバーグがクローン病を患っていたことと無関係ではないように思います。弱い体を駆使して過酷な現実に対処する方法を模索する人、それが、僕の持つワインバーグのイメージです。

興味を持たれた方はぜひワインバーグ本を読まれてください。
DirectX12 事始め フェンスの生成&シェーダ

今回は、フェンスとシェーダを書いて行きます。
フェンスは裏、表画面の入れ替えの待機を主に行うものです。

```Fence.h
#include "Obj.h"
class Device;
class Queue;
class Fence :
   public Obj
{
public:
   // コンストラクタ
   Fence(Device* dev, Queue* queue);
   // デストラクタ
   ~Fence();

   // 待機処理
   void Wait(void);

   // フェンスの取得
   ID3D12Fence* Get(void) const {
      return fence;
   }
   // フェンス値の取得
   UINT64 GetCnt(void) const {
      return cnt;
   }
private:
   // フェンスの取得
   HRESULT CreateFence(void);
   // フェンスイベントの生成
   HRESULT CreateEvt(void);

   // デバイス
   Device* dev;
   // コマンドキュー
   Queue* queue;
   //フェンス
   ID3D12Fence* fence;
   //フェンスイベント
   HANDLE handle;
   //フェンス値
   UINT64 cnt;
};
```

```Fence.cpp
#include "Fence.h"
#include "Device.h"
#include "Queue.h"

// コンストラクタ
Fence::Fence(Device* dev, Queue* queue) :
	dev(dev), queue(queue), fence(nullptr), handle(nullptr), cnt(0)
{
   CreateFence();
   CreateEvt();
}
// デストラクタ
Fence::~Fence()
{
   Release(fence);
   delete queue;
   delete dev;
}
// フェンスの取得
HRESULT Fence::CreateFence(void)
{
   result = dev->Get()->CreateFence(cnt, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&fence));

   //フェンス値の更新
   cnt = 1;

   return result;
}
// フェンスイベントの生成
HRESULT Fence::CreateEvt(void)
{
   handle = CreateEventEx(nullptr, FALSE, FALSE, EVENT_ALL_ACCESS);

   return S_OK;
}
// 待機処理
void Fence::Wait(void)
{
   //フェンス値更新
   ++cnt;

   //フェンス値を変更
   result = queue->Get()->Signal(fence, cnt);

   //完了を待機(ポーリング)
   while (fence->GetCompletedValue() != cnt)
   {
      //フェンスイベントのセット
      result = fence->SetEventOnCompletion(cnt, handle);

      //フェンスイベントの待機
      WaitForSingleObject(handle, INFINITE);
   }
}
```

次にシェーダを書いて行きます。

```Shader.hlsl
Texture2D<float4> tex : register(t0);
SamplerState      smp : register(s0);

//ワールドビュープロジェクション
cbuffer wvp : register(b0)
{
   //ワールド行列
   float4x4 world;
   //ビュープロジェクション行列
   float4x4 viewProjection;
}
//出力
struct Out
{
   //システム座標
   float4 svpos  : SV_POSITION;
   //座標
   float4 pos    : POSITION;
   //uv値
   float2 uv     : TEXCOORD;
};
//入力
struct Input
{
   //座標
   float4 pos : POSITION;
   //uv
   float2 uv  : TEXCOORD;
};
// 頂点シェーダ
Out VS(Input input)
{
   input.pos = mul(mul(viewProjection, world), input.pos);
   Out o;
   o.svpos = input.pos;
   o.pos   = input.pos;
   o.uv    = input.uv;

   return o;
}
// ピクセルシェーダ
float4 PS(Out o) : SV_TARGET
{
    return float4(1, 1, 1, 1);
}
```

シェーダはこんな感じです。
最終的には白に染まった三角形が描画されます。
Order graph using python for comparing time complexity

```python
import math
import numpy as np
import matplotlib.pyplot as plt 

n = np.arange(5, 10, 0.1)
y = [nn*np.log(nn) for nn in n]
plt.plot(n,y,label="n*log(n)")
y = n 
plt.plot(n,y,label="n")
y = [np.log(nn)**2 for nn in n]
plt.plot(n,y,label="log(n)**2")
y = n**(1/2)
plt.plot(n,y,label="n**(1/2)")
y = [np.log(nn) for nn in n]
plt.plot(n,y,label="log(n)")
plt.legend()
plt.show()

n = np.arange(1,6,1)
y = [math.factorial(nn) for nn in n]
plt.plot(n,y,label="n!")
y = 2**n
plt.plot(n,y,label="2**n")
y = n**2
plt.plot(n,y,label="n**2")
y = n*(n**(1/2))
plt.plot(n,y,label="n*(n**(1/2)")
y = [np.log(nn) for nn in n]
plt.plot(n,y,label="log(n)")
plt.legend()
plt.show()
```
<img width="538" alt="スクリーンショット 2018-08-11 14.45.58.png" src="https://qiita-image-store.s3.amazonaws.com/0/147303/2bd3df17-4b6a-5f3f-291e-5d69361976f3.png">
<img width="549" alt="スクリーンショット 2018-08-11 14.46.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/147303/fc897866-ec33-bf77-bf10-4b55d6268d9d.png">
log(n) < n^(1/2) < log(n)^2 < n < n*log(n) < n*(n^(1/2)) < n^2 < 2^n < n!
# Refs.
* [matplotlib](https://qiita.com/namitop/items/31326293c92522cf11c1)
* [base of a log](https://qiita.com/shiozaki/items/eb8226c3144ab6d46b4d)
* [np.log](https://stackoverflow.com/questions/11656767/how-to-take-the-log-of-all-elements-of-a-list)
* [label](http://bicycle1885.hatenablog.com/entry/2014/02/14/023734)
* [legend](http://paper.hatenadiary.jp/entry/2017/05/02/152223#%E3%82%B0%E3%83%A9%E3%83%95%E3%81%AE%E6%9E%A0%E5%A4%96%E3%81%AB%E8%A1%A8%E7%A4%BA%E3%81%99%E3%82%8B)
CentOS7に最新のgitとvimとtmuxをインストールする

健忘録です。

CentOS7のデフォルトで入っているvimやgitは古かったりするため、最新のものを自分でコンパイルして使います。gitからtarball落としたりタグをチェックあうとしたり一貫性がないのは参考サイトからコピったからです。

### 環境

```sh
$ cat /etc/redhat-release
CentOS Linux release 7.5.1804 (Core) 
```

### ローカルのフォルダの作成と環境変数の設定

```sh
$ mkdir -p local/src
$ vim ~/.bashrc

export LANG=ja_JP.UTF-8

$ source ~/.bashrc
```

### 最新のGitのインストール

```sh
$ sudo yum update -y
$ sudo yum -y remove git
$ sudo yum -y install curl-devel expat-devel gettext-devel openssl-devel perl-devel zlib-devel autoconf asciidoc xmlto docbook2X make gcc
$ sudo ln -s /usr/bin/db2x_docbook2texi /usr/bin/docbook2x-texi
$ cd $HOME/local/src
$ wget https://github.com/git/git/archive/v2.18.0.tar.gz
$ tar -zxf v2.18.0.tar.gz
$ cd git-2.18.0
$ make configure
$ ./configure --prefix=/usr/local
$ make all doc info
$ sudo make install install-doc install-html install-info
$ git --version
```

### 最新のVimのインストール

```sh
$ sudo yum -y remove vim
$ sudo yum install -y git gcc ncurses-devel
$ cd $HOME/local/src
$ git clone https://github.com/vim/vim.git
$ cd vim
$ ./configure --prefix=/usr/local --with-features=huge --enable-multibyte --enable-cscope --enable-fail-if-missing
$ make
$ sudo make install
$ vim --version
```

### 最新のtmuxのインストール

```sh
$ sudo yum install automake libevent-devel ncurses-devel xsel
$ cd $HOME/local/src
$ git clone https://github.com/tmux/tmux.git
$ cd tmux
$ git checkout 2.7
$ ./autogen.sh
$ ./configure --prefix=/usr/local
$ make
$ sudo make install
$ tmux --version
```

参考:
https://qiita.com/noraworld/items/8546c44d1ec6d739493f
http://stupiddog.jp/note/archives/1147
https://qiita.com/koara-local/items/7e8391b837fb6f834cb9
nvcc の --generate-code オプションについて解説

nvcc コンパイラに `--generate-code` オプションを指定することで特定環境向けの(おそらく最適な)コードを生成するように指示できる。

対象にしたい Compute Capability (CC) の番号を arch と code のサブオプションに指定する。お使いの NVIDIA GPU の CC は [CUDA GPUs | NVIDIA Developer](https://developer.nvidia.com/cuda-gpus) から調べられる。

```
$ nvcc --generate-code arch=compute_30,code=sm_30
```

arch には 'virtual' architecture (compute_xx) を指定する。これは PTX コードを生成する時に使われる。

ある CC 向けに生成された PTX コードは、同じかそれより新しい CC 向けのバイナリにコンパイルすることができる。例えば CC5.0 (compute_50) 向けにビルドした PTX コードは CC6.0 の環境でも(最適ではないにしろ)使うことができるが、CC4.0 の環境では使うことができない。

code には 'real' architecture (sm_xx) を指定する。これは PTX コードから sass ないしは cubin を生成する時に使われる。

cubin はメジャーバージョンの互換性は保証されない. 例えば CC5.0 (sm_50) 向けにビルドしたバイナリは CC6.0 の環境で動作することは保証されないし、CC4.0 の環境では動作しない。

複数の CC に対して最適化しておきたい場合は複数指定する。その分コンパイル時間は伸びる。

```
$ nvcc --generate-code arch=compute_30,code=sm_30 --generate-code arch=compute_50,code=sm_50
```

このようにして複数の cubin を含めることができるので fatbin と呼ばれている。

## fatbin に含めるものを指定

code に real architecture (sm_xx) を指定した場合は fatbin に cubin が含まれる。

```
$ nvcc --generate-code arch=compute_30,code=sm_30
```

fatbin に PTX を入れておくこともできる。その場合は code に real architecture (sm_xx) ではなく virtual architecture (compute_xx) を指定する。

```
$ nvcc --generate-code arch=compute_30,code=compute_30
```

この場合、cubin はいつ作られるかというと、実行時にJITされる。実行時の JIT は１並列で行われるのでけっこう遅い。一度 JIT したものはファイルシステムにキャッシュされるので2回目の実行からは速い。オプションなしのデフォルト動作時もJITしている。

fatbin に PTX と cubin の両方を入れて置きたい場合は、code に compute_xx と sm_xx の両方を指定する。

```
$ nvcc --generate-code arch=compute_30,code=compute_30 \
  --generate-code arch=compute_30,code=sm_30
```

この例では、実行環境が sm_30 であれば、その cubin をそのまま使うし、CC が新しい環境であれば PTX コードを JIT して使う。古い環境では動かない。

ちなみに短縮 `-arch` オプションで、`-arch=sm_30` と指定した場合、この動作と同等の意味になる。

## 参考

* [1] https://sites.google.com/site/cudajpn/chapter-3-programming-interface/3-1-compilation-with-nvcc
* [2] https://devblogs.nvidia.com/cuda-pro-tip-understand-fat-binaries-jit-caching/
Ubuntu 18.04 LTS LAMP + Let's Encrypt 環境構築

# Ubuntu18.04 LTS LAMP環境構築
普段は、CentOSでLAMP環境構築、業務で使用しています。
**Ubuntu触ってみよう！**という、手段目的化による私的備忘。
## 諸々インストール
```terminal
// Apache2.4
# apt install apache2

// PHP7.2
# apt install php7.2-cli

// mod_php
$ apt install libapache2-mod-php

// php mysql
# apt install php7.2-mysql

// Mysql5.7
# apt install mysql-server

// Mysql Secure Install
# mysql_secure_installation
```
## MySQL文字コード設定
```/etc/mysql/mysql.conf.d/mysqld.cnf
[client]
default-character-set= utf8mb4

[mysqld]
character-set-server = utf8mb4
collation_server= utf8mb4_unicode_ci
default_password_lifetime = 0
```
## Apache起動、MySql再起動
```console
# systemctl start apache2
# systemctl restart mysql
```
## MySQLログインと必要なDB, USERの作成
```terminal
// ログイン
# mysql -u root -p
CREATE USER '[UserName]'@'localhost' IDENTIFIED BY '[Password]';
GRANT ALL ON [DbName].* TO '[UserName]'@'localhost';
```
## ufw有効化、設定
```console
// 有効化
# ufw enable

// ufw確認
# ufw status

// HTTP
# ufw allow 80

// HTTPS
# ufw allow 443

// ufw再起動
# ufw reload

// ufw確認 Port開放できているか確認
# ufw status
```
## 自動起動の確認、disableの場合は、enableに変更
```console
// 有効・無効確認
# systemctl list-unit-files --type=service | grep "mysql\|apache2\|ufw"

// 有効にする
# systemctl enable apache2 mysql ufw
```
## /etc/apache2 ドメイン、諸々設定後 Let's Encrypt
```terminal
// 該当ファイルをよしなに変更する
# vim /etc/apache2/

// Let's Encrypt インストール、実行
# wget https://dl.eff.org/certbot-auto
# chmod a+x certbot-auto
# ./certbot-auto
// 後は公式ドキュメント、表示されるメッセージ通りに
```
### 感想
コマンドは違えど、ほぼCentOSと同じでした。
たまには触ったことがないディストリビューションで環境構築も楽しいですね。
Twitterの自分をフォローしてないユーザーをPythonで削除するスクリプト

##説明

tweepyを使って、自分をフォローしてない（こっちはフォローしてるのに）ユーザーをアンフォローするスクリプトを書きました。

##環境

- mac
- python3.5
- ローカル

##流れ
自分をフォローしてるユーザーのリストと、自分がフォローしてるユーザーのリストを取得して、相思相愛ではないリストを生成、相思相愛ではないリストをループで一個づつ回して、Twitterのapiを使ってユーザーをリムーブします。

##使い方

キー関係を自分用に設定して、`python unf.py`とかでローカルで叩けばそのまま動くはずです。

##備考

apiを叩きまくると制限が掛かります。なので、一旦、お試しで、スクリプトを叩けるように、`time`を使うのをやめて、５回だけループするようにしています。自動化（システムを裏側で動かして、毎日１０人づつ決していきたい）みたいなことをしたい場合は、ここらへんをどうにかします。

```python

index = 0
follower_list = []
for follower in tweepy.Cursor(api.followers).items():
    #print( follower.screen_name )
    follower_list.append( follower.screen_name )
    #time.sleep(5)

    if index == 5:
        break

    index += 1
```

## 実装
```python
"""
#
#
#
# - mac os local
# - Python 3.5.0
# *******************************************************************
# *You always should remove someone who is not following you.       *
# *The human always should be in love with each other NOT one-sided *
# *******************************************************************
#
#
"""
import time
import tweepy
import sys



"""
#
#
#自分の環境に合わせてください
#Your environment
#
#
"""
CONSUMER_KEY = 'fzTU~~~~~~'
CONSUMER_SECRET = 'aSsW~~~~~~'
ACCESS_TOKEN = '8161~~~~~~'
ACCESS_TOKEN_SECRET = 'hoxQC~~~~~~'

auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
auth.set_access_token(ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
api = tweepy.API(auth, wait_on_rate_limit=True, wait_on_rate_limit_notify=True) 


"""
#
#
#自分をフォローしているユーザーを取得する
#Someone who is follow me
#
#
"""
index = 0
follower_list = []
for follower in tweepy.Cursor(api.followers).items():
    #print( follower.screen_name )
    follower_list.append( follower.screen_name )
    #time.sleep(5)

    if index == 5:
        break

    index += 1

"""
#
#
#自分がフォローしているユーザーを取得する
#Someone who is I am follow them 
#
#
"""
index = 0
friends_list = []
for friends in tweepy.Cursor(api.friends).items():
    #print( friends.screen_name )
    friends_list.append( friends.screen_name )
    #time.sleep(5)

    if index == 5:
        break
        
    index += 1

"""
#
#
#
#自分はフォローしてるのに、あっちは自分をフォローしてないユーザーを取得
#Get list someone who is not following me even though I following
#
"""
def intersect_list(lst1, lst2):

    lst1 = lst1.copy()
    for element in lst2:
        try:
            lst1.remove(element)
        except ValueError:
            continue
        else:
            print(element)
            print("love each other")
    return lst1


"""
#
#
#
#自分をフォローしてないユーザー削除
#remove someone who is not following me
#
"""
#print( intersect_list(friends_list, follower_list) )
not_following_me_list = intersect_list(friends_list, follower_list)

for you_unfollowing in not_following_me_list:
    api.destroy_friendship(you_unfollowing)
```
落ち着いて聞いてほしい、@Mockでモックを初期化する方法は3つある。

mockitoでは、モックにしたい変数に@Mockアノテーションを付けるだけでモックを作れます。この場合、アノテーションを有効にする記述をする必要があります。アノテーションの有効化は、initMocksを呼び出す、Runnerを使う、Ruleを使うの3つの方法で行えます。

# mockito
[mockito](https://site.mockito.org/)はモック作成、呼び出しの検証、スタブの作成が行えるユニットテスト用のJavaライブラリです。  
以下は公式サイトにあるキャッチコピー。
> Tasty mocking framework for unit tests in Java  
> Javaのユニットテストのための味わい深い（？）モックフレームワーク

## インストール
gradleを使っている場合は、build.gradleのdependenciesにmockitoを追加してください。

```groovy:build.gradle
group 'net.example'
version '1.0-SNAPSHOT'

apply plugin: 'java'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'
    testCompile group: 'org.mockito', name: 'mockito-core', version: '2.21.0'
}

```

## 基本的な使い方
モックにしたクラスのメソッドにスタブを作ってテストするという使い方をよくします。

[基本的な使い方](https://gist.github.com/ytnk531/a9a645fcc8b480e7cf0aff2165c76060)

### mockの作り方
mockを作る方法は、mockメソッドを使う方法と、@Mockアノテーションを使う方法があります。


上の例で使っていたので、mockメソッドを使う方法です。

```java
private List mockedList = mock(List.class);
```

もう一つが@Mockアノテーションを使う方法です。

```java
@Mock
private List mockedList;
```

アノテーションを使ったほうが記述が少なく、見栄えもいいのですが注意が必要です。
@Mockに限らず、mockitoが提供しているいくつかのアノテーションを使うときはアノテーションを使ったMockを初期化する処理を書かなければいけません。  

# アノテーションを使ったmockを初期化する方法
@Mockとかを初期化する方法は3つあります。
私はRunnerを使うのが楽なので好きです。

## initMocks()を使う

@Beforeなメソッドの中でinitMocksを使います。

[initMocksを使う](https://gist.github.com/59577fc0d0289268684dda853fd52b86)



## Runnerを使う

@RunWith(MockitoJUnitRunner.class)をクラスにつけます。
Mockito用のRunnerが適用されるので、Mockの初期化だけでなくスタブの用法が間違ってないか検証するなどの機能もあります。

[Runnerを使う](https://gist.github.com/32ec191cfd6beedf6919546226531f06)




## Ruleを使う
JUnitのRuleを使ってMockitoJUnit用のルールを適用します。

```java
@Rule public MockitoRule rule = MockitoJUnit.rule();
```

効果としてはRunWithを使った場合と変わらないようです。

[Ruleをつかう](https://gist.github.com/9f84aef93b4ceab30af2de8e392a1b50)



# 情報源
https://static.javadoc.io/org.mockito/mockito-core/2.21.0/org/mockito/Mockito.html#mock_annotation

https://static.javadoc.io/org.mockito/mockito-core/2.21.0/org/mockito/MockitoAnnotations.html#initMocks-java.lang.Object-

https://static.javadoc.io/org.mockito/mockito-core/2.21.0/org/mockito/junit/MockitoJUnitRunner.html

https://static.javadoc.io/org.mockito/mockito-core/2.21.0/org/mockito/junit/MockitoRule.html
DirectX12 事始め 頂点バッファの生成

今回は、頂点バッファを作って行きます。
頂点バッファは、バッファに頂点情報を渡す役割をします。

```c++:Triangle.h
#include "Descriptor.h"
#include "Typedef.h"
#include <vector>
class Texture :
   public Descriptor
{
public:
   // コンストラクタ
   Texture(Device* dev, List* list);
   // デストラクタ
   ~Texture();

   // 描画
   void Draw(void);
private:
   // 頂点リソースの生成
   HRESULT CreateResource(UINT* index);

   頂点データ
   std::vector<Vertex>vertex;
   // リソース
   ID3D12Resource* resource;
   // 頂点バッファビュー
   D3D12_VERTEX_BUFFER_VIEW view;
   // 送信データ
   UINT8* data;
};
```

```c++:Triangle.cpp
#include "Triangle.h"
#include "Device.h"
#include "List.h"

// 頂点の最大数
#define VERTEX_MAX 3

// コンストラクタ
Triangle::Triangle(Device* dev, List* list) :
   resource(nullptr), data(nullptr)
{
   this->dev = dev;
   this->list = list;

   vertex.clear();
   view = {};

   CreateResource();
}
// デストラクタ
Triangle::~Triangle()
{
   Release(resource);
   delete list;
   delete dev;
}
// リソースの生成
HRESULT Triangle::CreateResource(void)
{
   //頂点の数分メモリを確保
   vertex.resize(VERTEX_MAX);
   vertex[0] = { { -1.0f, -1.0f, 0.0f }, { 0.0f, 0.0f } };//左上
   vertex[1] = { {  1.0f, -1.0f, 0.0f }, { 1.0f, 0.0f } };//右上
   vertex[2] = { {  1.0f,  1.0f, 0.0f }, { 1.0f, 1.0f } };//右下

   //プロパティ設定用構造体の設定
   D3D12_HEAP_PROPERTIES prop = {};
   prop.Type                 = D3D12_HEAP_TYPE_UPLOAD;
   prop.CPUPageProperty      = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
   prop.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
   prop.CreationNodeMask     = 1;
   prop.VisibleNodeMask      = 1;

   //リソース設定用構造体の設定
   D3D12_RESOURCE_DESC desc = {};
   desc.Dimension        = D3D12_RESOURCE_DIMENSION_BUFFER;
   desc.Width            = sizeof(Vertex) * vertex.size();
   desc.Height           = 1;
   desc.DepthOrArraySize = 1;
   desc.MipLevels        = 1;
   desc.Format           = DXGI_FORMAT_UNKNOWN;
   desc.SampleDesc.Count = 1;
   desc.Flags            = D3D12_RESOURCE_FLAG_NONE;
   desc.Layout           = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;

   //リソースの生成
   result = dev->Get()->CreateCommittedResource(&prop, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&resource));

   //送信範囲
   D3D12_RANGE range = { 0,0 };

   //マッピング
   result = resource->Map(0, &range, reinterpret_cast<void**>(&data));

   //頂点データのコピー
   memcpy(data, vertex.data(), sizeof(Vertex) * vertex.size());

   //アンマップ
   resource->Unmap(0, nullptr);

   //頂点バッファ設定用構造体の設定
   view.BufferLocation = resource->GetGPUVirtualAddress();
   view.SizeInBytes    = sizeof(Vertex) * vertex.size();
   view.StrideInBytes  = sizeof(Vertex);

   return result;
}
// 描画
void Triangle::Draw(void)
{
   //頂点バッファビューのセット
   list->GetList()->IASetVertexBuffers(0, 1, &view);

   //トポロジータイプのセット
   list->GetList()->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

   //描画
   list->GetList()->DrawInstanced(VERTEX_MAX, 1, 0, 0);
}
```

以上で頂点バッファの生成は終了です。
とりあえず三角形の頂点情報を作ってます。