OmniAICreator/Qiita-1.07M huggingface dataset:
技術書典に参加してきた話

#当日の様子

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">技術書典なう <a href="https://t.co/Um7e7Bonqs">pic.twitter.com/Um7e7Bonqs</a></p>&mdash; 出水 (@izmktr) <a href="https://twitter.com/izmktr/status/987872218695712768?ref_src=twsrc%5Etfw">2018年4月22日</a></blockquote>

毎回使っているこの折りたたみ棚、シロイタナっていうんですが、最高です。
一番上が立っている目線の高さに来るので非常に目に付きやすいですし、
棚の後ろのスペースに在庫やお金を隠しておけます。

シロイタナ自体は絶版っぽいですが、他の会社も似た商品を出しています。

#売上
大体こんな感じです

・ソートの本 80冊
・仮面ライダービルドの数式が分かる本　30冊
・VRコンテンツ制作記 30冊
・ゲームの修羅場(3種類)　計60冊

売ってるものがバラバラなので、まとめて一気にという人は少なかったですね。

な新刊は「仮面ライダービルドの数式が分かる本」です。
大体2時頃に完売しました。
この本は、完結するのがおそらく8月末なので、売り切れるだけしか出したくないんですよね。
手に取る人は多かったですが、なんだかんだでガチの数学本なのでそっと戻す人が多かったです。

ソートの本は去年の夏コミの新刊で、コミケ2回と前回の技術書典でも出していて、
通算200冊以上売れてたため、前回の技術書典ではもう持っているという人が多くて売れませんでした。
でも、今回は既刊にもかかわらずまだまだ売れていて、それだけ新規の人が多かったんでしょうね。

ちなみに以下のリンクから買えます。
[仮面ライダービルドの数式が分かる本](https://booth.pm/ja/items/830506)(BOOTH/ダウンロード)
[ソートの本](http://shop.comiczin.jp/products/detail.php?product_id=34599)(ZIN/通販)
[VRコンテンツ制作記](http://shop.comiczin.jp/products/detail.php?product_id=36454)(ZIN/通販)


#印刷
最近お気に入りのキンコーズで印刷しています。
当日の朝7時に印刷しに行ってました。
(当日3時まで原稿書いてました… 意外に直す場所が多くて…)

元々、キンコーズで印刷するために、A5サイズの本にしています。
理由はA4の紙が使えるので安く済むからです。

以前、B5の本を作ったのですが、同じページ数でも時間がA5の3倍かかります。
B5を作るなら、オンライン入稿して冊子印刷で受け取るのがいいかもです。

#サークルチェック数
技術書典のサイトでサークルカタログが見られますが、
誰も見ないだろ～と思ってたら、結構見ている人が多くて
当日見ると私のサークルをチェックしている人が60人いました。
早いうちから頒布情報とか入力しておけばよかったと思います。
3日前までに登録しておけば電子決済用のQRコードやおしながきのカードが貰えます。

#決済アプリ
待望のiOS版が出たので、使ってみましたがやや問題ありと感じました。

決済アプリは
・カメラ画面でQRコードを読み取り
・数量変更画面で、読み取ったリストの数量を変更
・決済画面で決済を確定
の順で進みます。

数量変更画面では、削除ができません。
カメラ画面でなら読み取ったリストから×ボタンで消せますが、
カメラが生きているので、途中にQRコードが映ると勝手に追加されます。

また、数量変更画面では一画面に収まらない場合、画面外の商品の数量が変更できません。
指でスクロールはできるのですが、指を離すと一番上に戻ってしまいます。

正直、QRコードは商品ごとではなく、サークルのQRを読み込んで、
数量変更画面から追加していったほうが便利かなと思いました。

欲を言えば、技術書典のアカウントでログインしているので、
カタログ兼チェックリストビュアーとして機能してくれれば最高ですね。

#他のサークル
ざっと見て回ったんですが、正直興味が持てるサークルが思ったより少ないというか、
一口に技術と言っても広すぎて全然カバーできていない、という感じがします。
スマートフォンアプリを作るならUnityを使うし、
サーバ側も仕事でいじってますが、C++かPhoton/C#しか使ってないので、
ライブラリやソフトの名前だけ書かれてもわかんないんですよね。
まぁ、そういうレベルの人は読んでも仕方ないんでしょう。

#最後に
晴れた日の技術書典は本当に人が途切れないんだな、と改めて思いました。
実際原稿でヘロヘロだったので、あんまり見て回れなかったんですが、
次回こそはちゃんと準備して万全な体制で行きたいと思います。

まぁ、落選しなければですが…最近倍率が高くなる一方ですからね…。
IP アドレスの種類について (身内向け)

まずは, 以下の *第19回レイヤ３ 概要* から *第23回レイヤ３ サブネッティング* までを読んでほしい。

- [3 Minutes Networking](http://www5e.biglobe.ne.jp/aji/3min/)

その上で, まずはアドレスの種類を整理する。

## Internet Protocol (IP)

Internet Protocol (IP) は 2 つのバージョンが存在する。
それぞれのバージョンでアドレスの詳細な種類が異なってくる。

### IPv4

- IP アドレス
   - グローバルアドレス
   - プライベートアドレス
- ネットワークアドレス
- ブロードキャストアドレス
- マルチキャストアドレス

上記のサイトで例えられた市外局番が **ネットワーク部,** 市内局番が **ホスト部** と呼称される。

### IPv6
- ユニキャストアドレス
- エニーキャストアドレス
- マルチキャストアドレス

上記のサイトで例えられた市外局番が **プレフィックス,** 市内局番が **インターフェース ID** と呼称される。
なお, IPv6 にブロードキャストアドレスは存在しない。また, グローバルアドレスやプライベートアドレスの区別も存在しない。

## 例題の考え方

問題文に *プレフィックス, インターフェース識別子* という単語が存在する場合, IPv4 ではなく IPv6 を扱っていることが分かる。
そのためこの時点で, プライベートアドレスという選択肢は無くなる。

続いて, *インタフェース単位で 1 つずつ付与する* と記載されているため, 複数の宛先を設定するマルチキャストアドレスや, アドレスそのものを表現するわけではないサブネットアドレスという選択肢も無くなる。

問題はユニキャストかエニーキャストか。
仮に, 問題文に「単一のホストに **のみ** 設定できるアドレス」というキーワードがあれば, ユニキャストで確定。
逆に, 「同一のアドレスを **複数のホスト**  ipipに設定できる」というキーワードがあれば, エニーキャストで確定。

この辺は問題をよく読むしかないかな。。。

以上。
CocosCreatorの音の読み込みで詰まった話

こんばんは、やわらーです。
本日は音の読み込みで少し詰まってしまいました。

## 環境
windows10
CocosCreator v1.9.0

---

音も先日の画像の一括読み込み
https://qiita.com/Yawarakko/items/98b5fc6c516bdd700909
と同じ要領でできると思い、こんな感じで書いてみました。

```js:Sounds.js
cc.Class({
    extends: cc.Component,

    properties: {
        soundsData: null,
        _bgmID: null,
    },

    // LIFE-CYCLE CALLBACKS:

    onLoad () {
        this._loadSounds();
    },

    start(){
        this._bgmID = cc.audioEngine.play(this.soundsData[0], true);
    },

    // resourcesフォルダの読み込み
    _loadSounds(){
        let self = this;
        cc.loader.loadResDir("Sounds", cc.AudioClip, function(err, assets){
            if(err){
                cc.error(err);
                return;    
            }
            self.soundsData = assets;
        })
    },
});
```
音はresources/Soundsフォルダに2曲入れてあります。
BGMを再生したいのでstart()で再生しました。
これで実行してみました、音は再生されたのですがエラー発生。確認するとどうやら読み込みができていないのに再生しようとしているエラーのようです。
cc.log()を入れて確認してみると読み込みが終わる前に再生を呼び出しているのが原因だとわかりました。
しかし、BGMなのでシーンが始まったタイミングで再生したい....

# 解決策1
というわけで解決策その1。
あらかじめエディタ側でセットしてしまう方法です。

```js:Sounds.js
cc.Class({
    extends: cc.Component,

    properties: {
        soundsData: {
            default: [],
            url: cc.AudioClip
        },
        _bgmID: null,
    },

    // LIFE-CYCLE CALLBACKS:

    onLoad () {
        //this._loadSounds();
    },

    start(){
        this._bgmID = cc.audioEngine.play(this.soundsData[0], true);
    },

    // resourcesフォルダの読み込み
    // _loadSounds(){
    //     let self = this;
    //     cc.loader.loadResDir("Sounds", cc.AudioClip, function(err, assets){
    //         if(err){
    //             cc.error(err);
    //             return;    
    //         }
    //         self.soundsData = assets;
    //     })
    // },
});
```

![bandicam 2018-04-26 00-38-05-676.jpg](https://qiita-image-store.s3.amazonaws.com/0/167483/69d12fb4-ba32-d44c-9bd0-a0323f95e475.jpeg)

このように、あらかじめエディタ側でセットする方法です。これなら問題なく再生されます。しかしこの方法、使用する音が少ないならいいのですが、使いたい音が何十曲もあった場合いちいちセットするのが大変です。

# 解決策2
そこで、解決策2は読み込みの方法は変えずに、読み込みが終わるのを待ち、そこで再生する方法です。

```js:Sounds.js
cc.Class({
    extends: cc.Component,

    properties: {
        soundsData: null,
        _bgmID: null,
    },

    // LIFE-CYCLE CALLBACKS:

    onLoad () {
        this._loadSounds();
    },

    //start(){
    //   this._bgmID = cc.audioEngine.play(this.soundsData[0], true);
    //},

    // resourcesフォルダの読み込み
    _loadSounds(){
        let self = this;
        cc.loader.loadResDir("Sounds", cc.AudioClip, function(err, assets){
            if(err){
                cc.error(err);
                return;    
            }
            self.soundsData = assets;
            self.playBGM();
        })
    },

    // 音の再生
    playBGM(){
        this._bgmID = cc.audioEngine.play(this.soundsData[0], true);
    }
});
```
cc.loader.loadResDir()の第3引数のコールバック関数は読み込みが終了したタイミングで呼ばれるようです。なのでそこで再生する方法です。これなら、一括で読み込みつつシーンの開始時に再生できます。しかし、読み込みが終わってから再生されるので、シーン開始から音の再生までラグが生じてしまう可能性があります。

---

以上が音の読み込みの方法です。どちらの方法も一長一短なので使い分ける必要がありますね。
読み込みは非同期なので気をつけないといけないです。
今回の音は魔王魂様[(https://maoudamashii.jokersounds.com/)](https://maoudamashii.jokersounds.com/)のものを使用させていただきました。
確かにひどすぎる>Rによるデータクリーニング実践――政府統計からのグラフ作成を例として

[Rによるデータクリーニング実践――政府統計からのグラフ作成を例として](http://id.fnshr.info/2018/04/23/r-data-cleaning-school/)

このデータは廣済堂というとこが作っているらしいが確かにひどい。

 - ファイル名が様式番号で何が入っているかわからない。
 - 何年のデータかわからない。
 - xlsとxlsxが混在
 - しかもhttps

このようにスクリプトを作れないことはないのだが…

```powershell
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls11
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$strURI = 'https://www.e-stat.go.jp/stat-search/file-download?statInfId=000029085316&fileKind=0'
$sfolder = 'D:\1983Excel'
If(!(Test-Path -Path $sfolder)){md $sfolder} 
$cli = New-Object System.Net.WebClient
$uri = New-Object System.Uri($strURI)
$file = Split-Path $uri.AbsolutePath -Leaf
  $cli.DownloadFile($uri, (Join-Path $sfolder "1983.xls"))
  $file + "をダウンロード完了しました。"

```
#ここからダウンロードする
https://www.e-stat.go.jp/stat-search/files?page=1&query=%E7%94%B7%E5%A5%B3%E5%88%A5%E5%AD%A6%E6%A0%A1%E6%95%B0&layout=dataset

ちなみに一括ダウンロードすると同じ名前のxlsファイルができて全く分からない。
これではまとめて抜いたとしてもいつのファイルかわからないので役に立たない。
excelのアイコンをクリックし、拡張子を確かめ、リンクのURLを取得したらPowershellのスクリプトが使える。
この作業を30回ほど繰り返さなければならない。

#Scriptの参考サイト
[PowerShellを使って指定したファイルをインターネットからダウンロードする](http://www.atmarkit.co.jp/fwin2k/win2ktips/995dlfile/dlfile.html)
これをもとに、検索結果のExcelアイコンからURIを取得し、ファイルと拡張子を確認してフォルダ名とファイル名を決めなくてはならない。

[PowerShellでサイトからファイルをダウンロードしたい](https://teratail.com/questions/58824)
これはエラーになってしまう

`"要求は中止されました: SSL/TLS のセキュリティで保護されているチャネルを作成できませんでした"`

[Invoke-RestMethod、Invoke-WebRequestが失敗する](https://social.msdn.microsoft.com/Forums/ja-JP/5d614cf3-a45f-4e25-86b7-5b1fafb7285a/systemnetwebexception-ssltls-?forum=aspnetja)
Netflix 同時字幕で英語学習

Netflixで英語音声と英語字幕で英語学習する際、日本語字幕を見たい時に動画を一時停止して画面右下の設定から日本語に切り替える作業が大変でしたので、英語字幕と日本語字幕を同時に表示させるChrome拡張機能を公開しました。動画の再生速度は0.1倍速ずつ遅く速く出来ます。
![Netflix - Google Chrome 2018_04_21 14_28_52_Moment(4).jpg](https://qiita-image-store.s3.amazonaws.com/0/69351/4e19a826-0d86-132a-e29e-991ca8be7985.jpeg)


hulu版の拡張機能も作成したのですが、すっかり有名になってしまって最近は日本の番組を配信するのに力を注いでいるらしく海外のは少なくなっているのでもっと増やして欲しいです。

Netflixで最近はまった海外ドラマはオルタードカーボンで、攻殻機動隊が好きな方にはおすすめです。上の画像がそうです。
>250年の眠りから覚め、新たな体でよみがえった犯罪者。だが自由と引き換えに突き付けられた条件は、絶対的権力を持つ大富豪殺害の謎を追うことだった。

#chrome拡張機能のダウンロードはこちらから
[Netflix 同時字幕で英語学習](https://chrome.google.com/webstore/detail/gibmkmmdicoffkhjkfimmjkojjopoagg)
[Hulu 同時字幕で英語学習](https://chrome.google.com/webstore/detail/lmmahellpnmhbpmimpebhikpjhiojhok)
[解決方法] upath@1.0.4: The engine "node" is incompatible with this module. Expected version ">=4 <=9".

node 10.0 で webpackをインストールしようとすると表題のエラーが起きます。

## 原因

https://github.com/anodynos/upath/blob/3bdcd474017e7635ecbc7509ea03c6b036df3b8d/package.json#L43

## 解決方法

```
yarn install --ignore-engines
```


参考 https://github.com/anodynos/upath/issues/14
micro:bitがUSBドライブとして認識されない場合の対処方法

## やりたいこと
PC (Windows) と micro:bit をマイクロUSBケーブルで接続し、micro:bitを認識させたい。

## 現象
PCとmicor:bitを、USBケーブルで接続したが、全く認識してくれない。

## 解決策
以下の公式サポートの情報によると、USBケーブルが怪しい。
一部のUSBは充電のみで、データ転送はできないとのこと。


[Fault finding with a micro:bit](https://support.microbit.org/support/solutions/articles/19000024000-fault-finding-with-a-micro-bit)

```
(google翻訳)
一部のUSBリードは「パワーのみ」のリードです（特に本当に安価なリード、携帯電話を充電するために設計されたもの）。
スマートフォンやデジタルカメラの鉛などデータを転送するために使用されている既知の動作中のUSBリードを見つけて、
もう一度試してみてください。...

```

USBケーブルを変えて試してもダメだったのであせったが、
あきらめず、別のケーブルで試してみたところ、無事に認識された。

（なお、充電専用のUSBケーブルと、データ転送用のケーブルの明白な見分け方を調べたが見当たらなかった。。。）

## 参考
[知恵袋 : このUSBケーブルの〇で囲んだマークはデータ転送用ケーブルですか？](https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q12171700417)
[データ分析]エネルギーデータを4年分析してわかったこと

# 概要
　私は建築物の消費エネルギーのデータ分析(省エネ分析)を4年行ってきました。大学・病院・事務所ビルなど
様々な建物のエネルギーデータの分析をさせていただきました。4年分析してきてわかったことを書きます。

1. **お客様はそれほど分析内容に興味がない（結果には興味がある）**
2. **お客様はデータがあればデータ分析は簡単にできると思っている（簡単ではない）**
3. **データ分析は楽しい（楽しい!!)**


#1. お客様はそれほど分析内容に興味がない
![cost_cut_sakugen_samurai.png](https://qiita-image-store.s3.amazonaws.com/0/148213/a1048f65-cdda-5dbb-6cd1-5d1f98b06a50.png)

* **建物のオーナーサイドは、ほぼ分析内容に興味はありません。(90%ぐらいのオーナーは興味を示しませんでした。）** 
当然といえば当然ですが、お金に換算できるものには興味を示されます。オーナーサイドとしては当然かと思います。
ただ、ご依頼のあった報告書(両面100ページ程度)を全くご覧にならずに、別途~~ただ働き~~作成させていただいたA3用紙1枚のコスト削減量しか記載していないグラフのみで打ち合わせをされたときは絶句しました。
<br>

* **逆に建物の管理を委託されている方々は、分析内容に比較的興味を持たれているようでした。** 
当然といえば当然ですが、委託された側からすると余計な業務（データ提供など）が増えるので、
最初はものすごーくめんどくさそうにされることも多々あります。

#2. お客様はデータがあればデータ分析は簡単にできると思っている
![business_marunage.png](https://qiita-image-store.s3.amazonaws.com/0/148213/d65d901e-62bf-e1ac-f18a-7bea3ffb5677.png)

* **過去1年分のデータあるし、データ分析なんて簡単だよね？（簡単ではない）**  
建築業界のエネルギーデータをご覧になったことはあるでしょうか？  
現場とデータ分析の部署が分かれていることが多く、現場サイドでデータのカラム名や最終的なデータの精度を決めてることが多いのです。  
時系列データなのでindexはタイムスタンプにはなっており、基本的にindexは問題ありません。（1sec~1yearまで様々）　

 問題は、
 <b>
 1. カラム名が重複している。
 2. 重複しているのに全く違うデータが入っている。
 3. 指示したカラム名が存在しない。。。etc
 </b>　
 言い始めたらきりがない、これはひどい。
「データが正しい状態で保存されている≠データが存在している」と理解している人が社外だけでなく社内ですら少ない。
この業界だけですか？ほかの業界はもっと違うんですかね？


#3. データ分析は楽しい　　
データの前処理は泥臭くて、課題解決できなけりゃ文句を言われて、社内外に敵が多いデータ分析の楽しい要素  
 ![business_man_macho.png](https://qiita-image-store.s3.amazonaws.com/0/148213/72ff3472-4efb-ca41-174d-9986a7c356ae.png)

 1. 課題解決のプロセスは、オープンワールド謎解きゲームをしてる感じで楽しい！  
     * 解決に至るプロセスが複数ある！（マルチエンディングだけど、すべてバッドエンドの場合もあるぞ！）
     * ダミーの手掛かりがあったり、なかったり！（ダミーを選択しないようにしよう！）
     * 仲間と協力することで解決がスムーズにいく場合が多いぞ！（ソロプレイはリアルオンラインゲームでは不利だ！）
     * クリアの証は、ニーズのあるところにもっていかないとだめだぞ！（依頼者がクリアの証を欲しがってるとは限らないぞ！）
 2. データ分析は、料理のようでたのしい！  
     * 下ごしらえが大事（データの前処理、精度の担保）
     * 工程が大事（セオリーがあるなら、先にセオリーを）
     * 盛り付けも大事（いい結果を出せても可視化してわかりにくければ×）
     * コンビニ弁当が好きな人に高級料理を出してもダメ（ニーズにあったものを提供しないと理解してもらえない）
 

# おわりに
つらいこともあるけど楽しいこともあるデータ分析。
今後もデータ分析していきたいなと考えている今日この頃。
ビッグデータに疎い建築業界の僕にこの先生き残る道は残されているのか！
ライフはまだ残ってる。ここを耐えれば、この荒波に勝てるんだから！
次回！@snuow死す！デュエルスタンバイ！
Emacsからシリアルポートを開く

# シリアルポートを開くには
組込み開発で必須のシリアルポート
Linuxでは`screen`や`minicom`
Windowsでは`TeraTerm`を使う方が多いと思います

しかし、EmacserならばEmacsの中から
シリアルポートを開きたいと考えるのが当然

もちろん標準で`serial-term`というものが用意されています

ただ、シリアルデバイスによっては上手く動かなかったり
`serial-term`の挙動自体が少し特殊だったりします

この記事ではそういったトラブルシューティングを紹介します

# 基本の使い方
`M-x serial-term`でポートとボーレートを順に指定して起動します
Linuxではポートは`/dev/ttyUSB0`のように指定します
Windowsではポートは`COM2`のように指定します

# ポートとボーレート指定しても何も起きない
## ポートの指定ミス
- path指定が間違っていないか?
- 他のプログラムがデバイス握っていないか?

## ボーレートの指定ミス
- 正しいボーレートか?
- `nil`(ドライバのデフォルトで動かす)を試す  
  `nil`が指定できること自体が気付きにくいのですが  
  デバイスによっては`nil`で上手くいくことがあります

# C-x, C-p, C-nなどEmacsのバインドが効かなくなる
これは`term-mode`(`serial-term`はこれをベースにしている)の
`char-mode`と呼ばれる状態で、キー入力を全て端末に送っているため
Emacsにはキーが送られません（一部プレフィックス除く）
なので`line-mode`というEmacsがキーを拾えるモードに変える必要があります
- `C-c C-j` で `line-mode`
- `C-c C-k` で `char-mode`
です（デフォルトでは)

**`C-c C-j`** だけは覚えて起きましょう
焦らなくて済みます

また最初から`line-mode`にする方法もあります

```emacs-lisp:linemode.el
;; serial-term-mode デフォルトで line-mode に
(defun enable-term-line-mode (&rest ignored) (term-line-mode))
(advice-add 'serial-term :after #'enable-term-line-mode)
```

`M-x shell`と同じ動きだと１番良いのですが…

# スクロールが中途半端なところで始まる
以下の設定にすればTeraTerm等に近い感じに
- 画面埋まるまでは上から順に埋めていく
- 埋まり切ったら、追加の行の分だけスクロール

```emacs-lisp:serialscroll.el
(defun term-mode-init ()
  (setq scroll-margin 0)
  (setq term-scroll-to-bottom-on-output t)
  (setq term-scroll-show-maximum-output t) )
(add-hook 'term-mode-hook 'term-mode-init)
```

# シリアルデバイスが切断され再度繋がった時、serial-termのプロセス死んだまま
解決法求む

# まとめ
色々と目をつむる点もありますが
コピペやファイルとしての保存が楽だったり
`occur`で正規表現フィルタリングしたりと
ログ取り、検索、集計をEmacsで一貫してできるのは強みだと思います
リセットボタンの付け方

Create>UI>Buttonから作ります。そのあとCaNvasからButtonを選択しInsoectorの名前をResetに変えます。
Resetの▼を押しTextをクリック、Resetの表示名を変更できます。
次にスクリプトを作るためにcreate>FolderからScriptsを選択します。名前の表示をResetScriptsにしたほうが見やすくなります。次にこのようにコードを打ちましょう。


	

	void Update () {
        if (Input.GetMouseButtonDown(0))
        {
            
        }

    }
    public void RestartButton()
    {
       PlayerScript.score = 0;
       SceneManager.LoadScene("main");
    }

このように打てばおそらくResetができるはずです。
作ったResetのオブジェクトにScriptsを当てはめて終わりです。
自分だけのPGP公開キー検索サイトを作ってみた

自分のアドレスだけのPGPの公開キー検索サイトを作ってみました。

# 久しぶりのJavaScript
久しぶりに、JavaScriptを触りました。
functionの綴りを間違えたりして、たった3行なのに、苦戦しました…

# まぁ～仕様はシンプル
まぁ～仕様は、簡単にしてみました。
メールアドレスをファイル名にしました。
もちろん、ファイル名として使えない文字(＠)は、変換をしました。
＃今は、使えるかもしれないけど、昔の人なので…
# 一応、robots.txtを設置して、検索に引っかからないようにした
万が一ロボットで、特定のメールアドレスのファイルを見つけてしまったとしても大丈夫なように、robots.txtを設置しました。
本当は、メールアドレスをハッシュ化して、それをファイル名にしてもよかったんだけど、めんどくさいのと、だれも使わないと思い、単純化しました。
# ソース
めんどくさいので、index.htmlにJavaScriptを入れました。

```javascript:index.html
function getpgp(){
	var pgpmail = document.fm.email.value;
	var gnumail = pgpmail.replace( '@', '-');
	location.href = gnumail + '.asc';
};
```

本当は、分けたほうがいいのだけど、めんどくさかったから、というのが、一番の理由です。

formのほうは、こんな感じに作りました。

```html:index.html
<form name="fm" onsubmit="return false;">
<input type="email" name="email">
<input type="submit" value="検索" onclick="getpgp()">
</form>
```

もうちょっとカスタマイズすれば、見栄えはよくなると思いますが、めんどくさかったので、シンプルにしました。
# スマートフォンで、ちゃんと見られるように設定した
何も設定しないで、そのままhtmlでアップロードしても、スマートフォンで見ると、何か違和感があり、使いづらかったので、以下のサイトを参考にして、追加してみました。
[1時間で携帯サイトをスマートフォン対応にする方法 | GREE Engineers' Blog](http://labs.gree.jp/blog/2011/04/3282/)
まぁ～記事は古い(7年前かよ…orz)けど、気にせず、設定しました。

```html:index.html
<head>
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0a4.1/jquery.mobile-1.0a4.1.min.css" />
・
・
・
<script src="http://code.jquery.com/jquery-1.5.2.min.js"></script>
<script src="http://code.jquery.com/mobile/1.0a4.1/jquery.mobile-1.0a4.1.min.js"></script>
</body>
```

多分、ちゃんと調べれば、最新の方法があるはず。

# 検索してくれるファイル形式
同じディレクトリ内で以下のようなフォーマットのファイルをアップロードしておきます。
```
(メールID)-(ドメイン名).asc
```
例えば、メールアドレスが```hogehoge@example.com```の場合は、```hogehoge-example.com.asc```というファイル名で```index.html```があるディレクトリーにアップロードする。

# 実際作ったサイト
実際作ったサイトは、以下の場所にあります。
[PGP検索](https://pgp.kohei.biz/)

# ということで
日本でももっとPGPが普及しないかなと思っていたりします。
Lombokの@Valueや@Dataは他に明示的なコンストラクタが宣言されているとコンストラクタを生成しない

# なんの話か
言いたいことはほぼタイトルに書いてしまいました。
本記事で言いたいことは以下だけです。

Lombok1.16.18での挙動となります。

 * Lombokの@Valueや@Dataは他に明示的なコンストラクタが宣言されているとコンストラクタを生成しない（そういう仕様である）
 * @NoArgsConstructorなどと併用した場合も同様
 * @Valueと@Dataを両方つけると@AllArgsConstructorが勝つ（Setterも生成される）

# 通常の使い方
```Java
import lombok.*;

@Data
public class Test {

	private final int value1;

	private final int value2;

	public static void main(String[] args){
		new Test(1, 1);
	}
}
```

この場合@Dataが@RequiredArgsConstructorをバンドルしているため、コンストラクタが生成されコンパイルが通ります。

# コンストラクタが生成されないケース
しかし、このバンドルされた@RequiredArgsConstructorによるコンストラクタの生成は、明示的なコンストラクタの宣言がない場合にのみ行われます。
これはドキュメントにも記載されている正常な動作です。

>(except that no constructor will be generated if any explicitly written constructors already exist). 
[@Data](https://projectlombok.org/features/Data)より引用

## 例（明示的なコンストラクタの宣言）
例えば、以下のコードはコンパイルが通りません。

```Java
import lombok.*;

@Data
public class Test {

	private final int value1;

	private final int value2;

	public static void main(String[] args){
		new Test(1, 1);
	}

	// 明示的なコンストラクタ
	public Test() {

	}
}
```

## 例（アノテーションによるコンストラクタの生成）
@NoArgsConstructorなどのコンストラクタを生成するアノテーションをつけた場合も、同様に@Dataによるコンストラクタの生成が行われません。
よって、以下のコードはコンパイルが通りません。

```Java
import lombok.*;

@NoArgsConstructor
@Data
public class Test {

	private final int value1;

	private final int value2;

	public static void main(String[] args){
		new Test(1, 1);
	}
}
```

@Dataと@Valueを両方ともつけると@AllArgsConstructorが勝つようです。

```Java
import lombok.*;
import java.util.Arrays;

@Data
@Value
public class Test {

	int value1;

	int value2;

	public static void main(String[] args){
		Arrays.stream(Test.class.getConstructors()).forEach(System.out::println);
		new Test(1, 1); // これは通る
		new Test(); // これは通らない
	}
}
```

一応明示的なコンストラクタ+@Data+@Valueも試しましたが、いずれのコンストラクタも生成されませんでした。

```Java
import lombok.*;
import java.util.Arrays;

@Value
@Data
public class Test {

	int value1;

	int value2;

	public static void main(String[] args){
		Arrays.stream(Test.class.getConstructors()).forEach(System.out::println);
	}

	// 明示的なコンストラクタ
	public Test(int i){

	}
}
```
Python + DjangoのTemplateを試す

Djangoのテンプレートエンジンを使ってhtmlを表示してみます

1.環境
OS Windows 10 Home 64bit
Python 3.6.5
Django 2.0.4

Python、Djangoのインストールは以下を参照。
https://qiita.com/tiguchi919/items/f9052d259cec7fe54a00

2.アプリケーションを作成する。

今回は、myapp2とします。

仮想環境のディレクトリ「c:\python\env1」に移動して、Scripts\activate
を実行してアプリケーション「myapp2」を作成します

```
c:\python>env1>Scripts\activate
(env1) c:\python\env1>cd ..
(env1) c:\python>cd mysite
(env1) c:\python\mysite>django-admin startapp myapp2
```
3.テンプレートは、サイトの下にディレクトリ「templates」を作成

```
c:\python\mysite>mkdir templates
```

4.settings.pyに「templates」フォルダを追加する。
C:\python\mysite\mysite\settings.pyのTEMPATESの「DIRS」を以下のように修正する

```settings.py
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [
            os.path.join(BASE_DIR, 'templates'),
        ],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]
```

5.HTML
C:\python\mysite\templatesの下にmyapp2.htmlを作成します

```myapp2.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>myapp2</title>
</head>
<body>
<p>template sample(myapp2)</p>
</body>
</html>
```

6.アプリケーションのファイルを編集します
C:\python\mysite\myapp2
│  admin.py
│  apps.py
│  models.py
│  tests.py
│  urls.py
│  views.py

urls.pyは作成されていないので作成します

```urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
    url('', views.myapp2_template, name='myapp2_template'),
]
```
views.pyを編集します

```views.py
from django.shortcuts import render
from django.http.response import HttpResponse
 
def myapp2_template(request):
    return render(request, 'myapp2.html')
```

6.動作確認

サーバを起動して、URLにアクセスしてみます

```cmd.prompt
c:\python>cd env1
c:\python\env1>Scripts\activate
(env1) c:\python\mysite>python manage.py runserver

```

http://localhost:8000/myapp2/

![image.png](https://qiita-image-store.s3.amazonaws.com/0/246741/16c5bfd7-044e-7afd-5a5b-c5fbc5c55d78.png)

テンプレートを表示できました
ArrayListでのremoveメソッドはあまり使わない方がいいかもしれない

今日クラッシュしまくったのでメモとして残して置く

※下に追記

## クラッシュするソースコード

```kotlin

fun releaseGroupItem(uri: Uri){

        var i = 0
        selectImageList.forEach {
            if (it.imageUri == uri){
                selectImageList.removeAt(i)
            }
            i++
        }

        val adapter = SelectImageFragmentAdapter(supportFragmentManager, selectImageList)
        select_image_pager.adapter = adapter
        indicator_default.setViewPager(select_image_pager)
}
```

これだとこのメソッドが連続でよばれたときに `java.util.ConcurrentModificationException` が発生してクラッシュします。

これはJavaでは有名な話でプログラミングを始めたばかりのときにだいたいハマります。
(もうAndroidやって２年たつのにこの現象が起こるコードを書いてしまいました、、、)

~~原因はArrayList#removeだとリストの順番を考慮して削除してくれないとかなんとか
下にいい感じにまとめられています。~~(下に追記しました)
http://programming-study.com/technology/java-list-remove/

## クラッシュしないコード

```kotlin

fun releaseGroupItem(uri: Uri){

        val iterator = selectImageList.iterator()
        while (iterator.hasNext()){
            val removeUri = iterator.next()
            if (removeUri.imageUri == uri) {
                iterator.remove()
            }
        }

        val adapter = SelectImageFragmentAdapter(supportFragmentManager, selectImageList)
        select_image_pager.adapter = adapter
        indicator_default.setViewPager(select_image_pager)
    }

```
`iterator` を使います。
こっちの方がパフォーマンスもいいそうなので、削除する要素が単純で一回しか呼ばないとか以外は基本的に `iterator` を使った方がいいかもしれません。

特に中身のない記事になってしまいましたが、個人的なメモとして残しておきます。

## ※追記


コメント欄に教えていただきました！

https://docs.oracle.com/javase/jp/8/docs/api/java/util/ArrayList.html

単にiteratorはfor文の中でList内の要素のadd、removeできるようにしているが、ArrayListはそれをすると例外を投げるようになっているからだそうです。

教えていただきありがとうございます！
正しい平均の使い方


日能研の問題にこんなのがありました。
https://www.nichinoken.co.jp/shikakumaru/201805_sa/

リンク先を簡単に解説すると、
平均以下の人は下位50%にいるといえるか、という問題です。

ここで言いたいのは、平均と個人の値を比較するのは無意味です。

ちょっと例で考えてみます。

---
・A学校の松田くんは70点でした
・B学校の竹田くんは60点でした

・A学校の生徒が受けたテストの得点合計は10000点でした
・B学校の生徒が受けたテストの得点合計は7000点でした

・A学校の国語の平均点は70点でした
・B学校の理科の平均点は60点でした

よって、A学校の方が優秀な学校と言えます。

---

どれもおかしいことがわかります。

・1人の成績だけで比較するのはおかしい
・得点合計では人数が多いほうが多くなってしまう
・テストは同じ問題を使うべき

こういう問題点が上がるでしょう。

ですから、A学校とB学校で同じテストを実施して、
・A学校の平均点は70点でした
・B学校の平均点は60点でした

これならA学校のほうが優秀と結論づけられるでしょう。
最も一回のテストではまだわからないですから、
より多くテストはやったほうがいいのは言うまでもありません。


データを取るときには、できるだけ比べたい部分以外は同じ条件にする、
当たり前に聞こえますが、それを理解している人は少ないです。

例えば、全国テストで、全国平均が60点、学校平均が70点だったら、
この学校は優秀と言えるでしょうか。

優秀を上位50％に入っていると捉えるのなら、必ずしも優秀とは言えません。
これは冒頭のテストと同じ理屈です。

母集団が全国と学校という、同じものではないのが原因です。
これが、A学校の平均、B学校の平均を比べるのなら、意味があると言えます。

冒頭の問題も同様で、平均と個人というのは同じ条件ではありません。
ですから、比較することには意味がありません。

実際、このように変な結果が出るものとしては、平均年収があります。
年収の計算は年収がほぼ0の人は働いてないものとして除外されがちです。
また、年収は1千万や1億を超える人もいますから、平均が上に引っ張られます。
よって、中央値(上位50％に入るライン)と結構な乖離があります。

平均年収は年齢別でどのぐらいアップするのかとか、
30歳の平均年収の推移とかの用途として使うのが適切です。
平均年収と自分自身の年収を比べるのは、
条件が同じではないので、意味がない比較です。

ところで、平均年収で検索すると転職サイトが出てきますね。
本来、上位50%をみるのなら、中央年収を使うべきなのですが、
数値が高く出てしまう平均年収を使うのはどういう意味があるんでしょうね。
容量の少ないMacでWindowsを動作させるための備忘録

#経緯
 筆者は長年、MacでWindowsを動作させる方法を様々に模索してきたが、この現在(2018/5)においてようやく最良と言えるものが決まった。
まず筆者の環境を示す。
#環境

- MacbookPro 13inch(Early2015) 128GB カスタマイズ無し

#方法
この環境においてWindowsを動作させるには基本的に２つの方法が考えられる。

- BootCamp
- 仮想化アプリケーション

## BootCampを試してみる
M.2なだけあり、起動も動作もサクサク。むしろサクサクじゃないとBootCampな意味がない。

##Parallelsを用いて仮想にする(内臓SSD)
BootCampには速度は若干劣るが、十分な速度で動作する、ゲーム等も十分(勿論、同等のWidnwosPC以下の性能しかないが)である。

しかし、上に記した２つの方法にはいずれも越えられない壁がある、容量である。筆者の場合,SSDが128GBしかなく、あくまでもメインはMacなのでWindowsに割り当てられる容量には限りがある。Windowsの容量が小さく、VisualStudioや各種ゲームがインストール出来ないのであればWindowsをインストールする意味がない。それを踏まえて次の方法を試す。

##Parallelsを用いて仮想化する(外付けHDD＆USB3.0)
この方法は容量面に関しては非常によかった。しかし、当たり前だが通信速度がネックとなり、性能の低下が著しかった。

このことから、仮想をよりよくするには、通信速度を向上させることが重要なことが分かった。よって解決策は次の通りだ。

- USB3.0の通信速度が遅い
    - ThunderBoltやUSB3.1対応のHDDにする
- HDDが遅い
    - 外付けSSDにする

つまり、ThunderBold or USB3.1対応のSSDが最強となる。
しかし、筆者は一つのことを思いついた

RAID組めばよくね？


##RAIDを組んで外付けHDDで仮想化する
MacにはソフトウェアRAIDを組む機能がある。
DiskUtility->ファイル->RAIDアシスタントから作成可能である
![スクリーンショット 2018-05-15 23.49.20.png](https://qiita-image-store.s3.amazonaws.com/0/204702/7e5f917f-1757-52dd-21e6-70e72681d728.png)

これで作成したRAIDを用いて仮想マシンを作成する
#結果
RAIDをくみ外付けHDDで仮想化ソフトを用いた場合、SSDよりはモッサリしているが内臓HDDで動作させているのと遜色ない速度が出ることが分かった
CrystalDiskで測定した結果でも同等の速度は出ていることが分かっている

#あとがき
仮想化ソフトはParallelsに限らずVisualBoxでも作成可能である
今回Windowsでのみ動作確認しているため確実なことは言えないがLinuxにも同等の効果があると思われる為
試してみたい方はVisualBox＆Linuxで試すことをオススメする
さすがにcomposer installが遅いのでなんとかしてみる

# Composerが重いのはリポジトリが日本から遠いかららしい

そのままの理由。アメリカとかだと爆速らしい。なんてこったい。

## ミラーサイトを変更する

```shell
composer config -g repositories.packagist composer http://packagist.jp
```

しかし、`composer install`しようとしても、リポジトリを変更しただと怒られる
リポジトリがhttpなのが、原因らしい

```shell:エラーログ
[Composer\Downloader\TransportException]                                     
Your configuration does not allow connection to http://pear.php.net. 
See https://getcomposer.org/doc/06-config.md#secure-http for details. 
```

## httpを許可してやる

```shell
composer config -g secure-http false
```

試しにLaravelインストールしてみたら確かに早くなった。快適！

## 参考記事&サイト
[【PHP】たった1行コマンドを入力するだけでComposerを劇的に速くする方法【アジア圏限定】](http://yuzurus.hatenablog.jp/entry/composer-hayai)
[composer install で Downloading の時点で失敗する](https://qiita.com/shinkuFencer/items/00c6cdbc0d0e0e081e38)
Redshiftのテーブル作成する時のかゆいところをまとめてみた

Redshiftのテーブル作成でよく忘れるポイントをまとめておこうと思います。
主に作成する際のポイントだけで、データ設計に関することは書きません。

# レコード作成時間

使うかどうかはわからなけいけど、わりとつけ得なカラムだと思うのでよくつけます。
ただ、よくあるRDBで設定する`default current_timestamp`とかは使えないので注意。

とりあえずこんな感じで設定しておきましょう。

```sql
create table hoge (
  // なんか他のカラム
  created_time timestamp encode DELTA default sysdate
)
```

# ソートキー、分散キー

Redshiftのパフォーマンスを上げるために、なんなら一番重要とも言えるところ。

* ソートキー：レコードのソート順
* 分散キー：複数のノードに分散するためのキー

## ソートキーの設定

特に理由がなければcreated_timeとかでいいと思います。
というのも、新しいデータだけを処理したい時に早くselect出来るためです。
ただ、特別に重いjoinなどをするときは考え直したほうがいいです。
複数設定できますが、ソートキーを複数設定するだけなので、こだわりがなければ一つでOKです。

複数設定する時は複合ソートキーと言いますが、あんまりソートキーを増やしすぎるとテーブルのディスク容量が増えます。なので、ちゃんとソートしておくべきものを設定しておきましょう。

```sql
create table hoge (
  // カラム
)
sortkey(created_time)
```

## 分散キーの設定

ユーザーのログなどであればユーザーIDとか分散しやすいものがいいです。
変なのを設定するとノードごとにデータ量の偏りができます。
もちろん、特別に重いjoinなどをするときは考え直したほうがいいです。

```sql
create table hoge (
  // カラム
)
distkey(created_time)
```
※ちなみに、distkeyはsortkeyより先に設定しないとクエリエラーになったりします

## JOINするのがわかっている時

RedshiftのJOIN処理は、内部的に３種類あります。
細かいところは [こちら（公式ヘルプ）](https://docs.aws.amazon.com/ja_jp/redshift/latest/dg/query-performance-improvement-opportunities.html) を見てください。ただ、だいたい下記の覚え方でいいと思います。
１ノードで運用していたりすると、たまーにMerge JoinよりもHash Joinのが速い時もありますが、だいたいの場合Merge Joinのが速いです。

* Nested Loop Join: やべーやつ
* Hash Join: 普通のやつ
* Merge Join: 速いやつ

ただ、Merge Joinはかなり条件が厳しいです。

* 結合する列が、ソートキーと分散キーの両方に設定されている
* 両方のテーブルが、それぞれ80%以上ソートされている

このJoinをしようと思ったら、テーブルを作る際に狙って作るしか無いです。

# 圧縮形式

圧縮形式によってディスク使用量、パフォーマンスがかなり変わるので、設定し得です。
ただいっぱいあってよくわからないので、軽くまとめておきます。

![圧縮エンコードの選び方.png](https://qiita-image-store.s3.amazonaws.com/0/242274/47fbddb6-222e-300e-0dc4-72324e0c6921.png)

もちろん、突き詰めればもっと効率よく圧縮方式を選択することも出来ますが、あくまで雑にまとめてます。
（せめてこれくらい判断条件に入れたほうがいいよ、とかあれば教えてください、更新します）

設定方法

```sql
create table hoge (
  // なんかカラム
  columnName varchar(255) encode lzo,
  // なんかカラム
)
```

これで幸せなRedshiftライフを送りましょう。
可視化ツールDashのチュートリアル - Part 3: State -

# はじめに

[前回のチュートリアル](https://qiita.com/pinocookie/items/8f524916eeac8c445cf0)で、グラフを対話的に動作させる方法を学びました。

しかし、一般的なウェブページのログイン画面や会員登録画面を考えると、入力ボックスに情報を入力すると即座に反映されるのではなく、登録ボタンやログインボタンを入力することで情報が出力されます。

今回のチュートリアルで、こうした入力値をいったん止めておく機能を実装していきます。

[公式HPのチュートリアル](https://dash.plot.ly/state)

# Dash Input and Output

まずは前回の内容の復習として、入力ボックスを実装します。

まず最初に必要なライブラリをインポートします。

```python
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
```

次にアプリの外観を決めていきます。

```python
app = dash.Dash(__name__)

app.layout = html.Div([
    dcc.Input(id="input-1", type="text", value="Montreal"),
    dcc.Input(id="input-2", type="text", value="Canada"),
    # 出力する場所
    html.Div(id="output")
])
```

次に入力値と出力値を決めていきます。

```python
@app.callback(
    Output("output", "children"),
    [Input("input-1", "value"),
     Input("input-2", "value")]
)
def update_output(input1, input2):
    return "input 1 is {} and input 2 is {}".format(input1, input2)

if __name__ == "__main__":
    app.run_server(debug=True)
```

![01.gif](https://qiita-image-store.s3.amazonaws.com/0/194085/6a956984-2a46-264e-5a3c-f659d398218e.gif)

この例では、`dash.dependencies.Input`の属性が変化した際に常にコールバック関数が動作してしまっています。

# Dash State

上記の対策として、`dash.dependencies.State`を使います。この関数を使えばコールバックせずにデータの受け渡しが可能です。

では最初の例にボタンを導入したアプリを実装します。

まず必要なライブラリをインポートします。

```python
import dash
import dash_core_components as dcc
import dash_html_components as html
# 追加でStateをインポート
from dash.dependencies import Input, Output, State
```

次にアプリの外観を決めていきます。

```python
app = dash.Dash()

app.layout = html.Div([
    dcc.Input(id="input-1-state", type="text", value="Montreal"),
    dcc.Input(id="input-2-state", type="text", value="Canada"),
    html.Button(id="submit-button", n_clicks=0, children="Submit"),
    html.Div(id="output-state")
])
```

次に入力値と出力値、Stateを決めていきます。
イメージとして、いったんデータを送る前に入力値を`State`させ、ボタンが押されたら`State`してあるデータを出力するといった感じです。

```python
@app.callback(
    Output("output-state", "children"),
    [Input("submit-button", "n_clicks")],
    [State("input-1-state", "value"),
     State("input-2-state", "value")]
)
def update_output(n_clicks, input1, input2):
    return """
        The Button has been pressed {} times,
        Input 1 is {},
        and Input 2 is {}
    """.format(n_clicks, input1, input2)


if __name__ == '__main__':
    app.run_server(debug=True)
```

![02.gif](https://qiita-image-store.s3.amazonaws.com/0/194085/f3187471-ec6e-c360-000d-c6f91cdc3f99.gif)

この例を見てみると、`dcc.Input`の入力ボックスに文字が入力されてもコールバックは起きず、ボタンを押したときにコールバックが発生し入力値が更新されています。

今回コールバックを発生させている箇所は、`html.Button`コンポーネントに存在している`n_clicks`プロパティです。このプロパティは、コンポーネントの部分がクリックされるたびに1ずつ増加していきます。

このプロパティは、`dash_html_components`ライブラリのすべてのコンポーネントで使用できます。
【備忘録】タグの使い方

##前書き

Gitにはタグという便利なものがあります。

コミットに対してタグを付けることができます。
作成したタグを指定して、その時点のソースを簡単に落とすことが可能です。

##タグの一覧を確認

```shell
$git tag
```

##タグの作成

```shell
$git tag 【タグ名】 【ブランチ名】
```

例）

```shell
$git tag V1.0.0 master
```

この場合、masterブランチの最後のコミットに対して、タグが付けられるようです。

##タグの反映

```shell
$git push 【リモートリポジトリ】 【タグ名】　// 指定したタグをリモートへ
```

```shell
$git push 【リモートリポジトリ】 --tags  　// ローカルのタグ全てを一括でリモートへ
```

タグはリモートにプッシュして初めてリモートに反映されます。

##タグを指定してエクスポート

```shell
$git archive --format zip --prefix=export/ 【タグ名】> 【出力先】
```

例）

```shell
$git archive --format zip --prefix=export/ v_1.0.0 > ../export.zip
```

プロジェクトフォルダの一つ上の階層に、export.zipが作られます。
階層構造を保ったまま、タグを付けた時点のソースコードを落とせます。
RaspberryPiでらじるらじる(m3u8)を聞く方法

2018年5月現在コマンドライン環境でHLS(HTTP Live Streaming).m3u8形式の配信をパッケージアプリケーションで簡単に受信する方法をメモします。2018年3月でradikoでの配信実験が一旦終了し12日後に再編再開されました。中断期間もありましたし、今の配信実験も期間が定まっているため本家サービス側m3u8への対応の手順です。より各種リソースやナレッジが豊富なIAマシンやDebian/Ubuntu等OSでも同様にvlc/ffmpegで動作すると思います。
インタラクティブに再生だけかプロセス間通信とかできるならdefaultインストールされているomxplayerで再生できますが、ストリームメディアの場合止めない限り止まらないのです。難しいことせずに止まるプレーヤー探しました。

##環境
-Raspberry Pi
-Raspbian jessie / stretch　GUI無し
-スピーカー
#リアルタイム再生
vlcのコマンドライン版でvlcに画面出力無しのオプションをつけたエイリアスのcvlcを使います。vlcのパッケージにcvlcも入っています。vlcが入っていない場合はapt-getでインストールします。jessieではupdateしてから、
stretchは定期自動updateだと思うのでupdateは任意で。

```
　sudo apt-get update
　sudo apt-get -y install vlc
```

###再生実行方法

```
cvlc <m3u4のURL>
```

らじるらじるのURLは<http://www.nhk.or.jp/radio/config/config_web.xml>にあります。

視聴時間を指定する場合

```
cvlc --run-time <秒> <m3u4のURL>
```

これだけだとcvlcの再生が停止するだけでcvlcは終了しません。

```
cvlc --run-time <秒> <m3u4のURL> vlc://quit
```

vlc://quitをつけるとcvlcが終了します。cron実行で目覚ましや学習にどうぞ。

結構カラフルなwarnやerrorが出ます、気になる場合`--quiet`で抑制してください。
#録音
こちらを参照させていただきました。
　[らじるらじる m3u8 を ffmpeg で録音する（８放送局）2017/9 以降対応](http://gist.github.com/riocampos/93739197ab7c765d16004cd4164dca73)

Raspbian stretchの場合は各種エンコーダ、デコーダをサポートしたパッケージがリポジトリにありましたのでffmpegをインストールします。

```
sudo apt-get -y install ffmpeg
```
###録音実行方法
使い方についても上記サイトどおりで、録音時間を秒で設定します。

```
ffmpeg -i <m3u4のURL> -t <秒> -c copy <m4a出力ファイル名>
```
こちらもcronでスケジュールが可能ですね。

###Raspbian jessieの場合
Raspbian jessieのリポジトリにはffmpegのパッケージが無いようです。ソースからビルドする必要があります。以下のサイトの全自動スクリプトがRaspberry Piでも動作しました。こちらを利用させていただきます。

　[自分に負けないラボラトリー LinuxでFFmpegをほぼ全自動でビルドする（CentOS、Ubuntu等に対応）](https://www.jifu-labo.net/2015/09/ffmpeg_build/)
説明には
>64bit版（amd64）のLinux OSで実行して下さい。32bit版（i386）ではビルドに失敗します。

と記載ありましたが、ARM32のRaspbianでもだいたい動作しました。一点、x265の途中で止まってしまいました。

　[Umbrella RaspberryPi　Pi3でlibx265 リベンジ](http://wbbwbb.blog83.fc2.com/blog-entry-244.html)
こちらのサイトのCMakeListsの修正点を反映させると通ります。しかしながら、H.265エンコードは非力なRaspberry Piでは途方もなく時間がかかり実用的ではないので、全自動ビルドスクリプトで`enable_h265=0`として無効にしたほうがよいともいます。

この全自動ビルドスクリプトのままではhttpsのm3u8が取得できないので全自動ビルドスクリプトの最後のほうの./configureに `--enable-openssl \`を追加します。
　`sudo apt-get install libssl-dev`　でsslのライブラリを追加した後全自動スクリプトを実行するか手動で`make install`まで動かせば当初の目的のm3u8受信録音可能なffmpegが完成します。この全自動スクリプトでは専用の場所にインストールされるので使い方に記載のPATHを通しておいてください。

ちなみに、本家Raspberry PiサイトからMPEG2ハードウェアライセンス(£2.40)を買って、起動ファイルに設定したうえでRaspbian stretchのパッケージのffmpegやビルド時に`--enable-mmal  --enable-omx  --enable-omx-rpi`が追加されたffmpegではRaspberry Pi 3でもHD動画のリアルタイムデコード＋エンコードが一応可能でした。 
##注意
環境にもよると思いますが、らじるらじる は感覚的にはradikoよりさらに遅延しているようです。私の場合ラジオ波と比べて1分ぐらいは遅れている感じです。お尻が切れないように余裕持たせてください。

##参照
[GitHubGist riocampos らじるらじる m3u8 を ffmpeg で録音する（８放送局）2017/9 以降対応](http://gist.github.com/riocampos/93739197ab7c765d16004cd4164dca73)

[自分に負けないラボラトリー LinuxでFFmpegをほぼ全自動でビルドする（CentOS、Ubuntu等に対応）](https://www.jifu-labo.net/2015/09/ffmpeg_build/)

[Umbrella RaspberryPi　Pi3でlibx265 リベンジ](http://wbbwbb.blog83.fc2.com/blog-entry-244.html)

##メモ
http://min117.hatenablog.com/entry/2018/06/04/231650
【VMware】isoファイルを保存する時の注意点

駆け出しエンジニアです。

VMware_ESXi 5.5にisoファイルを使ってCentOS7を入れる際、とても簡単な事で丸1日ハマってしまいましたので備忘録としたく投稿します。

【ハマったポイント】
CentOS7.4のisoファイルをこちらのサイトからダウンロードする時、http://ftp.riken.jp/Linux/centos/7.4.1708/isos/x86_64/
格納場所を指定せずにダウンロードしました。

結果、きちんとDVDドライブにインストールできたのですが、
ESXiのデータストアにアップロードする際、DVDドライブから直接実行すると
datastore_name is already exsists.のエラーが出てしまいできませんでした。

datastore_nameはすでに存在している？　それならデータストアの名前を変えてみたらどうだろう、と思い以下の様にトライしてみましたが

最初のデータストアの名前：datastore1 →　変更後：datastore2とか、hogehogestoreとか

今度はdatastore2 is already exsists.(hogehogestoreも)となってしまいました（なんでだ）。
エラーの出方を考えてみると、DVDドライブからアップロードするファイルは何らかの原因で格納場所と同じファイル名で保存されようとするみたいです。

という事を考え、それならisoファイルを別の場所からアップロードしたらどうだ？と思い、isoファイルを上記のサイトから、今度は:Cドライブへ再インストールし、再チャレンジしたら上手くいきました（DVDドライブから:Cドライブにコピーすればいいじゃないか、と思いますが、それだとなぜかフォルダ形式でコピーされてしまうのでESXiでのゲストOSとしての機能を失ってしまいます）。

もし何らかの原因、の原因がわかる方いたら教えていただきたいです。
Xamarinを独学していてつまずいたところ(随時更新予定)

最近独学でXamarinを勉強していますが、色々とつまずいています。日本語の解説があんましないので、とりあえず書けるとこは書いていこうかなと思います。

学習にあたってはこちらの本を参考にしています。
[https://www.amazon.co.jp/dp/4774188956](https://www.amazon.co.jp/dp/4774188956)

どなたか、良い勉強方法があったら教えてください。。。有料でも構いません。。。

ちなみに環境は
- VisualStudio2017 Community
です。

# InitializeComponent は現在のコンテキスト内に存在しません。

最初、「なんでここでエラーが出るの！？」ってめっちゃハマりました。
調べたところ、ソースに問題があるわけではなくVisualStudioがXAMLをうまく認識できていないことが問題のようです。

解決策としては、**プロジェクトに空のクラスを追加する** で僕の場合は解決しています。(エラーが解決したらそのファイルを削除)

ぶっちゃけ、それは解決してないんじゃないかという気もするんですが。。。
結構頻発するので根本的な解決方法をどなたかご存知でしたら教えていただけると非常に助かります。

参考：
[http://ytabuchi.hatenablog.com/entry/2017/04/14/203000](http://ytabuchi.hatenablog.com/entry/2017/04/14/203000)
  
  
# SearchBarが表示されない
MainPage.xamlに下記のコードを書くだけでは表示されませんでした。

```XAML:MainPage.xaml

<StackLayout Padding="20" Spacing="15" BackgroundColor="White" >
    <!-- SarchBarの使用例-->
    <SearchBar x:Name="searchingBar" Placeholder="Keyword" CancelButtonColor="Red" TextColor="Black" />
    <Label Text="検索結果" FontSize="Small" FontAttributes="Bold" TextColor="Black" />
    <Label x:Name="lblResult" TextColor="Black" />
</StackLayout>

```

これは、下記のようにSearchBar.HeightRequest というプロパティを記述することで解決しました。

```XAML:MainPage.xaml

<StackLayout Padding="20" Spacing="15" BackgroundColor="White" >
    <!-- SarchBarの使用例-->
    <SearchBar x:Name="searchingBar" Placeholder="Keyword" CancelButtonColor="Red" TextColor="Black" >
        <SearchBar.HeightRequest>
            <OnPlatform x:TypeArguments="x:Double"
                            iOS="-1.0"
                            Android="40.0"
                            WinPhone="-1">
            </OnPlatform>
        </SearchBar.HeightRequest>

    </SearchBar>
    <Label Text="検索結果" FontSize="Small" FontAttributes="Bold" TextColor="Black" />
    <Label x:Name="lblResult" TextColor="Black" />
</StackLayout>

```
参考：
[https://stackoverflow.com/questions/45472329/xamarin-forms-android-7-0-searchbar](https://stackoverflow.com/questions/45472329/xamarin-forms-android-7-0-searchbar)


なかなか悪戦苦闘中というか、書いててしっくりこないとこが多くてモヤモヤ。
業務でC# (アプリではなく普通のMVCweb)をやっているのでXamarinがいいかなーと始めてみたものの、早くもKotlinに乗り換えたくなってきました。笑
Vapor 3.0 でコマンド内でデータベースに接続する

Vapor には Command というモジュールがあり、これを利用すると CLI のコマンドを作ることができる (ややこしいことに、これを使いたい場合は vapor/console を依存関係に追加する必要がある) 。

https://github.com/vapor/console

だが、その中でデータベースにアクセスしようとして困った。

やろうとしたことは、

- コマンドを実行してユーザーを作りたい

というもので、当然データベースにデータを `INSERT` する必要がある。

CLI を作る場合、`Command` プロトコルに準拠した型を用意し、その `run` メソッドに処理を実装するのだが、その際に利用できる `CommandContext` というコンテナは `DatabaseConnectable` を満たさないのだ。

```
argument type 'Container' does not conform to expected type 'DatabaseConnectable'
```

で、質問して教えてもらった方法が、[ここ](https://github.com/vapor/database-kit/blob/0db303439e5ef8b6df50a2b6c4029edddee90cb0/Sources/DatabaseKit/Connection/Container%2BNewConnection.swift) にあるように、`Conitainer` には `withNewConnection` という拡張メソッドがあり、それを使うとクロージャに `Database.Connection` が渡るのでデータベースにアクセスすることができる。

例えばやりたかったことは↓で実現可能。

```

...

    func run(using context: CommandContext) throws -> Future<Void> {
        let email = try context.argument("email")
        let password = try context.requireOption("password")
        let passwordHash = try BCrypt.hash(password)
        let user = User(email: email, password: passwordHash)
        return context.container.withNewConnection(to: .psql) { db in
            return user.save(on: db).transform(to: ())
        }
    }

...
```

ちなみに `newConnection` というメソッドもあるが、こちらは自分でコネクションを閉じる必要があるため、普通は `withNewConnection` を使ったほうが良いと思う。
名刺の代わりにCLIアプリを書く


ここ1週間自己紹介用のCLIアプリを書くのが流行ってる。
はじまりはいつものSindre Sorhus。

<blockquote class="twitter-tweet" data-conversation="none" data-cards="hidden" data-partner="tweetdeck"><p lang="en" dir="ltr">My new business card <a href="https://t.co/koVIsUT5np">pic.twitter.com/koVIsUT5np</a></p>&mdash; Sindre Sorhus (@sindresorhus) <a href="https://twitter.com/sindresorhus/status/994438517576028160?ref_src=twsrc%5Etfw">May 10, 2018</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

nodeが入っていれば

```
npx sindresorhus
```

すると自己紹介CLIアプリが起動。

<blockquote class="twitter-tweet" data-partner="tweetdeck"><p lang="de" dir="ltr">```<br>$ npx sindresorhus<br>```<a href="https://t.co/QO3ogKmu1d">https://t.co/QO3ogKmu1d</a> <a href="https://t.co/xZdQSzFLAq">pic.twitter.com/xZdQSzFLAq</a></p>&mdash; Sindre Sorhus (@sindresorhus) <a href="https://twitter.com/sindresorhus/status/994307954030526464?ref_src=twsrc%5Etfw">May 9, 2018</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

基本的には、このレポジトリを適当に書き換えれば簡単にできる。
はじめてのnpmライブラリにちょうどいいかも知れない。

https://github.com/sindresorhus/sindresorhus

また、使っている技術がちょっとおもしろくて、`ink`を使っている。
これは何かとCLIのためのReactだ。

https://github.com/vadimdemedes/ink

普通にReactでCLIを書くことができる。
なお、`ｖ０．５`がちょっと壊れている雰囲気あってエラーが出るので`v0.4`推奨です。

```jsx
const {h, render, Component, Color } = require('ink');

class Counter extends Component {
	constructor() {
		super();

		this.state = {
			i: 0
		};
	}

	render() {
		return (
			<Color green>
				{this.state.i} tests passed
			</Color>
		);
	}

	componentDidMount() {
		this.timer = setInterval(() => {
			this.setState({
				i: this.state.i + 1
			});
		}, 100);
	}

	componentWillUnmount() {
		clearInterval(this.timer);
	}
}

render(<Counter/>);
```

![](https://github.com/vadimdemedes/ink/raw/master/media/demo.svg?sanitize=true)


また、本家では、`import-jsx`を使って実行時にばべっているのだけど、これだとインストールに時間かかるので、普通にバベるのがいいと思う。

それでは、よいCLIライフを。

<blockquote class="twitter-tweet" data-partner="tweetdeck"><p lang="ja" dir="ltr">流行に乗るオタクなのでnpx akamecoつくってしまった <a href="https://t.co/CkdYHj2NGA">https://t.co/CkdYHj2NGA</a> <a href="https://t.co/f8kGNT6FKk">pic.twitter.com/f8kGNT6FKk</a></p>&mdash; あかめ@社会性.js (@akameco) <a href="https://twitter.com/akameco/status/996378646192377857?ref_src=twsrc%5Etfw">May 15, 2018</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
Xamarin.iOSでビルドエラーが出た場合の解決方法(AdMob関連)

# 現象

iOS用のAdMob表示で後述のNuGetパッケージを使用していると、iOSビルド時に下記のエラーが発生しました。

```text
Native linking failed, duplicate symbol: '_OBJC_METACLASS_$_GADMediatedNativeAd'.
Native linking failed, duplicate symbol: '_OBJC_CLASS_$_GADMediatedNativeAd'.
Native linking error: 2 duplicate symbols for architecture arm64
```

# 環境

* Windows 10 Pro
* Visual Studio 2017 Community (Ver15.7.1)
* Visual Studio 2017 for Mac Community (Ver7.5)
* iPhone 7 (iOS11.3.1)

## NuGet

* Xamarin.Google.iOS.MobileAds (Ver.7.27.0.2)
    * https://www.nuget.org/packages/Xamarin.Google.iOS.MobileAds/

# 解決方法

上記NuGetパッケージを最新に更新すれば直りました。

* 変更前：Xamarin.Google.iOS.MobileAds (Ver.7.27.0.2)
* 変更後：Xamarin.Google.iOS.MobileAds (Ver.7.27.0.3)


# 参考

* https://github.com/xamarin/GoogleApisForiOSComponents/issues/146
* https://github.com/xamarin/GoogleApisForiOSComponents/pull/148
デフォルトゲートウェイを２つ指定してはいけない理由

NICが２本刺さっていた場合、ネットワークのプロパティからデフォルトゲートウェイをネットワークインターフェースごとに設定することができるが、なぜ２つ以上指定してはいけないのか(警告がでるのか)分かった気がするのでメモ

# きっかけ
PowerShellからデフォルトゲートウェイを設定したいニーズがあり、

``` powershell
New-NetRoute -DestinationPrefix 192.168.10.0/24 -NextHop 192.168.10.1
```

というPowerShellを書きながら、なぜここでNextHopがでてくるのか気になった。

# ルーティングテーブルの設定をしている
![network.PNG](https://qiita-image-store.s3.amazonaws.com/0/167027/d1cd6928-3222-16cb-5029-78a48caf0b85.png)
画像の「デフォルトゲートウェイ(D)」にIPアドレスを入力後

```
route print
```

でルーティングテーブルを確認すると、たしかにネットワーク宛先0.0.0.0 ネットマスク0.0.0.0 に対応するゲートウェイには入力した「192.168.10.1」が反映されていた。

# デフォルトルートに対するルーティング
[Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%87%E3%83%95%E3%82%A9%E3%83%AB%E3%83%88%E3%83%AB%E3%83%BC%E3%83%88)曰く、「ルーティングテーブルに設定されていないIPアドレス宛ての全てのパケットは、デフォルトルート経由で送信される。」ちなみに、「デフォルトルートが指し示すデバイスはデフォルトゲートウェイ」と呼ばれるらしい。

# まとめ
なるほど、ルーティングテーブルにネットワーク宛先が無いと最終的になんでも解釈してくれるIPアドレス0.0.0.0(デフォルトルート)に宛先が行く。そして、ネクストホップであるゲートウェイ(多くの場合ルーターのIP)に渡されていい感じにしてくれるのか。

そのデフォルトルートが２通り存在するとどっちのルーターを見に行くか分からなくなるからデフォルトゲートウェイは基本的に２種類指定してはいけない。

# 最後に
まとめながら色んなサイト検索してたら、[こんなサイト](http://www.atmarkit.co.jp/ait/articles/0212/14/news002.html)見つけた。
まとめたことが大体書いてある。。。
[ メモ ] laravel gitからクローンしてきた場合の設定

# Gitから既存のプロジェクトをクローン

Git(SourceTree)からクローンしてきた際の順序をメモしておきます。

Sourcetreeからクローンしてきたら、

#####composerをコマンドでインストール

```
$ composer install
```

- .env.exampleを複製し、.envファイルを作成
- Homestead.yaml.exampleを複製し、Homestead.yamlファイルを作成

```ruby:.env
APP_ENV=local
APP_DEBUG=true
APP_KEY=
```
##### Homestead.yamlファイルを編集

(ipアドレスやpoot等を変更する)

```ruby:Homestead.yaml
ip: "10.0.0.10"
hostname: "local"
memory: 1024
cpus: 1
provider: virtualbox
```

#####[Hosts](https://download.cnet.com/Hosts/3000-2094_4-76044627.html)に設定（Windowsにあるか、分かりません）

ipアドレスとhostnameを設定する
（設定するとhostnameでもアクセス出来るようになる）


#####(使用する場合は)npmをコマンドでインストール
（package.jsonがあれば使用する）

```
$ npm install
```

#####vagrantをコマンドで起動、接続

```
$ vagrant up

$ vagrant ssh
```

##### .envファイルのAPP_KEYをコマンドで設定

```
$ php artisan key:generate
```

#DB（データベースがある場合）

#####migrationをコマンドで実行

```
$ php artisan migrate
```

migrateを実行する、とDBのmigration（テーブル）に登録される
（テーブルが作成される）

#####シーダーをコマンドで実行

```
$ php artisan db:seed
```

Seederの情報がデータベースに入る <br>

<br>
（私のやり方なので、もっと良い方法や間違っている部分があれば教えてください！）
VirtualBoxで仮想環境が起動できなくなって焦った話(VT-xが有効なのに認識しない)

# 前提条件
## 使用しているPC
![キャプチャ.png](https://qiita-image-store.s3.amazonaws.com/0/51498/484bb23e-01df-88d3-b085-2e41fa912d20.png)

## VirtualBoxのバージョン
![キャプチャ.png](https://qiita-image-store.s3.amazonaws.com/0/51498/0b0431c2-37e1-5005-9e19-cc94ef559a2e.png)

# 解決方法
Windows Defender セキュリティセンター
->デバイス セキュリティ
->コア分離
->メモリ整合性
をオフにする。

# 何が起こったか
* 仮想で64bitのOSを起動しようとしたらエラーが出る
    * エラーメッセージは"VT-x is not available (VERR_VMX_NO_VMX)."
* BIOSのオプションを確認(そう言えばBIOSアップデートしたしなあ…)
    * VT-xオプションは有効になっている
* 再起動してから仮想をもう一度起動しようとしても同じエラーになる
    * ?????
* 思いついた策は…
    * BIOSのバージョンを戻す
    * TPM側のアップデート(していなかったので)
    * 他に設定変更したところあったっけ…　->　解決方法へ

# 所感
* 久々に思いがけないところではまった
* 作業ログとか残しておけば良かったけれど、「思いがけない」ので残していなかった
* セキュリティ的に万全ではなくなるけれど、仮想環境が使えないままでは生きられないので仕方ない…
* 自分で設定変更した内容を思い出せたので良かった
* 同じ所ではまった情報が見当たらなかったのでもしかするとはまったのは自分だけかも…
    * 検索能力が低いだけかも

# おまけ
メモリ整合性をオフにしようとしても管理者権限云々で出来ない可能性がある。
https://answers.microsoft.com/ja-jp/protect/forum/protect_defender-protect_start-windows_10/windows10-1803/9016fcfc-abeb-4ffe-a9f1-37abdfd77a9c
を参考にレジストリを編集して再起動したらオフに出来た。

# 参考にしたもの
* VirtualChecker3(https://openlibsys.org/index-ja.html)
    * VT-xの状態を手早く確認するツール。都度VirtualBoxを起動するのが時間がかかって仕方なかったので
pythonでPDCAサイクルを回す

皆さんはPDCAを回していますか？僕は回しています。

![pdca_slow.mov.gif](https://qiita-image-store.s3.amazonaws.com/0/256666/9f5d31dd-a28d-9374-b18a-81d1d16010af.gif)

## ソースコード
https://github.com/zena-dual/pdca-cycle/blob/master/pdca_cycle.py
Pythonの練習で書きました。

## 環境
Python3で書きました。2.7.10でも動きました。
`python3 pdca_cycle.py`で気が済むまでお回しください。

## なんとなく解説

```python:pdca_cycle.py
# coding: utf-8

import os
import time

def main():
    """
    PDCAを回す
    """

    # PDCAの辺の長さ（平日は5日なので5固定）
    SIDE_LENGTH = 5
    base = make_pdca_base(SIDE_LENGTH)

    # PDCAを回す時にはバッファを持たせよう
    buf = [' '] * (SIDE_LENGTH-2)
    pdca = ['P'] + buf + ['D'] + buf + ['C'] + buf + ['A'] + buf

    # PDCAを回し続ける
    while True:
        # 前回のPDCAをクリア
        os.system('clear')

        # PDCAを回す
        for i in range(SIDE_LENGTH):
            print(base[i].format(pdca, ' '))

        # 次のPDCAの準備をしつつ休憩を取る
        pdca = pdca[1:] + [pdca[0]]
        time.sleep(0.1)


def make_pdca_base(side_length):
    """
    PDCAを回すための土台作り
    """

    bases = []
    for i in range(side_length):
        if i == 0:
            l = [str(x) for x in range(side_length)]
            base = '{0[' + ']}{0['.join(l) + ']}'
        elif i == side_length - 1:
            l = [str((side_length-1)*3 - x) for x in range(side_length)]
            base = '{0[' + ']}{0['.join(l) + ']}'
        else:
            base = '{0[' + str((side_length-1)*4-i) + ']}' \
                   + '{1}' * (side_length-2) \
                   + '{0[' + str((side_length-1)+i) + ']}'

        bases.append(base)

    return bases


if __name__ == '__main__':
    main()

```

１. 配列`pdca`にPDCAとそれっぽく表示するための空白を入れる。

```pdca_cycle.py:配列pdcaの中身
['P', ' ', ' ', ' ', 'D', ' ', ' ', ' ', 'C', ' ', ' ', ' ', 'A', ' ', ' ', ' ']
```

２. 関数`make_pdca_base`で、format関数で置換するための文字列を作っておく。

```pdca_cycle.py:配列baseの中身
['{0[0]}{0[1]}{0[2]}{0[3]}{0[4]}',
 '{0[15]}{1}{1}{1}{0[5]}',
 '{0[14]}{1}{1}{1}{0[6]}',
 '{0[13]}{1}{1}{1}{0[7]}',
 '{0[12]}{0[11]}{0[10]}{0[9]}{0[8]}']
```

３. `format`関数で配列`base`の`{0[n]}`をpdcaの内容に、`{1}`を空白に置換して出力。
　 上記の`pdca`と`base`を用いて置換すると↓になる。

```pdca_cycle.py:置換後の配列
['P   D',
 '     ',
 '     ',
 '     ',
 'A   C']
```

４. 配列`pdca`の内容を、先頭の要素が末尾にくるようにずらす。

```pdca_cycle.py:配列pdcaの中身（先頭のPが末尾に移動した）
[' ', ' ', ' ', 'D', ' ', ' ', ' ', 'C', ' ', ' ', ' ', 'A', ' ', ' ', ' ', 'P']
```

５. 前回の出力をクリア。
６. ３.と同様に`format`関数で置換して出力。ずれた分だけPDCAが反時計回りに進む。

```pdca_cycle.py:置換後の配列
['   D ',
 'P    ',
 '     ',
 '    C',
 ' A   ']
```

７. 繰り返し。


無限ループになっていますが、CPUもメモリも食わない省エネサイクルになっているはずです。
是非視界の片隅でPDCAしてください。めっちゃターミナル出力することにはお気をつけて。


## おまけ
コードゴルフっぽく書いてみた版。意味は特にありません。
本職のコードゴルファーの方々ならもっと短くなるんでしょうか。
https://github.com/zena-dual/pdca-cycle/blob/master/illegible_pdca_cycle.py

```python:illegible_pdca_cycle.py
import os,time;s=5;t=s-1;v=s-2;u=[];b=str;r=range(s);c=' '*v;p=c.join('PDCA')+c;m='{0[';n=']}';o=n+m;q=o.join;[u.append(m+(q(b(x)for x in r) if i==0 else q(b(t*3-x)for x in r) if i==t else b(t*4-i)+n+'{1}'*v+m+b(t+i))+n)for i in r]
while 1:os.system('clear');[print(u[i].format(p,' '))for i in r];p=p[1:]+p[0];time.sleep(.1)
```
VMwareでNICがeth1になったのでeth0に修正する。

# 1 悲しみ

Webアプリケーションの本を購入し、付属していたVMwareとUbuntuを起動すると、eth0がなくて、eth1がある。
eth1は127.0.0.1。eth0を使えるようにして、IPアドレスを割り振りたい。

# 2 原因

VMwareが、新たにMACアドレスを生成している。

# 3 やること

1. udev のネットワークのルール設定ファイルを編集する
1. ネットワークの設定ファイルを確認する。
1. システムを再起動する。 

### 3-1 udev のネットワークのルール設定ファイルを編集する

古いMACアドレス（NAME="eth0"）の記述を削除（コメントアウト）し、
新しくVMwareが作成したMACアドレス（NAME="eth1"）のNAMEをeth0に変更する。

```
vi /etc/udev/rules.d/70-persistent-net.rules
```

### 3-2 ネットワークの設定ファイルを確認する。

"primary network interface"として、eth0が存在することを確認する。

```
less /etc/network/interfaces
```

### 3-3 システムを再起動する。

```
shutdown -r now
```

# 4 喜び

学習を進めることができる。

# 5 参考

[レンタルサーバー・自宅サーバー設定・構築のヒント](https://server-setting.info/centos/centos-vmware-clone-eth0-fail.html#vmware_centos_scientifixc_linux_cloneeth0_3)