OmniAICreator/Qiita-1.07M huggingface dataset:
IntelliJ の Terraform プラグインでカスタムプロバイダの定義を補完できるようにする

IntelliJ の Terraform / HCL プラグインではリソース名や属性の補完ができて便利なのですが、カスタムプロバイダは補完が効かず不便です。

どうやら[スキーマ定義の JSON ファイルを然るべき場所に置けば認識されるらしい](https://github.com/VladRassokhin/intellij-hcl/issues/75)のですが、肝心の JSON ファイルの作り方のドキュメントがありません。

プラグインのソースを眺めていたら、無理やり JSON ファイルを生成できたのでまとめておきます。

以下、terraform-provider-sakuracloud プロバイダのスキーマ定義を生成する例です。

 1. Go をインストールして $GOPATH を設定する
 2. terraform-provider-sakuracloud のソースをダウンロードする

    ```
    $ go get github.com/sacloud/terraform-provider-sakuracloud
    ```

 3. intellij-hcl のソースをダウンロードして schemas-extractor ディレクトリに移動

    ```
    $ git clone https://github.com/VladRassokhin/intellij-hcl.git
    $ cd intellij-hcl/schemas-extractor
    ```

 4. terraform-provider-sakuracloud を対象にするようコードを書き換える

    ```
    $ sed -i -e 's/terraform-providers/sacloud/g' build-all.sh template/generate-schema.go
    $ echo terraform-provider-sakuracloud > providers.list.full
    ```

 5. スキーマ定義ファイルを生成する

    ```
    $ make
    Updating terraform-provider-sakuracloud
    
    ========================================
    Waiting for update processes to finish
    All providers updated
    
    Preparing terraform-provider-sakuracloud
    fatal: No annotated tags can describe '36fd67475a6f3b9e53da8e9d45f579a37b1720d5'.
    However, there were unannotated tags: try --tags.
    Generating schema for terraform-provider-sakuracloud
    Finished terraform-provider-sakuracloud
    ========================================
    Everything done!
    ```

 6. できたスキーマ定義ファイルをインストール

    ```
    $ mkdir -p ~/.terraform.d/schemas
    $ cp schemas/sakuracloud.json ~/.terraform.d/schemas
    ```

 7. IntelliJ を再起動

参考: [Document support for custom providers #128](https://github.com/VladRassokhin/intellij-hcl/issues/128)
AWS CLI を使って RDS を作成する (自分用メモ)

AWS CLI を使って外部からアクセス出来る RDS インスタンスを作る方法が公式ドキュメントに無かったのでメモ。
`aws rds` コマンドを使って rds を作成するには、DB subnet group を指定する必要があるらしい。さもなければ以下のようなエラーが出る。

    An error occurred (InsufficientDBInstanceCapacity) when calling the CreateDBInstance operation: Cannot create a db.t2.micro database instance because there are no availability zones with sufficient capacity for non-VPC and storage type

新しい DB subnet group を作るには [チュートリアル: Amazon RDS DB インスタンスで使用する Amazon VPC の作成](https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/CHAP_Tutorials.WebServerDB.CreateVPC.html) の手順が近い。ここでは Single Public Subnet を作る(us-west-2 の例)。

## VPC と DB Subnet Group の作成

* VPC 作成
  * https://console.aws.amazon.com/vpc/
  * Launch VPC Wizard
  * VPC with a Single Public Subnet
  * VPC name: hogehoge-db-vpc
  * Availability Zone: us-west-2a
  * Subnet name: hogehoge-db-subnet
* Subnet 作成
  * https://console.aws.amazon.com/vpc/
  * Subnets
  * Create subnet
    * Name tag: hogehoge-db-subnet2
    * VPC: hogehoge-db-vpc
    * Availability zone: us-west-2b (VPC 作成で作った subnet と違う zone)
    * IPv4 CIDR: 10.0.1.0/24
  * hogehoge-db-subnet > Route Table > Route Table をメモ (例 rtb-0f80a908802976794)
  * hogehoge-db-subnet2 > Route Table > Edit route table association > メモした Route Table を選択
* セキュリティグループ作成
  * https://console.aws.amazon.com/vpc/
  * Security Groups
  * Create Security Groups
    * Security group name: hogehoge-db-security-group
    * VPC: hogehoge-db-vpc
  * hogehoge-db-security-group > Inbound Rules > Edit Rules > Add Rule
    * Port: 3306
    * Source: My IP
  * あとはデフォルト
  * Security Group 名をメモ: 例 sg-0ffa93ab8dc49aea1
* DB サブネットグループ作成
  * https://console.aws.amazon.com/rds/
  * Subnet groups
  * Create DB subnet groups
    * Name: hogehoge-db-subnet-group
    * VPC: hogehoge-db-vpc
    * Add subnets > Add all the subnets related to this VPC

## RDS 作成

```
export AWS_PROFILE=hogehoge_profile
export AWS_REGION=us-west-2

aws rds create-db-instance \
    --db-instance-identifier hogehoge-db-instance \
    --db-instance-class db.t2.micro \
    --engine MySQL \
    --engine-version 8.0.11 \
    --allocated-storage 20 \
    --master-username root \
    --master-user-password password \
    --backup-retention-period 3 \
    --vpc-security-group-ids sg-0ffa93ab8dc49aea1 \
    --publicly-accessible \
    --db-subnet-group-name hogehoge-db-subnet-group
```

進捗表示

    aws rds describe-db-instances | jq '.DBInstances[] | {"name": .DBInstanceIdentifier, "status":.DBInstanceStatus}'

Endpoint 表示

    aws rds describe-db-instances | jq '.DBInstances[].Endpoint'

ログイン

    mysql -uroot -ppassword -hhogehoge-db-instance.higehoge.us-west-2.rds.amazonaws.com

## RDS 削除

削除

    aws rds delete-db-instance --db-instance-identifier hogehoge-db-instance --skip-final-snapshot

DB サブネットグループと VPC も削除

## Terraform で同じ事をやる

(TBD)
【Rails】 flash時にメッセージにリンクを埋め込む

flashで通知させるときにどうすれば文字列にリンクを貼るのか悩んだので書きます。

#html_safeを使う

html_safeを使えば解決します。

```ruby:
if @user.save
  link = "<a href=#{edit_user_path(:id)}>こちら</a>"
  flash[:success] = "ユーザー登録に成功しました。変更は#{link}でできます。".html_safe
  redirect_to user_path
end
```

「こちら」がURLになってますね。
html_safeを末尾に記入すれば解決！
アーカイブ化したmp3をデコードしよう【Unity】

#UnityでMP3をちょっとトリッキーに扱いたい
Unityくんは優秀なので、wwwで外部のサウンドファイルを指定すれば勝手にデコードしてオーディオクリップにしてくれます。

https://docs.unity3d.com/ja/2018.2/ScriptReference/WWW.GetAudioClip.html

しかし……
<b>「スタンドアロン(パソコン)でもMP3使いたいな～」</b>とか
<b>「アーカイブ化したファイルから読み込ませたいんだよね」</b>とか
Unityくんは、そんな隙間ニーズには対応してくれていないのです。
(MP3はこないだまで有料規格だったしね……色々あるんだろうね)

という訳で、自力でどうにかしましょう。

#Windows用アプリケーションを作る場合
<b>NAudio</b>という偉大なモノがあるので楽勝ですね。
先達たちに感謝。

https://github.com/naudio/NAudio
https://so-zou.jp/software/tech/programming/c-sharp/media/audio/naudio/

#Windows用アプリケーションではない場合
NAudio!　おまえはクロスプラットフォームではないのだね……。
https://github.com/naudio/NAudio/issues/184
https://stackoverflow.com/questions/6186559/will-naudio-support-mac-osx

ということで、私はC#で書かれたプラットフォームに依存しないMP3デコーダーの情報を探してネットの海を彷徨うことになりました。
※しかし、全然情報なくてビックリだね。同じニーズは割とあると思うんだけど、検索しても日本語の情報はゼロ、英語でも検索からは全然情報が見つからず。わざわざ同じ苦労する人がいないように記事書いてます。

そして、最終的に辿り着いたのがコイツ。
https://github.com/naudio/NLayer

コイツをNAudioと一緒に使いましょう。まぁ、NAudioの説明をよく読んでれば探し回る必要もなかったんだけど……。
https://github.com/naudio/NAudio/blob/master/Docs/ConvertMp3ToWav.md
<b>NLayer is a fully managed MP3 decoder, meaning it can run on any version of Windows (or indeed any .NET platform). </b>
……ちゃんと書いてたね。NLayerを使えば『.NETが使える環境なら何でもいける(or indeed any .NET platform)』って。見落としてました。.NET(Mono)はクロスプラットフォームなので、この組み合わせで動きます。

　<b>情報捜索で潰れた私の土曜日は何だったんや……。</b>

#具体的な手順
１　NAudioとNLayerの関数を使えるようにしよう
　NAudioとNLayerをGitHubから[Clone or download]→[Download ZIP]でダウンロード。ZIPを解凍したら中身をそのままプロジェクトのAssetフォルダ内のどこかにどーん。（もちろん常識的な人はAssetフォルダ内にScriptフォルダを作ってるだろうから、整理整頓のためにもその中に入れよう）。これでNAudioやNLayerの名前空間を呼び出せばいつでも使えるようになった！
※この手のC#ソースを複数使ってるとソースごとのAssemblyInfo.csとかの記述が二重に被ってエラー出たりするので、消しておきましょう。(AssemblyInfoについて調べると分かると思いますが、基本的に動作には直接影響しないので消して大丈夫です)

２　関数を使ってデコードしよう！

<b>mp3形式のStreamをwav形式のbyte配列に変換する関数</b>

    private byte[] Mp3ToWav(Stream st)
    {
        using (MemoryStream ms = new MemoryStream())
        {
            using (var reader = new NAudio.Wave.Mp3FileReader(st, wf => new NLayer.NAudioSupport.Mp3FrameDecompressor(wf)))
            {
                if (reader.WaveFormat.Encoding == NAudio.Wave.WaveFormatEncoding.IeeeFloat)
                {
                    NAudio.Wave.WaveFloatTo16Provider w32to16 = new NAudio.Wave.WaveFloatTo16Provider(reader);
                    byte[] tmp=new byte[10000];
                    w32to16.Read(tmp,0,10000);
                    NAudio.Wave.WaveFileWriter.WriteWavFileToStream(ms, w32to16);
                }
                if (reader.WaveFormat.Encoding == NAudio.Wave.WaveFormatEncoding.Pcm)
                {
                    NAudio.Wave.WaveFileWriter.WriteWavFileToStream(ms, reader);
                }
            }
            return ms.ToArray();
        }
    }

……せや、wavのbyte配列をAudioClipにする方法説明してなかった。
https://github.com/deadlyfingers/UnityWav
コイツを使いましょう。例の如く（手順１を参照）AssetフォルダにＤＬしたファイルをぶち込めばＯＫ。
で、上の関数とUnityWavを組み合わせて

<b>mp3ファイルのStreamをAudioClipに変換する関数</b>

      public AudioClip Mp3ToAudioClip(Stream st)
      {
      return WavUtility.ToAudioClip (Mp3ToWav(stream));
      }

できあがり。
# I want to prevent KeyError using python's defaultdict

<h1> import </h1>

<pre> <code>&gt;&gt;&gt; from collections import defaultdict 
</code> </pre>

<h1> int </h1>

<p> Create a dictionary with default value 0 for any key </p>

<pre> <code class="py">&gt;&gt;&gt; a = defaultdict(int) 
 &gt;&gt;&gt; a 
 defaultdict(&lt;class &#39;int&#39;&gt;, {}) 
 &gt;&gt;&gt; a[&quot;1&quot;] 
 0 
 &gt;&gt;&gt; a[1] 
 0 
 &gt;&gt;&gt; a[&quot;a&quot;] 
 0 
 &gt;&gt;&gt; a[&quot;b&quot;] 
 0 
 &gt;&gt;&gt; a[&quot;c&quot;] 
 0 
 &gt;&gt;&gt; a[0] 
 0 
 &gt;&gt;&gt; a[1] 
 0 
 &gt;&gt;&gt; a[2] 
 0 
 &gt;&gt;&gt; a[1] 
 0 
</code> </pre>

<h1> str </h1>

<p> Default for any key creates a dictionary of empty strings </p>

<pre> <code class="py">&gt;&gt;&gt; a = defaultdict(str) 
 &gt;&gt;&gt; a[0] 
 &#39;&#39; 
 &gt;&gt;&gt; a[1] 
 &#39;&#39; 
 &gt;&gt;&gt; a[&#39;some&#39;] 
 &#39;&#39; 
 &gt;&gt;&gt; a[&#39;what&#39;] 
 &#39;&#39; 
</code> </pre>

<h1> dict </h1>

<p> Dictionary whose default value is Dictionary </p>

<pre> <code class="py">&gt;&gt;&gt; a = defaultdict(dict) 
 &gt;&gt;&gt; a[0] 
 {} 
 &gt;&gt;&gt; a[&#39;some&#39;] 
 {} 
</code> </pre>

<h1> nested </h1>

<p> Defaultdict whose default value is defaultdict </p>

<pre> <code class="py">&gt;&gt;&gt; a = defaultdict(lambda: defaultdict(int)) 
 &gt;&gt;&gt; a[0] 
 defaultdict(&lt;class &#39;int&#39;&gt;, {}) 
 &gt;&gt;&gt; a[0][0] 
 0 
 &gt;&gt;&gt; a[&quot;a&quot;][&quot;b&quot;] 
 0 
</code> </pre>


# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/1292








<!-- Update From Qiita API -->

# チャットメンバー募集


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

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





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
Example of merging a dictionary with default values into an existing dictionary with values in #python (I don't want to write if 'key' in dict anymore ..)

# another answers here comments

[#python で値を持った既存の辞書に、デフォルト値つきの辞書をマージする例 ( もう if 'key' in dict なんて書きたくないんですよ‥ ) - Qiita](https://qiita.com/YumaInaura/items/52e110976b069106f0c2)

---


<p> Using collections defaultdict and ChainMap together </p>

<h1> wanna do </h1>

<ul>
<li> This dictionary <code>d = {&quot;a&quot;:1, &quot;b&quot;,2}</code> </li>
<li> When calling this way <code>d[&quot;c&quot;]</code> </li>
<li> I want the default value to be entered instead of KeyError </li>
</ul>

<h1> example </h1>

<pre> <code class="py">from collections import defaultdict 
 import collections 
 
 existing_dict = {&quot;a&quot;:1, &quot;b&quot;:2} 
 
 default_dict = defaultdict(int) 
 
 merged_dict = collections.ChainMap(existing_dict, default_dict) 
</code> </pre>

<h1> EXE </h1>

<pre> <code class="py">Python 3.7.2 (default, Jan 13 2019, 12:50:01) 
 [Clang 10.0.0 (clang-1000.11.45.5)] on darwin 
 Type &quot;help&quot;, &quot;copyright&quot;, &quot;credits&quot; or &quot;license&quot; for more information. 
 &gt;&gt;&gt; from collections import defaultdict 
 &gt;&gt;&gt; import collections 
 &gt;&gt;&gt; existing_dict = {&quot;a&quot;:1, &quot;b&quot;:2} 
 &gt;&gt;&gt; default_dict = defaultdict(int) 
 &gt;&gt;&gt; merged_dict = collections.ChainMap(existing_dict, default_dict) 
 &gt;&gt;&gt; merged_dict[&quot;a&quot;] 
 1 
 &gt;&gt;&gt; merged_dict[&quot;b&quot;] 
 2 
 &gt;&gt;&gt; merged_dict[&quot;c&quot;] 
 0 
 &gt;&gt;&gt; merged_dict[&quot;d&quot;] 
 0 
</code> </pre>

<h1> ps </h1>

<ul>
<li> Maybe we aren&#39;t doing something really careless </li>
<li> Please write from the white goat if something is wrong </li>
</ul>


# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/1291








<!-- Update From Qiita API -->

# チャットメンバー募集


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

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





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
NVIDIAさんのSPADEを使ってみた。

実際に学習済みモデルを使って生成した画像
**セマンティックマップを画像に変換することができる**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315063/d09654fc-b9db-f24c-cea2-54f5c6982ccc.png)


#生成画像
**セマンティックマップ→画像**



①
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315063/6a3802e9-eea8-37e5-1823-37d09f8b5aaf.png)

②
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315063/e1dba3a4-704d-08f7-c452-39e03087a04d.png)

③
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315063/f78cd4ca-dae3-b7d5-74c5-d8b22ee01c33.png)

④
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315063/fed5026e-a4de-19bc-3983-c9b5d2eee7d9.png)

⑤
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315063/10ddeb08-ed98-7a91-ce77-9df2dffc91db.png)

⑥
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315063/7779483a-b6f1-a185-9b39-aa041a77783d.png)

⑦
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315063/06273eb6-26bd-f4c7-0d0a-aa439636dc50.png)

#コード
>https://github.com/NVlabs/SPADE
Azure DevOpsで承認後本番リリースするには

# 前提
私が勤務している会社ではお客様社内で利用するWebアプリを受注開発を行っています。
このときのAzure契約はお客様が行い、アカウントを作成してもらい開発者が利用します。
DevOpsを使ってテストおよびリリースを自動化する第１段のプロジェクトで、すべてが手作ぐり状態。

# 目的
Azure DevOpsにてMasterブランチにPushを検知し、ビルド＆テストそして、検証サーバにデプロイを行う。
検証サーバで検証できた後に、お客様のリリース担当者が意思入れのもと本番サーバにデプロイを行う。

# プロジェクト作成
今回は.NetCoreをWeb Apps for Containerで運用します。
まずはAzure DevOpsプロジェクトの作成ですね。
追加をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136187/f5864382-444c-7eb3-2b77-11298ce36fbd.png)
.Netを選択（お好きなアプリケーションを選んでください）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136187/218ce1df-964b-1ca1-d302-fa50685295ac.png)
ASPNET Coreを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136187/76a7b305-5771-f188-ba55-e8b8aae1d8ea.png)
Web App for Containerを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136187/d628edaf-1453-e692-4a35-5bc57abb2d87.png)
その後、プロジェクト名やらはお好みを入れてください。
これで初期のプロジェクトが出来上がりますので、早速Azure ReposからソースをCloneします。

# パイプラインの変更
プロジェクト作成当初のパイプライン(Release)はこんな感じになっています。
Stagesにdevが一つあります。今回はdevの他に本番リリースを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136187/433c4bcb-4aaf-9090-6b4b-393b8a327a5e.png)

## Web Apps for Containerの作成
まずは本番リリース用のWeb Apps for Containerを新たに作成します(ここではApprovalTestReleaseとする）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136187/b790cb51-22c1-a1e0-4fe9-dfcb771c3499.png)

## Releaseパイプラインに本番リリースを追加
ReleaseパイプラインのEditを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136187/3a8f274b-9ffd-0761-7ce5-48446ada4660.png)
devStageの後に本番リリースStageを追加します。
やることはdevStageと同じでデプロイ先を変更するだけなのでdevStageをCloneしましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136187/92e0fc29-626e-6745-1f55-2559573113ab.png)
Cloneすると"Copy of dev"が追加されます。
ここで、Copy of Devを編集していきましょう。

## デプロイ先を変更
ステージ名を"本番リリース"に変更後
Deploy Azure App Serviceにある"App Service Name"を先程作ったApprovalTestReleaseに変更します。

## 承認を追加
パイプライン(Release)のPre-deployment approvalsをEnabledにし
Approvaersに承認する人を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136187/0870e88d-8abd-8a8b-df14-19ca8fb2da05.png)

## 確認
Cloneしたソースを変更しMasterブランチにPushします。
Buildパイプラインが走り、続いていReleaseパイプラインが走ります。

先程作成した本番リリースのパイプラインが追加されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136187/cf34875c-99d5-ca38-f10c-77575a991e84.png)
あと、本番リリースを選択し"Approve"で本番サーバにリリースが行われます。
検証し、不具合がある場合は再度MasterブランチのPushを行いましょう。

このApproveボタンがあることにより不用意にMasterブランチをPushしても本番サーバに適用されませんし、リリース担当者が
検証を行うので（今回はお客さん）、安心して開発を進められますね。

なかなかDevOpsの日本語の資料が少なく、承認を入れるだけで苦労しましたが、分かってしまえば簡単ですね。
翻訳記事: IBM Watson OpenScaleを使用したAIモデルの振る舞いの説明(Explain)

![image](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108535/d941e436-2da0-024e-3fce-67d07ae400f2.png)

# はじめに
2019/4/12に公開されたMediumの記事 :newspaper: 「**[Explaining AI Model Behaviour with IBM Watson OpenScale](https://medium.com/trusted-ai/explaining-ai-model-behaviour-with-ibm-watson-openscale-86515702c177)**」の翻訳です。
最近話題の「説明可能なAI(XAI)」の実装例としてWOSの提供している機能をシンプルに説明していますので、自分なりに翻訳しました。(翻訳作業については著者了承済み)

---

#  IBM Watson OpenScaleを使用したAIモデルの振る舞いの説明(Explain)

April 12, 2019 by Manish Bhide 

与えられた画像がオオカミかシベリアン・ハスキーかを判定するモデルをデータサイエンティストが作ったとしましょう。下のイメージで見るに、モデルは明らかに素晴らしい結果をもたらしているように見えます。

![image](https://cdn-images-1.medium.com/max/873/1*WuEbe8IJuxYR8x3tzGq_YA.png)[^1]

[^1]: ImageSource:Internet

上のイメージでは、モデルが誤ったのは左下の画像に対してのみです。そこでデータサイエンティストはそのモデルが優れていると考え、本番環境に反映しようと考えました。しかしモデルの訓練データのすべてのオオカミ画像の背景には雪があり、すべてのハスキー画像の背景には雪がなかったかもしれません。その場合、モデルは**背景に雪があるならば、オオカミである**ことを学習したのでしょう。雪が無ければハスキーです！ →これではどうみても素晴らしいモデルとは言えませんね。。。

IBM Watson OpenScaleは、AIモデルに関するこのような問題があるかどうかの識別に役立ちます。この例では、予測に寄与した画像の部分を強調表示します。そのため、左下の画像では、雪が強調表示され、画像がオオカミだと予測するモデルにおいて雪が存在することが大きな役割を果たしていたことを示します。

AIの採用における最大の障害の1つは、透明性の欠如、またはAIモデルのブラックボックス的な性質です（上記の例で明らかですね）。そのため、ビジネス・オーナーはAIモデルを本番に展開することに懐疑的です。 IBM Watson OpenScaleは、2種類の説明を提供することによって、この問題に対処します。

- **LIMEベース**の説明：LIMEアルゴリズムを使用して、予測に肯定的または否定的に寄与した特徴量(フィーチャー)のリストを見つけます（詳細は後述）。
- **対照的な(Contrastive)**説明：これはIBM リサーチの独自テクノロジーで、説明が必要なデータポイントの近傍でのモデルの振る舞いを説明します。


これらの概念を、もっと理解するために、保険業界での例を考えてみましょう。保険金請求を承認するか拒否するかを決定するモデルを考えてみます。モデルによって却下された保険金請求の説明を生成するようにIBM Watson OpenScaleにリクエストすると、以下のような説明が得られます。

![image](https://cdn-images-1.medium.com/max/873/1*F17Py2sSS8PKzKpSv9FTTw.png)[^2]: 

[^2]: WatsonOpenScaleによって生成された説明

まずLIMEベースの説明を示す画面の下半分に注目しましょう。この場合には保険契約の年齢が1年未満で保険金請求の頻度が多く、年齢が18歳であるために請求が却下された、という説明がなされています。これらは、保険金請求を却下すべきだと判断する場合のトップ３の要因です。ただし顧客のタイプが「個人」であるという事実は、請求が承認されるべきと判断する方向に貢献しています。 - したがって、予測に対する信頼度は100％ではありませんでした。このようにLIMEベースの説明では、予測にプラス方向にもマイナス方向にも寄与する一連の特徴量(フィーチャー)を示します。

次に、画面の上部の対照的な説明(Constractive Explanations)に注目しましょう。一つ目の部分は要求が承認されるための最低限の変更点(Minimum changes for approved outcome)を示しています。これは、モデルの予測が「拒否」から「承認」に変わるための、特徴量の最小の変化です。言い換えれば、「保険への加入から2〜3年」で、「請求頻度」が「低(Low)」なら、モデルの予測は「承認」になるはずだということを示しています。対照的な説明(Constractive Explanations)の残りの部分は、それが予測結果に何の変化ももたらさないであろう特徴量の最大の変更点(Minimum Factors supporting this outcome)を示します。この例では、「保険への加入から1〜2年」で、「請求の頻度」が「中(Medium)」なら、モデルの予測は相変わらず「拒否」のままであることがわかります。このように対照的な説明(Constractive Explanations)では説明を生成しているデータポイントの近傍・付近で判断に重要な役割を果たす特徴量(フィーチャー)を示してくれるので、ビジネスユーザーがモデルの判定を信用できるようになります。

要約すると、IBM Watson OpenScaleは、ビジネスユーザーがAIに対する信頼を築き、ブラックボックスAIモデルのボックス化を解き放つ(unbox)のに役立つLIMEベースおよび対照的な説明(Constractive Explanations)を提供します。

---
記事はここまで↑

# ご参考

記事翻訳のみならず、過去、自分でもWatson OpenScaleをご紹介した記事をQiitaに書いておりますので、ご興味あればご高覧ください。

:newspaper: [「AIへの信頼」や「説明可能なAI」に絡み、一部で話題の「IBM Watson OpenScale」をザクッとご紹介します](https://qiita.com/ishida330/items/ced6e5233ca61ae0af9d)
:newspaper: [Watson OpenScaleをもう少し「キチッ」とご紹介します(A.K.A.「麗しき誤解」を解く）](https://qiita.com/ishida330/items/db3cbb3763ac3067140f)
:newspaper: [Watson OpenScaleを触る前に知っておきたかったこと（技術Tipsなど)](https://qiita.com/ishida330/items/2c9b049966a988850b06)

以上です。
スマホで Repl.it

Repl.it
https://repl.it/

実は Repl.it はスマホのブラウザからでも使えます。
ただし、画面に収まりきれないほど部品が配置されます。

## 解決
設定メニューから `Stacked` を選択
すると、スマホの画面でも収まるようにレイアウトされるようになります。

これで電車の中でもちょっとお試しができますね！ 言語の勉強がはかどる。
java kotlin IntとIntの除算(割り算)にご注意

なんでこんな簡単なことにハマったのでしょう？
私と同じようにハマって時間を無駄にする方がいないように備忘録

下記は当然の如く0.25と出ると思っていましたが...

```
        var rate: Double = 0.0
        rate = 1 / 4
        Log.v("TEST:", "rate:${rate}")
```

下記のようなコンパイルエラーがでる。

```
Type mismatch: inferred type is Int but Double was expected
```


google翻訳様：「型が一致しません：推定型はIntですがDoubleが必要です」


そんなことわかっておるワイ！！！

ん？　あっ　Σ(ﾟдﾟ;)　,,,,　そういう事か。
IntとIntの計算なので計算結果の型の判定がIntになっていたんですね...
俺よ、なぜ気づかなかった。。。

ということで解決策。どっちか、もしくは両方をDoubleに合わせてやればよい。

```
        val num1 = 1.toDouble()
        val num2 = 4.toDouble()

        val aaa = num1 / num2

        Log.v("TEST:", "rate = ${aaa}")
```

```
V/TEST:: rate = 0.25
```

はい。想定どおりの結果が返ってきました。
自分の頭の悪さに涙が止まらんです。


補足
---

ちなみに...

```
        val aaa = (1/4).toDouble()
        Log.v("TEST:", "rate = ${aaa}")
```

```
V/TEST:: rate = 0.0
```

こうすると 計算結果がIntで来てそれをDoubleに変換しているみたいになるから
想定する結果が返ってきません。
`10 / 4` とかだと `2.0` になるから注意。



では、よい　kotlin　生活を！
attr prop removeAttrのこと

jqの

attr は属性の値を取得。
prop は属性の値を取得。

removeAttrは属性を削除する。

細かくいうと、
attrは属性の値を取得。変更もできる。
propは、プロパティの真偽を返す。true/false   （有効か無効か）
propは有効無効の切り替えができるもので、attrはその値を取るものだと思います。

なので、htmlのdisabled属性などは、attrで書き換えではなくpropで切り替えをした方がいいのではないかと思います。

覚書なので、他人がみたらわけわかめだと思いますね。。。
【Kaggle日記】 Kaggle Reference 一覧

# Kaggle Reference 一覧

私的にとても有用であると感じたレファレンスを羅列します。
随時更新します。

## Youtube

### 日本語

[pocketさん『猫でも取れる金メダル & 猫しか取れない金メダル』](https://www.youtube.com/watch?v=6DW5PCIo5qc&t=3s)
[flowlightさん『TalkingData AdTracking Fraud Detection Challenge』](https://www.youtube.com/watch?v=RKXUEJVJJ-o)
[osciiartさん『2018 Data Science Bowl』](https://www.youtube.com/watch?v=2FFDtSmAYPo)

### 英語

[raddarさんのKaggle Days Paris - "My journey to becoming a Kaggle Grandmaster"](https://www.youtube.com/watch?v=7XEMPU17-Wo)
[cpmpさんの"Beyond feature engineering and HPO"](https://www.youtube.com/watch?v=fH_FiquKhiI&t=1s)
[kazanovaさんの"An introduction to model stacking"](https://www.youtube.com/watch?v=9Vk1rXLhG48)

## Winner Solutions

[【神まとめ】sudalairajkumarさんによるKaggle Kernel上でのリスト](https://www.kaggle.com/sudalairajkumar/winning-solutions-of-kaggle-competitions)
[ShuaiWさんによるGithub上でのリスト](https://github.com/ShuaiW/kaggle-classification)
[EliotAndresさんによる検索可能のウェブサイト(2018-08-31までのみ)](https://ndres.me/kaggle-past-solutions/)
M5Stackで使おう オムロン 絶対圧センサ評価モジュール 2SMPB-02E　（２）

今回はちょっとコードをいじってみましょう。
https://qiita.com/usashirou/items/c09e1e41567dda6196c6


なぜか？
サンプルファイルはPaで表記されています
ふつうは、ｈPaなんですよ。
ということで1/100にします。
pressure⇒pressure/100
Pa⇒hPa
にし、Serial.print～～～を追加します。

![2smpb02e-M5stack-7-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/99e1437d-71fa-6a94-901c-6c7d5475ebb5.jpeg)

そして、シリアルモニターでデータが見えるようにしてみましょう。
![2smpb02e-M5stack-7-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/d8a83f9c-cb18-06c3-364d-b647fbb23b20.jpeg)

![2smpb02e-M5stack-7-3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/c39b39ec-7d47-298a-f24c-12f11140b36f.jpeg)

```
#include <driver/dac.h>
#include <M5Stack.h>
#include "Omron2SMPB02E.h"

Omron2SMPB02E prs;
// Omron2SMPB02E prs(0); // in case of SDO=0 configuration

void setup()
{
  M5.begin();
  dac_output_disable(DAC_CHANNEL_1);
  prs.begin();
  Serial.begin(9600);
  prs.set_mode(MODE_NORMAL);
  delay(300);
}

void loop()
{
  delay(2000);
  float temp = prs.read_temp();
  float pressure = prs.read_pressure();
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setCursor(0, 0);
  M5.Lcd.setTextSize(2);
  M5.Lcd.printf("Temperature:\r\n%f[degC]\r\n\r\n", temp);
  M5.Lcd.printf("Pressure:\r\n%f[hPa]\r\n", pressure/100);
  Serial.printf("Pressure:\r\n%f[hPa]\r\n", pressure/100);
  Serial.printf("Temperature:\r\n%f[degC]\r\n\r\n", temp);
}
```
Apollo+Expressで始めるGraphQL超入門 ~ データ取得Lv2

# あらすじ

[1.Apollo+Expressで始めるGraphQL超入門 ~ GraphQLをざっくり理解する](https://qiita.com/zonomaa/items/5de4b14dcd839db5f148)
[2.Apollo+Expressで始めるGraphQL超入門 ~ データ取得Lv1](https://qiita.com/zonomaa/items/69bedaae8208d8abc437)

# GraphQLの設計について

GraphQLの作者の言葉をお借りすると「GraphQLはできるだけ薄く保つ」ということなので、ネストは深くしないのが望ましい。

# なぜか

実際に私が陥った例を挙げると、簡易ECサイトをGraphQLで実装しようとしたとき
`User`が`Item`を買ったときの履歴`PurchaseHistory`をGraphQLで取得できるAPIを作ろうと思った

```typescript
type User {
  id: ID!
  name: String!
  purchase_history: [Item]
}
type Item {
  id: ID!
  name: String!
  catch_copy: String
}
```

`User`の型に購入履歴をはじめからぶら下げる形で実装しようとした。

しかし、これでは `User` の `id` や `name` だけ取得したい時に購入履歴まで取得するロジックが走ってしまう。
大体、購入履歴といえば`Item`とのリレーションされたデータであり取得コストが大きいため
いくらキャッシュされるとはいえ、必要な情報だけが走る形で実装するのが望ましい。

# どうするのか

GraphQLはQueryをまとめることができるので、薄く作ってあるQueryたちをまとめてほしい情報が取得できるQureyを新たに作る。

## バックエンドで実装されているQuery

```typescript
type Query {
  user(id: String!): User
  purchase_history(user_id: String!): [Purchase]
}
```

`user` → IDやユーザー名など取得できる
`purchase_history` → ユーザーの購入履歴が取得できる
各Qureyはそれぞれ `user_id` を指定すればユーザーの情報を取得できる

しかし、このまま使ってしまうとリクエストを2つになってしまうため、GraphQLの特性を活かしきれていない。

## Queryを１つにまとめる

`user` と `purchase_history` を１つのQueryで取得できるようにQueryを定義してあげよう

```typescript
query getUserPurchaseHistory($user_id: String) {
  user(id: $user_id) {
    id
    name
  }
  purchase_history(user_id: $user_id) {
    id
    name
    catch_copy
  }
}
```

`getUserPurchaseHistory` に対して `user_id` を渡すことで1つのリクエストで２つの情報をまとめて取得できる。
こうすることで、必要な情報を必要なときに取得でき、コストの掛かる処理も必要な時だけ行うことができる。

# まとめ

またGraphQLの凄さを知ることができ、 `GraphQLはできるだけ薄く保つ` の意味や意図が理解できました。

設計次第ではネストが深くなってしまい、部分的にしか使わないQueryが量産されてしまうこともあると思います。
そうなってしまうとGraphQLの良さがなくなってしまうので一旦立ち止まって `できるだけ薄く` を意識することが大事ですね。

※ 筆者はまだまだ初心者です。間違った解釈や実装などがあればご指摘お願いします。
[MySQL][ERROR] Fatal error: Please read “Security” section of the manual to find out how to run mysqld as root!と言われた時の行動

# 概要
レンタルしているサーバーがメンテナンスされることになったため、サーバーを一時停止。
メンテナンス後、サーバーを起動したらなぜかMySQLが起動していない・・・
ログを見てみても、一時停止まではログに記載されていて、それからの再開処理はどこにも書かれてない・・・
とりあえず直接コマンドをたたいて(` sudo mysqld `)みたところ、以下のことを言われます。

>[ERROR] Fatal error: Please read “Security” section of the manual to find out how to run mysqld as root!

というわけで、開始です。

なお手元の環境は
CentOS 6
MySQL 5.7

になっております。

# そもそもこのエラーって何よ
>[ERROR] Fatal error: Please read “Security” section of the manual to find out how to run mysqld as root!

雑に翻訳すると「**mysqldをrootで動かしたかったらマニュアルの「Security」を読んでね！**」とのこと。
そういうわけで読みに行きます。
[6.1.5 How to Run MySQL as a Normal User](https://dev.mysql.com/doc/refman/5.7/en/changing-mysql-user.html)

再び雑に翻訳すると「**rootユーザーでの実行は禁止！ そのかわりrootでもmy.cnfに書くか、--user={user_name}に一般ユーザーを指定するとそのユーザーを使って起動するよ！**」と書いてあります。
いちいち設定するのも面倒なので、my.cnfに書きに行きましょう。
すでにmysqlというユーザーがサーバー内に存在することを確認後、以下を追記します。

```
[mysqld]
...（いろいろ書いてある）
user=mysql
```

というわけでもう一度` sudo mysqld `。少なくともSecurityについては言われなくなるかと思われます。

# 余談：ところで何が問題だったの？
さて、それではと勇んで`service mysqld start` を行ったところ、やっぱり起動しない…
ログを見てみたところ、ログにも何も書き込まれていない…
ふと、思い立ってログの権限を確認してみたところ、なんとroot
というわけで、`chown mysql:mysql mysql.log`を実行。そうしてもう一度実行したところ、今度はログが記載されました。

```
can't create/write to mysql.pid
```

pidってのが触れないようです。
もしや・・・と疑いながら今度はpidに対して`chown mysql:mysql mysql.pid`
実行後serviceから起動したら、mysqldが正常に起動されました。

そしてその後、 `/etc/init.d/mysqld` を確認したら、開始ユーザーにもきちんと `--user=mysql` の記載が。

どうもmysql5.7、導入方法によっては初回起動がrootでされてしまい、そのままrootユーザーとして各種ファイルを作りながら実行成功してしまうようです。
そして再起動したときに改めてmysqlユーザーで起動し、各種ファイルにパーミッションエラーで弾かれる、と。~~あほの子かな？~~

そんなわけで、よくわからないエラーは解決しました。
とりあえず、logのパーミッションを疑うところから始めよう！という教訓でした。
Railsのエラーが何なのか辿り着くまでの思考プロセス

# ●●のエラーだなこれ・・・と正しい推測まで到達するために・・・

```
undefined hogehoge_method
```
まずこんな感じでRailsサーバーと立ち上げても長いエラーが出るばかりで、画面が出てこない状況になります。
ここからバトルスタートですね。

## やりたいこと
エラーがなんなのかを特定する。例えば、DBなのか、リダイレクト関係なのか、ルーティングミスなのかなどのタイポとかと比べて、根の深そうなエラー周りなのかどうかを先ず知りたい

## 手順
1.　こけているメソッドのインスタンスを見てみる
メソッドに問題がない場合、そのさらに先で定義されているかコールされているものがこけているので、そのインスタンスが宣言されているファイルを探しに行きます。

2.ファイルを探す

```
$ find ./探したいディレクトリ -type f -print | xargs grep '検索文字列'
```
findコマンドでファイルを特定し、xargsコマンドに渡して検索文字列がヒットしたファイルを弾きだします。
ここでページが多く作成されていたりすると、あちこちで同名インスタンスが呼ばれているので分からなくなりそうですが、表示できていないページがどこに当たるのかと、ファイルの命名規則が合致していれば、探しやすいはずです。ここで、、viewの名前が分かり易いもの、（Restfullに作られていると、このファイル探査がしやすいですね。）

そうやってネストしているメソッドを伝っていくと、最終的に落ちているメソッドがなんなのか理解できる。
後は、そこを修正するだけ。
Webpack + TypeScript + Vue環境でJestを最低限使えるようにする

# はじめに
事前にTypeScript+Vueの環境構築はできているものとします。
今回は下記環境でJestを使えるようにします。

- webpack: 4.29.6
- vue: 2.6.10
- typescript: 3.4.1

# インストール
```
yarn add -D @vue/test-utils jest ts-jest vue-jest
```

# 設定

```json:package.json
{
  // 省略
  "scripts": {
    // 省略
    "test": "jest"
  },
  "jest": {
    "moduleFileExtensions": [
      "js",
      "ts",
      "json",
      "vue"
    ],
    "transform": {
      ".*\\.(vue)$": "vue-jest",
      "^.+\\.tsx?$": "ts-jest"
    }
  },
}
```

# テストファイル配置
ソースファイルを配置しているディレクトリ配下に「\_\_tests\_\_」ディレクトリを作成します。

```js:__tests__/ChatMessage.spec.ts
import { shallowMount } from "@vue/test-utils";
import ChatMessage from "../components/ChatMessage.vue";

describe("ChatMessage.vue", () => {
  test("renders props.message when passed", () => {
    const message = "new message";
    const wrapper = shallowMount(ChatMessage, {
      propsData: {
        message
      }
    });
    expect(wrapper.find(".text-box").text()).toMatch(msg);
  });
});
```

# 実行
```
yarn test
```

問題なければテストが実行されると思います。

# 参考
https://vue-test-utils.vuejs.org/ja/guides/using-with-typescript.html
https://jestjs.io/docs/ja/configuration#transform-object-string-string
トレジャーデータとは？入門編

## トレジャーデータとは？

- 自社が管理している各Dataと他社が管理しているDataを統合して1つのDBにできる(シームレス化)
- そのDBを使って施策を行なう(広告配信/各種マーケティング/分析)
- テクノロジー/サービス(広告効果測定ツール/Webアナリティクス/SNS/機械学習 他多数)を使ってプラットフォーム構築/施策実行を行なう

## TREASURE DATAの活用図

1. 自社が管理している多種大量のデータをリアルタイムでTREASURE DATAに送る
2. 自社保有していない2nd、3rd PartyデータをIDをキーにTREASURE DATAに送る
3. 「1」「2」のデータを統合/分析/セグメンテーションをかける
4. それらを元に「広告配信」「各種マーケティング」「分析/レポーティング」サービスを使って施策を行なう

## 4つの新機能

1. TREASURE GLOBAL ID
共通IDでドメイン/ブラウザ/クロスデバイス/オフライン等のIDを一つにする

2. セグメントビルダー
管理画面でセグメントを作成し、各ツールへ反映させる

3. リアルタイムセグメンテーション
顧客のログをリアルタイムに解析し、コンテンツの出し分けをリアルタイムで反映

4. コンテンツ解析
ページ内のキーワード抽出を行ない、関心のあるキーワードを抽出してセグメント化

## 導入による問題点解消

- リアルな顧客像を明確化
- 顧客ごとに最適なコミュニケーションを実現
- データを使って営業職/売り場の支援
- データを使って機器/設備メンテナンスを効率化
- 膨大なデータ量の計算
- データをマーケティング活用
- ダッシュボードが充実しているのでKPIをモニタリング
- KPIの異常値を検知した場合、メールでアラート通知
- ユーザーごとの買い物行動圏を把握
- ライフスタイルや趣味嗜好など顧客に合わせてパーソナライズされたコンテンツを配信
- データに基づくマーケティングシナリオの仮説を立て、データを元に検証
- 会員登録後の動きをモニタリングすることでアプローチ見直し
- 顧客をスコアリングして将来購入する商品を予測して、行動傾向を把握

### 顧客の好みと現在の行動ログからユーザーのモーメントを把握

モーメントドリブンなコミュニケーションを実施

- 性別や年代、居住地、職業
- 購入ブランド、ブランドロイヤリティ
- 購買チャネルや利用デバイス
- ターゲットカテゴリー情報一般の興味

### 「来店前」「来店中」「来店後」顧客に行なう施策

#### 「来店前」

- エリアターゲティングによる来店促進キャンペーン
- 過去3ヶ月に店舗から半径5km以内でアプリを起動したユーザーにキャンペーンの通知

#### 「来店中」

- 一定の購入合計金額を超えるとキャンペーンを告知
- 上記の合計金額が超えないときに「あと**円でキャンペーンが受けられる」通知を購買直後にリアルタイム配信

#### 「来店後」

- ショップの評価をしてもらってロイヤリティを高める

## 活用事例

### 車販売業者

#### 課題

- 顧客情報が部門ごとに管理されているので、顧客情報や行動を統合したい
- 顧客データを断片的しか利活用できていない
- 他社サイト閲覧行動で全体の趣味嗜好を把握したい

#### 解決

- 自社で保有するデータと外部データを統合する
- 顧客の特徴や行動を立体的/多角的に理解する
- それを元にカスタマージャーニーの理解が可能になる
- 成約後のデータも取れるので営業支援が可能になる
- １人１人の行動プロセスを知ることができる

#### 疑問

Q. どうやって外部データからユーザーを紐付けるのか？
A. TREASURE DATAが同一のID(globalID)を発行してそれを元に紐づけ。TREASURE DATAを利用している企業とデータエクスチェンジが可能。そのため外部データを扱うにはその企業間と契約する必要がある。開示するデータは企業間同士で決める。



### 化粧品販売業者

ユーザーごとにCRM(顧客情報管理)を最適化

#### 課題

- 単一のメルマガを全会員に向けて配信する
- 顧客ごとに最適化されたコミュニケーションを取りたい

#### 解決

- 自社メディアと外部サイトの行動履歴を統合してより深い顧客理解を果たす
- 上記の行動履歴から顧客の気分(モーメント)を把握
 - モーメントに合わせた施策を展開
 - ウキウキモーメント、ドンヨリモーメント、イライラモーメント

#### 疑問

Q. 行動履歴を知る手段は？
A. 例の1つとして、閲覧したページのキーワードを抽出(meta description、meta keyword)。そこから現在興味あることを知る = どういう状態なのかを把握

### 保険会社

#### 課題

- 契約時に契約者の情報を得ることはできるが、契約後の情報を把握することが難しい
- 契約後のライフステージに変化があったかを把握することが難しい
- ライフステージの変化に伴い、その変化に見合った保険を提案したい

#### 解決

- 契約者情報とオンライン行動データを結合してライフステージを推計
- ライフステージを把握することで、営業活動の優先付や案内商品の選定が可能に
- 保険商品の見直しを考える時期を知る
- 契約/解約の先手を打つ
- リアルタイムでユーザー情報に最適化された広告を配信

### 食品宅配

#### 課題

- 会員の属性や行動を把握できているが解約数を減らす対策が打てない
- 解約しそうな会員を知りたい

#### 解決

- 過去1ヶ月のデータをもとに機械学習を行ない、解約しそうな会員をリストアップ
- 解約する顧客の振る舞い、解約しない顧客の振る舞いを把握
- 顧客スコアリングを測定
- 解約抑止策を実施(ポイント付与/WEB UIの改善)

#### 疑問

Q. 顧客スコアリングってなに？
A. 過去1ヶ月間で解約した人の行動プロセスを分析。また解約と継続した人の理由を分解した結果、解約しそうなユーザーをスコアリング。高いスコアほど解約する確率が高いユーザーである。
Djangoでmatplotlibの図をPNG画像で表示

環境
OS : macOS Mojave
Anaconda : python3.6.7
Django==2.1.5

#matplotlibの図を表示する
Djangoでの計算アプリを作成するときにはmatplotlibの図をhtml上に埋め込むことが不可欠。
いろいろ調べるとsvg形式で埋め込む方法がよく出てくるが、svg形式だとアプリ上から保存したときにsvg形式で保存されてしまいその後の活用が厳しい。
PNG画像で出力できるように試行錯誤してみた。
結果としてはsvgの場合とほぼ同じだった。

#views.py
自分の現在作成中のものから一部を取り出す形で書くので少し見にくいかもしれないがご了承ください

```python:views.py
from django.http import HttpResponse
from django.shortcuts import render
import io
import matplotlib.pyplot as plt

#png画像形式に変換数関数
def plt2png():
    buf = io.BytesIO()
    plt.savefig(buf, format='png', dpi=200)
    s = buf.getvalue()
    buf.close()
    return s


# html表示view
def analysis_screen(request):
    return render(request, 'analysis.html')

#画像埋め込み用view
def img_plot(request):
    # matplotを使って作図する
    (ex)
    x = [1, 5, 9]
    y = [4, 6, 8]
    ax = plt.subplot()
    ax.scatter(x, y)
    png = plt2png()
    plt.cla()
    response = HttpResponse(png, content_type='image/png')
    return response
```

#urls.py
```python:urls.py
from django.urls import path
from . import views

app_name = 'analysis_app'
urlpatterns = [
    path('analysis', views.analysis_screen, name='analysis_screen'),
    path('analysis/plot', views.img_plot, name="img_plot"),
]
```

#analysis.html
```html:analysis.html
<img src="{% url 'analysis_app:img_plot' %}" alt="">
```

#終わりに
これでおそらくできるはずです(僕はできました。)
言葉少なめコードのみで申し訳ありません
Macでブロックチェーンに触れてみた -Marbles Demo-

#Hyperledger FabricのMarbles Demoを動かすまで

##まずは実行前に色々インストールします

```:自分がHyperledgerFabricの環境をインストールしたディレクトリへ移動
＄cd HyperledgerFabric
```

git cloneでサンプルをとってきます。
この時v4.0とバージョン指定してください。

```:
$ git clone http://github.com/IBM-Blockchain/marbles.git --single-branch --branch v4.0
```
インストール後mablesというフォルダがあるのでそこへ移動します。

```:marblesに移動
$ cd marbles
```
package.jsonに　“grpc”: “1.10.1”　を追加します

```:package.jsonを編集
$ vim package.json 
```

![スクリーンショット 2019-04-15 16.47.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393221/0e555460-a93a-2386-5992-15fcfb1bc2f1.png)
場所は赤線部分です。



次に依存モジュールをインストールしていきます。

```:依存モジュールをインストール
$ sudo npm install gulp -g
```
ここで何やらエラーを吐かれました。
npmのバージョンが違う的なことを言われています。
3.10.10にダウングレードします。

```:npmのダウングレード
＄sudo npm install npm@3.10.10 -g
```
しかし、以下のようなエラーが、、、

![スクリーンショット 2019-04-15 16.57.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393221/6a1c0368-1f36-925e-4efb-14b2fee8efcf.png)

npmの公式を確認しに行くと以下の手順でいけるそうです。

```:npmのディレクトリのパスを確認
$ npm config get prefix
/usr/local
```

```:npmディレクトリのオーナーを自分のアカウントに変更する
 ＄sudo chown -R $(whoami) $(npm config get prefix)/{lib/node_modules,bin,share}
```

この手順を踏んでから再チャレンジしたところ行けました。

```:依存モジュールをインストール
$ sudo npm install gulp -g
$ npm install
```

##実行していきます
5つのステップでMarbles Demoの実行をしていきます。
1. ブロックチェーンネットワークを起動
2. チェーンコードを導入
3. Mables Demoの起動
4. Webブラウザでアクセス
5. 初回のみ初期設定

###ブロックチェーンネットワークを起動
```:ブロックチェーンネットワーク起動
$ cd HyperledgerFabric/fabric-samples/basic-network
$ rm -fr ~/.hfc-key-store
$ mkdir ~/.hfc-key-store
$ ./start.sh
```

###チェーンコードを導入
チェーンコードの導入はPeerへのインストールとインスタンス化の2ステップで行います。

```:チェーンコードをインストール
$ cd ~/HyperledgerFabric/marbles
$ cd scripts
$ node install_chaincode.js 
```

```:チェーンコードのインスタンス化
$ node instantiate_chaincode.js 
```

###Mables Demoの起動

```:Demoの起動
$ cd ../   <—marblesに移動
$ gulp marbles_local & 
　　（略）
debug: Open your browser to http://localhost:3001 and login as "admin" to initiate startup
```

###Webブラウザでアクセス
起動するとURLとログインに必要な"admin"というユーザ名みたいなのが出力されます。
そこへアクセスします。

###初期設定

スクリーンショットを撮り忘れました。
以下の手順でいけるので公式の画像などを参考にして設定してください。

Start—>Next Step—>Next Step—>Next Step—>Create—>(アニメーションが停止するのを待ってから)Next Step—>Enter

以上のやり方でDemoが起動できました。
パスを通すってどうするの？(macOS)

わかりにくいことを少し記録、忘備録としてこちらにも残しておきます。

いろんなものをダウンロードしてうまく使えるようにするためによく**"パスを通す"**という言葉をよく耳にします。
知らず知らずのうちにターミナルを起動し、コマンドを打って、いろんな情報、プログラムを起動させています。
さて、コマンド、実行ファイルはどこに入っているのでしょうか。

いろんなところに点在しているのが実際です。

```
echo $PATH
```

と打ち込んで実行してみましょう！私の環境(mac)では以下の通り。

```
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
```

/usr/local/bin
/usr/bin:/bin
/usr/sbin
/sbin

この4つの場所にいろんなコマンドやら何やらが格納されていて、環境変数PATHを利用してコマンドのみ打てば使えるようにしています。

**環境変数PATH**を登録することを**"パスを通す"**と言います。

**.bash_profile**に記述することで実現します。

ない場合は作ります。

```
touch .bash_profile
```

そして開いて編集します。

```
open ~/.bash_profile
```

とコマンド打つと、macですとTextEditが開いて編集できる状態になります。

```
export PATH=$PATH:/希望のパス/
```

と打ち込みます。続いて、

```
source ~/.bash_profile
```

とすると、実際に使えるようになります。
M5Stackで使おう オムロン 絶対圧センサ評価モジュール 2SMPB-02E

オムロンの絶対圧センサ評価モジュール2SMPB-02EをM5Stackで使ってみましょう。
といってもGithubの内容をインクルードして起動するだけです。

https://github.com/omron-devhub/2smpb02e-grove-m5stack
GithubからChrone or downloadをクリックし、DownloadZipで保存します。
![2smpb02e-M5stack-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/20bb7985-3be7-45ce-d6c2-39a9602c9c3f.jpeg)

Arduinoを開いてスケッチ→ライブラリをインクルード→Zip形式のライブラリをインクルード
![2smpb02e-M5stack-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/eeb5a0a8-5d8a-36f8-5bf6-64dfe8cc3a1f.jpeg)
該当ファイルを選択
![2smpb02e-M5stack-3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/656b0218-c026-6fde-4c95-418df207890f.jpeg)
ファイル→スケッチ例→Omron 2smpb02e-grove-m5stackからスケッチ例を選択します。
![2smpb02e-M5stack-4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/50a2f235-38a1-4ef8-e6d7-ea3e9f11a674.jpeg)

次は、M5StackとGroveコネクタを接続します。
M5Stackの左端にある赤いコネクタ（Coreの場合）に差し込みます。
![2smpb02e-M5stack-6-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/e8d4ccde-f3f2-070d-026e-4bde42afdd59.jpeg)

そして、再起動すると、正常な値が表示されるはずです。
![2smpb02e-M5stack-6-3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/14e28d97-6847-effe-961d-5382f0a5a001.jpeg)
Alpine linux でユーザとグループをサッと作る

## ユーザとグループを作る

alpine linux には useradd や groupadd がありません。
代わりに以下のようなコードを実行することで、ユーザとグループが設定できます。
パスワードは必要に応じて設定しましょう！

```sh
$ addgroup -S www \
  && adduser -S www -G www \
  && echo "www ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers \
  && echo 'www:www' | chpasswd
```
BottomSheetDialogFragmentで全画面表示だけ有効にしたい

目的

BottomSheetDialogFragmentで全画面表示だけ有効にしたい

コード

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {

        val dialog = super.onCreateDialog(savedInstanceState) as BottomSheetDialog

        dialog.setOnShowListener { dialog ->
            val d = dialog as BottomSheetDialog

            val bottomSheet = d.findViewById(com.google.android.material.R.id.design_bottom_sheet) as FrameLayout?
            val behavior = BottomSheetBehavior.from(bottomSheet)
            behavior.state = BottomSheetBehavior.STATE_COLLAPSED

            behavior.setBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
                override fun onSlide(bottomSheet: View, slideOffset: Float) {
                    //何もしない
                }

                override fun onStateChanged(bottomSheet: View, newState: Int) {
                    //この条件分岐追加しないと画面が消えた後モーダルの半透明黒マスクだけが残る
                    if (newState == BottomSheetBehavior.STATE_HIDDEN) {
                        dismiss()
                        behavior.state = BottomSheetBehavior.STATE_COLLAPSED
                    }
                    //途中で止まろうとするので強制的に全画面表示する
                    else if (newState == BottomSheetBehavior.STATE_COLLAPSED) {
                        behavior.state = BottomSheetBehavior.STATE_EXPANDED
                    }
                }
            })

            //下から出てきて全画面表示されるようにする
            behavior.state = BottomSheetBehavior.STATE_EXPANDED
        }
Vtuberの生放送、コメントの流速が早い＝面白い部分なのでは？と思った

# tl;dr
* Vtuberの生放送がめっちゃ多いので切り抜きとかの要約技術が求められる
* 類似の研究をパクってコメントの流速が早いところを重要（＝おもしろい）とみなせばいいんじゃない？と思った
* やってみた。
* なんとなく抽出できてるような。。。？という気持ちになった

# 背景
* Vtuberの生放送、めっちゃ多くて見きれない問題がある
    * 「にじさんじ」のライバーは現在70？人らしい
        * https://nijisanji.ichikara.co.jp/member/
    * 1人あたり週1時間の生放送をやっていたとすると、全部見るのに週70時間必要
    * 週70時間＝10時間/日
    * むりぃ。。。
* ということで、生放送の中で特に良かった部分がどこか知りたい需要があり、その需要に対する対応がいくつかある
    * 「切り抜き」動画
        * 生放送の面白い部分だけを切り取った動画　 
        * 元の動画に字幕をつけたり、他の動画とか見てないとわからない部分のサポートがついてたりする
    * 視聴者による面白かった部分を時間情報と併せたコメント
    * 配信者によるまとめ動画

# 関連
動画の重要な部分を抜き出すのは映像要約というジャンルとして研究されている
近そうなやつとして、ニコニコ動画でコメントの流速を使った動画要約が研究されている
https://research.miyashita.com/papers/D6

# ということで
youtubeの生放送（アーカイブ）からコメントを拾ってきて、その流速が早い箇所は面白かったのか見てみた

# やり方
1. 頑張ってコメントを取得する
    * やり方はこちらへ -> https://qiita.com/miyatsuki/items/f86c1a751123b5e4107f
    * 力技すぎるのでなんとかしたい。。。
2. コメント数/分を動画時間の最初から最後まで数え上げる
    * 配信開始前にコメントするとマイナス時間として記録されるが、面倒だったのでそれはすべて弾いた
3. グラフ化して眺めてみる

# 結果を眺めてみる

使った動画
笹木ＶＳ叶　～テトリス編～｜ぷよぷよテトリス
https://www.youtube.com/watch?v=lNWvuV9mzQI

# 注意: 此処から先はネタバレになるので、見る予定がある方は先に見てきてください
というか一回見てこないとこのあとの話意味わからないかも。。。

## グラフ化した
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176335/776968fc-487b-0456-f879-aade8e19b08a.png)
※ 数字がついている部分は流速が早かった時間帯top5。
　 例: 39は39:00~39:59までを表す

## コメント流速top5の部分で何が起きていたか

* 39分(259, 流速2位)
    * （２人ともぷよぷよ初プレイだったので）ハンデになるはずのぷよvsテトで笹木が惨敗
    * 質問コーナー１
* 44分(243, 4位)
    * 笹木負ける
    * 二色オムライスの話
    * 質問コーナー２
* 60分(257, 3位)
    * 泣きの一回を速攻やり直す
    * やり直した結果、初手全消しを決められる
* 62分(242, 5位)
    * 笹木の上目づかいが怖い
* 68分(262, 1位)
    * 最終戦でもボコられる&うそなき

## 実際に切り抜かれたり、コメントで言及されていたもの
* 2分（流速55位）
    * ここから動画開始というコメントなので他と毛色が違う
* 17分（8位）
* 21分（27位）
* 29分（15位）
* 42分（23位）
* 44分（4位）
* 49分（6位）
* 62分（5位）
    * 言及数3回 + 切り抜き動画を一つ発見

# 所感
* すごく大雑把には動画の主要地点が拾えてるような気がしないでもない
* とはいえ一番言及されている地点とコメント流速が一致していない
    * 残りがほぼ試合終了タイミングなので、対戦系の実況動画だと、決着がついた瞬間のほうが流速が早くなりがち？
    * 配信者が視聴者に問いかけるようなことをすると必然的に流速が上がるのでそのバイアスを考える必要がある
* 要約という観点だとその瞬間だけ拾ってもコンテキストがつながらないので難しい
    * 39分は流速数２位だが、２人ともぷよぷよ未経験という事実を知らないと面白さの意味がわからない
    * 他の動画からのコンテキストを引っ張ってる場合もあり、それだと一つの動画だけ見ててもわからなかったり

# いつかやる
* 今回の結果をもとに要約動画を作ってみたい
    * 元の研究だと流速ピークから2,3秒間で拾っているが、youtube liveの場合、体感的にはもっとラグが大きいような気がしている
    * コメントピーク前後1分くらい？
    * 生放送中になにか起きてそれに反応するのに数秒だと厳しいのでは。。。？
* あとコメント収集が力技すぎてスケーラビリティ0なのでなんとかしたい
M5Stackをはじめよう　Arduino編

今日は「M5Stackユーザーミーティング vol.4」の日です。
ということで、一個書いてみました。

M5StackとはESP-32が入ったマイコンボードです。
M5Stackが良いところは、ケースに入っており、日本人受けしやすいところです。
（外人さんは基板むき出しても問題ないですが、日本人はむき出しを嫌がります。）

ESP-32に液晶を付けたものは2000円出せば買えますが、M5Stackは4000円ということで
文句を言う人もおり、キラーを作りたいという人もいましたが、私はM５Stackは面白いガジェットであり
完成度が高いともいます（中身ではなく、プロダクトとして）

さて、御託は良いので、使い方です。
まずは、Arduinoをインストールします。
https://www.arduino.cc/en/Main/Software
Arduinoをダウンロードしましょう
![Arduino-DL.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/8504c9e0-0eda-e79e-9184-2ffd18ce38dd.jpeg)

ファイル⇒環境設定を開きます
![ESP-32-Arduino-0.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/f28ce29d-373c-dbd4-fe9d-972e1ee43eca.jpeg)

以下のアドレスをボードマネージャーのURLに入力します。
https://dl.espressif.com/dl/package_esp32_index.json
![ESP-32-Arduino.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/17b79639-855d-a025-0a7e-86ac1255cd59.jpeg)

ツール→ボード（？？？ここは気にしないでね）→ボードマネージャーをクリックします。
![M5Stack-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/9f3f24a3-fcc3-799b-3467-53bdd3945e6f.jpeg)
「ESP32」と入力し、インストールします。
![M5Stack-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/b7dda189-7637-9555-8b9a-bfb2d55c8410.jpeg)

ボードをM5Stackにします
私はCoreですがFireやM5Stickなどの人はそちらを選択してください。
![M5Stack-3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/a5e35def-1316-000d-8bc6-83906c83d031.jpeg)

次にライブラリ（サンプルプログラムんど）をインストールします。
スケッチ→ライブラリをインクルード→ライブラリを管理
をクリックします。
![M5Stack-4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/310cbd44-7d81-77a8-4e9f-5495dc19014a.jpeg)
検索に「M5Stack」と入れ、インストールをクリックします。
![M5Stack-4-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/99f5a0fa-f1f4-c7d1-8e74-c74c106f1b60.jpeg)

これで、M5Stackのサンプルスケッチが使えます。
ファイル→スケッチ例→M5Stack
から使っていたいものを選択します。
![M5Stack-5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/bfabba28-6cd3-f943-6d4e-3afce7a8d81f.jpeg)

さあ、プログラムを書き込みますよ
とその前に、ポートをセッティングします。
ツール→シリアルポート→Com？？？
このCom？？？がM5Stackが接続されているポートになります。
これを選択します。
![M5Stack-6-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/2bd6ef72-aa22-7d55-ef16-8cb2591a072d.jpeg)

このポートは、デバイスマネージャーにてSilicon Labs～～～と書いてあるものがM5Stackとつながっているものになります（ここは変わる可能性があります）
![M5Stack-6-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/1233fa0d-f6ef-03a3-de2e-ea7bd8d7a704.jpeg)

最後に、矢印を押します。
![M5Stack-6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/799e5591-715d-ea18-1607-3efdb9d18284.jpeg)
ボードへの書き込みが完了しました。
となれば書き込み完了です。
![M5Stack-7.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/a5baa17e-7ccf-52c8-96dd-90f60929a0a9.jpeg)
SmartGit > Branches ペイン > ブランチのチェックボックスの色 > commit graphの色と一致. commit graphのどのcommitに対応するかの目せ方

```txt:動作環境
Windows 10 Pro (64bit) バージョン 1809
SmartGit v18.2.3
```

### 疑問

SmartGitを使っていて感じた疑問。

![2019-04-15_16h13_53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/fdb5ea09-4fa3-fa58-bcf5-6348ef7e2265.png)

「ブランチの左側のチェックボックスの色は何を意味するのか?」

### チェックボックスの色

- 同じブランチが常に同じ色になるわけではない
    - green: feature/190415/XXX
    - や
    - pink: feature/190415/XXX
- チェックアウト中のブランチは黒?

### 意味

有償サポートより回答をいただいた。

意訳「それらはCommits graphのbranch linesに使われるものと同じ色です」

どのブランチがどのコミットに該当するか、を可視化するための機能のようです。

さらに、有償サポートより情報が届きました。

意訳「限られた色を選択されたブランチに割当てている（決定的な順番で）。選択によっては、一つのブランチは別の色になる。しかしながら、Branchesペインの色は必ずcommit graphの色と一致するようになっている。もしそうでなければ、screenshotを取って連絡ください」

ありがとうございます。
技術書典6の振り返り

今回、4月14日に開催された「技術書典6」にサークル参加してきました。

![IMG_0725.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171989/9ed675fb-9aa8-47d7-ec7c-58e6007f78c2.jpeg)

[「六木本未来ラボ」サークル詳細はこちら](https://techbookfest.org/event/tbf06/circle/34330004)

頒布物は　「[Developers Magazine vol. 1](https://booth.pm/ja/items/1289841)」

雑誌風にということで、AWS関連の記事が8本と豪華な内容になっています。

結果は、印刷本とダウンロード版合わせて350冊を世に出すことができました。

当日ブースに立ち寄ってくれた方ありがとうございます。

また、手に取っていただいた方、感謝です。次号へのモチベーションになります。

さあ、技術書典6の振り返りです。


## まずは、印刷本数から

印刷本の冊数については、最終的に__300冊__を注文したのですが

当初の計画では、100冊の予定でした。

早々に非リンク数が100を超えたという劇薬の効果もあり、

ほどなくして「妖怪倍プッシュ」がメンバーに取り付き始め、

ある時期から200冊はいけるでしょ！となり、話のベースは200冊か300冊どちらにするか？いや400冊も届くかも・・・。

あー怖い怖い。。。

そして決断したのは__300冊__！

結局、妖怪倍プッシュの思うつぼです。しょせん凡人は煩悩の塊なのです。

> ちなみに当日朝の9時で非リンク数は250でした。

それでも何冊注文するのか？という話題の時には、記事を書き上げた高揚感もあったり、チキンレース的なところもありとても楽しかったです。

ちなみに、300冊という数字がどういうことかといいますと「__1分12秒で1冊を売っていく__」計算になります。

実際には、15時30分で完売になりましたので「54秒で1冊が売れた」ことになります。←何それ怖い。。。

## 当日について

ブースは狭い。そして、300冊分の段ボールに若干気後れしたのは事実です。

![IMG_0726.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171989/8e1138aa-0d98-eb7b-54ab-dafb5485650a.jpeg)

やっておいて、良かったことは事前のリハーサルです。

イメージだけではなく、実際に会議室で設営してみてあれやこれやと手を入れてました。

写真にとっておいたのですが、とても役に立ちます。

![IMG_0720-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171989/f8727a4d-aebe-a650-45df-26cc69cc3d44.jpeg)

当日は2人しか入れないので、写真にとっておいたものを見比べながら迷わず作れたのはリハーサルのおかげです。

![iOS の画像 (2).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171989/d6abb8ed-6825-5cf3-0e2d-b2ef731f2cee.jpeg)


以下は僕の個人的な心構えになりました。

 * 飲み物は事前に確保する事！
 * ご飯は食べれないと思え！
 * トイレは我慢！

この字ずらだけだと、劣悪な環境に見えますが楽しいから大丈夫です。

後、人が多すぎです。

来場者数は前回と同様に1万人をこえていたようで、人人人でした。

雰囲気にのまれながら必死に売り子をしていたため気が付かなかったのですが、

人に埋もれて、もはや何を売っているのかわからない状態だったようです。

twitterに流れてきたこちらのツィートを知らせてくれたメンバーがいて、

https://twitter.com/careerupdate/status/1117294228831391746?s=21

売り子を代わった後は、

メンバーの後ろで、近くに来ている方に本が見えるように掲げて立っていました。

後ろから見ていると、上げている本に目線が言っているのが良くわかりましたよ。とてもおすすめです！

## 簡単後払いについて

運営が作成しているサービスだけあって人気ですね。

今回は対応しなかったのですが、対応したほうが絶対に良いです。

結構な確率で利用されているなあという感覚です。

次回は対応しようという話になりました。当選できればですが・・・。


## 最後に

独特な雰囲気にのみ込まれそうになりながら、飲まれてたのかもしれませんが、楽しく6時間を過ごせました。

ただ、売り子で疲れてしまい戦利品が1つしかなかったのが悔やまれます。

やはり、買ったものを並べたりしたいですよね！
git add -uで変更箇所だけaddする

#変更ファイルのみgit addしたいときはこのコマンド

```
$ git add -u
```


#実行例
まだbranch上に何もない
<img width="1436" alt="スクリーンショット 2019-04-15 14.25.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319526/8c03c425-6547-24f3-8e88-fee75953781f.png">

コード追加する
<img width="1313" alt="スクリーンショット 2019-04-15 14.26.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319526/6d200608-3cf8-b1a5-6f52-2fe5c07c51fd.png">


ここで

```
$ git add -u
```


変更ファイルのみaddされる
<img width="1436" alt="スクリーンショット 2019-04-15 14.26.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/319526/3fc97b75-aadd-3587-1154-8a457a580048.png">

最後にmasterにpush

```
$ git commit -m 'fix'
$ git push origin master
```
Debugの.ipaを作成する方法


Xcodeで.ipaを作成するとき、初期設定だとRelease形式になっています。
Debug形式でExportする方法を記載します。

## 開発環境

Mac: 10.13.6 High Sierra
Xcode: 10.1

## 1. Archive時のBuild Configuration変更

これが今回一番大事な作業。
`Command + Shift + ,` などでEdit Schemeを開きます。
ArchiveのBuild ConfigurationをReleaseからDebugに変更します。

![](https://i.imgur.com/Iec6Jsd.png)

## 2. flagの設定

swift flagで環境を切り替えている人は、変更をしておきましょう。
今回作るのは `Debug` が対象となります。

![](https://i.imgur.com/2wRTi9u.png)

## 3. Archive実行

メニューバーのProductにある `Archive` を選択、実行します。

<img width=180px src="https://i.imgur.com/2KmD9l6.png">

## 4. Distribute App

Archiveが成功したら、Organizerが立ち上がります。
※余談ですが、Organizerってなんか前とUI変わりましたね。

`Distribute App` を選択します。

<img width=240px src="https://i.imgur.com/TXSCDWr.png">

Developmentを選択してNext。

<img width=600px src="https://i.imgur.com/A698lyn.png">

App Thinningはスルーで大丈夫です、NoneのままNext。

<img width=600px src="https://i.imgur.com/wNJi3eF.png">

signingをよしなに選択します。

<img width=600px src="https://i.imgur.com/aKM0Sik.png">

この後結構時間かかります、おそらく。
ロードが完了したら、Exportしましょう。

## 5. Exportしたファイルを開く

Exportしたファイルを任意のところに置いて、開きます。
`xxx.ipa` ファイルが作成できました。

<img width=240px src="https://i.imgur.com/WiPXapi.png">

## 最後に

Xcode10.2って、mojaveじゃないと使えなくてつらい。